You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@locus.apache.org on 2000/01/20 07:35:26 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core StandardContext.java StandardEngine.java StandardHost.java StandardResources.java ValveBase.java

craigmcc    00/01/19 22:35:26

  Added:       proposals/catalina/src/share/org/apache/tomcat/core
                        StandardContext.java StandardEngine.java
                        StandardHost.java StandardResources.java
                        ValveBase.java
  Log:
  Check-in #2 of the core component implementations for the
  "Catalina" proposal.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java
  
  Index: StandardContext.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java,v 1.1 2000/01/20 06:35:25 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:35:25 $
   *
   * ====================================================================
   *
   * 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.tomcat.core;
  
  
  import java.io.IOException;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletResponse;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Lifecycle;
  import org.apache.tomcat.LifecycleException;
  import org.apache.tomcat.Request;
  import org.apache.tomcat.Response;
  import org.apache.tomcat.Wrapper;
  import org.apache.tomcat.deployment.WebApplicationDescriptor;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  
  
  /**
   * Standard implementation of the <b>Context</b> interface.  Each
   * child container must be a Wrapper implementation to process the
   * requests directed to a particular servlet.
   * <p>
   * Lifecycle configuration of this component assumes an XML node
   * in the following format:
   * <code>
   *   &lt;Context className="org.apache.tomcat.core.StandardContext"
   *             path="xxx"/>
   * </code>
   * where you can adjust the following parameters, with default values
   * in square brackets:
   * <ul>
   * <li><b>path</b> - Context path for URIs that are processed by this
   *     Context.  Per the servlet API specification, you must define a
   *     Context with a path of "/", which serves as the default Context
   *     within a particular environment.  [/]
   * <li><b>FIXME - add other properties supported by Tomcat 3.0</b>.
   * </ul>
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:35:25 $
   */
  
  public final class StandardContext
      extends ContainerBase
      implements Context, Lifecycle {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Has this component been configured?
       */
      private boolean configured = false;
  
  
      /**
       * The ServletContext implementation associated with this Context.
       */
      private ApplicationContext context = null;
  
  
      /**
       * The web application deployment descriptor associated with this context.
       */
      private WebApplicationDescriptor descriptor = null;
  
  
      /**
       * The descriptive information string for this implementation.
       */
      private static final String info =
  	"org.apache.tomcat.core.StandardContext/1.0";
  
  
      /**
       * Has this component been started?
       */
      private boolean started = false;
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return the context configuration descriptor for this web application.
       */
      public WebApplicationDescriptor getDescriptor() {
  
  	return (this.descriptor);
  
      }
  
  
      /**
       * Set the context configuration descriptor for this web application.
       *
       * @param descriptor The new context configuration descriptor
       */
      public void setDescriptor(WebApplicationDescriptor descriptor) {
  
  	this.descriptor = descriptor;
  
      }
  
  
      /**
       * Return the context path for this Context.
       */
      public String getPath() {
  
  	return (getName());
  
      }
  
  
      /**
       * Set the context path for this Context.
       * <p>
       * <b>IMPLEMENTATION NOTE</b>:  The context path is used as the "name" of
       * a Context, because it must be unique.
       *
       * @param path The new context path
       */
      public void setPath(String path) {
  
  	setName(path);
  
      }
  
  
      /**
       * Return the servlet context for which this Context is a facade.
       */
      public ServletContext getServletContext() {
  
  	if (context == null)
  	    context = new ApplicationContext(this);
  	return (context);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Add a child Container, only if the proposed child is an implementation
       * of Wrapper.
       *
       * @param child Child container to be added
       */
      public void addChild(Container child) {
  
  	if (!(child instanceof Wrapper))
  	    throw new IllegalArgumentException
  		(sm.getString("standardContext.notWrapper"));
  	super.addChild(child);
  
      }
  
  
      /**
       * Return descriptive information about this Container implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      /**
       * Return the Wrapper associated with the servlet that matches the
       * specified context-relative URI, if any; otherwise return
       * <code>null</code>.
       *
       * @param uri Context-relative URI, which must start with a "/"
       */
      public Wrapper map(String uri) {
  
  	return (null);	// FIXME - map() via servlet mappings
  
      }
  
  
      /**
       * Select the appropriate child Wrapper to process this request,
       * based on the specified request URI.  If no matching Wrapper can
       * be found, return an appropriate HTTP error.
       *
       * @param request Request to be processed
       * @param response Response to be produced
       */
      public void service(Request request, Response response)
          throws IOException, ServletException {
  
  	// Select the Wrapper to be used for this Request
  	String path = request.getRequest().getRequestURI();
  	Wrapper wrapper = map(path);
  	if (wrapper == null) {
  	    response.getResponse().sendError
  		(HttpServletResponse.SC_NOT_FOUND,
  		 sm.getString("standardContext.notFound"));
  	    return;
  	}
  
  	// Ask this Wrapper to process this Request
  	;	// XXX - Tell the request which Wrapper we are using?
  	;	// XXX - Would seem to be necesary to calculate getServletPath
  	wrapper.invoke(request, response);
  
      }
  
  
      // ------------------------------------------------------ Lifecycle Methods
  
  
      /**
       * Configure this component, based on the specified configuration
       * parameters.  This method should be called immediately after the
       * component instance is created, and before <code>start()</code>
       * is called.
       *
       * @param parameters Configuration parameters for this component
       *  (<B>FIXME: What object type should this really be?)
       *
       * @exception IllegalStateException if this component has already been
       *  configured and/or started
       * @exception LifecycleException if this component detects a fatal error
       *  in the configuration parameters it was given
       */
      public void configure(Node parameters)
  	throws LifecycleException {
  
  	// Validate and update our current component state
  	if (configured)
  	    throw new LifecycleException
  		(sm.getString("standardContext.alreadyConfigured"));
  	configured = true;
  	if (parameters == null)
  	    return;
  
  	// Parse and process our configuration parameters
  	if (!("Context".equals(parameters.getNodeName())))
  	    return;
  	NamedNodeMap attributes = parameters.getAttributes();
  	Node node = null;
  	String value = null;
  
  	node = attributes.getNamedItem("path");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setPath(value);
  	}
  
  	// Parse and process our subordinate components
  	subconfigure(parameters);
  	;	// XXX - configure servlet definitions in descriptor?
  
      }
  
  
      /**
       * Prepare for the beginning of active use of the public methods of this
       * component.  This method should be called after <code>configure()</code>,
       * and before any of the public methods of the component are utilized.
       *
       * @exception IllegalStateException if this component has not yet been
       *  configured (if required for this component)
       * @exception IllegalStateException if this component has already been
       *  started
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      public void start() throws LifecycleException {
  
  	// Validate and update our current component state
  	if (!configured)
  	    throw new LifecycleException
  		(sm.getString("standardContext.notConfigured"));
  	if (started)
  	    throw new LifecycleException
  		(sm.getString("standardContext.alreadyStarted"));
  	started = true;
  
  	// Start our subordinate components
  	substart();
  	;	// XXX - start servlet definitions in descriptor?
  
      }
  
  
      /**
       * Gracefully terminate the active use of the public methods of this
       * component.  This method should be the last one called on a given
       * instance of this component.
       *
       * @exception IllegalStateException if this component has not been started
       * @exception IllegalStateException if this component has already
       *  been stopped
       * @exception LifecycleException if this component detects a fatal error
       *  that needs to be reported
       */
      public void stop() throws LifecycleException {
  
  	// Validate and update our current state
  	if (!started)
  	    throw new LifecycleException
  		(sm.getString("standardContext.notStarted"));
  
  	// Stop our subordinate components
  	;	// XXX - stop servlet definitions in descriptor?
  	substop();
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardEngine.java
  
  Index: StandardEngine.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardEngine.java,v 1.1 2000/01/20 06:35:26 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:35:26 $
   *
   * ====================================================================
   *
   * 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.tomcat.core;
  
  
  import java.io.IOException;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletResponse;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Engine;
  import org.apache.tomcat.Host;
  import org.apache.tomcat.Lifecycle;
  import org.apache.tomcat.LifecycleException;
  import org.apache.tomcat.Request;
  import org.apache.tomcat.Response;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  
  
  /**
   * Standard implementation of the <b>Engine</b> interface.  Each
   * child container must be a Host implementation to process the specific
   * fully qualified host name of that virtual host.
   * <p>
   * Lifecycle configuration of this component assumes an XML node
   * in the following format:
   * <code>
   *   &lt;Engine className="org.apache.tomcat.core.StandardEngine"
   *           defaultHost="www.mycompany.com"
   *           unknownHost="www.mycompany.com"/>
   * </code>
   * where you can adjust the following parameters, with default values
   * in square brackets:
   * <ul>
   * <li><b>defaultHost</b> - Default host name to use if none was specified
   *     in the incoming request (a corresponding <code>&lt;Host&gt;</code>
   *     child component must be configured.  [none]
   * <li><b>unknownHost</b> - Host name to use if an unknown host name was
   *     specified in the incoming request (a corresponding
   *     <code>&lt;Host&gt;</code> child component must be configured.  [none]
   * </ul>
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:35:26 $
   */
  
  public final class StandardEngine
      extends ContainerBase
      implements Engine, Lifecycle {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Has this component been configured?
       */
      private boolean configured = false;
  
  
      /**
       * Host name to use when no server host is specified in the request.
       */
      private String defaultHost = null;
  
  
      /**
       * The descriptive information string for this implementation.
       */
      private static final String info =
  	"org.apache.tomcat.core.StandardEngine/1.0";
  
  
      /**
       * Has this component been started?
       */
      private boolean started = false;
  
  
      /**
       * Host name to use when an unknown host name is specified.
       */
      private String unknownHost = null;
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return the default host.
       */
      public String getDefaultHost() {
  
  	return (defaultHost);
  
      }
  
  
      /**
       * Set the default host.
       *
       * @param host The new default host
       */
      public void setDefaultHost(String host) {
  
  	defaultHost = host;
  
      }
  
  
      /**
       * Return the unknown host.
       */
      public String getUnknownHost() {
  
  	return (unknownHost);
  
      }
  
  
      /**
       * Set the unknown host.
       *
       * @param host The new unknown host
       */
      public void setUnknownHost(String host) {
  
  	unknownHost = host;
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Add a child Container, only if the proposed child is an implementation
       * of Host.
       *
       * @param child Child container to be added
       */
      public void addChild(Container child) {
  
  	if (!(child instanceof Host))
  	    throw new IllegalArgumentException
  		(sm.getString("standardEngine.notHost"));
  	super.addChild(child);
  
      }
  
  
      /**
       * Return descriptive information about this Container implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      /**
       * Return the Host that should be used to process this request,
       * based on the server name that was included.  If no such Host
       * can be identified, return <code>null</code> instead.
       *
       * @param request Request being processed
       */
      public Host map(Request request) {
  
  	// Extract the requested server name
  	String server = request.getRequest().getServerName();
  	if (server == null)
  	    server = defaultHost;
  	if (server == null)
  	    return (null);
  
  	// Find the matching child Host
  	Host host = (Host) findChild(server);
  	if ((host == null) && (unknownHost != null))
  	    host = (Host) findChild(unknownHost);
  	return (host);
  
      }
  
  
      /**
       * Select the appropriate child Host to process this request,
       * based on the requested server name.  If no matching Host can
       * be found, return an appropriate HTTP error.
       *
       * @param request Request to be processed
       * @param response Response to be produced
       */
      public void service(Request request, Response response)
          throws IOException, ServletException {
  
  	// Select the host to be used for this request
  	Host host = map(request);
  	if (host == null) {
  	    response.getResponse().sendError
  		(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  		 sm.getString("standardEngine.noHost"));
  	    return;
  	}
  
  	// Ask this Host to process this request
  	host.invoke(request, response);
  
      }
  
  
      /**
       * Disallow any attempt to set a parent for this Container, since an
       * Engine is supposed to be at the top of the Container hierarchy.
       *
       * @param container Proposed parent Container
       */
      public void setParent(Container container) {
  
  	throw new IllegalArgumentException
  	    (sm.getString("standardEngine.notParent"));
  
      }
  
  
      // ------------------------------------------------------ Lifecycle Methods
  
  
      /**
       * Configure this component, based on the specified configuration
       * parameters.  This method should be called immediately after the
       * component instance is created, and before <code>start()</code>
       * is called.
       *
       * @param parameters Configuration parameters for this component
       *  (<B>FIXME: What object type should this really be?)
       *
       * @exception IllegalStateException if this component has already been
       *  configured and/or started
       * @exception LifecycleException if this component detects a fatal error
       *  in the configuration parameters it was given
       */
      public void configure(Node parameters)
  	throws LifecycleException {
  
  	// Validate and update our current component state
  	if (configured)
  	    throw new LifecycleException
  		(sm.getString("standardEngine.alreadyConfigured"));
  	configured = true;
  	if (parameters == null)
  	    return;
  
  	// Parse and process our configuration parameters
  	if (!("Engine".equals(parameters.getNodeName())))
  	    return;
  	NamedNodeMap attributes = parameters.getAttributes();
  	Node node = null;
  	String value = null;
  
  	node = attributes.getNamedItem("defaultHost");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setDefaultHost(value);
  	}
  
  	node = attributes.getNamedItem("unknownHost");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setUnknownHost(value);
  	}
  
  	// Parse and process our subordinate components
  	subconfigure(parameters);
  
      }
  
  
      /**
       * Prepare for the beginning of active use of the public methods of this
       * component.  This method should be called after <code>configure()</code>,
       * and before any of the public methods of the component are utilized.
       *
       * @exception IllegalStateException if this component has not yet been
       *  configured (if required for this component)
       * @exception IllegalStateException if this component has already been
       *  started
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      public void start() throws LifecycleException {
  
  	// Validate and update our current component state
  	if (!configured)
  	    throw new LifecycleException
  		(sm.getString("standardEngine.notConfigured"));
  	if (started)
  	    throw new LifecycleException
  		(sm.getString("standardEngine.alreadyStarted"));
  	started = true;
  
  	// Start our subordinate components
  	substart();
  
      }
  
  
      /**
       * Gracefully terminate the active use of the public methods of this
       * component.  This method should be the last one called on a given
       * instance of this component.
       *
       * @exception IllegalStateException if this component has not been started
       * @exception IllegalStateException if this component has already
       *  been stopped
       * @exception LifecycleException if this component detects a fatal error
       *  that needs to be reported
       */
      public void stop() throws LifecycleException {
  
  	// Validate and update our current state
  	if (!started)
  	    throw new LifecycleException
  		(sm.getString("standardEngine.notStarted"));
  
  	// Stop our subordinate components
  	substop();
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardHost.java
  
  Index: StandardHost.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardHost.java,v 1.1 2000/01/20 06:35:26 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:35:26 $
   *
   * ====================================================================
   *
   * 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.tomcat.core;
  
  
  import java.io.IOException;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletResponse;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Host;
  import org.apache.tomcat.Lifecycle;
  import org.apache.tomcat.LifecycleException;
  import org.apache.tomcat.Request;
  import org.apache.tomcat.Response;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  
  
  /**
   * Standard implementation of the <b>Host</b> interface.  Each
   * child container must be a Context implementation to process the
   * requests directed to a particular web application.
   * <p>
   * Lifecycle configuration of this component assumes an XML node
   * in the following format:
   * <code>
   *   &lt;Host className="org.apache.tomcat.core.StandardHost"
   *         name="www.mycompany.com" root="false"/>
   * </code>
   * where you can adjust the following parameters, with default values
   * in square brackets:
   * <ul>
   * <li><b>name</b> - Fully qualified host name of the virtual host
   *     represented by this component.  [REQUIRED - NO DEFAULT]
   * <li><b>root</b> - <code>true</code> if getRootContext() should return
   *     a valid object, or <code>false</code> if getRootContext()
   *     should return null (normally the case in secure environments).
   *     [false]
   * </ul>
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:35:26 $
   */
  
  public final class StandardHost
      extends ContainerBase
      implements Host, Lifecycle {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Has this component been configured?
       */
      private boolean configured = false;
  
  
      /**
       * The descriptive information string for this implementation.
       */
      private static final String info =
  	"org.apache.tomcat.core.StandardHost/1.0";
  
  
      /**
       * Should we return a root context?
       */
      private boolean root = false;
  
  
      /**
       * The root context for this virtual host.
       */
      private ServletContext rootContext = null;
  
  
      /**
       * Has this component been started?
       */
      private boolean started = false;
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return the canonical, fully qualified, name of the virtual host
       * this Container represents.
       */
      public String getName() {
  
  	return (name);
  
      }
  
  
      /**
       * Set the canonical, fully qualified, name of the virtual host
       * this Container represents.
       *
       * @param name Virtual host name
       *
       * @exception IllegalArgumentException if name is null
       */
      public void setName(String name) {
  
  	if (name == null)
  	    throw new IllegalArgumentException
  		(sm.getString("standardHost.nullName"));
  
  	this.name = name;
  
      }
  
  
      /**
       * Return the root context flag.
       */
      public boolean getRoot() {
  
  	return (this.root);
  
      }
  
  
      /**
       * Set the root context flag.
       *
       * @param root The new root context flag
       */
      public void setRoot(boolean root) {
  
  	this.root = root;
  
      }
  
  
      /**
       * Return a specialized ServletContext instance that wraps the
       * resources of the underlying virtual host; or <code>null</code>
       * if access to these resources is not supported or not allowed.
       * In general, this method will be used when a servlet calls
       * <code>ServletContext.getContext("/")</code>.
       */
      public ServletContext getRootContext() {
  
  	if (!root)
  	    return (null);
  
  	// Construct a root context object if necessary
  	rootContext = null;	// XXX - create root context object
  
  	return (rootContext);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Add a child Container, only if the proposed child is an implementation
       * of Context.
       *
       * @param child Child container to be added
       */
      public void addChild(Container child) {
  
  	if (!(child instanceof Context))
  	    throw new IllegalArgumentException
  		(sm.getString("standardHost.notContext"));
  	super.addChild(child);
  
      }
  
  
      /**
       * Return descriptive information about this Container implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      /**
       * Return the Context that should be used to process this request,
       * based on matching the longest possible context path (or selecting
       * the default context.  If no such Context can be identified,
       * return <code>null</code> instead.
       *
       * @param uri Request URI, which must start with a '/'
       */
      public Context map(String uri) {
  
  	String path = uri;
  	Context context = null;
  	while (path.length() > 1) {
  	    context = (Context) findChild(path);
  	    if (context != null)
  		break;
  	    path = path.substring(0, path.lastIndexOf("/"));
  	}
  	return (context);
  
      }
  
  
      /**
       * Select the appropriate child Context to process this request,
       * based on the specified request URI.  If no matching Context can
       * be found, return an appropriate HTTP error.
       *
       * @param request Request to be processed
       * @param response Response to be produced
       */
      public void service(Request request, Response response)
          throws IOException, ServletException {
  
  	// Select the context to be used for this request
  	String path = request.getRequest().getRequestURI();
  	Context context = map(path);
  	if (context == null) {
  	    response.getResponse().sendError
  		(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  		 sm.getString("standardHost.noContext"));
  	    return;
  	}
  
  	// Ask this Context to process this request
  	request.setContext(context);
  	response.setContext(context);
  	context.invoke(request, response);
  
      }
  
  
      // ------------------------------------------------------ Lifecycle Methods
  
  
      /**
       * Configure this component, based on the specified configuration
       * parameters.  This method should be called immediately after the
       * component instance is created, and before <code>start()</code>
       * is called.
       *
       * @param parameters Configuration parameters for this component
       *  (<B>FIXME: What object type should this really be?)
       *
       * @exception IllegalStateException if this component has already been
       *  configured and/or started
       * @exception LifecycleException if this component detects a fatal error
       *  in the configuration parameters it was given
       */
      public void configure(Node parameters)
  	throws LifecycleException {
  
  	// Validate and update our current component state
  	if (configured)
  	    throw new LifecycleException
  		(sm.getString("standardHost.alreadyConfigured"));
  	configured = true;
  	if (parameters == null)
  	    return;
  
  	// Parse and process our configuration parameters
  	if (!("Host".equals(parameters.getNodeName())))
  	    return;
  	NamedNodeMap attributes = parameters.getAttributes();
  	Node node = null;
  	String value = null;
  
  	node = attributes.getNamedItem("name");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setName(value);
  	}
  
  	node = attributes.getNamedItem("root");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setRoot("true".equals(value.toLowerCase()));
  	}
  
  	// Parse and process our subordinate components
  	subconfigure(parameters);
  
      }
  
  
      /**
       * Prepare for the beginning of active use of the public methods of this
       * component.  This method should be called after <code>configure()</code>,
       * and before any of the public methods of the component are utilized.
       *
       * @exception IllegalStateException if this component has not yet been
       *  configured (if required for this component)
       * @exception IllegalStateException if this component has already been
       *  started
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      public void start() throws LifecycleException {
  
  	// Validate and update our current component state
  	if (!configured)
  	    throw new LifecycleException
  		(sm.getString("standardHost.notConfigured"));
  	if (started)
  	    throw new LifecycleException
  		(sm.getString("standardHost.alreadyStarted"));
  	started = true;
  
  	// Start our subordinate components
  	substart();
  
      }
  
  
      /**
       * Gracefully terminate the active use of the public methods of this
       * component.  This method should be the last one called on a given
       * instance of this component.
       *
       * @exception IllegalStateException if this component has not been started
       * @exception IllegalStateException if this component has already
       *  been stopped
       * @exception LifecycleException if this component detects a fatal error
       *  that needs to be reported
       */
      public void stop() throws LifecycleException {
  
  	// Validate and update our current state
  	if (!started)
  	    throw new LifecycleException
  		(sm.getString("standardHost.notStarted"));
  
  	// Stop our subordinate components
  	substop();
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardResources.java
  
  Index: StandardResources.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardResources.java,v 1.1 2000/01/20 06:35:26 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:35:26 $
   *
   * ====================================================================
   *
   * 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.tomcat.core;
  
  
  import java.io.File;
  import java.io.InputStream;
  import java.io.IOException;
  import java.net.MalformedURLException;
  import java.net.URL;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Lifecycle;
  import org.apache.tomcat.LifecycleException;
  import org.apache.tomcat.Resources;
  import org.apache.tomcat.util.StringManager;
  import org.apache.tomcat.util.URLUtil;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  
  
  /**
   * Standard implementation of the <b>Resources</b> interface.  Resource
   * requests are resolved against the document base URL that is configured.
   * <p>
   * Lifecycle configuration of this component assumes an XML node
   * in the following format:
   * <code>
   *   <Resources className="org.apache.tomcat.core.StandardResources"
   *              docRoot="webpages"/>
   * </code>
   * where you can adjust the following parameters, with default values
   * in square brackets:
   * <ul>
   * <li><b>docRoot</b> - Directory name, directory path, or base URL from
   *     which this component can derive URLs of desired resources.
   *     [webpages]
   * </ul>
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:35:26 $
   */
  
  public final class StandardResources
      implements Resources, Lifecycle {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new instance of this class with default values.
       */
      public StandardResources() {
  
  	super();
  	setDocRoot("webpages");
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Has this component been configured?
       */
      private boolean configured = false;
  
  
      /**
       * The Container this component is associated with.
       */
      private Container container = null;
  
  
      /**
       * The document root URL for this component.
       */
      private String docRoot = null;
  
  
      /**
       * The descriptive information string for this implementation.
       */
      private static final String info =
  	"org.apache.tomcat.core.StandardResources/1.0";
  
  
      /**
       * The string manager for this package.
       */
      private StringManager sm = StringManager.getManager(Constants.Package);
  
  
      /**
       * Has this component been started?
       */
      private boolean started = false;
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return the Container with which this Resources has been associated.
       */
      public Container getContainer() {
  
  	return (this.container);
  
      }
  
  
      /**
       * Set the Container with which this Resources has been associated.
       *
       * @param container The associated Container
       */
      public void setContainer(Container container) {
  
  	this.container = container;
  
      }
  
  
      /**
       * Return the document root for this component.
       */
      public String getDocRoot() {
  
  	return (this.docRoot);
  
      }
  
  
      /**
       * Set the document root for this component.
       *
       * @param docRoot The new document root
       *
       * @exception IllegalArgumentException if this would create a
       *  malformed URL
       */
      public void setDocRoot(String docRoot) {
  
  	URL url = null;
  	try {
  	    url = URLUtil.resolve(docRoot);
  	} catch (MalformedURLException e) {
  	    throw new IllegalArgumentException
  		(sm.getString("standardResources.malformedURL"));
  	}
  	this.docRoot = url.toString();
  
      }
  
  
      /**
       * Return descriptive information about this Resources implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Return the MIME type of the specified file, or <code>null</code> if
       * the MIME type is not known.  The MIME type is determined by the
       * configuration of the servlet container, and may be specified in a
       * web application descriptor.  Common MIME types are
       * <code>"text/html"</code> and <code>"image/gif"</code>.
       *
       * @param file Name of the file whose MIME type is to be determined
       */
      public String getMimeType(String file) {
  
  	return (null);	// FIXME - Ask container if it is a Context, else map?
  
      }
  
  
      /**
       * Return the real path for a given virtual path.  For example, the
       * virtual path <code>"/index.html"</code> has a real path of whatever
       * file on the server's filesystem would be served by a request for
       * <code>"/index.html"</code>.
       * <p>
       * The real path returned will be in a form appropriate to the computer
       * and operating system on which the servlet container is running,
       * including the proper path separators.  This method returns
       * <code>null</code> if the servlet container cannot translate the
       * virtual path to a real path for any reason (such as when the content
       * is being made available from a <code>.war</code> archive).
       *
       * @param path The virtual path to be translated
       */
      public String getRealPath(String path) {
  
  	if ((path == null) || (!path.startsWith("/")))
  	    return (null);
  	if (docRoot.startsWith("file://"))
  	    return (docRoot.substring(6) + path);	// FIXME: Windows?
  	else
  	    return (null);
  
      }
  
  
      /**
       * Return a URL to the resource that is mapped to the specified path.
       * The path must begin with a "/" and is interpreted as relative to
       * the current context root.
       * <p>
       * This method allows the Container to make a resource available to
       * servlets from any source.  Resources can be located on a local or
       * remote file system, in a database, or in a <code>.war</code> file.
       * <p>
       * The servlet container must implement the URL handlers and
       * <code>URLConnection</code> objects that are necessary to access
       * the resource.
       * <p>
       * This method returns <code>null</code> if no resource is mapped to
       * the pathname.
       * <p>
       * Some Containers may allow writing to the URL returned by this method,
       * using the methods of the URL class.
       * <p>
       * The resource content is returned directly, so be aware that
       * requesting a <code>.jsp</code> page returns the JSP source code.
       * Use a <code>RequestDispatcher</code> instead to include results
       * of an execution.
       * <p>
       * This method has a different purpose than
       * <code>java.lang.Class.getResource()</code>, which looks up resources
       * based on a class loader.  This method does not use class loaders.
       *
       * @param path The path to the desired resource
       *
       * @exception MalformedURLException if the pathname is not given
       *  in the correct form
       */
      public URL getResource(String path) throws MalformedURLException {
  
  	if ((path == null) || (!path.startsWith("/")))
  	    throw new MalformedURLException
  		(sm.getString("standardResources.malformedPath"));
  	return (new URL(docRoot + path));
  
      }
  
  
      /**
       * Return the resource located at the named path as an
       * <code>InputStream</code> object.
       * <p>
       * The data in the <code>InputStream</code> can be of any type or length.
       * The path must be specified according to the rules given in
       * <code>getResource()</code>.  This method returns <code>null</code>
       * if no resource exists at the specified path.
       * <p>
       * Meta-information such as content length and content type that is
       * available via the <code>getResource()</code> method is lost when
       * using this method.
       * <p>
       * The servlet container must implement the URL handlers and
       * <code>URLConnection</code> objects that are necessary to access
       * the resource.
       * <p>
       * This method is different from
       * <code>java.lang.Class.getResourceAsStream()</code>, which uses a
       * class loader.  This method allows servlet containers to make a
       * resource available to a servlet from any location, without using
       * a class loader.
       *
       * @param path The path to the desired resource
       */
      public InputStream getResourceAsStream(String path) {
  
  	try {
  	    URL url = getResource(path);
  	    return (url.openStream());
  	} catch (MalformedURLException e) {
  	    return (null);
  	} catch (IOException e) {
  	    return (null);
  	}
  
      }
  
  
      // ------------------------------------------------------ Lifecycle Methods
  
  
      /**
       * Configure this component, based on the specified configuration
       * parameters.  This method should be called immediately after the
       * component instance is created, and before <code>start()</code>
       * is called.
       *
       * @param parameters Configuration parameters for this component
       *  (<B>FIXME: What object type should this really be?)
       *
       * @exception IllegalStateException if this component has already been
       *  configured and/or started
       * @exception LifecycleException if this component detects a fatal error
       *  in the configuration parameters it was given
       */
      public void configure(Node parameters)
  	throws LifecycleException {
  
  	// Validate and update our current component state
  	if (configured)
  	    throw new LifecycleException
  		(sm.getString("standardResources.alreadyConfigured"));
  	configured = true;
  	if (parameters == null)
  	    return;
  
  	// Parse and process our configuration parameters
  	if (!("Resources".equals(parameters.getNodeName())))
  	    return;
  	NamedNodeMap attributes = parameters.getAttributes();
  	Node node = null;
  	String value = null;
  
  	node = attributes.getNamedItem("docRoot");
  	if (node != null) {
  	    value = node.getNodeValue();
  	    if (value != null)
  		setDocRoot(value);
  	}
  
      }
  
  
      /**
       * Prepare for the beginning of active use of the public methods of this
       * component.  This method should be called after <code>configure()</code>,
       * and before any of the public methods of the component are utilized.
       *
       * @exception IllegalStateException if this component has not yet been
       *  configured (if required for this component)
       * @exception IllegalStateException if this component has already been
       *  started
       * @exception LifecycleException if this component detects a fatal error
       *  that prevents this component from being used
       */
      public void start() throws LifecycleException {
  
  	// Validate and update our current component state
  	if (!configured)
  	    throw new LifecycleException
  		(sm.getString("standardResources.notConfigured"));
  	if (started)
  	    throw new LifecycleException
  		(sm.getString("standardResources.alreadyStarted"));
  	started = true;
  
      }
  
  
      /**
       * Gracefully terminate the active use of the public methods of this
       * component.  This method should be the last one called on a given
       * instance of this component.
       *
       * @exception IllegalStateException if this component has not been started
       * @exception IllegalStateException if this component has already
       *  been stopped
       * @exception LifecycleException if this component detects a fatal error
       *  that needs to be reported
       */
      public void stop() throws LifecycleException {
  
  	// Validate and update our current state
  	if (!started)
  	    throw new LifecycleException
  		(sm.getString("standardResources.notStarted"));
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ValveBase.java
  
  Index: ValveBase.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ValveBase.java,v 1.1 2000/01/20 06:35:26 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:35:26 $
   *
   * ====================================================================
   *
   * 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.tomcat;
  
  
  import java.io.IOException;
  import javax.servlet.ServletException;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Request;
  import org.apache.tomcat.Response;
  import org.apache.tomcat.Valve;
  
  
  /**
   * Convenience base class for implementations of the <b>Valve</b> interface.
   * A subclass <strong>MUST</strong> implement an <code>invoke()</code>
   * method to provide the required functionality, and <strong>MAY</strong>
   * implement the <code>Lifecycle</code> interface to provide configuration
   * management and lifecycle support.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:35:26 $
   */
  
  public abstract class ValveBase
      implements Valve {
  
  
      //------------------------------------------------------ Instance Variables
  
  
      /**
       * The Container whose pipeline this Valve is a component of.
       */
      protected Container container = null;
  
  
      /**
       * Descriptive information about this Valve implementation.  This value
       * should be overridden by subclasses.
       */
      protected static String info =
  	"org.apache.tomcat.core.ValveBase/1.0";
  
  
      /**
       * Dummy object used for global synchronization of the double linked
       * lists that make up each pipeline.
       */
      protected static String lock = "";
  
  
      /**
       * The next Valve in the pipeline this Valve is a component of.
       */
      protected ValveBase next = null;
  
  
      /**
       * The previous Valve in the pipeline this Valve is a component of.
       */
      protected ValveBase previous = null;
  
  
      //-------------------------------------------------------------- Properties
  
  
      /**
       * Return the Container to which this Valve is connected, if any.
       */
      public Container getContainer() {
  
  	return (container);
  
      }
  
  
      /**
       * Return descriptive information about this Valve implementation.
       */
      public String getInfo() {
  
  	return (info);
  
      }
  
  
      /**
       * Return the next Valve in this pipeline, or <code>null</code> if this
       * is the last Valve in the pipeline.
       */
      public ValveBase getNext() {
  
  	return (next);
  
      }
  
  
      /**
       * Set the Valve that follows this one in the pipeline it is part of.
       *
       * @param valve The new next valve
       */
      public void setNext(ValveBase valve) {
  
  	this.next = valve;
  
      }
  
  
      /**
       * Return the previous Valve in this pipeline, or <code>null</code> if
       * this is the first Valve in the pipeline.
       */
      public ValveBase getPrevious() {
  
  	return (previous);
  
      }
  
  
      /**
       * Set the Valve that preceeds this one in the pipeline it is part of.
       *
       * @param valve The previous valve
       */
      public void setPrevious(ValveBase valve) {
  
  	this.previous = valve;
  
      }
  
  
      //---------------------------------------------------------- Public Methods
  
  
      /**
       * Insert this Valve after the specified Valve in the pipeline it is a
       * part of.  The specified Valve will become the value returned by
       * the <code>getPrevious()</code> method of this instance.
       *
       * @param valve The Valve to become the predecessor to this Valve
       */
      public void insertAfter(ValveBase valve) {
  
  	synchronized (lock) {
  	    previous = valve;
  	    next = valve.getNext();
  	    valve.setNext(this);
  	}
  
      }
  
  
      /**
       * Insert this Valve before the specified Valve in the pipeline it is a
       * part of.  The specified Valve will become the value returned by
       * the <code>getNext()</code> method of this instance.
       *
       * @param valve The Valve to become the successor to this Valve
       */
      public void insertBefore(ValveBase valve) {
  
  	synchronized (lock) {
  	    next = valve;
  	    previous = valve.getPrevious();
  	    valve.setPrevious(this);
  	}
  
      }
  
  
      /**
       * The implementation-specific logic represented by this Valve.  See the
       * class description for the normal design patterns for this method.
       * <p>
       * This method <strong>MUST</strong> be provided by a subclass.
       *
       * @param request The servlet request to be processed
       * @param response The servlet response to be created
       *
       * @exception IOException if an input/output error occurs
       * @exception ServletException if a servlet error occurs
       */
      public abstract void invoke(Request request, Response response)
  	throws IOException, ServletException;
  
  
      /**
       * Method to pass responsibility for processing this request to the next
       * Valve in the pipeline (if any).  Call this from your
       * <code>invoke()</code> method if you have not completely handled this
       * request, and want to pass it on for the usual processing.
       * <p>
       * This method is not normally overridden.
       *
       * @param request The servlet request to be processed
       * @param response The servlet response to be created
       *
       * @exception IOException if an input/output error occurs
       * @exception ServletException if a servlet error occurs
       */
      public void invokeNext(Request request, Response response)
  	throws IOException, ServletException {
  
  	if (next == null) {
  	    throw new IllegalStateException("No next 'valve' in the pipeline");
  	} else {
  	    next.invoke(request, response);
  	}
  
      }
  
  
      /**
       * Remove this Valve from the pipeline it is a part of.  The links of
       * the current "previous" and "next" Valves will be adjusted to omit
       * this one.
       */
      public void remove() {
  
  	synchronized (lock) {
  	    if (next != null) {
  		next.setPrevious(previous);
  	    }
  	    if (previous != null) {
  		previous.setNext(next);
  	    }
  	}
  
      }
  
  
  }