You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2001/01/23 04:55:55 UTC

cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10 Constants.java HttpConnector.java HttpProcessor.java HttpRequestImpl.java HttpResponseImpl.java LocalStrings.properties

remm        01/01/22 19:55:55

  Added:       catalina/src/share/org/apache/catalina/connector/http10
                        Constants.java HttpConnector.java
                        HttpProcessor.java HttpRequestImpl.java
                        HttpResponseImpl.java LocalStrings.properties
  Log:
  - Rename "test" connector to "http10" connector.
  - Added a socket timeout, and a connection timeout parameter
    (which default to 30s).
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/Constants.java
  
  Index: Constants.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/Constants.java,v 1.1 2001/01/23 03:55:54 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/01/23 03:55:54 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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.catalina.connector.http10;
  
  
  import org.apache.catalina.Globals;
  
  
  /**
   * Static constants for this package.
   */
  
  public final class Constants {
  
      public static final String Package = 
          "org.apache.catalina.connector.http10";
      public static final String ServerInfo =
  	Globals.SERVER_INFO + " (HTTP/1.0 Connector)";
      public static final int DEFAULT_CONNECTION_TIMEOUT = 30000;
  
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpConnector.java
  
  Index: HttpConnector.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpConnector.java,v 1.1 2001/01/23 03:55:54 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/01/23 03:55:54 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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.catalina.connector.http10;
  
  
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.util.Stack;
  import java.util.Vector;
  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.net.DefaultServerSocketFactory;
  import org.apache.catalina.net.ServerSocketFactory;
  import org.apache.catalina.util.LifecycleSupport;
  import org.apache.catalina.util.StringManager;
  
  
  /**
   * Simple implementation of an HTTP/1.0 Connector, for testing and debugging
   * purposes.  Not intended to be the final solution.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2001/01/23 03:55:54 $
   */
  
  
  public final class HttpConnector
      implements Connector, Lifecycle, Runnable {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * 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 server socket factory for this component.
       */
      private ServerSocketFactory factory = null;
  
  
      /**
       * Descriptive information about this Connector implementation.
       */
      private static final String info =
  	"org.apache.catalina.connector.http10.HttpConnector/1.0";
  
  
      /**
       * The lifecycle event support for this component.
       */
      protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  
  
      /**
       * Timeout value on the incoming connection.
       * Note : a negative value of 0 means no timeout.
       */
      private int connectionTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT;
  
  
      /**
       * 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;
  
  
      /**
       * The port number on which we listen for HTTP 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 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 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();
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * 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;
  
      }
  
  
      /**
       * 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 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 HTTP requests.
       */
      public int getPort() {
  
  	return (this.port);
  
      }
  
  
      /**
       * Set the port number on which we listen for HTTP requests.
       *
       * @param port The new port number
       */
      public void setPort(int port) {
  
  	this.port = port;
  
      }
  
  
      /**
       * 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;
  
      }
  
  
      // --------------------------------------------------------- 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() {
  
  	HttpRequestImpl request = new HttpRequestImpl();
  	request.setConnector(this);
  	return (request);
  
      }
  
  
      /**
       * Create (or allocate) and return a Response object suitable for
       * receiving the contents of a Response from the responsible Container.
       */
      public Response createResponse() {
  
  	HttpResponseImpl response = new HttpResponseImpl();
  	response.setConnector(this);
  	return (response);
  
      }
  
  
      // -------------------------------------------------------- Package Methods
  
  
      /**
       * Recycle the specified Processor so that it can be used again.
       *
       * @param processor The processor to be recycled
       */
      void recycle(HttpProcessor processor) {
  
          processors.push(processor);
  
      }
  
  
      // -------------------------------------------------------- Private Methods
  
  
      /**
       * Create (or allocate) and return an available processor for use in
       * processing a specific HTTP request, if possible.  If the maximum
       * allowed processors have already been created and are in use, return
       * <code>null</code> instead.
       */
      private HttpProcessor createProcessor() {
  
  	synchronized (processors) {
  	    if (processors.size() > 0)
  		return ((HttpProcessor) processors.pop());
  	    if ((maxProcessors > 0) && (curProcessors < maxProcessors))
  	        return (newProcessor());
  	    else
  	        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();
  	if (logger != null)
  	    logger.log(threadName + " " + message);
  	else
  	    System.out.println(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 = container.getLogger();
  	if (logger != null)
  	    logger.log(threadName + " " + message, throwable);
  	else {
  	    System.out.println(threadName + " " + message);
  	    throwable.printStackTrace(System.out);
  	}
  
      }
  
  
      /**
       * Create and return a new processor suitable for processing HTTP
       * requests and returning the corresponding responses.
       */
      private HttpProcessor newProcessor() {
  
          HttpProcessor processor = new HttpProcessor(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 if an input/output error occurs
       */
      private ServerSocket open() throws IOException {
  
          // 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("httpConnector.allAddresses"));
              return (factory.createSocket(port, acceptCount));
  	}
  
  	// Open a server socket on the specified address
  	InetAddress[] addresses =
  	    InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
  	int i;
  	for (i = 0; i < addresses.length; i++) {
  	    if (addresses[i].getHostAddress().equals(address))
  		break;
  	}
  	if (i < addresses.length) {
  	    log(sm.getString("httpConnector.anAddress", address));
              return (factory.createSocket(port, acceptCount, addresses[i]));
  	} else {
  	    log(sm.getString("httpConnector.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 {
  		socket = serverSocket.accept();
                  if (connectionTimeout > 0)
                      socket.setSoTimeout(connectionTimeout);
  	    } catch (IOException e) {
  		if (started && !stopped)
  		    log("accept: ", e);
  		break;
  	    }
  
  	    // Hand this socket off to an appropriate processor
  	    HttpProcessor processor = createProcessor();
  	    if (processor == null) {
  		try {
  		    log(sm.getString("httpConnector.noProcessor"));
  		    socket.close();
  		} catch (IOException e) {
  		    ;
  		}
  		continue;
  	    }
  	    processor.assign(socket);
  
  	    // The processor will recycle itself when it finishes
  
  	}
  
  	// Notify the threadStop() method that we have shut ourselves down
  	synchronized (threadSync) {
  	    threadSync.notifyAll();
  	}
  
      }
  
  
      /**
       * Start the background processing thread.
       */
      private void threadStart() {
  
  	log(sm.getString("httpConnector.starting"));
  
  	thread = new Thread(this, threadName);
  	thread.setDaemon(true);
  	thread.start();
  
      }
  
  
      /**
       * Stop the background processing thread.
       */
      private void threadStop() {
  
  	log(sm.getString("httpConnector.stopping"));
  
  	stopped = true;
  	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);
  
      }
  
  
      /**
       * Remove a lifecycle event listener from this component.
       *
       * @param listener The listener to add
       */
      public void removeLifecycleListener(LifecycleListener listener) {
  
  	lifecycle.removeLifecycleListener(listener);
  
      }
  
  
      /**
       * 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("httpConnector.alreadyStarted"));
          threadName = "HttpConnector[" + port + "]";
  	lifecycle.fireLifecycleEvent(START_EVENT, null);
  	started = true;
  
  	// Establish a server socket on the specified port
  	try {
  	    serverSocket = open();
  	} catch (IOException e) {
  	    throw new LifecycleException(threadName + ".open", e);
  	}
  
  	// Start our background thread
  	threadStart();
  
  	// Create the specified minimum number of processors
  	while (curProcessors < minProcessors) {
  	    if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
  		break;
  	    HttpProcessor 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("httpConnector.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--) {
  	    HttpProcessor processor = (HttpProcessor) created.elementAt(i);
  	    if (processor instanceof Lifecycle) {
  		try {
  		    ((Lifecycle) processor).stop();
  		} catch (LifecycleException e) {
  		    log("HttpConnector.stop", e);
  		}
  	    }
  	}
  
  	// Close the server socket we were using
  	if (serverSocket != null) {
  	    try {
  		serverSocket.close();
  	    } catch (IOException e) {
  		;
  	    }
  	    serverSocket = null;
  	}
  
  	// Stop our background thread
  	threadStop();
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpProcessor.java
  
  Index: HttpProcessor.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpProcessor.java,v 1.1 2001/01/23 03:55:54 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/01/23 03:55:54 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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.catalina.connector.http10;
  
  
  import java.io.BufferedInputStream;
  import java.io.InputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.net.InetAddress;
  import java.net.Socket;
  import java.util.NoSuchElementException;
  import java.util.StringTokenizer;
  import java.util.Locale;
  import java.util.Hashtable;
  import java.util.Vector;
  import java.util.Enumeration;
  import javax.servlet.ServletException;
  import javax.servlet.http.Cookie;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  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.RequestUtil;
  import org.apache.catalina.util.LifecycleSupport;
  import org.apache.catalina.util.StringManager;
  
  
  /**
   * Implementation of a request processor (and its associated thread) that may
   * be used by an HttpConnector to process individual requests.  The connector
   * will allocate a processor from its pool, assign a particular socket to it,
   * and the processor will then execute the processing required to complete
   * the request.  When the processor is completed, it will recycle itself.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2001/01/23 03:55:54 $
   */
  
  final class HttpProcessor
      implements Lifecycle, Runnable {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new HttpProcessor associated with the specified connector.
       *
       * @param connector HttpConnector that owns this processor
       * @param id Identifier of this HttpProcessor (unique per connector)
       */
      public HttpProcessor(HttpConnector connector, int id) {
  
  	super();
  	this.connector = connector;
  	this.debug = connector.getDebug();
  	this.id = id;
  	this.request = (HttpRequest) connector.createRequest();
  	this.response = (HttpResponse) connector.createResponse();
  	this.threadName =
  	  "HttpProcessor[" + connector.getPort() + "][" + id + "]";
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Is there a new socket available?
       */
      private boolean available = false;
  
  
      /**
       * The HttpConnector with which this processor is associated.
       */
      private HttpConnector connector = 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 HTTP request object we will pass to our associated container.
       */
      private HttpRequest request = null;
  
  
      /**
       * The HTTP response object we will pass to our associated container.
       */
      private HttpResponse response = null;
  
  
      /**
       * 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();
  
  
      // -------------------------------------------------------- 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);
  
      }
  
  
      /**
       * Parse and record the connection parameters related to this request.
       *
       * @param socket The socket on which we are connected
       *
       * @exception IOException if an input/output error occurs
       * @exception ServletException if a parsing error occurs
       */
      private void parseConnection(Socket socket)
          throws IOException, ServletException {
  
  	if (debug >= 2)
  	    log("  parseConnection: address=" + socket.getInetAddress() +
  		", port=" + connector.getPort());
  	((HttpRequestImpl) request).setInet(socket.getInetAddress());
  	request.setServerPort(connector.getPort());
          request.setSocket(socket);
  
      }
  
  
      /**
       * Parse the incoming HTTP request headers, and set the appropriate
       * request headers.
       *
       * @param input The input stream connected to our socket
       *
       * @exception IOException if an input/output error occurs
       * @exception ServletException if a parsing error occurs
       */
      private void parseHeaders(InputStream input)
          throws IOException, ServletException {
  
  	while (true) {
  
  	    // Read the next header line
  	    String line = read(input);
  	    if ((line == null) || (line.length() < 1))
  		break;
  
  	    // Parse the header name and value
  	    int colon = line.indexOf(":");
  	    if (colon < 0)
  		throw new ServletException
  		    (sm.getString("httpProcessor.parseHeaders.colon"));
  	    String name = line.substring(0, colon).trim();
  	    String match = name.toLowerCase();
  	    String value = line.substring(colon + 1).trim();
  	    if (debug >= 1)
  	        log(" Header " + name + " = " + value);
  
  	    // Set the corresponding request headers
  	    if (match.equals("authorization")) {
  		request.setAuthorization(value);
  		request.addHeader(name, value);
  	    } else if (match.equals("accept-language")) {
            request.addHeader(name, value);
            //
            // Adapted from old code perhaps maybe optimized
            //
            //
            Hashtable languages = new Hashtable();
            StringTokenizer languageTokenizer = new StringTokenizer(value, ",");
  
            while (languageTokenizer.hasMoreTokens()) {
              String language = languageTokenizer.nextToken().trim();
              int qValueIndex = language.indexOf(';');
              int qIndex = language.indexOf('q');
              int equalIndex = language.indexOf('=');
              Double qValue = new Double(1);
  
              if (qValueIndex > -1 && qValueIndex < qIndex && qIndex < equalIndex) {
                String qValueStr = language.substring(qValueIndex + 1);
                language = language.substring(0, qValueIndex);
                qValueStr = qValueStr.trim().toLowerCase();
                qValueIndex = qValueStr.indexOf('=');
                qValue = new Double(0);
                if (qValueStr.startsWith("q") &&
                    qValueIndex > -1) {
                    qValueStr = qValueStr.substring(qValueIndex + 1);
                    try {
                        qValue = new Double(qValueStr.trim());
                    } catch (NumberFormatException nfe) {
                    }
                }
              }
              // XXX
              // may need to handle "*" at some point in time
              if (! language.equals("*")) {
                  String key = qValue.toString();
                  Vector v = (Vector)((languages.containsKey(key)) ? languages.get(key) : new Vector());
                  v.addElement(language);
                  languages.put(key, v);
              }
            }
            Vector l = new Vector();
            Enumeration e = languages.keys();
            while (e.hasMoreElements()) {
                String key = (String)e.nextElement();
                Vector v = (Vector)languages.get(key);
                Enumeration le = v.elements();
                while (le.hasMoreElements()) {
                  String language = (String)le.nextElement();
                  String country = "";
                  int countryIndex = language.indexOf("-");
                  if (countryIndex > -1) {
                      country = language.substring(countryIndex + 1).trim();
                      language = language.substring(0, countryIndex).trim();
                  }
                  request.addLocale(new Locale(language, country));
                }
            }
  	    } else if (match.equals("cookie")) {
  		Cookie cookies[] = RequestUtil.parseCookieHeader(value);
  		for (int i = 0; i < cookies.length; i++) {
  		    if (cookies[i].getName().equals
  			(Globals.SESSION_COOKIE_NAME)) {
  
  			// Override anything requested in the URL
  			request.setRequestedSessionId(cookies[i].getValue());
  			request.setRequestedSessionCookie(true);
  			request.setRequestedSessionURL(false);
  			if (debug >= 1)
  			  log(" Requested cookie session id is " +
  			      ((HttpServletRequest) request.getRequest()).getRequestedSessionId());
                          break;  // Accept only the first session id value
  
  		    }
                      request.addCookie(cookies[i]);
  		}
  		// Keep Watchdog from whining by adding the header as well
  		// (GetHeaderTest, GetIntHeader_1Test)
  		request.addHeader(name, value);
  	    } else if (match.equals("content-length")) {
  		int n = -1;
  		try {
  		    n = Integer.parseInt(value);
  		} catch (Exception e) {
  		    throw new ServletException
  			(sm.getString("httpProcessor.parseHeaders.contentLength"));
  		}
  		request.setContentLength(n);
  		request.addHeader(name, value);
  	    } else if (match.equals("content-type")) {
  		request.setContentType(value);
  		request.addHeader(name, value);
  	    } else if (match.equals("host")) {
  		int n = value.indexOf(":");
  		if (n < 0)
  		    request.setServerName(value);
  		else {
  		    request.setServerName(value.substring(0, n).trim());
  		    int port = 80;
  		    try {
  			port = Integer.parseInt(value.substring(n+1).trim());
  		    } catch (Exception e) {
  			throw new ServletException
  			    (sm.getString("httpProcessor.parseHeaders.portNumber"));
  		    }
  		    request.setServerPort(port);
  		}
  		request.addHeader(name, value);
  	    } else {
  		request.addHeader(name, value);
  	    }
  	}
  
      }
  
  
      /**
       * Parse the incoming HTTP request and set the corresponding HTTP request
       * properties.
       *
       * @param input The input stream attached to our socket
       *
       * @exception IOException if an input/output error occurs
       * @exception ServletException if a parsing error occurs
       */
      private void parseRequest(InputStream input)
          throws IOException, ServletException {
  
  	// Parse the incoming request line
  	String line = read(input);
  	if (line == null)
  	    throw new ServletException
  		(sm.getString("httpProcessor.parseRequest.read"));
  	StringTokenizer st = new StringTokenizer(line);
  
  	String method = null;
  	try {
  	    method = st.nextToken();
  	} catch (NoSuchElementException e) {
  	    method = null;
  	}
  
  	String uri = null;
  	try {
  	    uri = st.nextToken();
  	    ;	// FIXME - URL decode the URI?
  	} catch (NoSuchElementException e) {
  	    uri = null;
  	}
  
  	String protocol = null;
  	try {
  	    protocol = st.nextToken();
  	} catch (NoSuchElementException e) {
  	    protocol = "HTTP/0.9";
  	}
  
  	// Validate the incoming request line
  	if (method == null) {
  	    throw new ServletException
  		(sm.getString("httpProcessor.parseRequest.method"));
  	} else if (uri == null) {
  	    throw new ServletException
  		(sm.getString("httpProcessor.parseRequest.uri"));
  	}
  
  	// Parse any query parameters out of the request URI
  	int question = uri.indexOf("?");
  	if (question >= 0) {
  	    request.setQueryString(uri.substring(question + 1));
  	    if (debug >= 1)
  	        log(" Query string is " +
  		    ((HttpServletRequest) request.getRequest()).getQueryString());
  	    uri = uri.substring(0, question);
  	} else
  	    request.setQueryString(null);
  
  	// Parse any requested session ID out of the request URI
  	int semicolon = uri.indexOf(match);
  	if (semicolon >= 0) {
  	    String rest = uri.substring(semicolon + match.length());
  	    int semicolon2 = rest.indexOf(";");
  	    if (semicolon2 >= 0) {
  		request.setRequestedSessionId(rest.substring(0, semicolon2));
  		rest = rest.substring(semicolon2);
  	    } else {
  		request.setRequestedSessionId(rest);
  		rest = "";
  	    }
  	    request.setRequestedSessionURL(true);
  	    uri = uri.substring(0, semicolon) + rest;
  	    if (debug >= 1)
  	        log(" Requested URL session id is " +
  		    ((HttpServletRequest) request.getRequest()).getRequestedSessionId());
  	} else {
  	    request.setRequestedSessionId(null);
  	    request.setRequestedSessionURL(false);
  	}
  
  	// Set the corresponding request properties
  	((HttpRequest) request).setMethod(method);
  	request.setProtocol(protocol);
  	((HttpRequest) request).setRequestURI(uri);
  	request.setSecure(false);	// No SSL support
  	request.setScheme("http");	// No SSL support
  
  	if (debug >= 1)
  	    log(" Request is " + method + " for " + uri);
  
      }
  
  
      /**
       * 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) {
  
  	boolean ok = true;
  	InputStream input = null;
  	OutputStream output = null;
  
  	// Construct and initialize the objects we will need
  	try {
  	    input = new BufferedInputStream(socket.getInputStream(),
  	    				    connector.getBufferSize());
  	    request.setStream(input);
  	    request.setResponse(response);
  	    output = socket.getOutputStream();
  	    response.setStream(output);
  	    response.setRequest(request);
  	    ((HttpServletResponse) response.getResponse()).setHeader
  		("Server", Constants.ServerInfo);
  	} catch (Exception e) {
  	    log("process.create", e);
  	    ok = false;
  	}
  
  	// Parse the incoming request
  	try {
  	    if (ok) {
  		parseConnection(socket);
  		parseRequest(input);
  		if (!request.getRequest().getProtocol().startsWith("HTTP/0"))
  		    parseHeaders(input);
  	    }
  	} catch (Exception e) {
  	    try {
  		log("process.parse", e);
  		((HttpServletResponse) response.getResponse()).sendError
  		    (HttpServletResponse.SC_BAD_REQUEST);
  	    } catch (Exception f) {
  		;
  	    }
  	}
  
  	// Ask our Container to process this request
  	try {
  	    if (ok) {
  		connector.getContainer().invoke(request, response);
  	    }
  	} catch (ServletException e) {
  	    log("process.invoke", e);
  	    try {
  		((HttpServletResponse) response.getResponse()).sendError
  		    (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  	    } catch (Exception f) {
  		;
  	    }
  	    ok = false;
  	} catch (Throwable e) {
  	    log("process.invoke", e);
  	    try {
  		((HttpServletResponse) response.getResponse()).sendError
  		    (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  	    } catch (Exception f) {
  		;
  	    }
  	    ok = false;
  	}
  
  	// Finish up the handling of the response
  	try {
  	    if (ok)
  		response.finishResponse();
  	} catch (IOException e) {
  	    log("FIXME-Exception from finishResponse", e);
  	}
  	try {
  	    if (output != null)
  		output.flush();
  	} catch (IOException e) {
  	    log("FIXME-Exception flushing output", e);
  	}
  	try {
  	    if (output != null)
  		output.close();
  	} catch (IOException e) {
  	    log("FIXME-Exception closing output", e);
  	}
  
  	// Finish up the handling of the request
  	try {
  	    if (ok)
  		request.finishRequest();
  	} catch (IOException e) {
  	    log("FIXME-Exception from finishRequest", e);
  	}
  	try {
  	    if (input != null)
  	        input.close();
  	} catch (IOException e) {
  	    log("FIXME-Exception closing input", e);
  	}
  
  	// Finish up the handling of the socket connection itself
  	try {
  	    socket.close();
  	} catch (IOException e) {
  	    log("FIXME-Exception closing socket", e);
  	}
  	socket = null;
  
      }
  
  
      /**
       * Read a line from the specified input stream, and strip off the
       * trailing carriage return and newline (if any).  Return the remaining
       * characters that were read as a String.
       *
       * @param input The input stream connected to our socket
       *
       * @returns The line that was read, or <code>null</code> if end-of-file
       *  was encountered
       *
       * @exception IOException if an input/output error occurs
       */
      private String read(InputStream input) throws IOException {
  
  	StringBuffer sb = new StringBuffer();
  	while (true) {
  	    int ch = input.read();
  	    if (ch < 0) {
  		if (sb.length() == 0) {
  		    return (null);
  		} else {
  		    break;
  		}
  	    } else if (ch == '\r') {
  		continue;
  	    } else if (ch == '\n') {
  		break;
  	    }
  	    sb.append((char) ch);
  	}
  	if (debug >= 2)
  	    log("  Read: " + sb.toString());
  	return (sb.toString());
  
      }
  
  
      // ---------------------------------------------- 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
  	    request.recycle();
  	    response.recycle();
  	    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);
  	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);
  
      }
  
  
      /**
       * 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"));
  	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-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpRequestImpl.java
  
  Index: HttpRequestImpl.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpRequestImpl.java,v 1.1 2001/01/23 03:55:54 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/01/23 03:55:54 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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.catalina.connector.http10;
  
  
  import java.net.InetAddress;
  import org.apache.catalina.connector.HttpRequestBase;
  
  
  /**
   * Implementation of <b>HttpRequest</b> specific to the HTTP connector.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2001/01/23 03:55:54 $
   */
  
  final class HttpRequestImpl
      extends HttpRequestBase {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The InetAddress of the remote client of ths request.
       */
      protected InetAddress inet = null;
  
  
      /**
       * Descriptive information about this Request implementation.
       */
      protected static final String info =
  	"org.apache.catalina.connector.http10.HttpRequestImpl/1.0";
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * [Package Private] Return the InetAddress of the remote client of
       * this request.
       */
      InetAddress getInet() {
  
  	return (inet);
  
      }
  
  
      /**
       * [Package Private] Set the InetAddress of the remote client of
       * this request.
       *
       * @param inet The new InetAddress
       */
      void setInet(InetAddress inet) {
  
  	this.inet = inet;
  
      }
  
  
      /**
       * Return descriptive information about this Request implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Release all object references, and initialize instance variables, in
       * preparation for reuse of this object.
       */
      public void recycle() {
  
  	super.recycle();
  	inet = null;
  
      }
  
  
      // ------------------------------------------------- ServletRequest Methods
  
  
      /**
       * Return the Internet Protocol (IP) address of the client that sent
       * this request.
       */
      public String getRemoteAddr() {
  
  	return (inet.getHostAddress());
  
      }
  
  
      /**
       * Return the fully qualified name of the client that sent this request,
       * or the IP address of the client if the name cannot be determined.
       */
      public String getRemoteHost() {
  
  	return (inet.getHostName());
  
      }
  
  
      // --------------------------------------------- HttpServletRequest Methods
  
  
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpResponseImpl.java
  
  Index: HttpResponseImpl.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpResponseImpl.java,v 1.1 2001/01/23 03:55:54 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2001/01/23 03:55:54 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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.catalina.connector.http10;
  
  
  import org.apache.catalina.connector.HttpResponseBase;
  
  
  /**
   * Implementation of <b>HttpResponse</b> specific to the HTTP connector.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2001/01/23 03:55:54 $
   */
  
  final class HttpResponseImpl
      extends HttpResponseBase {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Descriptive information about this Response implementation.
       */
      protected static final String info =
  	"org.apache.catalina.connector.http10.HttpResponseImpl/1.0";
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return descriptive information about this Response implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Release all object references, and initialize instance variables, in
       * preparation for reuse of this object.
       */
      public void recycle() {
  
  	super.recycle();
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  httpConnector.alreadyStarted=HTTP connector has already been started
  httpConnector.allAddresses=Opening server socket on all host IP addresses
  httpConnector.anAddress=Opening server socket on host IP address {0}
  httpConnector.noAddress=No host IP address matching {0}, opening on all addresses
  httpConnector.noProcessor=No processor available, rejecting this connection
  httpConnector.notStarted=HTTP connector has not yet been started
  httpConnector.starting=Starting background thread
  httpConnector.stopping=Stopping background thread
  httpProcessor.alreadyStarted=HTTP processor has already been started
  httpProcessor.notStarted=HTTP processor has not yet been started
  httpProcessor.parseHeaders.contentLength=Invalid 'Content-Length' header
  httpProcessor.parseHeaders.colon=Invalid HTTP header format
  httpProcessor.parseHeaders.portNumber=Invalid TCP/IP port number in 'Host' header
  httpProcessor.parseRequest.method=Missing HTTP request method
  httpProcessor.parseRequest.read=Missing HTTP request line
  httpProcessor.parseRequest.uri=Missing HTTP request URI
  httpProcessor.start=HTTP processor has already been started
  httpProcessor.starting=Starting background thread
  httpProcessor.stopping=Stopping background thread