0001: /*
0002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpConnector.java,v 1.17 2002/03/18 07:15:40 remm Exp $
0003: * $Revision: 1.17 $
0004: * $Date: 2002/03/18 07:15:40 $
0005: *
0006: * ====================================================================
0007: *
0008: * The Apache Software License, Version 1.1
0009: *
0010: * Copyright (c) 1999 The Apache Software Foundation. All rights
0011: * reserved.
0012: *
0013: * Redistribution and use in source and binary forms, with or without
0014: * modification, are permitted provided that the following conditions
0015: * are met:
0016: *
0017: * 1. Redistributions of source code must retain the above copyright
0018: * notice, this list of conditions and the following disclaimer.
0019: *
0020: * 2. Redistributions in binary form must reproduce the above copyright
0021: * notice, this list of conditions and the following disclaimer in
0022: * the documentation and/or other materials provided with the
0023: * distribution.
0024: *
0025: * 3. The end-user documentation included with the redistribution, if
0026: * any, must include the following acknowlegement:
0027: * "This product includes software developed by the
0028: * Apache Software Foundation (http://www.apache.org/)."
0029: * Alternately, this acknowlegement may appear in the software itself,
0030: * if and wherever such third-party acknowlegements normally appear.
0031: *
0032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0033: * Foundation" must not be used to endorse or promote products derived
0034: * from this software without prior written permission. For written
0035: * permission, please contact apache@apache.org.
0036: *
0037: * 5. Products derived from this software may not be called "Apache"
0038: * nor may "Apache" appear in their names without prior written
0039: * permission of the Apache Group.
0040: *
0041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0052: * SUCH DAMAGE.
0053: * ====================================================================
0054: *
0055: * This software consists of voluntary contributions made by many
0056: * individuals on behalf of the Apache Software Foundation. For more
0057: * information on the Apache Software Foundation, please see
0058: * <http://www.apache.org/>.
0059: *
0060: * [Additional notices, if required by prior licensing conditions]
0061: *
0062: */
0063:
0064: package org.apache.catalina.connector.http10;
0065:
0066: import java.io.IOException;
0067: import java.net.InetAddress;
0068: import java.net.ServerSocket;
0069: import java.net.Socket;
0070: import java.security.AccessControlException;
0071: import java.util.Stack;
0072: import java.util.Vector;
0073: import java.security.KeyStoreException;
0074: import java.security.NoSuchAlgorithmException;
0075: import java.security.cert.CertificateException;
0076: import java.security.UnrecoverableKeyException;
0077: import java.security.KeyManagementException;
0078: import org.apache.catalina.Connector;
0079: import org.apache.catalina.Container;
0080: import org.apache.catalina.HttpRequest;
0081: import org.apache.catalina.HttpResponse;
0082: import org.apache.catalina.Lifecycle;
0083: import org.apache.catalina.LifecycleEvent;
0084: import org.apache.catalina.LifecycleException;
0085: import org.apache.catalina.LifecycleListener;
0086: import org.apache.catalina.Logger;
0087: import org.apache.catalina.Request;
0088: import org.apache.catalina.Response;
0089: import org.apache.catalina.Service;
0090: import org.apache.catalina.net.DefaultServerSocketFactory;
0091: import org.apache.catalina.net.ServerSocketFactory;
0092: import org.apache.catalina.util.LifecycleSupport;
0093: import org.apache.catalina.util.StringManager;
0094:
0095: /**
0096: * Simple implementation of an HTTP/1.0 Connector, for testing and debugging
0097: * purposes. Not intended to be the final solution.
0098: *
0099: * @author Craig R. McClanahan
0100: * @version $Revision: 1.17 $ $Date: 2002/03/18 07:15:40 $
0101: * @deprecated
0102: */
0103:
0104: public final class HttpConnector implements Connector, Lifecycle,
0105: Runnable {
0106:
0107: // ----------------------------------------------------- Instance Variables
0108:
0109: /**
0110: * The accept count for this Connector.
0111: */
0112: private int acceptCount = 10;
0113:
0114: /**
0115: * The IP address on which to bind, if any. If <code>null</code>, all
0116: * addresses on the server will be bound.
0117: */
0118: private String address = null;
0119:
0120: /**
0121: * The input buffer size we should create on input streams.
0122: */
0123: private int bufferSize = 2048;
0124:
0125: /**
0126: * The Container used for processing requests received by this Connector.
0127: */
0128: protected Container container = null;
0129:
0130: /**
0131: * The set of processors that have ever been created.
0132: */
0133: private Vector created = new Vector();
0134:
0135: /**
0136: * The current number of processors that have been created.
0137: */
0138: private int curProcessors = 0;
0139:
0140: /**
0141: * The debugging detail level for this component.
0142: */
0143: private int debug = 0;
0144:
0145: /**
0146: * The "enable DNS lookups" flag for this Connector.
0147: */
0148: private boolean enableLookups = false;
0149:
0150: /**
0151: * The server socket factory for this component.
0152: */
0153: private ServerSocketFactory factory = null;
0154:
0155: /**
0156: * Descriptive information about this Connector implementation.
0157: */
0158: private static final String info = "org.apache.catalina.connector.http10.HttpConnector/1.0";
0159:
0160: /**
0161: * The lifecycle event support for this component.
0162: */
0163: protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0164:
0165: /**
0166: * Timeout value on the incoming connection.
0167: * Note : a negative value of 0 means no timeout.
0168: */
0169: private int connectionTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT;
0170:
0171: /**
0172: * The minimum number of processors to start at initialization time.
0173: */
0174: protected int minProcessors = 5;
0175:
0176: /**
0177: * The maximum number of processors allowed, or <0 for unlimited.
0178: */
0179: private int maxProcessors = 20;
0180:
0181: /**
0182: * The port number on which we listen for HTTP requests.
0183: */
0184: private int port = 8080;
0185:
0186: /**
0187: * The set of processors that have been created but are not currently
0188: * being used to process a request.
0189: */
0190: private Stack processors = new Stack();
0191:
0192: /**
0193: * The server name to which we should pretend requests to this Connector
0194: * were directed. This is useful when operating Tomcat behind a proxy
0195: * server, so that redirects get constructed accurately. If not specified,
0196: * the server name included in the <code>Host</code> header is used.
0197: */
0198: private String proxyName = null;
0199:
0200: /**
0201: * The server port to which we should pretent requests to this Connector
0202: * were directed. This is useful when operating Tomcat behind a proxy
0203: * server, so that redirects get constructed accurately. If not specified,
0204: * the port number specified by the <code>port</code> property is used.
0205: */
0206: private int proxyPort = 0;
0207:
0208: /**
0209: * The redirect port for non-SSL to SSL redirects.
0210: */
0211: private int redirectPort = 443;
0212:
0213: /**
0214: * The request scheme that will be set on all requests received
0215: * through this connector.
0216: */
0217: private String scheme = "http";
0218:
0219: /**
0220: * The secure connection flag that will be set on all requests received
0221: * through this connector.
0222: */
0223: private boolean secure = false;
0224:
0225: /**
0226: * The server socket through which we listen for incoming TCP connections.
0227: */
0228: private ServerSocket serverSocket = null;
0229:
0230: /**
0231: * The <code>Service</code> we are associated with (if any).
0232: */
0233: private Service service = null;
0234:
0235: /**
0236: * The string manager for this package.
0237: */
0238: private StringManager sm = StringManager
0239: .getManager(Constants.Package);
0240:
0241: /**
0242: * Has this component been initialized yet?
0243: */
0244: private boolean initialized = false;
0245:
0246: /**
0247: * Has this component been started yet?
0248: */
0249: private boolean started = false;
0250:
0251: /**
0252: * The shutdown signal to our background thread
0253: */
0254: private boolean stopped = false;
0255:
0256: /**
0257: * The background thread.
0258: */
0259: private Thread thread = null;
0260:
0261: /**
0262: * The name to register for the background thread.
0263: */
0264: private String threadName = null;
0265:
0266: /**
0267: * The thread synchronization object.
0268: */
0269: private Object threadSync = new Object();
0270:
0271: // ------------------------------------------------------------- Properties
0272:
0273: /**
0274: * Return the connection timeout for this Connector.
0275: */
0276: public int getConnectionTimeout() {
0277:
0278: return (connectionTimeout);
0279:
0280: }
0281:
0282: /**
0283: * Set the connection timeout for this Connector.
0284: *
0285: * @param count The new connection timeout
0286: */
0287: public void setConnectionTimeout(int connectionTimeout) {
0288:
0289: this .connectionTimeout = connectionTimeout;
0290:
0291: }
0292:
0293: /**
0294: * Return the accept count for this Connector.
0295: */
0296: public int getAcceptCount() {
0297:
0298: return (acceptCount);
0299:
0300: }
0301:
0302: /**
0303: * Set the accept count for this Connector.
0304: *
0305: * @param count The new accept count
0306: */
0307: public void setAcceptCount(int count) {
0308:
0309: this .acceptCount = count;
0310:
0311: }
0312:
0313: /**
0314: * Return the bind IP address for this Connector.
0315: */
0316: public String getAddress() {
0317:
0318: return (this .address);
0319:
0320: }
0321:
0322: /**
0323: * Set the bind IP address for this Connector.
0324: *
0325: * @param address The bind IP address
0326: */
0327: public void setAddress(String address) {
0328:
0329: this .address = address;
0330:
0331: }
0332:
0333: /**
0334: * Is this connector available for processing requests?
0335: */
0336: public boolean isAvailable() {
0337:
0338: return (started);
0339:
0340: }
0341:
0342: /**
0343: * Return the input buffer size for this Connector.
0344: */
0345: public int getBufferSize() {
0346:
0347: return (this .bufferSize);
0348:
0349: }
0350:
0351: /**
0352: * Set the input buffer size for this Connector.
0353: *
0354: * @param bufferSize The new input buffer size.
0355: */
0356: public void setBufferSize(int bufferSize) {
0357:
0358: this .bufferSize = bufferSize;
0359:
0360: }
0361:
0362: /**
0363: * Return the Container used for processing requests received by this
0364: * Connector.
0365: */
0366: public Container getContainer() {
0367:
0368: return (container);
0369:
0370: }
0371:
0372: /**
0373: * Set the Container used for processing requests received by this
0374: * Connector.
0375: *
0376: * @param container The new Container to use
0377: */
0378: public void setContainer(Container container) {
0379:
0380: this .container = container;
0381:
0382: }
0383:
0384: /**
0385: * Return the current number of processors that have been created.
0386: */
0387: public int getCurProcessors() {
0388:
0389: return (curProcessors);
0390:
0391: }
0392:
0393: /**
0394: * Return the debugging detail level for this component.
0395: */
0396: public int getDebug() {
0397:
0398: return (debug);
0399:
0400: }
0401:
0402: /**
0403: * Set the debugging detail level for this component.
0404: *
0405: * @param debug The new debugging detail level
0406: */
0407: public void setDebug(int debug) {
0408:
0409: this .debug = debug;
0410:
0411: }
0412:
0413: /**
0414: * Return the "enable DNS lookups" flag.
0415: */
0416: public boolean getEnableLookups() {
0417:
0418: return (this .enableLookups);
0419:
0420: }
0421:
0422: /**
0423: * Set the "enable DNS lookups" flag.
0424: *
0425: * @param enableLookups The new "enable DNS lookups" flag value
0426: */
0427: public void setEnableLookups(boolean enableLookups) {
0428:
0429: this .enableLookups = enableLookups;
0430:
0431: }
0432:
0433: /**
0434: * Return the server socket factory used by this Container.
0435: */
0436: public ServerSocketFactory getFactory() {
0437:
0438: if (this .factory == null) {
0439: synchronized (this ) {
0440: this .factory = new DefaultServerSocketFactory();
0441: }
0442: }
0443: return (this .factory);
0444:
0445: }
0446:
0447: /**
0448: * Set the server socket factory used by this Container.
0449: *
0450: * @param factory The new server socket factory
0451: */
0452: public void setFactory(ServerSocketFactory factory) {
0453:
0454: this .factory = factory;
0455:
0456: }
0457:
0458: /**
0459: * Return descriptive information about this Connector implementation.
0460: */
0461: public String getInfo() {
0462:
0463: return (info);
0464:
0465: }
0466:
0467: /**
0468: * Return the minimum number of processors to start at initialization.
0469: */
0470: public int getMinProcessors() {
0471:
0472: return (minProcessors);
0473:
0474: }
0475:
0476: /**
0477: * Set the minimum number of processors to start at initialization.
0478: *
0479: * @param minProcessors The new minimum processors
0480: */
0481: public void setMinProcessors(int minProcessors) {
0482:
0483: this .minProcessors = minProcessors;
0484:
0485: }
0486:
0487: /**
0488: * Return the maximum number of processors allowed, or <0 for unlimited.
0489: */
0490: public int getMaxProcessors() {
0491:
0492: return (maxProcessors);
0493:
0494: }
0495:
0496: /**
0497: * Set the maximum number of processors allowed, or <0 for unlimited.
0498: *
0499: * @param maxProcessors The new maximum processors
0500: */
0501: public void setMaxProcessors(int maxProcessors) {
0502:
0503: this .maxProcessors = maxProcessors;
0504:
0505: }
0506:
0507: /**
0508: * Return the port number on which we listen for HTTP requests.
0509: */
0510: public int getPort() {
0511:
0512: return (this .port);
0513:
0514: }
0515:
0516: /**
0517: * Set the port number on which we listen for HTTP requests.
0518: *
0519: * @param port The new port number
0520: */
0521: public void setPort(int port) {
0522:
0523: this .port = port;
0524:
0525: }
0526:
0527: /**
0528: * Return the proxy server name for this Connector.
0529: */
0530: public String getProxyName() {
0531:
0532: return (this .proxyName);
0533:
0534: }
0535:
0536: /**
0537: * Set the proxy server name for this Connector.
0538: *
0539: * @param proxyName The new proxy server name
0540: */
0541: public void setProxyName(String proxyName) {
0542:
0543: this .proxyName = proxyName;
0544:
0545: }
0546:
0547: /**
0548: * Return the proxy server port for this Connector.
0549: */
0550: public int getProxyPort() {
0551:
0552: return (this .proxyPort);
0553:
0554: }
0555:
0556: /**
0557: * Set the proxy server port for this Connector.
0558: *
0559: * @param proxyPort The new proxy server port
0560: */
0561: public void setProxyPort(int proxyPort) {
0562:
0563: this .proxyPort = proxyPort;
0564:
0565: }
0566:
0567: /**
0568: * Return the port number to which a request should be redirected if
0569: * it comes in on a non-SSL port and is subject to a security constraint
0570: * with a transport guarantee that requires SSL.
0571: */
0572: public int getRedirectPort() {
0573:
0574: return (this .redirectPort);
0575:
0576: }
0577:
0578: /**
0579: * Set the redirect port number.
0580: *
0581: * @param redirectPort The redirect port number (non-SSL to SSL)
0582: */
0583: public void setRedirectPort(int redirectPort) {
0584:
0585: this .redirectPort = redirectPort;
0586:
0587: }
0588:
0589: /**
0590: * Return the scheme that will be assigned to requests received
0591: * through this connector. Default value is "http".
0592: */
0593: public String getScheme() {
0594:
0595: return (this .scheme);
0596:
0597: }
0598:
0599: /**
0600: * Set the scheme that will be assigned to requests received through
0601: * this connector.
0602: *
0603: * @param scheme The new scheme
0604: */
0605: public void setScheme(String scheme) {
0606:
0607: this .scheme = scheme;
0608:
0609: }
0610:
0611: /**
0612: * Return the secure connection flag that will be assigned to requests
0613: * received through this connector. Default value is "false".
0614: */
0615: public boolean getSecure() {
0616:
0617: return (this .secure);
0618:
0619: }
0620:
0621: /**
0622: * Set the secure connection flag that will be assigned to requests
0623: * received through this connector.
0624: *
0625: * @param secure The new secure connection flag
0626: */
0627: public void setSecure(boolean secure) {
0628:
0629: this .secure = secure;
0630:
0631: }
0632:
0633: /**
0634: * Return the <code>Service</code> with which we are associated (if any).
0635: */
0636: public Service getService() {
0637:
0638: return (this .service);
0639:
0640: }
0641:
0642: /**
0643: * Set the <code>Service</code> with which we are associated (if any).
0644: *
0645: * @param service The service that owns this Engine
0646: */
0647: public void setService(Service service) {
0648:
0649: this .service = service;
0650:
0651: }
0652:
0653: // --------------------------------------------------------- Public Methods
0654:
0655: /**
0656: * Create (or allocate) and return a Request object suitable for
0657: * specifying the contents of a Request to the responsible Container.
0658: */
0659: public Request createRequest() {
0660:
0661: HttpRequestImpl request = new HttpRequestImpl();
0662: request.setConnector(this );
0663: return (request);
0664:
0665: }
0666:
0667: /**
0668: * Create (or allocate) and return a Response object suitable for
0669: * receiving the contents of a Response from the responsible Container.
0670: */
0671: public Response createResponse() {
0672:
0673: HttpResponseImpl response = new HttpResponseImpl();
0674: response.setConnector(this );
0675: return (response);
0676:
0677: }
0678:
0679: // -------------------------------------------------------- Package Methods
0680:
0681: /**
0682: * Recycle the specified Processor so that it can be used again.
0683: *
0684: * @param processor The processor to be recycled
0685: */
0686: void recycle(HttpProcessor processor) {
0687:
0688: processors.push(processor);
0689:
0690: }
0691:
0692: // -------------------------------------------------------- Private Methods
0693:
0694: /**
0695: * Create (or allocate) and return an available processor for use in
0696: * processing a specific HTTP request, if possible. If the maximum
0697: * allowed processors have already been created and are in use, return
0698: * <code>null</code> instead.
0699: */
0700: private HttpProcessor createProcessor() {
0701:
0702: synchronized (processors) {
0703: if (processors.size() > 0)
0704: return ((HttpProcessor) processors.pop());
0705: if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {
0706: return (newProcessor());
0707: } else {
0708: if (maxProcessors < 0) {
0709: return (newProcessor());
0710: } else {
0711: return (null);
0712: }
0713: }
0714: }
0715:
0716: }
0717:
0718: /**
0719: * Log a message on the Logger associated with our Container (if any).
0720: *
0721: * @param message Message to be logged
0722: */
0723: private void log(String message) {
0724:
0725: Logger logger = container.getLogger();
0726: String localName = threadName;
0727: if (localName == null)
0728: localName = "HttpConnector";
0729: if (logger != null)
0730: logger.log(localName + " " + message);
0731: else
0732: System.out.println(localName + " " + message);
0733:
0734: }
0735:
0736: /**
0737: * Log a message on the Logger associated with our Container (if any).
0738: *
0739: * @param message Message to be logged
0740: * @param throwable Associated exception
0741: */
0742: private void log(String message, Throwable throwable) {
0743:
0744: Logger logger = container.getLogger();
0745: String localName = threadName;
0746: if (localName == null)
0747: localName = "HttpConnector";
0748: if (logger != null)
0749: logger.log(localName + " " + message, throwable);
0750: else {
0751: System.out.println(localName + " " + message);
0752: throwable.printStackTrace(System.out);
0753: }
0754:
0755: }
0756:
0757: /**
0758: * Create and return a new processor suitable for processing HTTP
0759: * requests and returning the corresponding responses.
0760: */
0761: private HttpProcessor newProcessor() {
0762:
0763: HttpProcessor processor = new HttpProcessor(this ,
0764: curProcessors++);
0765: if (processor instanceof Lifecycle) {
0766: try {
0767: ((Lifecycle) processor).start();
0768: } catch (LifecycleException e) {
0769: log("newProcessor", e);
0770: return (null);
0771: }
0772: }
0773: created.addElement(processor);
0774: return (processor);
0775:
0776: }
0777:
0778: /**
0779: * Open and return the server socket for this Connector. If an IP
0780: * address has been specified, the socket will be opened only on that
0781: * address; otherwise it will be opened on all addresses.
0782: *
0783: * @exception IOException input/output or network error
0784: * @exception KeyStoreException error instantiating the
0785: * KeyStore from file (SSL only)
0786: * @exception NoSuchAlgorithmException KeyStore algorithm unsupported
0787: * by current provider (SSL only)
0788: * @exception CertificateException general certificate error (SSL only)
0789: * @exception UnrecoverableKeyException internal KeyStore problem with
0790: * the certificate (SSL only)
0791: * @exception KeyManagementException problem in the key management
0792: * layer (SSL only)
0793: */
0794: private ServerSocket open() throws IOException, KeyStoreException,
0795: NoSuchAlgorithmException, CertificateException,
0796: UnrecoverableKeyException, KeyManagementException {
0797:
0798: // Acquire the server socket factory for this Connector
0799: ServerSocketFactory factory = getFactory();
0800:
0801: // If no address is specified, open a connection on all addresses
0802: if (address == null) {
0803: log(sm.getString("httpConnector.allAddresses"));
0804: return (factory.createSocket(port, acceptCount));
0805: }
0806:
0807: // Open a server socket on the specified address
0808: InetAddress[] addresses = InetAddress.getAllByName(InetAddress
0809: .getLocalHost().getHostName());
0810: int i;
0811: for (i = 0; i < addresses.length; i++) {
0812: if (addresses[i].getHostAddress().equals(address))
0813: break;
0814: }
0815: if (i < addresses.length) {
0816: log(sm.getString("httpConnector.anAddress", address));
0817: return (factory.createSocket(port, acceptCount,
0818: addresses[i]));
0819: } else {
0820: log(sm.getString("httpConnector.noAddress", address));
0821: return (factory.createSocket(port, acceptCount));
0822: }
0823:
0824: }
0825:
0826: // ---------------------------------------------- Background Thread Methods
0827:
0828: /**
0829: * The background thread that listens for incoming TCP/IP connections and
0830: * hands them off to an appropriate processor.
0831: */
0832: public void run() {
0833:
0834: // Loop until we receive a shutdown command
0835: while (!stopped) {
0836:
0837: // Accept the next incoming connection from the server socket
0838: Socket socket = null;
0839: try {
0840: socket = serverSocket.accept();
0841: if (connectionTimeout > 0)
0842: socket.setSoTimeout(connectionTimeout);
0843: } catch (AccessControlException ace) {
0844: log("socket accept security exception: "
0845: + ace.getMessage());
0846: continue;
0847: } catch (IOException e) {
0848: if (started && !stopped)
0849: log("accept: ", e);
0850: break;
0851: }
0852:
0853: // Hand this socket off to an appropriate processor
0854: HttpProcessor processor = createProcessor();
0855: if (processor == null) {
0856: try {
0857: log(sm.getString("httpConnector.noProcessor"));
0858: socket.close();
0859: } catch (IOException e) {
0860: ;
0861: }
0862: continue;
0863: }
0864: processor.assign(socket);
0865:
0866: // The processor will recycle itself when it finishes
0867:
0868: }
0869:
0870: // Notify the threadStop() method that we have shut ourselves down
0871: synchronized (threadSync) {
0872: threadSync.notifyAll();
0873: }
0874:
0875: }
0876:
0877: /**
0878: * Start the background processing thread.
0879: */
0880: private void threadStart() {
0881:
0882: log(sm.getString("httpConnector.starting"));
0883:
0884: thread = new Thread(this , threadName);
0885: thread.setDaemon(true);
0886: thread.start();
0887:
0888: }
0889:
0890: /**
0891: * Stop the background processing thread.
0892: */
0893: private void threadStop() {
0894:
0895: log(sm.getString("httpConnector.stopping"));
0896:
0897: stopped = true;
0898: synchronized (threadSync) {
0899: try {
0900: threadSync.wait(5000);
0901: } catch (InterruptedException e) {
0902: ;
0903: }
0904: }
0905: thread = null;
0906:
0907: }
0908:
0909: // ------------------------------------------------------ Lifecycle Methods
0910:
0911: /**
0912: * Add a lifecycle event listener to this component.
0913: *
0914: * @param listener The listener to add
0915: */
0916: public void addLifecycleListener(LifecycleListener listener) {
0917:
0918: lifecycle.addLifecycleListener(listener);
0919:
0920: }
0921:
0922: /**
0923: * Get the lifecycle listeners associated with this lifecycle. If this
0924: * Lifecycle has no listeners registered, a zero-length array is returned.
0925: */
0926: public LifecycleListener[] findLifecycleListeners() {
0927:
0928: return lifecycle.findLifecycleListeners();
0929:
0930: }
0931:
0932: /**
0933: * Remove a lifecycle event listener from this component.
0934: *
0935: * @param listener The listener to add
0936: */
0937: public void removeLifecycleListener(LifecycleListener listener) {
0938:
0939: lifecycle.removeLifecycleListener(listener);
0940:
0941: }
0942:
0943: /**
0944: * Initialize this connector (create ServerSocket here!)
0945: */
0946: public void initialize() throws LifecycleException {
0947: if (initialized)
0948: throw new LifecycleException(sm
0949: .getString("httpConnector.alreadyInitialized"));
0950:
0951: this .initialized = true;
0952: Exception eRethrow = null;
0953:
0954: // Establish a server socket on the specified port
0955: try {
0956: serverSocket = open();
0957: } catch (IOException ioe) {
0958: log("httpConnector, io problem: ", ioe);
0959: eRethrow = ioe;
0960: } catch (KeyStoreException kse) {
0961: log("httpConnector, keystore problem: ", kse);
0962: eRethrow = kse;
0963: } catch (NoSuchAlgorithmException nsae) {
0964: log("httpConnector, keystore algorithm problem: ", nsae);
0965: eRethrow = nsae;
0966: } catch (CertificateException ce) {
0967: log("httpConnector, certificate problem: ", ce);
0968: eRethrow = ce;
0969: } catch (UnrecoverableKeyException uke) {
0970: log("httpConnector, unrecoverable key: ", uke);
0971: eRethrow = uke;
0972: } catch (KeyManagementException kme) {
0973: log("httpConnector, key management problem: ", kme);
0974: eRethrow = kme;
0975: }
0976:
0977: if (eRethrow != null)
0978: throw new LifecycleException(threadName + ".open", eRethrow);
0979:
0980: }
0981:
0982: /**
0983: * Begin processing requests via this Connector.
0984: *
0985: * @exception LifecycleException if a fatal startup error occurs
0986: */
0987: public void start() throws LifecycleException {
0988:
0989: // Validate and update our current state
0990: if (started)
0991: throw new LifecycleException(sm
0992: .getString("httpConnector.alreadyStarted"));
0993: threadName = "HttpConnector[" + port + "]";
0994: lifecycle.fireLifecycleEvent(START_EVENT, null);
0995: started = true;
0996:
0997: // Start our background thread
0998: threadStart();
0999:
1000: // Create the specified minimum number of processors
1001: while (curProcessors < minProcessors) {
1002: if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
1003: break;
1004: HttpProcessor processor = newProcessor();
1005: recycle(processor);
1006: }
1007:
1008: }
1009:
1010: /**
1011: * Terminate processing requests via this Connector.
1012: *
1013: * @exception LifecycleException if a fatal shutdown error occurs
1014: */
1015: public void stop() throws LifecycleException {
1016:
1017: // Validate and update our current state
1018: if (!started)
1019: throw new LifecycleException(sm
1020: .getString("httpConnector.notStarted"));
1021: lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1022: started = false;
1023:
1024: // Gracefully shut down all processors we have created
1025: for (int i = created.size() - 1; i >= 0; i--) {
1026: HttpProcessor processor = (HttpProcessor) created
1027: .elementAt(i);
1028: if (processor instanceof Lifecycle) {
1029: try {
1030: ((Lifecycle) processor).stop();
1031: } catch (LifecycleException e) {
1032: log("HttpConnector.stop", e);
1033: }
1034: }
1035: }
1036:
1037: // Close the server socket we were using
1038: if (serverSocket != null) {
1039: try {
1040: serverSocket.close();
1041: } catch (IOException e) {
1042: ;
1043: }
1044: serverSocket = null;
1045: }
1046:
1047: // Stop our background thread
1048: threadStop();
1049:
1050: }
1051:
1052: }
|