KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ajp > tomcat4 > Ajp13Connector


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 JavaDoc;
20 import java.net.InetAddress JavaDoc;
21 import java.net.ServerSocket JavaDoc;
22 import java.net.Socket JavaDoc;
23 import java.security.AccessControlException JavaDoc;
24 import java.util.Stack JavaDoc;
25 import java.util.Vector JavaDoc;
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: 1.20 $ $Date: 2004/02/24 08:48:41 $
45  */

46
47
48 public final class Ajp13Connector
49     implements Connector, Lifecycle, Runnable JavaDoc {
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 JavaDoc 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 JavaDoc created = new Vector JavaDoc();
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 JavaDoc 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 JavaDoc processors = new Stack JavaDoc();
164
165
166     /**
167      * The request scheme that will be set on all requests received
168      * through this connector.
169      */

170     private String JavaDoc 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 JavaDoc 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 JavaDoc thread = null;
209
210
211     /**
212      * This connector's thread group.
213      */

214     private ThreadGroup JavaDoc threadGroup = null;
215
216
217     /**
218      * The name to register for the background thread.
219      */

220     private String JavaDoc 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 JavaDoc threadSync = new Object JavaDoc();
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 JavaDoc 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 JavaDoc s ) {
297         secret=s;
298     }
299
300     public String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc open() throws IOException JavaDoc {
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 JavaDoc ex ) {
776         ex.printStackTrace();
777         return null;
778         }
779     }
780
781     // Open a server socket on the specified address
782
try {
783             InetAddress JavaDoc is = InetAddress.getByName(address);
784         logger.log(sm.getString("ajp13Connector.anAddress", address));
785             return (factory.createSocket(port, acceptCount, is));
786     } catch (Exception JavaDoc e) {
787         try {
788         logger.log(sm.getString("ajp13Connector.noAddress", address));
789         return (factory.createSocket(port, acceptCount));
790         } catch( Exception JavaDoc 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 JavaDoc 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 JavaDoc ace) {
866                 logger.log("socket accept security exception: "
867                            + ace.getMessage());
868                 continue;
869         } catch (IOException JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc(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 JavaDoc 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 JavaDoc(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 JavaDoc 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 JavaDoc 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 JavaDoc
1090    {
1091        public void run() {
1092            while (true) {
1093                try {
1094                    sleep(60 * 1000);
1095                } catch (InterruptedException JavaDoc 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}
1109
Popular Tags