Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/ajp/tomcat4/Ajp13Connector.java


1   /*
2    *  Copyright 1999-2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package org.apache.ajp.tomcat4;
18  
19  import java.io.IOException;
20  import java.net.InetAddress;
21  import java.net.ServerSocket;
22  import java.net.Socket;
23  import java.security.AccessControlException;
24  import java.util.Stack;
25  import java.util.Vector;
26  
27  import org.apache.catalina.Connector;
28  import org.apache.catalina.Container;
29  import org.apache.catalina.Lifecycle;
30  import org.apache.catalina.LifecycleException;
31  import org.apache.catalina.LifecycleListener;
32  import org.apache.catalina.Request;
33  import org.apache.catalina.Response;
34  import org.apache.catalina.Service;
35  import org.apache.catalina.net.DefaultServerSocketFactory;
36  import org.apache.catalina.net.ServerSocketFactory;
37  import org.apache.catalina.util.LifecycleSupport;
38  import org.apache.catalina.util.StringManager;
39  
40  /**
41   * Implementation of an Ajp13 connector.
42   *
43   * @author Kevin Seguin
44   * @version $Revision: 299218 $ $Date: 2004-02-24 03:48:44 -0500 (Tue, 24 Feb 2004) $
45   */
46  
47  
48  public final class Ajp13Connector
49      implements Connector, Lifecycle, Runnable {
50  
51  
52      // ----------------------------------------------------- Instance Variables
53  
54  
55      /**
56       * The accept count for this Connector.
57       */
58      private int acceptCount = 10;
59  
60  
61      /**
62       * The IP address on which to bind, if any.  If <code>null</code>, all
63       * addresses on the server will be bound.
64       */
65      private String address = null;
66  
67  
68      /**
69       * The input buffer size we should create on input streams.
70       */
71      private int bufferSize = 2048;
72  
73  
74      /**
75       * The Container used for processing requests received by this Connector.
76       */
77      protected Container container = null;
78  
79  
80      /**
81       * The set of processors that have ever been created.
82       */
83      private Vector created = new Vector();
84  
85  
86      /**
87       * The current number of processors that have been created.
88       */
89      private int curProcessors = 0;
90  
91  
92      /**
93       * The debugging detail level for this component.
94       */
95      private int debug = 0;
96  
97  
98      /**
99       * The server socket factory for this component.
100      */
101     private ServerSocketFactory factory = null;
102 
103 
104     /**
105      * Descriptive information about this Connector implementation.
106      */
107     private static final String info =
108         "org.apache.catalina.connector.ajp.Ajp13Connector/1.0";
109 
110 
111     /**
112      * redirect port.
113      */
114     private int redirectPort = -1;
115 
116     /**
117      * enable DNS lookups.
118      */
119     private boolean enableLookups = false;
120 
121     /**
122      * The lifecycle event support for this component.
123      */
124     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
125 
126 
127     /**
128      * The minimum number of processors to start at initialization time.
129      */
130     protected int minProcessors = 5;
131 
132 
133     /**
134      * The maximum number of processors allowed, or <0 for unlimited.
135      */
136     private int maxProcessors = 20;
137 
138 
139     /**
140      * Timeout value on the incoming connection.
141      * Note : a value of 0 means no timeout.
142      */
143     private int connectionTimeout = -1;
144 
145 
146     /**
147      * Linger value to be used on socket close.
148      * Note : a value of -1 means no linger used on close.
149      */
150     private int connectionLinger = -1;
151 
152 
153     /**
154      * The port number on which we listen for ajp13 requests.
155      */
156     private int port = 8009;
157 
158 
159     /**
160      * The set of processors that have been created but are not currently
161      * being used to process a request.
162      */
163     private Stack processors = new Stack();
164 
165 
166     /**
167      * The request scheme that will be set on all requests received
168      * through this connector.
169      */
170     private String scheme = "http";
171 
172 
173     /**
174      * The secure connection flag that will be set on all requests received
175      * through this connector.
176      */
177     private boolean secure = false;
178 
179 
180     /**
181      * The server socket through which we listen for incoming TCP connections.
182      */
183     private ServerSocket serverSocket = null;
184 
185 
186     /**
187      * The string manager for this package.
188      */
189     private StringManager sm =
190   StringManager.getManager(Constants.PACKAGE);
191 
192 
193     /**
194      * Has this component been started yet?
195      */
196     private boolean started = false;
197 
198 
199     /**
200      * The shutdown signal to our background thread
201      */
202     private boolean stopped = false;
203 
204 
205     /**
206      * The background thread.
207      */
208     private Thread thread = null;
209 
210 
211     /**
212      * This connector's thread group.
213      */
214     private ThreadGroup threadGroup = null;
215 
216 
217     /**
218      * The name to register for the background thread.
219      */
220     private String threadName = null;
221 
222 
223     /**
224      * A thread that periodically logs debug info if debug > 0.
225      */
226     private DebugThread debugThread = null;
227 
228 
229     /**
230      * The thread synchronization object.
231      */
232     private Object threadSync = new Object();
233 
234     private Ajp13Logger logger = new Ajp13Logger();
235 
236     /**
237      * The service which which the connector is associated
238      */
239     private Service service = null;
240 
241     private String secret = null;
242 
243 
244     /**
245      * Tomcat authentication flag. If true, the authnetication is done by
246      * Tomcat, otherwise, it is done by the native webserver.
247      */
248     private boolean tomcatAuthentication = true;
249 
250 
251     // ------------------------------------------------------------- Properties
252 
253 
254     /**
255      * Return the connection timeout for this Connector.
256      */
257     public int getConnectionTimeout() {
258 
259   return (connectionTimeout);
260 
261     }
262 
263 
264     /**
265      * Set the connection timeout for this Connector.
266      *
267      * @param connectionTimeout The new connection timeout
268      */
269     public void setConnectionTimeout(int connectionTimeout) {
270 
271   this.connectionTimeout = connectionTimeout;
272 
273     }
274 
275     /**
276      * Return the connection linger settings for this Connector.
277      */
278     public int getConnectionLinger() {
279 
280   return (connectionLinger);
281 
282     }
283 
284 
285     /**
286      * Set the connection linger for this Connector.
287      *
288      * @param connectionLinger The new connection linger
289      */
290     public void setConnectionLinger(int connectionLinger) {
291 
292   this.connectionLinger = connectionLinger;
293 
294     }
295 
296     public void setSecret( String s ) {
297         secret=s;
298     }
299 
300     public String getSecret() {
301         return secret;
302     }
303     
304 
305     /**
306      * Return the accept count for this Connector.
307      */
308     public int getAcceptCount() {
309 
310   return (acceptCount);
311 
312     }
313 
314 
315     /**
316      * Set the accept count for this Connector.
317      *
318      * @param count The new accept count
319      */
320     public void setAcceptCount(int count) {
321 
322   this.acceptCount = count;
323 
324     }
325 
326 
327 
328     /**
329      * Return the bind IP address for this Connector.
330      */
331     public String getAddress() {
332 
333   return (this.address);
334 
335     }
336 
337 
338     /**
339      * Set the bind IP address for this Connector.
340      *
341      * @param address The bind IP address
342      */
343     public void setAddress(String address) {
344 
345   this.address = address;
346 
347     }
348 
349 
350     /**
351      * Is this connector available for processing requests?
352      */
353     public boolean isAvailable() {
354 
355   return (started);
356 
357     }
358 
359 
360     /**
361      * Return the input buffer size for this Connector.
362      */
363     public int getBufferSize() {
364 
365   return (this.bufferSize);
366 
367     }
368 
369 
370     /**
371      * Set the input buffer size for this Connector.
372      *
373      * @param bufferSize The new input buffer size.
374      */
375     public void setBufferSize(int bufferSize) {
376 
377   this.bufferSize = bufferSize;
378 
379     }
380 
381 
382     /**
383      * Return the Container used for processing requests received by this
384      * Connector.
385      */
386     public Container getContainer() {
387 
388   return (container);
389 
390     }
391 
392 
393     /**
394      * Set the Container used for processing requests received by this
395      * Connector.
396      *
397      * @param container The new Container to use
398      */
399     public void setContainer(Container container) {
400 
401   this.container = container;
402 
403     }
404 
405 
406     /**
407      * Return the current number of processors that have been created.
408      */
409     public int getCurProcessors() {
410 
411   return (curProcessors);
412 
413     }
414 
415 
416     /**
417      * Return the debugging detail level for this component.
418      */
419     public int getDebug() {
420 
421         return (debug);
422 
423     }
424 
425 
426     /**
427      * Set the debugging detail level for this component.
428      *
429      * @param debug The new debugging detail level
430      */
431     public void setDebug(int debug) {
432 
433         this.debug = debug;
434 
435     }
436 
437     /**
438      * Return the "enable DNS lookups" flag.
439      */
440     public boolean getEnableLookups() {
441         return this.enableLookups;
442     }
443 
444     /**
445      * Set the "enable DNS lookups" flag.
446      *
447      * @param enableLookups The new "enable DNS lookups" flag value
448      */
449     public void setEnableLookups(boolean enableLookups) {
450         this.enableLookups = enableLookups;
451     }
452 
453     /**
454      * Return the port number to which a request should be redirected if
455      * it comes in on a non-SSL port and is subject to a security constraint
456      * with a transport guarantee that requires SSL.
457      */
458     public int getRedirectPort() {
459         return this.redirectPort;
460     }
461 
462 
463     /**
464      * Set the redirect port number.
465      *
466      * @param redirectPort The redirect port number (non-SSL to SSL)
467      */
468     public void setRedirectPort(int redirectPort) {
469         this.redirectPort = redirectPort;
470     }
471 
472     /**
473      * Return the server socket factory used by this Container.
474      */
475     public ServerSocketFactory getFactory() {
476 
477         if (this.factory == null) {
478             synchronized (this) {
479                 this.factory = new DefaultServerSocketFactory();
480             }
481         }
482         return (this.factory);
483 
484     }
485 
486 
487     /**
488      * Set the server socket factory used by this Container.
489      *
490      * @param factory The new server socket factory
491      */
492     public void setFactory(ServerSocketFactory factory) {
493 
494         this.factory = factory;
495 
496     }
497 
498 
499     /**
500      * Return descriptive information about this Connector implementation.
501      */
502     public String getInfo() {
503 
504   return (info);
505 
506     }
507 
508 
509     /**
510      * Return the minimum number of processors to start at initialization.
511      */
512     public int getMinProcessors() {
513 
514   return (minProcessors);
515 
516     }
517 
518 
519     /**
520      * Set the minimum number of processors to start at initialization.
521      *
522      * @param minProcessors The new minimum processors
523      */
524     public void setMinProcessors(int minProcessors) {
525 
526   this.minProcessors = minProcessors;
527 
528     }
529 
530 
531     /**
532      * Return the maximum number of processors allowed, or <0 for unlimited.
533      */
534     public int getMaxProcessors() {
535 
536   return (maxProcessors);
537 
538     }
539 
540 
541     /**
542      * Set the maximum number of processors allowed, or <0 for unlimited.
543      *
544      * @param maxProcessors The new maximum processors
545      */
546     public void setMaxProcessors(int maxProcessors) {
547 
548   this.maxProcessors = maxProcessors;
549 
550     }
551 
552 
553     /**
554      * Return the port number on which we listen for AJP13 requests.
555      */
556     public int getPort() {
557 
558   return (this.port);
559 
560     }
561 
562 
563     /**
564      * Set the port number on which we listen for AJP13 requests.
565      *
566      * @param port The new port number
567      */
568     public void setPort(int port) {
569 
570   this.port = port;
571 
572     }
573 
574 
575     /**
576      * Return the scheme that will be assigned to requests received
577      * through this connector.  Default value is "http".
578      */
579     public String getScheme() {
580 
581   return (this.scheme);
582 
583     }
584 
585 
586     /**
587      * Set the scheme that will be assigned to requests received through
588      * this connector.
589      *
590      * @param scheme The new scheme
591      */
592     public void setScheme(String scheme) {
593 
594   this.scheme = scheme;
595 
596     }
597 
598 
599     /**
600      * Return the secure connection flag that will be assigned to requests
601      * received through this connector.  Default value is "false".
602      */
603     public boolean getSecure() {
604 
605   return (this.secure);
606 
607     }
608 
609 
610     /**
611      * Set the secure connection flag that will be assigned to requests
612      * received through this connector.
613      *
614      * @param secure The new secure connection flag
615      */
616     public void setSecure(boolean secure) {
617 
618   this.secure = secure;
619 
620     }
621 
622 
623     /**
624      * Returns the <code>Service</code> with which we are associated.
625      */
626     public Service getService() {
627   return service;
628     }
629 
630 
631     /**
632      * Set the <code>Service</code> with which we are associated.
633      */
634     public void setService(Service service) {
635   this.service = service;
636     }
637 
638 
639     /**
640      * Get the value of the tomcatAuthentication flag.
641      */
642     public boolean getTomcatAuthentication() {
643         return tomcatAuthentication;
644     }
645 
646 
647     /**
648      * Set the value of the tomcatAuthentication flag.
649      */
650     public void setTomcatAuthentication(boolean tomcatAuthentication) {
651         this.tomcatAuthentication = tomcatAuthentication;
652     }
653 
654 
655     // --------------------------------------------------------- Public Methods
656 
657 
658     /**
659      * Create (or allocate) and return a Request object suitable for
660      * specifying the contents of a Request to the responsible Container.
661      */
662     public Request createRequest() {
663 
664   Ajp13Request request = new Ajp13Request(this);
665   request.setConnector(this);
666   return (request);
667 
668     }
669 
670 
671     /**
672      * Create (or allocate) and return a Response object suitable for
673      * receiving the contents of a Response from the responsible Container.
674      */
675     public Response createResponse() {
676 
677   Ajp13Response response = new Ajp13Response();
678   response.setConnector(this);
679   return (response);
680 
681     }
682 
683     /**
684      * Invoke a pre-startup initialization. This is used to allow connectors
685      * to bind to restricted ports under Unix operating environments.
686      * ServerSocket (we start as root and change user? or I miss something?).
687      */
688     public void initialize() throws LifecycleException {
689     }
690 
691 
692     // -------------------------------------------------------- Package Methods
693 
694 
695     /**
696      * Recycle the specified Processor so that it can be used again.
697      *
698      * @param processor The processor to be recycled
699      */
700     void recycle(Ajp13Processor processor) {
701 
702         synchronized(processors) {
703             if (debug > 0) {
704                 logger.log("added processor to available processors, available="
705                            + processors.size());
706             }
707             processors.push(processor);
708         }
709 
710     }
711 
712 
713     // -------------------------------------------------------- Private Methods
714 
715 
716     /**
717      * Create (or allocate) and return an available processor for use in
718      * processing a specific AJP13 request, if possible.  If the maximum
719      * allowed processors have already been created and are in use, return
720      * <code>null</code> instead.
721      */
722     private Ajp13Processor createProcessor() {
723 
724   synchronized (processors) {
725       if (processors.size() > 0)
726     return ((Ajp13Processor) processors.pop());
727       if ((maxProcessors > 0) && (curProcessors < maxProcessors))
728           return (newProcessor());
729       else
730           return (null);
731   }
732 
733     }
734 
735 
736     /**
737      * Create and return a new processor suitable for processing AJP13
738      * requests and returning the corresponding responses.
739      */
740     private Ajp13Processor newProcessor() {
741 
742         Ajp13Processor processor = new Ajp13Processor(this, curProcessors++, threadGroup);
743   if (processor instanceof Lifecycle) {
744       try {
745           ((Lifecycle) processor).start();
746       } catch (LifecycleException e) {
747           logger.log("newProcessor", e);
748                 curProcessors--;
749           return (null);
750       }
751   }
752   created.addElement(processor);
753   return (processor);
754 
755     }
756 
757 
758     /**
759      * Open and return the server socket for this Connector.  If an IP
760      * address has been specified, the socket will be opened only on that
761      * address; otherwise it will be opened on all addresses.
762      *
763      * @exception IOException if an input/output error occurs
764      */
765     private ServerSocket open() throws IOException {
766 
767         // Acquire the server socket factory for this Connector
768         ServerSocketFactory factory = getFactory();
769 
770   // If no address is specified, open a connection on all addresses
771         if (address == null) {
772       logger.log(sm.getString("ajp13Connector.allAddresses"));
773             try {
774     return (factory.createSocket(port, acceptCount));
775       } catch(Exception ex ) {
776     ex.printStackTrace();
777     return null;
778       }
779   }
780 
781   // Open a server socket on the specified address
782         try {
783             InetAddress is = InetAddress.getByName(address);
784       logger.log(sm.getString("ajp13Connector.anAddress", address));
785             return (factory.createSocket(port, acceptCount, is));
786   } catch (Exception e) {
787       try {
788     logger.log(sm.getString("ajp13Connector.noAddress", address));
789     return (factory.createSocket(port, acceptCount));
790       } catch( Exception e1 ) {
791     e1.printStackTrace();
792     return null;
793       }
794   }
795 
796     }
797 
798 
799     // ---------------------------------------------- Background Thread Methods
800 
801 
802     /**
803      * The background thread that listens for incoming TCP/IP connections and
804      * hands them off to an appropriate processor.
805      */
806     public void run() {
807 
808         // Loop until we receive a shutdown command
809   while (!stopped) {
810 
811       // Accept the next incoming connection from the server socket
812       Socket socket = null;
813       try {
814                 if (debug > 0) {
815                     logger.log("accepting socket...");
816                 }
817                 
818     socket = serverSocket.accept();
819 
820                 if (debug > 0) {
821                     logger.log("accepted socket, assigning to processor.");
822                 }
823                 
824                 /* Warning :
825                  * 
826                  * To be able to close more quickly a connection, it's recommanded
827                  * to set linger to a small value.
828                  * 
829                  * AJP13 connection SHOULD be closed under webserver responsability and 
830                  * in such case it's safe to close socket on Tomcat side without delay,
831                  * which may be also the case for HTTP connectors.
832                  * 
833                  * I (henri) recommand to set Linger to 0, making socket closed immediatly
834                  * so the OS will free faster the underlying io descriptor and resources.
835                  * It's very important under heavy load !
836                  */
837                 
838                 if (connectionLinger < 0)
839                   socket.setSoLinger(false, 0);
840                 else  
841                   socket.setSoLinger(true, connectionLinger);
842                   
843                 /* We don't need it since it's the native side which 
844                  * will set the connection with keep alive
845                  * if specified in workers.properties.
846                  * 
847                  * socket.setKeepAlive(true); 
848                  */
849                 
850                 /* Warning :
851                  * 
852                  * AJP13 shouldn't use socket timeout on tomcat site since
853                  * when Tomcat close a connection after a timeout is reached
854                  * the socket stay in half-closed state until the webserver
855                  * try to send a request to tomcat and detect the socket close
856                  * when it will try to read the reply.
857                  * 
858                  * On many Unix platforms the write() call didn't told
859                  * webserver that the socket is closed.
860                  */
861                  
862                 if (connectionTimeout >= 0) {
863                     socket.setSoTimeout(connectionTimeout);
864                 }
865             } catch (AccessControlException ace) {
866                 logger.log("socket accept security exception: "
867                            + ace.getMessage());
868                 continue;
869       } catch (IOException e) {
870     if (started && !stopped)
871         logger.log("accept: ", e);
872     try {
873                     if (serverSocket != null) {
874                         serverSocket.close();
875                     }
876                     if (stopped) {
877                         if (debug > 0) {
878                             logger.log("run():  stopped, so breaking");
879                         }
880                         break;
881                     } else {
882                         if (debug > 0) {
883                             logger.log("run():  not stopped, " +
884                                        "so reopening server socket");
885                         }
886                         serverSocket = open();
887                     }
888                 } catch (IOException ex) {
889                     // If reopening fails, exit
890                     logger.log("socket reopen: ", ex);
891                     break;
892                 }
893                 continue;
894       }
895 
896       // Hand this socket off to an appropriate processor
897             if (debug > 0) {
898                 synchronized(processors) {
899                     logger.log("about to create a processor, available="
900                                + processors.size() + ", created=" + created.size()
901                                + ", maxProcessors=" + maxProcessors);
902                 }
903             }
904       Ajp13Processor processor = createProcessor();
905       if (processor == null) {
906     try {
907         logger.log(sm.getString("ajp13Connector.noProcessor"));
908         socket.close();
909     } catch (IOException e) {
910         ;
911     }
912     continue;
913       }
914       processor.assign(socket);
915 
916       // The processor will recycle itself when it finishes
917 
918   }
919 
920   // Notify the threadStop() method that we have shut ourselves down
921   synchronized (threadSync) {
922       threadSync.notifyAll();
923   }
924 
925     }
926 
927 
928     /**
929      * Start the background processing thread.
930      */
931     private void threadStart() {
932 
933   logger.log(sm.getString("ajp13Connector.starting"));
934 
935   thread = new Thread(threadGroup, this, threadName);
936   thread.setDaemon(true);
937   thread.start();
938 
939     }
940 
941 
942     /**
943      * Stop the background processing thread.
944      */
945     private void threadStop() {
946 
947   logger.log(sm.getString("ajp13Connector.stopping"));
948 
949   stopped = true;
950   synchronized (threadSync) {
951       try {
952     threadSync.wait(5000);
953       } catch (InterruptedException e) {
954     ;
955       }
956   }
957   thread = null;
958 
959     }
960 
961 
962     // ------------------------------------------------------ Lifecycle Methods
963 
964 
965     /**
966      * Add a lifecycle event listener to this component.
967      *
968      * @param listener The listener to add
969      */
970     public void addLifecycleListener(LifecycleListener listener) {
971 
972   lifecycle.addLifecycleListener(listener);
973 
974     }
975 
976     /**
977      * Get the lifecycle listeners associated with this lifecycle. If this
978      * Lifecycle has no listeners registered, a zero-length array is returned.
979      */
980     public LifecycleListener[] findLifecycleListeners() {
981         return null; // FIXME: lifecycle.findLifecycleListeners();
982     }
983 
984 
985     /**
986      * Remove a lifecycle event listener from this component.
987      *
988      * @param listener The listener to add
989      */
990     public void removeLifecycleListener(LifecycleListener listener) {
991 
992   lifecycle.removeLifecycleListener(listener);
993 
994     }
995 
996 
997     /**
998      * Begin processing requests via this Connector.
999      *
1000     * @exception LifecycleException if a fatal startup error occurs
1001     */
1002    public void start() throws LifecycleException {
1003
1004  // Validate and update our current state
1005  if (started)
1006      throw new LifecycleException
1007    (sm.getString("ajp13Connector.alreadyStarted"));
1008
1009        if (debug > 0) {
1010            debugThread = new DebugThread();
1011            debugThread.setDaemon(true);
1012            debugThread.start();
1013        }
1014
1015        threadName = "Ajp13Connector[" + port + "]";
1016        threadGroup = new ThreadGroup(threadName);
1017        threadGroup.setDaemon(true);
1018        logger.setConnector(this);
1019        logger.setName(threadName);
1020  lifecycle.fireLifecycleEvent(START_EVENT, null);
1021  started = true;
1022
1023  // Establish a server socket on the specified port
1024  try {
1025      serverSocket = open();
1026  } catch (IOException e) {
1027      throw new LifecycleException(threadName + ".open", e);
1028  }
1029
1030  // Start our background thread
1031  threadStart();
1032
1033  // Create the specified minimum number of processors
1034  while (curProcessors < minProcessors) {
1035      if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
1036    break;
1037      Ajp13Processor processor = newProcessor();
1038      recycle(processor);
1039  }
1040
1041    }
1042
1043
1044    /**
1045     * Terminate processing requests via this Connector.
1046     *
1047     * @exception LifecycleException if a fatal shutdown error occurs
1048     */
1049    public void stop() throws LifecycleException {
1050
1051  // Validate and update our current state
1052  if (!started)
1053      throw new LifecycleException
1054    (sm.getString("ajp13Connector.notStarted"));
1055  lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1056  started = false;
1057
1058  // Gracefully shut down all processors we have created
1059  for (int i = created.size() - 1; i >= 0; i--) {
1060      Ajp13Processor processor = (Ajp13Processor) created.elementAt(i);
1061      if (processor instanceof Lifecycle) {
1062    try {
1063        ((Lifecycle) processor).stop();
1064    } catch (LifecycleException e) {
1065        logger.log("Ajp13Connector.stop", e);
1066    }
1067      }
1068  }
1069
1070  // Stop our background thread
1071  threadStop();
1072
1073  // Close the server socket we were using
1074  if (serverSocket != null) {
1075      try {
1076    serverSocket.close();
1077      } catch (IOException e) {
1078    ;
1079      }
1080      serverSocket = null;
1081  }
1082
1083    }
1084
1085    /**
1086     * Debugging thread used to debug thread activity in this
1087     * connector.
1088     */
1089    private class DebugThread extends Thread
1090    {
1091        public void run() {
1092            while (true) {
1093                try {
1094                    sleep(60 * 1000);
1095                } catch (InterruptedException e) {
1096                    break;
1097                }
1098                logger.log("active threads=" + threadGroup.activeCount());
1099                System.out.println("===================================");
1100                System.out.println("Ajp13Connector active threads="
1101                                   + threadGroup.activeCount());
1102                threadGroup.list();
1103                System.out.println("===================================");
1104            }
1105        }
1106    }
1107
1108}