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:34:50 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core ApplicationContext.java Constants.java ContainerBase.java LocalStrings.properties RootContext.java

craigmcc    00/01/19 22:34:49

  Added:       proposals/catalina/src/share/org/apache/tomcat/core
                        ApplicationContext.java Constants.java
                        ContainerBase.java LocalStrings.properties
                        RootContext.java
  Log:
  Check-in #1 of the core component implementations for the
  "Catalina" proposal.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ApplicationContext.java
  
  Index: ApplicationContext.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ApplicationContext.java,v 1.1 2000/01/20 06:34:49 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:34:49 $
   *
   * ====================================================================
   *
   * 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.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Vector;
  import javax.servlet.RequestDispatcher;
  import javax.servlet.Servlet;
  import javax.servlet.ServletContext;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Host;
  import org.apache.tomcat.Logger;
  import org.apache.tomcat.Resources;
  import org.apache.tomcat.Wrapper;
  import org.apache.tomcat.deployment.ContextParameter;
  import org.apache.tomcat.deployment.WebApplicationDescriptor;
  
  
  /**
   * Standard implementation of <code>ServletContext</code> that represents
   * a web application's execution environment.  An instance of this class is
   * associated with each instance of <code>StandardContext</code>.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:34:49 $
   */
  
  final class ApplicationContext
      implements ServletContext {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new instance of this class, associated with the specified
       * Context instance.
       *
       * @param context The associated Host instance
       */
      public ApplicationContext(StandardContext context) {
  
  	super();
  	this.context = context;
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The context attributes for this context.
       */
      private Hashtable attributes = new Hashtable();
  
  
      /**
       * The Context instance with which we are associated.
       */
      private StandardContext context = null;
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Return the value of the specified context attribute, if any;
       * otherwise return <code>null</code>.
       *
       * @param name Name of the context attribute to return
       */
      public Object getAttribute(String name) {
  
  	return (attributes.get(name));
  
      }
  
  
      /**
       * Return an enumeration of the names of the context attributes
       * associated with this context.
       */
      public Enumeration getAttributeNames() {
  
  	return (attributes.keys());
  
      }
  
  
      /**
       * Return a <code>ServletContext</code> object that corresponds to a
       * specified URI on the server.  This method allows servlets to gain
       * access to the context for various parts of the server, and as needed
       * obtain <code>RequestDispatcher</code> objects or resources from the
       * context.  The given path must be absolute (beginning with a "/"),
       * and is interpreted based on the server's document root.
       * <p>
       * <b>IMPLEMENTATION NOTE</b>:  This implementation is dependent upon
       * our associated Context having a parent that is a StandardHost.  :-(
       *
       * @param uri Absolute URI of a resource on the server
       */
      public ServletContext getContext(String uri) {
  
  	// Identify the parent Host of our Context, if any
  	StandardHost host = null;
  	try {
  	    host = (StandardHost) context.getParent();
  	} catch (Throwable t) {
  	    host = null;
  	}
  	if (host == null)
  	    return (null);
  	if (!host.getRoot())
  	    return (null);
  
  	// Return the appropriate Context for the specified URI
  	if (uri.equals("/"))
  	    return (host.getRootContext());
  	else {
  	    Context child = (Context) host.map(uri);
  	    if (child != null)
  		return (child.getServletContext());
  	    else
  		return (null);
  	}
  
      }
  
  
      /**
       * Return the value of the specified initialization parameter, or
       * <code>null</code> if this parameter does not exist.
       *
       * @param name Name of the initialization parameter to retrieve
       */
      public String getInitParameter(String name) {
  
  	// Acquire the context parameters for this Context.
  	WebApplicationDescriptor descriptor = context.getDescriptor();
  	if (descriptor == null)
  	    return (null);
  	Enumeration params = descriptor.getContextParameters();
  	if (params == null)
  	    return (null);
  
  	// Return the specified parameter value if it is present
  	while (params.hasMoreElements()) {
  	    ContextParameter param = (ContextParameter) params.nextElement();
  	    if (!name.equals(param.getName()))
  		continue;
  	    return (param.getValue());
  	}
  
  	// The specified initialization parameter is not present
  	return (null);
  
      }
  
  
      /**
       * Return the names of the context's initialization parameters, or an
       * empty enumeration if the context has no initialization parameters.
       */
      public Enumeration getInitParameterNames() {
  
  	Vector results = new Vector();
  
  	// Acquire the context parameters for this Context
  	WebApplicationDescriptor descriptor = context.getDescriptor();
  	if (descriptor == null)
  	    return (results.elements());
  
  	// Enumerate the context parameter names for this Context
  	Enumeration params = descriptor.getContextParameters();
  	if (params == null)
  	    return (results.elements());
  	while (params.hasMoreElements()) {
  	    ContextParameter param = (ContextParameter) params.nextElement();
  	    results.addElement(param.getName());
  	}
  
  	return (results.elements());
  
      }
  
  
      /**
       * Return the major version of the Java Servlet API that we implement.
       */
      public int getMajorVersion() {
  
  	return (Constants.MAJOR_VERSION);
  
      }
  
  
      /**
       * Return the minor version of the Java Servlet API that we implement.
       */
      public int getMinorVersion() {
  
  	return (Constants.MINOR_VERSION);
  
      }
  
  
      /**
       * Return the MIME type of the specified file, or <code>null</code> if
       * the MIME type cannot be determined.
       *
       * @param file Filename for which to identify a MIME type
       */
      public String getMimeType(String file) {
  
  	Resources resources = context.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getMimeType(file));
  
      }
  
  
      /**
       * Return a <code>RequestDispatcher</code> object that acts as a
       * wrapper for the named servlet.
       *
       * @param name Name of the servlet for which a dispatcher is requested
       */
      public RequestDispatcher getNamedDispatcher(String name) {
  
  	// Identify the Wrapper for the specified servlet, if any
  	Wrapper wrapper = (Wrapper) context.findChild(name);
  	if (wrapper == null)
  	    return (null);
  
  	// Create and return a corresponding request dispatcher
  	return (null);	// FIXME - getNamedDispatcher()
  
      }
  
  
      /**
       * Return the real path for a given virtual path, if possible; otherwise
       * return <code>null</code>.
       *
       * @param path The path to the desired resource
       */
      public String getRealPath(String path) {
  
  	Resources resources = context.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getRealPath(path));
  
      }
  
  
      /**
       * Return the URL to the resource that is mapped to a specified path.
       * The path must begin with a "/" and is interpreted as relative to the
       * current context root.
       *
       * @param path The path to the desired resource
       *
       * @exception MalformedURLException if the path is not given
       *  in the correct form
       */
      public URL getResource(String path) throws MalformedURLException {
  
  	Resources resources = context.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getResource(path));
  
      }
  
  
      /**
       * Return a <code>RequestDispatcher</code> instance that acts as a
       * wrapper for the resource at the given path.  The path must begin
       * with a "/" and is interpreted as relative to the current context root.
       *
       * @param path The path to the desired resource.
       */
      public RequestDispatcher getRequestDispatcher(String path) {
  
  	// Identify the Wrapper for the servlet to process this request
  	Wrapper wrapper = context.map(path);
  	if (wrapper == null)
  	    return (null);
  
  	// Create and return a corresponding request dispatcher
  	return (null);	// FIXME - getRequestDispatcher()
  
      }
  
  
  
      /**
       * Return the requested resource as an <code>InputStream</code>.  The
       * path must be specified according to the rules described under
       * <code>getResource</code>.  If no such resource can be identified,
       * return <code>null</code>.
       *
       * @param path The path to the desired resource.
       */
      public InputStream getResourceAsStream(String path) {
  
  	Resources resources = context.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getResourceAsStream(path));
  
      }
  
  
      /**
       * Return the name and version of the servlet container.
       */
      public String getServerInfo() {
  
  	return (Constants.SERVER_INFO);
  
      }
  
  
      /**
       * @deprecated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Servlet getServlet(String name) {
  
  	return (null);
  
      }
  
  
      /**
       * @deprecated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Enumeration getServletNames() {
  
  	return ((new Vector()).elements());
  
      }
  
  
      /**
       * @deprectated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Enumeration getServlets() {
  
  	return ((new Vector()).elements());
  
      }
  
  
      /**
       * Writes the specified message to a servlet log file.
       *
       * @param message Message to be written
       */
      public void log(String message) {
  
  	Logger logger = context.getLogger();
  	if (logger != null)
  	    logger.log(message);
  
      }
  
  
      /**
       * Writes the specified exception and message to a servlet log file.
       *
       * @param exception Exception to be reported
       * @param message Message to be written
       *
       * @deprecated As of Java Servlet API 2.1, use
       *  <code>log(String, Throwable)</code> instead
       */
      public void log(Exception exception, String message) {
  
  	Logger logger = context.getLogger();
  	if (logger != null)
  	    logger.log(exception, message);
  
      }
  
  
      /**
       * Writes the specified message and exception to a servlet log file.
       *
       * @param message Message to be written
       * @param throwable Exception to be reported
       */
      public void log(String message, Throwable throwable) {
  
  	Logger logger = context.getLogger();
  	if (logger != null)
  	    logger.log(message, throwable);
  
      }
  
  
      /**
       * Remove the context attribute with the specified name, if any.
       *
       * @param name Name of the context attribute to be removed
       */
      public void removeAttribute(String name) {
  
  	attributes.remove(name);
  
      }
  
  
      /**
       * Bind the specified value with the specified context attribute name,
       * replacing any existing value for that name.
       *
       * @param name Attribute name to be bound
       * @param value New attribute value to be bound
       */
      public void setAttribute(String name, Object value) {
  
  	attributes.put(name, value);
  
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/Constants.java
  
  Index: Constants.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/Constants.java,v 1.1 2000/01/20 06:34:49 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:34:49 $
   *
   * ====================================================================
   *
   * 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;
  
  
  public class Constants {
  
      public static final String Package = "org.apache.tomcat.core";
      public static final int MAJOR_VERSION = 2;
      public static final int MINOR_VERSION = 2;
      public static final String SERVER_INFO = "Apache Tomcat/X.X";
  
      // Default class names for Tomcat core components
      public static class Classes {
  	public static final String ContextClass =
  	    "org.apache.tomcat.core.StandardContext";
  	public static final String EngineClass =
  	    "org.apache.tomcat.core.StandardEngine";
  	public static final String HostClass =
  	    "org.apache.tomcat.core.StandardHost";
  	public static final String LoaderClass = "XXX";
  	public static final String LoggerClass =
  	    "org.apache.tomcat.logger.SystemOutLogger";
  	public static final String ManagerClass =
  	    "org.apache.tomcat.session.StandardManager";
  	public static final String RealmClass = "XXX";
  	public static final String ResourcesClass = "XXX";
  	public static final String WrapperClass =
  	    "org.apache.tomcat.core.StandardWrapper";
      }
  
  
      // Configuration component element names for Tomcat core components
      public static class Components {
  	public static final String ContextElement = "Context";
  	public static final String EngineElement = "Engine";
  	public static final String HostElement = "Host";
  	public static final String InterceptorElement = "Interceptor";
  	public static final String LoaderElement = "Loader";
  	public static final String LoggerElement = "Logger";
  	public static final String ManagerElement = "Manager";
  	public static final String RealmElement = "Realm";
  	public static final String ResourcesElement = "Resources";
  	public static final String WrapperElement = "Wrapper";
      }
  
  
  }
  
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ContainerBase.java
  
  Index: ContainerBase.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/ContainerBase.java,v 1.1 2000/01/20 06:34:49 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:34:49 $
   *
   * ====================================================================
   *
   * 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 java.util.Enumeration;
  import java.util.Hashtable;
  import javax.servlet.ServletException;
  import org.apache.tomcat.Container;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Engine;
  import org.apache.tomcat.Host;
  import org.apache.tomcat.Interceptor;
  import org.apache.tomcat.Lifecycle;
  import org.apache.tomcat.LifecycleException;
  import org.apache.tomcat.Loader;
  import org.apache.tomcat.Logger;
  import org.apache.tomcat.Manager;
  import org.apache.tomcat.Realm;
  import org.apache.tomcat.Request;
  import org.apache.tomcat.Resources;
  import org.apache.tomcat.Response;
  import org.apache.tomcat.util.StringManager;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  
  
  /**
   * Abstract basic implementation of the <b>Container</b> interface,
   * providing common functionality required by nearly every implementation.
   * Classes extending this base class must implement <code>getInfo()</code>
   * and <code>service()</code>.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:34:49 $
   */
  
  public abstract class ContainerBase {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The child Containers belonging to this Container, keyed by name.
       */
      protected Hashtable children = new Hashtable();
  
  
      /**
       * The set of Interceptors that have been added to this Container, in
       * reverse order of their addition.
       */
      protected Interceptor interceptors[] = new Interceptor[0];
  
  
      /**
       * The Loader implementation with which this Container is associated.
       */
      protected Loader loader = null;
  
  
      /**
       * The Logger implementation with which this Container is associated.
       */
      protected Logger logger = null;
  
  
      /**
       * The Manager implementation with which this Container is associated.
       */
      protected Manager manager = null;
  
  
      /**
       * The human-readable name of this Container.
       */
      protected String name = null;
  
  
      /**
       * The parent Container to which this Container is a child.
       */
      protected Container parent = null;
  
  
      /**
       * The Realm with which this Container is associated.
       */
      protected Realm realm = null;
  
  
      /**
       * The Resources object with which this Container is associated.
       */
      protected Resources resources = null;
  
  
      /**
       * The string manager for this package.
       */
      protected StringManager sm =
  	StringManager.getManager(Constants.Package);
  
  
      // ------------------------------------------------------------- Properties
  
  
      /**
       * Return descriptive information about this Container implementation and
       * the corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public abstract String getInfo();
  
  
      /**
       * Return the Loader with which this Container is associated.  If there is
       * no associated Loader, return the Loader associated with our parent
       * Container (if any); otherwise, return <code>null</code>.
       */
      public Loader getLoader() {
  
  	if (loader != null)
  	    return (loader);
  	if (parent != null)
  	    return (parent.getLoader());
  	return (null);
  
      }
  
  
      /**
       * Set the Loader with which this Container is associated.
       *
       * @param loader The newly associated loader
       */
      public void setLoader(Loader loader) {
  
  	this.loader = loader;
  
      }
  
  
      /**
       * Return the Logger with which this Container is associated.  If there is
       * no associated Logger, return the Logger associated with our parent
       * Container (if any); otherwise return <code>null</code>.
       */
      public Logger getLogger() {
  
  	if (logger != null)
  	    return (logger);
  	if (parent != null)
  	    return (parent.getLogger());
  	return (null);
  
      }
  
  
      /**
       * Set the Logger with which this Container is associated.
       *
       * @param logger The newly associated Logger
       */
      public void setLogger(Logger logger) {
  
  	this.logger = logger;
  
      }
  
  
      /**
       * Return the Manager with which this Container is associated.  If there is
       * no associated Manager, return the Manager associated with our parent
       * Container (if any); otherwise return <code>null</code>.
       */
      public Manager getManager() {
  
  	if (manager != null)
  	    return (manager);
  	if (parent != null)
  	    return (parent.getManager());
  	return (null);
  
      }
  
  
      /**
       * Set the Manager with which this Container is associated.
       *
       * @param manager The newly associated Manager
       */
      public void setManager(Manager manager) {
  
  	this.manager = manager;
  
      }
  
  
      /**
       * Return a name string (suitable for use by humans) that describes this
       * Container.  Within the set of child containers belonging to a particular
       * parent, Container names must be unique.
       */
      public String getName() {
  
  	return (name);
  
      }
  
  
      /**
       * Set a name string (suitable for use by humans) that describes this
       * Container.  Within the set of child containers belonging to a particular
       * parent, Container names must be unique.
       *
       * @param name New name of this container
       *
       * @exception IllegalStateException if this Container has already been
       *  added to the children of a parent Container (after which the name
       *  may not be changed)
       */
      public void setName(String name) {
  
  	this.name = name;
  
      }
  
  
      /**
       * Return the Container for which this Container is a child, if there is
       * one.  If there is no defined parent, return <code>null</code>.
       */
      public Container getParent() {
  
  	return (parent);
  
      }
  
  
      /**
       * Set the parent Container to which this Container is being added as a
       * child.  This Container may refuse to become attached to the specified
       * Container by throwing an exception.
       *
       * @param container Container to which this Container is being added
       *  as a child
       *
       * @exception IllegalArgumentException if this Container refuses to become
       *  attached to the specified Container
       */
      public void setParent(Container container) {
  
  	this.parent = parent;
  
      }
  
  
      /**
       * Return the Realm with which this Container is associated.  If there is
       * no associated Realm, return the Realm associated with our parent
       * Container (if any); otherwise return <code>null</code>.
       */
      public Realm getRealm() {
  
  	if (realm != null)
  	    return (realm);
  	if (parent != null)
  	    return (parent.getRealm());
  	return (null);
  
      }
  
  
      /**
       * Set the Realm with which this Container is associated.
       *
       * @param realm The newly associated Realm
       */
      public void setRealm(Realm realm) {
  
  	this.realm = realm;
  
      }
  
  
      /**
       * Return the Resources with which this Container is associated.  If there
       * is no associated Resources object, return the Resources associated with
       * our parent Container (if any); otherwise return <code>null</code>.
       */
      public Resources getResources() {
  
  	if (resources != null)
  	    return (resources);
  	if (parent != null)
  	    return (parent.getResources());
  	return (null);
  
      }
  
  
      /**
       * Set the Resources object with which this Container is associated.
       *
       * @param resources The newly associated Resources
       */
      public void setResources(Resources resources) {
  
  	this.resources = resources;
  
      }
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Add a new child Container to those associated with this Container,
       * if supported.  Prior to adding this Container to the set of children,
       * the child's <code>setParent()</code> method must be called, with this
       * Container as an argument.  This method may thrown an
       * <code>IllegalArgumentException</code> if this Container chooses not
       * to be attached to the specified Container, in which case it is not added
       *
       * @param child New child Container to be added
       *
       * @exception IllegalArgumentException if this exception is thrown by
       *  the <code>setParent()</code> method of the child Container
       * @exception IllegalArgumentException if the new child does not have
       *  a name unique from that of existing children of this Container
       * @exception IllegalStateException if this Container does not support
       *  child Containers
       */
      public void addChild(Container child) {
  
  	synchronized(children) {
  	    if (children.get(child.getName()) != null)
  		throw new IllegalArgumentException("addChild:  Child name '" +
  						   child.getName() +
  						   "' is not unique");
  	    child.setParent((Container) this);	// May throw IAE
  	    children.put(child.getName(), child);
  	}
  
      }
  
  
      /**
       * Add a new Interceptor to those associated with this Container, such
       * that the <code>preService()</code> method of this Interceptor will
       * be the first one called prior to servicing the request, and that the
       * <code>postService()</code> method of this Interceptor will be the
       * last one called after servicing the request.  Conceptually, this
       * Interceptor is pushed onto a stack of Interceptors.
       * <p>
       * Prior to adding this Interceptor to the stack, the Interceptor's
       * <code>setContainer()</code> method must be called, with this Container
       * as the argument.  This method may thrown an
       * <code>IllegalArgumentException</code> if this Interceptor chooses
       * not to be attached to the specified Container, in which case it will
       * not be added to the stack.
       *
       * @param interceptor New Interceptor to be added
       *
       * @exception IllegalArgumentException if this Interceptor refuses to
       *  be attached to this Container
       * @exception IllegalStateException if this Container does not support
       *  Interceptors
       */
      public void addInterceptor(Interceptor interceptor) {
  
  	synchronized (interceptors) {
  	    interceptor.setContainer((Container) this);	// May throw IAE
  	    Interceptor temp[] = new Interceptor[interceptors.length + 1];
  	    temp[0] = interceptor;
  	    for (int i = 1; i < temp.length; i++)
  		temp[i] = interceptors[i - 1];
  	    interceptors = temp;
  	}
  
      }
  
  
      /**
       * Return the child Container, associated with this Container, with
       * the specified name (if any); otherwise, return <code>null</code>
       *
       * @param name Name of the child Container to be retrieved
       */
      public Container findChild(String name) {
  
  	return ((Container) children.get(name));
  
      }
  
  
      /**
       * Return the set of children Containers associated with this Container.
       * If this Container has no children, a zero-length array is returned.
       */
      public Container[] findChildren() {
  
  	synchronized (children) {
  	    int n = children.size();
  	    Container results[] = new Container[n];
  	    Enumeration containers = children.elements();
  	    for (int i = 0; i < n; i++)
  		results[i] = (Container) containers.nextElement();
  	    return (results);
  	}
  
      }
  
  
      /**
       * Return the set of Interceptors associated with this Container, such
       * that the zero-th element contains the Interceptor most recently added
       * with <code>addInterceptor()</code>.  If this Container has no
       * Interceptors, a zero-length array is returned.
       */
      public Interceptor[] findInterceptors() {
  
  	return (interceptors);
  
      }
  
  
      /**
       * Process the specified Request, thereby producing the specified Response,
       * according to the following algorithm:
       * <ul>
       * <li><b>FIXME:  Describe algorithm concisely</b>
       * </ul>
       *
       * @param request Request to be processed
       * @param response Response to be produced
       *
       * @exception IOException if an input/output error occurred while
       *  processing
       * @exception ServletException if a ServletException was thrown
       *  while processing this request
       */
      public void invoke(Request request, Response response)
  	throws IOException, ServletException {
  
  	// Acquire a private copy of the current Interceptor list
  	// IMPLEMENTATION NOTE:  Not required if interceptors can only
  	// be added at startup time!
  	Interceptor list[] = null;
  	synchronized (interceptors) {
  	    list = new Interceptor[interceptors.length];
  	    for (int i = 0; i < interceptors.length; i++)
  		list[i] = interceptors[i];
  	}
  
  	// Call the preService() methods of all defined Interceptors
  	int last = -1;
  	for (int i = 0; i < list.length; i++) {
  	    last = i;
  	    if (!list[i].preService(request, response))
  		break;
  	}
  
  	// Call the service() method of this Container
  	service(request, response);
  
  	// Call the postService() methods of all defined Interceptors
  	for (int i = list.length - 1; i >= 0; i--) {
  	    if (i > last)
  		continue;
  	    list[i].postService(request, response);
  	}
  
  
      }
  
  
      /**
       * Perform the Container-specific processing supported by this particular
       * Container, independent of any Interceptors that have been added.  This
       * is a convenience method for use in developing implementations -- most
       * external users of this Container should call <code>invoke()</code>.
       *
       * @param request Request to be processed
       * @param response Response to be produced
       */
      public abstract void service(Request request, Response response)
          throws IOException, ServletException;
  
  
      // ------------------------------------------------------ Protected Methods
  
  
      /**
       * Instantiate a new object of the specified class.
       *
       * @param className Class name of the class to use for instantiation
       *
       * @exception LifecycleException if any exception is thrown
       */
      protected Object subcomponent(String className) throws LifecycleException {
  
  	try {
  	    Class classClass = Class.forName(className);
  	    return (classClass.newInstance());
  	} catch (Throwable t) {
  	    throw new LifecycleException
  		("subcomponent[" + className + "]: " + t);
  	}
  
      }
  
  
      /**
       * Configure subcomponents of the types recognized by this container.
       * This method should only be called in the context of a
       * <code>configure()</code> method for this component itself.
       *
       * @param parameters Configuration parameters for this component
       *
       * @exception LifecycleException if a subcomponent detects a fatal error
       *  in the configuration parameters it was given
       */
      protected void subconfigure(Node parameters)
          throws LifecycleException {
  
  	// Process the child nodes of our configuration node
  	NodeList children = parameters.getChildNodes();
  	for (int i = 0; i < children.getLength(); i++) {
  	    Node child = children.item(i);
  	    NamedNodeMap attrs = child.getAttributes();
  	    String className = null;
  	    Node classNode = attrs.getNamedItem("className");
  	    if (classNode != null)
  		className = classNode.getNodeValue();
  	    String elementName = null;
  	    Node elementNode = attrs.getNamedItem("name");
  	    if (elementNode != null)
  		elementName = elementNode.getNodeValue();
  	    String nodeName = child.getNodeName();
  	    Object component = null;
  	    if (nodeName.equals(Constants.Components.ContextElement)) {
  		if (className == null)
  		    className = Constants.Classes.ContextClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		((Context) component).setName(elementName);
  		addChild((Context) component);
  	    } else if (nodeName.equals(Constants.Components.EngineElement)) {
  		if (className == null)
  		    className = Constants.Classes.EngineClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		((Engine) component).setName(elementName);
  		addChild((Engine) component);
  	    } else if (nodeName.equals(Constants.Components.HostElement)) {
  		if (className == null)
  		    className = Constants.Classes.HostClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		((Host) component).setName(elementName);
  		addChild((Host) component);
  	    } else if (nodeName.equals
  		       (Constants.Components.InterceptorElement)) {
  		if (className != null) {	// Class name is required
  		    component = subcomponent(className);
  		    if (component instanceof Lifecycle)
  			((Lifecycle) component).configure(child);
  		    addInterceptor((Interceptor) component);
  		}
  	    } else if (nodeName.equals(Constants.Components.LoaderElement)) {
  		if (className == null)
  		    className = Constants.Classes.LoaderClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		setLoader((Loader) component);
  	    } else if (nodeName.equals(Constants.Components.LoggerElement)) {
  		if (className == null)
  		    className = Constants.Classes.LoggerClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		setLogger((Logger) component);
  	    } else if (nodeName.equals(Constants.Components.ManagerElement)) {
  		if (className == null)
  		    className = Constants.Classes.ManagerClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		setManager((Manager) component);
  	    } else if (nodeName.equals(Constants.Components.RealmElement)) {
  		if (className == null)
  		    className = Constants.Classes.RealmClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		setRealm((Realm) component);
  	    } else if (nodeName.equals
  		       (Constants.Components.ResourcesElement)) {
  		if (className == null)
  		    className = Constants.Classes.ResourcesClass;
  		component = subcomponent(className);
  		if (component instanceof Lifecycle)
  		    ((Lifecycle) component).configure(child);
  		setResources((Resources) component);
  	    }
  	}
  
      }
  
  
      /**
       * Start subcomponents of the types recognized by this container.
       * This method should only be called in the context of a
       * <code>start()</code> method for this component itself.
       *
       * @exception LifecycleException if a subcomponent start() method
       *  throws this exception
       */
      protected void substart() throws LifecycleException {
  
  	// Start our subordinate components
  	if ((loader != null) && (loader instanceof Lifecycle))
  	    ((Lifecycle) loader).start();
  	if ((logger != null) && (logger instanceof Lifecycle))
  	    ((Lifecycle) logger).start();
  	if ((manager != null) && (manager instanceof Lifecycle))
  	    ((Lifecycle) manager).start();
  	if ((realm != null) && (realm instanceof Lifecycle))
  	    ((Lifecycle) realm).start();
  	if ((resources != null) && (resources instanceof Lifecycle))
  	    ((Lifecycle) resources).start();
  
  	// Start our interceptor components
  	Interceptor interceptors[] = findInterceptors();
  	for (int i = 0; i < interceptors.length; i++) {
  	    if (interceptors[i] instanceof Lifecycle)
  		((Lifecycle) interceptors[i]).start();
  	}
  
  	// Start our child container components
  	Container children[] = findChildren();
  	for (int i = 0; i < children.length; i++) {
  	    if (children[i] instanceof Lifecycle)
  		((Lifecycle) children[i]).start();
  	}
  
      }
  
  
      /**
       * Stop subcomponents of the types recognized by this container.
       * This method should only be called in the context of a
       * <code>stop()</code> method for this component itself.
       *
       * @exception LifecycleException if a subcomponent stop() method
       *  throws this exception
       */
      protected void substop() throws LifecycleException {
  
  	// Stop our child container components
  	Container children[] = findChildren();
  	for (int i = 0; i < children.length; i++) {
  	    int j = children.length - (1 + i);
  	    if (children[j] instanceof Lifecycle)
  		((Lifecycle) children[j]).start();
  	}
  
  	// Stop our interceptor components
  	Interceptor interceptors[] = findInterceptors();
  	for (int i = 0; i < interceptors.length; i++) {
  	    int j = interceptors.length - (1 + i);
  	    if (interceptors[j] instanceof Lifecycle)
  		((Lifecycle) interceptors[j]).start();
  	}
  
  	// Stop our subordinate components
  	if ((resources != null) && (resources instanceof Lifecycle))
  	    ((Lifecycle) resources).stop();
  	if ((realm != null) && (realm instanceof Lifecycle))
  	    ((Lifecycle) realm).stop();
  	if ((manager != null) && (manager instanceof Lifecycle))
  	    ((Lifecycle) manager).stop();
  	if ((logger != null) && (logger instanceof Lifecycle))
  	    ((Lifecycle) logger).stop();
  	if ((loader != null) && (loader instanceof Lifecycle))
  	    ((Lifecycle) loader).stop();
  
      }
  
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  standardContext.alreadyConfigured=Context has already been configured
  standardContext.alreadyStarted=Context has already been started
  standardContext.notConfigured=Context has not yet been configured
  standardContext.notStarted=Context has not yet been started
  standardContext.notWrapper=Child of a Context must be a Wrapper
  standardEngine.alreadyConfigured=Engine has already been configured
  standardEngine.alreadyStarted=Engine has already been started
  standardEngine.notConfigured=Engine has not yet been configured
  standardEngine.notHost=Child of an Engine must be a Host
  standardEngine.notParent=Engine cannot have a parent Container
  standardEngine.notStarted=Engine has not yet been started
  standardEngine.unfoundHost=Virtual host $0 not found
  standardEngine.unknownHost=No server host specified in this request
  standardHost.alreadyConfigured=Host has already been configured
  standardHost.alreadyStarted=Host has already been started
  standardHost.noContext=No Context configured to process this request
  standardHost.noHost=No Host configured to process this request
  standardHost.notConfigured=Host has not yet been configured
  standardHost.notContext=Child of a Host must be a Context
  standardHost.notStarted=Host has not yet been started
  standardHost.nullName=Host name is required
  standardHost.unfoundContext=Cannot find context for request URI $0
  standardResources.malformedPath=Path must start with '/'
  standardResources.malformedURL=Malformed URL
  
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/RootContext.java
  
  Index: RootContext.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/RootContext.java,v 1.1 2000/01/20 06:34:49 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/01/20 06:34:49 $
   *
   * ====================================================================
   *
   * 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.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Vector;
  import javax.servlet.RequestDispatcher;
  import javax.servlet.Servlet;
  import javax.servlet.ServletContext;
  import org.apache.tomcat.Context;
  import org.apache.tomcat.Host;
  import org.apache.tomcat.Logger;
  import org.apache.tomcat.Resources;
  
  
  /**
   * Specialized implementation of <code>ServletContext</code> that represents
   * the "root" of a virtual host.  An instance of this class will typically
   * be returned by a call to <code>ServletContext.getContext("/")</code>, if
   * allowed by the security configuration of this deployment.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/01/20 06:34:49 $
   */
  
  final class RootContext
      implements ServletContext {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new instance of this class, associated with the specified
       * Host instance.
       *
       * @param host The associated Host instance
       */
      public RootContext(StandardHost host) {
  
  	super();
  	this.host = host;
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The context attributes for this context.
       */
      private Hashtable attributes = new Hashtable();
  
  
      /**
       * The Host instance with which we are associated.
       */
      private StandardHost host = null;
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Return the value of the specified context attribute, if any;
       * otherwise return <code>null</code>.
       *
       * @param name Name of the context attribute to return
       */
      public Object getAttribute(String name) {
  
  	return (attributes.get(name));
  
      }
  
  
      /**
       * Return an enumeration of the names of the context attributes
       * associated with this context.
       */
      public Enumeration getAttributeNames() {
  
  	return (attributes.keys());
  
      }
  
  
      /**
       * Return a <code>ServletContext</code> object that corresponds to a
       * specified URI on the server.  This method allows servlets to gain
       * access to the context for various parts of the server, and as needed
       * obtain <code>RequestDispatcher</code> objects or resources from the
       * context.  The given path must be absolute (beginning with a "/"),
       * and is interpreted based on the server's document root.
       *
       * @param uri Absolute URI of a resource on the server
       */
      public ServletContext getContext(String uri) {
  
  	Context context = host.map(uri);
  	if (context != null)
  	    return (context.getServletContext());
  	else
  	    return (null);
  
      }
  
  
      /**
       * Return the value of the specified initialization parameter, or
       * <code>null</code> if this parameter does not exist.
       *
       * @param name Name of the initialization parameter to retrieve
       */
      public String getInitParameter(String name) {
  
  	return (null);	// Not supported by this servlet context
  
      }
  
  
      /**
       * Return the names of the context's initialization parameters, or an
       * empty enumeration if the context has no initialization parameters.
       */
      public Enumeration getInitParameterNames() {
  
  	return ((new Vector()).elements());
  
      }
  
  
      /**
       * Return the major version of the Java Servlet API that we implement.
       */
      public int getMajorVersion() {
  
  	return (Constants.MAJOR_VERSION);
  
      }
  
  
      /**
       * Return the minor version of the Java Servlet API that we implement.
       */
      public int getMinorVersion() {
  
  	return (Constants.MINOR_VERSION);
  
      }
  
  
      /**
       * Return the MIME type of the specified file, or <code>null</code> if
       * the MIME type cannot be determined.
       *
       * @param file Filename for which to identify a MIME type
       */
      public String getMimeType(String file) {
  
  	Resources resources = host.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getMimeType(file));
  
      }
  
  
      /**
       * Return a <code>RequestDispatcher</code> object that acts as a
       * wrapper for the named servlet.
       *
       * @param name Name of the servlet for which a dispatcher is requested
       */
      public RequestDispatcher getNamedDispatcher(String name) {
  
  	return (null);	// Not supported by this servlet context
  
      }
  
  
      /**
       * Return the real path for a given virtual path, if possible; otherwise
       * return <code>null</code>.
       *
       * @param path The path to the desired resource
       */
      public String getRealPath(String path) {
  
  	Resources resources = host.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getRealPath(path));
  
      }
  
  
      /**
       * Return the URL to the resource that is mapped to a specified path.
       * The path must begin with a "/" and is interpreted as relative to the
       * current context root.
       *
       * @param path The path to the desired resource
       *
       * @exception MalformedURLException if the path is not given
       *  in the correct form
       */
      public URL getResource(String path) throws MalformedURLException {
  
  	Resources resources = host.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getResource(path));
  
      }
  
  
      /**
       * Return a <code>RequestDispatcher</code> instance that acts as a
       * wrapper for the resource at the given path.  The path must begin
       * with a "/" and is interpreted as relative to the current context root.
       *
       * @param path The path to the desired resource.
       */
      public RequestDispatcher getRequestDispatcher(String path) {
  
  	return (null);	// Not supported by this servlet context
  
      }
  
  
  
      /**
       * Return the requested resource as an <code>InputStream</code>.  The
       * path must be specified according to the rules described under
       * <code>getResource</code>.  If no such resource can be identified,
       * return <code>null</code>.
       *
       * @param path The path to the desired resource.
       */
      public InputStream getResourceAsStream(String path) {
  
  	Resources resources = host.getResources();
  	if (resources == null)
  	    return (null);
  	else
  	    return (resources.getResourceAsStream(path));
  
      }
  
  
      /**
       * Return the name and version of the servlet container.
       */
      public String getServerInfo() {
  
  	return (Constants.SERVER_INFO);
  
      }
  
  
      /**
       * @deprecated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Servlet getServlet(String name) {
  
  	return (null);
  
      }
  
  
      /**
       * @deprecated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Enumeration getServletNames() {
  
  	return ((new Vector()).elements());
  
      }
  
  
      /**
       * @deprectated As of Java Servlet API 2.1, with no direct replacement.
       */
      public Enumeration getServlets() {
  
  	return ((new Vector()).elements());
  
      }
  
  
      /**
       * Writes the specified message to a servlet log file.
       *
       * @param message Message to be written
       */
      public void log(String message) {
  
  	Logger logger = host.getLogger();
  	if (logger != null)
  	    logger.log(message);
  
      }
  
  
      /**
       * Writes the specified exception and message to a servlet log file.
       *
       * @param exception Exception to be reported
       * @param message Message to be written
       *
       * @deprecated As of Java Servlet API 2.1, use
       *  <code>log(String, Throwable)</code> instead
       */
      public void log(Exception exception, String message) {
  
  	Logger logger = host.getLogger();
  	if (logger != null)
  	    logger.log(exception, message);
  
      }
  
  
      /**
       * Writes the specified message and exception to a servlet log file.
       *
       * @param message Message to be written
       * @param throwable Exception to be reported
       */
      public void log(String message, Throwable throwable) {
  
  	Logger logger = host.getLogger();
  	if (logger != null)
  	    logger.log(message, throwable);
  
      }
  
  
      /**
       * Remove the context attribute with the specified name, if any.
       *
       * @param name Name of the context attribute to be removed
       */
      public void removeAttribute(String name) {
  
  	attributes.remove(name);
  
      }
  
  
      /**
       * Bind the specified value with the specified context attribute name,
       * replacing any existing value for that name.
       *
       * @param name Attribute name to be bound
       * @param value New attribute value to be bound
       */
      public void setAttribute(String name, Object value) {
  
  	attributes.put(name, value);
  
      }
  
  
  }