remm 02/01/17 13:08:44 Modified: coyote/src/java/org/apache/coyote/tomcat4 Constants.java Added: coyote/src/java/org/apache/coyote/tomcat4 CoyoteConnector.java CoyoteProcessor.java CoyoteRequest.java CoyoteResponse.java Log: - Add a skeleton of the Coyote connector for TC 4. Revision Changes Path 1.2 +6 -0 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/Constants.java Index: Constants.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/Constants.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Constants.java 4 Dec 2001 20:27:11 -0000 1.1 +++ Constants.java 17 Jan 2002 21:08:44 -0000 1.2 @@ -71,4 +71,10 @@ // -------------------------------------------------------------- Constants + public static final String Package = "org.apache.coyote.tomcat4"; + public static final int DEFAULT_CONNECTION_TIMEOUT = 60000; + + public static final int PROCESSOR_IDLE = 0; + public static final int PROCESSOR_ACTIVE = 1; + } 1.1 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteConnector.java Index: CoyoteConnector.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteConnector.java,v 1.1 2002/01/17 21:08:44 remm Exp $ * $Revision: 1.1 $ * $Date: 2002/01/17 21:08:44 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.coyote.tomcat4; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.security.AccessControlException; import java.util.Stack; import java.util.Vector; import java.util.Enumeration; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.UnrecoverableKeyException; import java.security.KeyManagementException; import org.apache.catalina.Connector; import org.apache.catalina.Container; import org.apache.catalina.HttpRequest; import org.apache.catalina.HttpResponse; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Logger; import org.apache.catalina.Request; import org.apache.catalina.Response; import org.apache.catalina.Service; import org.apache.catalina.net.DefaultServerSocketFactory; import org.apache.catalina.net.ServerSocketFactory; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.StringManager; /** * Implementation of a Coyote connector for Tomcat 4.x. * * @author Craig R. McClanahan * @author Remy Maucherat * @version $Revision: 1.1 $ $Date: 2002/01/17 21:08:44 $ */ public final class CoyoteConnector implements Connector, Lifecycle, Runnable { // ----------------------------------------------------- Instance Variables /** * The <code>Service</code> we are associated with (if any). */ private Service service = null; /** * The accept count for this Connector. */ private int acceptCount = 10; /** * The IP address on which to bind, if any. If <code>null</code>, all * addresses on the server will be bound. */ private String address = null; /** * The input buffer size we should create on input streams. */ private int bufferSize = 2048; /** * The Container used for processing requests received by this Connector. */ protected Container container = null; /** * The set of processors that have ever been created. */ private Vector created = new Vector(); /** * The current number of processors that have been created. */ private int curProcessors = 0; /** * The debugging detail level for this component. */ private int debug = 0; /** * The "enable DNS lookups" flag for this Connector. */ private boolean enableLookups = false; /** * The server socket factory for this component. */ private ServerSocketFactory factory = null; /** * Descriptive information about this Connector implementation. */ private static final String info = "org.apache.coyote.tomcat4.CoyoteConnector/1.0"; /** * The lifecycle event support for this component. */ protected LifecycleSupport lifecycle = new LifecycleSupport(this); /** * The minimum number of processors to start at initialization time. */ protected int minProcessors = 5; /** * The maximum number of processors allowed, or <0 for unlimited. */ private int maxProcessors = 20; /** * Timeout value on the incoming connection. * Note : a value of 0 means no timeout. */ private int connectionTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT; /** * The port number on which we listen for requests. */ private int port = 8080; /** * The set of processors that have been created but are not currently * being used to process a request. */ private Stack processors = new Stack(); /** * The server name to which we should pretend requests to this Connector * were directed. This is useful when operating Tomcat behind a proxy * server, so that redirects get constructed accurately. If not specified, * the server name included in the <code>Host</code> header is used. */ private String proxyName = null; /** * The server port to which we should pretent requests to this Connector * were directed. This is useful when operating Tomcat behind a proxy * server, so that redirects get constructed accurately. If not specified, * the port number specified by the <code>port</code> property is used. */ private int proxyPort = 0; /** * The redirect port for non-SSL to SSL redirects. */ private int redirectPort = 443; /** * The request scheme that will be set on all requests received * through this connector. */ private String scheme = "http"; /** * The secure connection flag that will be set on all requests received * through this connector. */ private boolean secure = false; /** * The server socket through which we listen for incoming TCP connections. */ private ServerSocket serverSocket = null; /** * The string manager for this package. */ private StringManager sm = StringManager.getManager(Constants.Package); /** * Has this component been initialized yet? */ private boolean initialized = false; /** * Has this component been started yet? */ private boolean started = false; /** * The shutdown signal to our background thread */ private boolean stopped = false; /** * The background thread. */ private Thread thread = null; /** * The name to register for the background thread. */ private String threadName = null; /** * The thread synchronization object. */ private Object threadSync = new Object(); /** * Is chunking allowed ? */ private boolean allowChunking = true; /** * Use TCP no delay ? */ private boolean tcpNoDelay = true; /** * Coyote Processor class name. Defaults to the Coyote HTTP/1.1 processor. */ private String processorClassName = "org.apache.coyote.http11.Http11Processor"; /** * Coyote Processor class. */ private Class processorClass = null; // ------------------------------------------------------------- Properties /** * Return the <code>Service</code> with which we are associated (if any). */ public Service getService() { return (this.service); } /** * Set the <code>Service</code> with which we are associated (if any). * * @param service The service that owns this Engine */ public void setService(Service service) { this.service = service; } /** * Return the connection timeout for this Connector. */ public int getConnectionTimeout() { return (connectionTimeout); } /** * Set the connection timeout for this Connector. * * @param count The new connection timeout */ public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; } /** * Return the accept count for this Connector. */ public int getAcceptCount() { return (acceptCount); } /** * Set the accept count for this Connector. * * @param count The new accept count */ public void setAcceptCount(int count) { this.acceptCount = count; } /** * Get the allow chunking flag. */ public boolean isChunkingAllowed() { return (allowChunking); } /** * Get the allow chunking flag. */ public boolean getAllowChunking() { return isChunkingAllowed(); } /** * Set the allow chunking flag. * * @param allowChunking Allow chunking flag */ public void setAllowChunking(boolean allowChunking) { this.allowChunking = allowChunking; } /** * Return the bind IP address for this Connector. */ public String getAddress() { return (this.address); } /** * Set the bind IP address for this Connector. * * @param address The bind IP address */ public void setAddress(String address) { this.address = address; } /** * Is this connector available for processing requests? */ public boolean isAvailable() { return (started); } /** * Return the input buffer size for this Connector. */ public int getBufferSize() { return (this.bufferSize); } /** * Set the input buffer size for this Connector. * * @param bufferSize The new input buffer size. */ public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } /** * Return the Container used for processing requests received by this * Connector. */ public Container getContainer() { return (container); } /** * Set the Container used for processing requests received by this * Connector. * * @param container The new Container to use */ public void setContainer(Container container) { this.container = container; } /** * Return the current number of processors that have been created. */ public int getCurProcessors() { return (curProcessors); } /** * Return the debugging detail level for this component. */ public int getDebug() { return (debug); } /** * Set the debugging detail level for this component. * * @param debug The new debugging detail level */ public void setDebug(int debug) { this.debug = debug; } /** * Return the "enable DNS lookups" flag. */ public boolean getEnableLookups() { return (this.enableLookups); } /** * Set the "enable DNS lookups" flag. * * @param enableLookups The new "enable DNS lookups" flag value */ public void setEnableLookups(boolean enableLookups) { this.enableLookups = enableLookups; } /** * Return the server socket factory used by this Container. */ public ServerSocketFactory getFactory() { if (this.factory == null) { synchronized (this) { this.factory = new DefaultServerSocketFactory(); } } return (this.factory); } /** * Set the server socket factory used by this Container. * * @param factory The new server socket factory */ public void setFactory(ServerSocketFactory factory) { this.factory = factory; } /** * Return descriptive information about this Connector implementation. */ public String getInfo() { return (info); } /** * Return the minimum number of processors to start at initialization. */ public int getMinProcessors() { return (minProcessors); } /** * Set the minimum number of processors to start at initialization. * * @param minProcessors The new minimum processors */ public void setMinProcessors(int minProcessors) { this.minProcessors = minProcessors; } /** * Return the maximum number of processors allowed, or <0 for unlimited. */ public int getMaxProcessors() { return (maxProcessors); } /** * Set the maximum number of processors allowed, or <0 for unlimited. * * @param maxProcessors The new maximum processors */ public void setMaxProcessors(int maxProcessors) { this.maxProcessors = maxProcessors; } /** * Return the port number on which we listen for requests. */ public int getPort() { return (this.port); } /** * Set the port number on which we listen for requests. * * @param port The new port number */ public void setPort(int port) { this.port = port; } /** * Return the class name of the Coyote processor in use. */ public String getProcessorClassName() { return (this.processorClassName); } /** * Set the class name of the Coyote processor which will be used * by the connector. * * @param processorClassName The new class name */ public void setProcessorClassName(String processorClassName) { this.processorClassName = processorClassName; } /** * Return the proxy server name for this Connector. */ public String getProxyName() { return (this.proxyName); } /** * Set the proxy server name for this Connector. * * @param proxyName The new proxy server name */ public void setProxyName(String proxyName) { this.proxyName = proxyName; } /** * Return the proxy server port for this Connector. */ public int getProxyPort() { return (this.proxyPort); } /** * Set the proxy server port for this Connector. * * @param proxyPort The new proxy server port */ public void setProxyPort(int proxyPort) { this.proxyPort = proxyPort; } /** * Return the port number to which a request should be redirected if * it comes in on a non-SSL port and is subject to a security constraint * with a transport guarantee that requires SSL. */ public int getRedirectPort() { return (this.redirectPort); } /** * Set the redirect port number. * * @param redirectPort The redirect port number (non-SSL to SSL) */ public void setRedirectPort(int redirectPort) { this.redirectPort = redirectPort; } /** * Return the scheme that will be assigned to requests received * through this connector. Default value is "http". */ public String getScheme() { return (this.scheme); } /** * Set the scheme that will be assigned to requests received through * this connector. * * @param scheme The new scheme */ public void setScheme(String scheme) { this.scheme = scheme; } /** * Return the secure connection flag that will be assigned to requests * received through this connector. Default value is "false". */ public boolean getSecure() { return (this.secure); } /** * Set the secure connection flag that will be assigned to requests * received through this connector. * * @param secure The new secure connection flag */ public void setSecure(boolean secure) { this.secure = secure; } /** * Return the TCP no delay flag value. */ public boolean getTcpNoDelay() { return (this.tcpNoDelay); } /** * Set the TCP no delay flag which will be set on the socket after * accepting a connection. * * @param tcpNoDelay The new TCP no delay flag */ public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; } // --------------------------------------------------------- Public Methods /** * Create (or allocate) and return a Request object suitable for * specifying the contents of a Request to the responsible Container. */ public Request createRequest() { // if (debug >= 2) // log("createRequest: Creating new request"); CoyoteRequest request = new CoyoteRequest(); request.setConnector(this); return null;//(request); } /** * Create (or allocate) and return a Response object suitable for * receiving the contents of a Response from the responsible Container. */ public Response createResponse() { // if (debug >= 2) // log("createResponse: Creating new response"); CoyoteResponse response = new CoyoteResponse(); response.setConnector(this); return null;//(response); } // -------------------------------------------------------- Package Methods /** * Recycle the specified Processor so that it can be used again. * * @param processor The processor to be recycled */ void recycle(CoyoteProcessor processor) { // if (debug >= 2) // log("recycle: Recycling processor " + processor); processors.push(processor); } // -------------------------------------------------------- Private Methods /** * Create (or allocate) and return an available processor for use in * processing a specific request, if possible. If the maximum * allowed processors have already been created and are in use, return * <code>null</code> instead. */ private CoyoteProcessor createProcessor() { synchronized (processors) { if (processors.size() > 0) { // if (debug >= 2) // log("createProcessor: Reusing existing processor"); return ((CoyoteProcessor) processors.pop()); } if ((maxProcessors > 0) && (curProcessors < maxProcessors)) { // if (debug >= 2) // log("createProcessor: Creating new processor"); return (newProcessor()); } else { if (maxProcessors < 0) { // if (debug >= 2) // log("createProcessor: Creating new processor"); return (newProcessor()); } else { // if (debug >= 2) // log("createProcessor: Cannot create new processor"); return (null); } } } } /** * Log a message on the Logger associated with our Container (if any). * * @param message Message to be logged */ private void log(String message) { Logger logger = container.getLogger(); String localName = threadName; if (localName == null) localName = "CoyoteConnector"; if (logger != null) logger.log(localName + " " + message); else System.out.println(localName + " " + message); } /** * Log a message on the Logger associated with our Container (if any). * * @param message Message to be logged * @param throwable Associated exception */ private void log(String message, Throwable throwable) { Logger logger = container.getLogger(); String localName = threadName; if (localName == null) localName = "CoyoteConnector"; if (logger != null) logger.log(localName + " " + message, throwable); else { System.out.println(localName + " " + message); throwable.printStackTrace(System.out); } } /** * Create and return a new processor suitable for processing * requests and returning the corresponding responses. */ private CoyoteProcessor newProcessor() { // if (debug >= 2) // log("newProcessor: Creating new processor"); CoyoteProcessor processor = new CoyoteProcessor(this, curProcessors++); if (processor instanceof Lifecycle) { try { ((Lifecycle) processor).start(); } catch (LifecycleException e) { log("newProcessor", e); return (null); } } created.addElement(processor); return (processor); } /** * Open and return the server socket for this Connector. If an IP * address has been specified, the socket will be opened only on that * address; otherwise it will be opened on all addresses. * * @exception IOException input/output or network error * @exception KeyStoreException error instantiating the * KeyStore from file (SSL only) * @exception NoSuchAlgorithmException KeyStore algorithm unsupported * by current provider (SSL only) * @exception CertificateException general certificate error (SSL only) * @exception UnrecoverableKeyException internal KeyStore problem with * the certificate (SSL only) * @exception KeyManagementException problem in the key management * layer (SSL only) */ private ServerSocket open() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException { // Acquire the server socket factory for this Connector ServerSocketFactory factory = getFactory(); // If no address is specified, open a connection on all addresses if (address == null) { log(sm.getString("coyoteConnector.allAddresses")); return (factory.createSocket(port, acceptCount)); } // Open a server socket on the specified address try { InetAddress is = InetAddress.getByName(address); log(sm.getString("coyoteConnector.anAddress", address)); return (factory.createSocket(port, acceptCount, is)); } catch (Exception e) { log(sm.getString("coyoteConnector.noAddress", address)); return (factory.createSocket(port, acceptCount)); } } // ---------------------------------------------- Background Thread Methods /** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. */ public void run() { // Loop until we receive a shutdown command while (!stopped) { // Accept the next incoming connection from the server socket Socket socket = null; try { // if (debug >= 3) // log("run: Waiting on serverSocket.accept()"); socket = serverSocket.accept(); // if (debug >= 3) // log("run: Returned from serverSocket.accept()"); if (connectionTimeout > 0) socket.setSoTimeout(connectionTimeout); socket.setTcpNoDelay(tcpNoDelay); } catch (AccessControlException ace) { log("socket accept security exception", ace); continue; } catch (IOException e) { // if (debug >= 3) // log("run: Accept returned IOException", e); try { // If reopening fails, exit synchronized (threadSync) { if (started && !stopped) log("accept: ", e); if (!stopped) { // if (debug >= 3) // log("run: Closing server socket"); serverSocket.close(); // if (debug >= 3) // log("run: Reopening server socket"); serverSocket = open(); } } // if (debug >= 3) // log("run: IOException processing completed"); } catch (IOException ioe) { log("socket reopen, io problem: ", ioe); break; } catch (KeyStoreException kse) { log("socket reopen, keystore problem: ", kse); break; } catch (NoSuchAlgorithmException nsae) { log("socket reopen, keystore algorithm problem: ", nsae); break; } catch (CertificateException ce) { log("socket reopen, certificate problem: ", ce); break; } catch (UnrecoverableKeyException uke) { log("socket reopen, unrecoverable key: ", uke); break; } catch (KeyManagementException kme) { log("socket reopen, key management problem: ", kme); break; } continue; } // Hand this socket off to an appropriate processor CoyoteProcessor processor = createProcessor(); if (processor == null) { try { log(sm.getString("coyoteConnector.noProcessor")); socket.close(); } catch (IOException e) { ; } continue; } // if (debug >= 3) // log("run: Assigning socket to processor " + processor); processor.assign(socket); // The processor will recycle itself when it finishes } // Notify the threadStop() method that we have shut ourselves down // if (debug >= 3) // log("run: Notifying threadStop() that we have shut down"); synchronized (threadSync) { threadSync.notifyAll(); } } /** * Start the background processing thread. */ private void threadStart() { log(sm.getString("coyoteConnector.starting")); thread = new Thread(this, threadName); thread.setDaemon(true); thread.start(); } /** * Stop the background processing thread. */ private void threadStop() { log(sm.getString("coyoteConnector.stopping")); stopped = true; try { threadSync.wait(5000); } catch (InterruptedException e) { ; } thread = null; } // ------------------------------------------------------ Lifecycle Methods /** * Add a lifecycle event listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return null;//lifecycle.findLifecycleListeners(); } /** * Remove a lifecycle event listener from this component. * * @param listener The listener to add */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } /** * Initialize this connector (create ServerSocket here!) */ public void initialize() throws LifecycleException { if (initialized) throw new LifecycleException ( sm.getString("coyoteConnector.alreadyInitialized")); this.initialized=true; Exception eRethrow = null; // Establish a server socket on the specified port try { serverSocket = open(); } catch (IOException ioe) { log("coyoteConnector, io problem: ", ioe); eRethrow = ioe; } catch (KeyStoreException kse) { log("coyoteConnector, keystore problem: ", kse); eRethrow = kse; } catch (NoSuchAlgorithmException nsae) { log("coyoteConnector, keystore algorithm problem: ", nsae); eRethrow = nsae; } catch (CertificateException ce) { log("coyoteConnector, certificate problem: ", ce); eRethrow = ce; } catch (UnrecoverableKeyException uke) { log("coyoteConnector, unrecoverable key: ", uke); eRethrow = uke; } catch (KeyManagementException kme) { log("coyoteConnector, key management problem: ", kme); eRethrow = kme; } if ( eRethrow != null ) throw new LifecycleException(threadName + ".open", eRethrow); } /** * Begin processing requests via this Connector. * * @exception LifecycleException if a fatal startup error occurs */ public void start() throws LifecycleException { // Validate and update our current state if (started) throw new LifecycleException (sm.getString("coyoteConnector.alreadyStarted")); threadName = "CoyoteConnector[" + port + "]"; lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; // Start our background thread threadStart(); // Create the specified minimum number of processors while (curProcessors < minProcessors) { if ((maxProcessors > 0) && (curProcessors >= maxProcessors)) break; CoyoteProcessor processor = newProcessor(); recycle(processor); } } /** * Terminate processing requests via this Connector. * * @exception LifecycleException if a fatal shutdown error occurs */ public void stop() throws LifecycleException { // Validate and update our current state if (!started) throw new LifecycleException (sm.getString("coyoteConnector.notStarted")); lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; // Gracefully shut down all processors we have created for (int i = created.size() - 1; i >= 0; i--) { CoyoteProcessor processor = (CoyoteProcessor) created.elementAt(i); if (processor instanceof Lifecycle) { try { ((Lifecycle) processor).stop(); } catch (LifecycleException e) { log("coyoteConnector.stop", e); } } } synchronized (threadSync) { // Close the server socket we were using if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { ; } } // Stop our background thread threadStop(); } serverSocket = null; } } 1.1 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteProcessor.java Index: CoyoteProcessor.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteProcessor.java,v 1.1 2002/01/17 21:08:44 remm Exp $ * $Revision: 1.1 $ * $Date: 2002/01/17 21:08:44 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.coyote.tomcat4; import java.io.BufferedInputStream; import java.io.EOFException; import java.io.InterruptedIOException; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.util.ArrayList; import java.util.Iterator; import java.util.Locale; import java.util.StringTokenizer; import java.util.TreeMap; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.coyote.Adapter; import org.apache.coyote.InputBuffer; import org.apache.coyote.OutputBuffer; import org.apache.coyote.Processor; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.catalina.Connector; import org.apache.catalina.Container; import org.apache.catalina.Globals; import org.apache.catalina.HttpRequest; import org.apache.catalina.HttpResponse; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Logger; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.RequestUtil; import org.apache.catalina.util.StringManager; import org.apache.catalina.util.StringParser; /** * Implementation of a request processor which delegates the processing to a * Coyote processor. * * @author Craig R. McClanahan * @author Remy Maucherat * @version $Revision: 1.1 $ $Date: 2002/01/17 21:08:44 $ */ final class CoyoteProcessor implements Lifecycle, Runnable, Adapter { // ----------------------------------------------------------- Constructors /** * Construct a new CoyoteProcessor associated with the specified connector. * * @param connector CoyoteConnector that owns this processor * @param id Identifier of this CoyoteProcessor (unique per connector) */ public CoyoteProcessor(CoyoteConnector connector, int id) { super(); this.connector = connector; this.debug = connector.getDebug(); this.id = id; this.proxyName = connector.getProxyName(); this.proxyPort = connector.getProxyPort(); this.request = (CoyoteRequest) connector.createRequest(); this.response = (CoyoteResponse) connector.createResponse(); this.serverPort = connector.getPort(); this.threadName = "CoyoteProcessor[" + connector.getPort() + "][" + id + "]"; } // ----------------------------------------------------- Instance Variables /** * Is there a new socket available? */ private boolean available = false; /** * The CoyoteConnector with which this processor is associated. */ private CoyoteConnector connector = null; /** * Coyote processor. */ private Processor processor = null; /** * The debugging detail level for this component. */ private int debug = 0; /** * The identifier of this processor, unique per connector. */ private int id = 0; /** * The lifecycle event support for this component. */ private LifecycleSupport lifecycle = new LifecycleSupport(this); /** * The match string for identifying a session ID parameter. */ private static final String match = ";" + Globals.SESSION_PARAMETER_NAME + "="; /** * The match string for identifying a session ID parameter. */ private static final char[] SESSION_ID = match.toCharArray(); /** * The string parser we will use for parsing request lines. */ private StringParser parser = new StringParser(); /** * The proxy server name for our Connector. */ private String proxyName = null; /** * The proxy server port for our Connector. */ private int proxyPort = 0; /** * The Coyote request object we will pass to our associated container. */ private CoyoteRequest request = null; /** * The Coyote response object we will pass to our associated container. */ private CoyoteResponse response = null; /** * The actual server port for our Connector. */ private int serverPort = 0; /** * The string manager for this package. */ protected StringManager sm = StringManager.getManager(Constants.Package); /** * The socket we are currently processing a request for. This object * is used for inter-thread communication only. */ private Socket socket = null; /** * Has this component been started yet? */ private boolean started = false; /** * The shutdown signal to our background thread */ private boolean stopped = false; /** * The background thread. */ private Thread thread = null; /** * The name to register for the background thread. */ private String threadName = null; /** * The thread synchronization object. */ private Object threadSync = new Object(); /** * Processor state */ private int status = Constants.PROCESSOR_IDLE; // --------------------------------------------------------- Public Methods /** * Return a String value representing this object. */ public String toString() { return (this.threadName); } // -------------------------------------------------------- Package Methods /** * Process an incoming TCP/IP connection on the specified socket. Any * exception that occurs during processing must be logged and swallowed. * <b>NOTE</b>: This method is called from our Connector's thread. We * must assign it to our own thread so that multiple simultaneous * requests can be handled. * * @param socket TCP socket to process */ synchronized void assign(Socket socket) { // Wait for the Processor to get the previous Socket while (available) { try { wait(); } catch (InterruptedException e) { } } // Store the newly available Socket and notify our thread this.socket = socket; available = true; notifyAll(); if ((debug >= 1) && (socket != null)) log(" An incoming request is being assigned"); } // -------------------------------------------------------- Private Methods /** * Await a newly assigned Socket from our Connector, or <code>null</code> * if we are supposed to shut down. */ private synchronized Socket await() { // Wait for the Connector to provide a new Socket while (!available) { try { wait(); } catch (InterruptedException e) { } } // Notify the Connector that we have received this Socket Socket socket = this.socket; available = false; notifyAll(); if ((debug >= 1) && (socket != null)) log(" The incoming request has been awaited"); return (socket); } /** * Log a message on the Logger associated with our Container (if any) * * @param message Message to be logged */ private void log(String message) { Logger logger = connector.getContainer().getLogger(); if (logger != null) logger.log(threadName + " " + message); } /** * Log a message on the Logger associated with our Container (if any) * * @param message Message to be logged * @param throwable Associated exception */ private void log(String message, Throwable throwable) { Logger logger = connector.getContainer().getLogger(); if (logger != null) logger.log(threadName + " " + message, throwable); } /** * Process an incoming HTTP request on the Socket that has been assigned * to this Processor. Any exceptions that occur during processing must be * swallowed and dealt with. * * @param socket The socket on which we are connected to the client */ private void process(Socket socket) { InputStream input = null; OutputStream output = null; try { input = socket.getInputStream(); output = socket.getOutputStream(); processor.process(input, output); } catch (Throwable t) { log(sm.getString("coyoteProcessor.process"), t); } try { int available = input.available(); // skip any unread (bogus) bytes if (available > 0) { input.skip(available); } } catch (Exception e) { ; } try { socket.close(); } catch (IOException e) { ; } socket = null; } /** * Service method. */ public void service(Request req, Response res) throws Exception { // Wrapping the Coyote requests request.setRequest(req); response.setResponse(res); try { // Calling the container //connector.getContainer().invoke(request, response); } finally { // Recycle the wrapper request and response request.recycle(); response.recycle(); } } // ---------------------------------------------- Background Thread Methods /** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. */ public void run() { // Process requests until we receive a shutdown signal while (!stopped) { // Wait for the next socket to be assigned Socket socket = await(); if (socket == null) continue; // Process the request from this socket process(socket); // Finish up this request connector.recycle(this); } // Tell threadStop() we have shut ourselves down successfully synchronized (threadSync) { threadSync.notifyAll(); } } /** * Start the background processing thread. */ private void threadStart() { log(sm.getString("httpProcessor.starting")); thread = new Thread(this, threadName); thread.setDaemon(true); thread.start(); if (debug >= 1) log(" Background thread has been started"); } /** * Stop the background processing thread. */ private void threadStop() { log(sm.getString("httpProcessor.stopping")); stopped = true; assign(null); if (status != Constants.PROCESSOR_IDLE) { // Only wait if the processor is actually processing a command synchronized (threadSync) { try { threadSync.wait(5000); } catch (InterruptedException e) { ; } } } thread = null; } // ------------------------------------------------------ Lifecycle Methods /** * Add a lifecycle event listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return null;//lifecycle.findLifecycleListeners(); } /** * Remove a lifecycle event listener from this component. * * @param listener The listener to add */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } /** * Start the background thread we will use for request processing. * * @exception LifecycleException if a fatal startup error occurs */ public void start() throws LifecycleException { if (started) throw new LifecycleException (sm.getString("httpProcessor.alreadyStarted")); // Instantiate the Coyote processor String className = connector.getProcessorClassName(); try { Class clazz = Class.forName(className); processor = (Processor) clazz.newInstance(); } catch (Exception e) { throw new LifecycleException (sm.getString("coyoteProcessor.processorInstantiationFailed", e)); } processor.setAdapter(this); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; threadStart(); } /** * Stop the background thread we will use for request processing. * * @exception LifecycleException if a fatal shutdown error occurs */ public void stop() throws LifecycleException { if (!started) throw new LifecycleException (sm.getString("httpProcessor.notStarted")); lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; threadStop(); } } 1.1 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteRequest.java Index: CoyoteRequest.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteRequest.java,v 1.1 2002/01/17 21:08:44 remm Exp $ * $Revision: 1.1 $ * $Date: 2002/01/17 21:08:44 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.coyote.tomcat4; import java.io.InputStream; import java.io.IOException; import java.net.Socket; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import org.apache.coyote.Request; import org.apache.catalina.Connector; /** * Wrapper object for the Coyote request. * * @author Remy Maucherat * @version $Revision: 1.1 $ $Date: 2002/01/17 21:08:44 $ */ public class CoyoteRequest { // ------------------------------------------------------------- Properties /** * Associated Catalina connector. */ protected Connector connector; /** * Return the Connector through which this Request was received. */ public Connector getConnector() { return (this.connector); } /** * Set the Connector through which this Request was received. * * @param connector The new connector */ public void setConnector(Connector connector) { this.connector = connector; } /** * Coyote request. */ protected Request request; /** * Set the Coyote request. * * @param request The Coyote request */ public void setRequest(Request request) { this.request = request; } // --------------------------------------------------------- Public Methods /** * Release all object references, and initialize instance variables, in * preparation for reuse of this object. */ public void recycle() { } } 1.1 jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java Index: CoyoteResponse.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteResponse.java,v 1.1 2002/01/17 21:08:44 remm Exp $ * $Revision: 1.1 $ * $Date: 2002/01/17 21:08:44 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.coyote.tomcat4; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; import org.apache.coyote.Response; import org.apache.catalina.Connector; /** * Wrapper object for the Coyote response. * * @author Remy Maucherat * @version $Revision: 1.1 $ $Date: 2002/01/17 21:08:44 $ */ public class CoyoteResponse { // ------------------------------------------------------------- Properties /** * Associated Catalina connector. */ protected Connector connector; /** * Return the Connector through which this Request was received. */ public Connector getConnector() { return (this.connector); } /** * Set the Connector through which this Request was received. * * @param connector The new connector */ public void setConnector(Connector connector) { this.connector = connector; } /** * Coyote response. */ protected Response response; /** * Set the Coyote response. * * @param response The Coyote response */ public void setResponse(Response response) { this.response = response; } // --------------------------------------------------------- Public Methods /** * Release all object references, and initialize instance variables, in * preparation for reuse of this object. */ public void recycle() { } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>