diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml	2005-09-26 01:21:13.000000000 -0400
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+  <component name="ModuleRootManager" />
+  <component name="NewModuleRootManager">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/WEB-INF/classes" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/WEB-INF/jsp/applet" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/plugin/applet" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr152/src/ant" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr152/src/share" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr154/examples/WEB-INF/classes" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jsr154/src/share" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+</module>
+
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default	2005-03-26 14:22:24.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default	2005-09-26 01:27:47.000000000 -0400
@@ -42,8 +42,8 @@
 cvsroot=":pserver:anoncvs@cvs.apache.org:/home/cvspublic"
 
 # ----- Default Base Path for Dependent Packages -----
-base.path=/usr/share/java
-#base.path=C:/path/to/the/repository
+base.path=/usr/share/java
+#base.path=C:/tmp/share/java
 #base.path=/usr/local
 
 # ----- Jakarta files base location -----
@@ -59,7 +59,7 @@
 base-struts.loc=http://archive.apache.org/dist/struts
 
 # ----- Sourceforge files base location -----
-base-sf.loc=http://unc.dl.sourceforge.net/sourceforge
+base-sf.loc=http://easynews.dl.sourceforge.net/sourceforge
 
 # --------------------------------------------------
 #                REQUIRED LIBRARIES
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml	2005-09-26 01:21:13.000000000 -0400
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+  <component name="ModuleRootManager" />
+  <component name="NewModuleRootManager">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+</module>
+
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java	2005-03-26 14:22:34.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java	2005-09-26 01:31:04.000000000 -0400
@@ -5008,6 +5008,10 @@
                 destroy();
                 throw e;
             }
+            // It's possible that addChild may have started us
+            if( initialized ) {
+                return;
+            }
         }
         super.init();
         
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt	2005-09-26 01:29:47.000000000 -0400
@@ -0,0 +1,5372 @@
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.catalina.core;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Stack;
+import java.util.TreeMap;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.ContainerListener;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Globals;
+import org.apache.catalina.Host;
+import org.apache.catalina.InstanceListener;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Loader;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.deploy.ApplicationParameter;
+import org.apache.catalina.deploy.ErrorPage;
+import org.apache.catalina.deploy.FilterDef;
+import org.apache.catalina.deploy.FilterMap;
+import org.apache.catalina.deploy.LoginConfig;
+import org.apache.catalina.deploy.MessageDestination;
+import org.apache.catalina.deploy.MessageDestinationRef;
+import org.apache.catalina.deploy.NamingResources;
+import org.apache.catalina.deploy.SecurityCollection;
+import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.catalina.loader.WebappLoader;
+import org.apache.catalina.startup.ContextConfig;
+import org.apache.catalina.startup.TldConfig;
+import org.apache.catalina.util.CharsetMapper;
+import org.apache.catalina.util.ExtensionValidator;
+import org.apache.catalina.util.RequestUtil;
+import org.apache.catalina.util.URLEncoder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.modeler.Registry;
+import org.apache.naming.ContextBindings;
+import org.apache.naming.resources.BaseDirContext;
+import org.apache.naming.resources.DirContextURLStreamHandler;
+import org.apache.naming.resources.FileDirContext;
+import org.apache.naming.resources.ProxyDirContext;
+import org.apache.naming.resources.WARDirContext;
+import org.apache.tomcat.util.compat.JdkCompat;
+
+/**
+ * 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.
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+ * @version $Revision: 1.2 $ $Date: 2006/12/19 02:51:58 $
+ */
+
+public class StandardContext
+    extends ContainerBase
+    implements Context, Serializable, NotificationEmitter
+{
+    private static transient Log log = LogFactory.getLog(StandardContext.class);
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Create a new StandardContext component with the default basic Valve.
+     */
+    public StandardContext() {
+
+        super();
+        pipeline.setBasic(new StandardContextValve());
+        broadcaster = new NotificationBroadcasterSupport();
+
+    }
+
+
+    // ----------------------------------------------------- Class Variables
+
+
+    /**
+     * The descriptive information string for this implementation.
+     */
+    private static final String info =
+        "org.apache.catalina.core.StandardContext/1.0";
+
+
+    /**
+     * JDK compatibility support
+     */
+    private static final JdkCompat jdkCompat = JdkCompat.getJdkCompat();
+
+
+    /**
+     * Array containing the safe characters set.
+     */
+    protected static URLEncoder urlEncoder;
+
+
+    /**
+     * GMT timezone - all HTTP dates are on GMT
+     */
+    static {
+        urlEncoder = new URLEncoder();
+        urlEncoder.addSafeCharacter('~');
+        urlEncoder.addSafeCharacter('-');
+        urlEncoder.addSafeCharacter('_');
+        urlEncoder.addSafeCharacter('.');
+        urlEncoder.addSafeCharacter('*');
+        urlEncoder.addSafeCharacter('/');
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The alternate deployment descriptor name.
+     */
+    private String altDDName = null;
+
+
+    /**
+     * Associated host name.
+     */
+    private String hostName;
+
+
+    /**
+     * The antiJARLocking flag for this Context.
+     */
+    private boolean antiJARLocking = false;
+
+    
+    /**
+     * The antiResourceLocking flag for this Context.
+     */
+    private boolean antiResourceLocking = false;
+
+    
+    /**
+     * The set of application listener class names configured for this
+     * application, in the order they were encountered in the web.xml file.
+     */
+    private String applicationListeners[] = new String[0];
+
+
+    /**
+     * The set of instantiated application event listener objects</code>.
+     */
+    private transient Object applicationEventListenersObjects[] = 
+        new Object[0];
+
+
+    /**
+     * The set of instantiated application lifecycle listener objects</code>.
+     */
+    private transient Object applicationLifecycleListenersObjects[] = 
+        new Object[0];
+
+
+    /**
+     * The set of application parameters defined for this application.
+     */
+    private ApplicationParameter applicationParameters[] =
+        new ApplicationParameter[0];
+
+
+    /**
+     * The application available flag for this Context.
+     */
+    private boolean available = false;
+    
+    /**
+     * The broadcaster that sends j2ee notifications. 
+     */
+    private NotificationBroadcasterSupport broadcaster = null;
+    
+    /**
+     * The Locale to character set mapper for this application.
+     */
+    private transient CharsetMapper charsetMapper = null;
+
+
+    /**
+     * The Java class name of the CharsetMapper class to be created.
+     */
+    private String charsetMapperClass =
+      "org.apache.catalina.util.CharsetMapper";
+
+
+    /**
+     * The path to a file to save this Context information.
+     */
+    private String configFile = null;
+
+
+    /**
+     * The "correctly configured" flag for this Context.
+     */
+    private boolean configured = false;
+
+
+    /**
+     * The security constraints for this web application.
+     */
+    private SecurityConstraint constraints[] = new SecurityConstraint[0];
+
+
+    /**
+     * The ServletContext implementation associated with this Context.
+     */
+    private transient ApplicationContext context = null;
+
+
+    /**
+     * Compiler classpath to use.
+     */
+    private String compilerClasspath = null;
+
+
+    /**
+     * Should we attempt to use cookies for session id communication?
+     */
+    private boolean cookies = true;
+
+
+    /**
+     * Should we allow the <code>ServletContext.getContext()</code> method
+     * to access the context of other web applications in this server?
+     */
+    private boolean crossContext = false;
+
+    
+    /**
+     * Encoded path.
+     */
+    private String encodedPath = null;
+    
+
+    /**
+     * The "follow standard delegation model" flag that will be used to
+     * configure our ClassLoader.
+     */
+    private boolean delegate = false;
+
+
+     /**
+     * The display name of this web application.
+     */
+    private String displayName = null;
+
+
+    /** 
+     * Override the default context xml location.
+     */
+    private String defaultContextXml;
+
+
+    /** 
+     * Override the default web xml location.
+     */
+    private String defaultWebXml;
+
+
+    /**
+     * The distributable flag for this web application.
+     */
+    private boolean distributable = false;
+
+
+    /**
+     * The document root for this web application.
+     */
+    private String docBase = null;
+
+
+    /**
+     * The exception pages for this web application, keyed by fully qualified
+     * class name of the Java exception.
+     */
+    private HashMap exceptionPages = new HashMap();
+
+
+    /**
+     * The set of filter configurations (and associated filter instances) we
+     * have initialized, keyed by filter name.
+     */
+    private HashMap filterConfigs = new HashMap();
+
+
+    /**
+     * The set of filter definitions for this application, keyed by
+     * filter name.
+     */
+    private HashMap filterDefs = new HashMap();
+
+
+    /**
+     * The set of filter mappings for this application, in the order
+     * they were defined in the deployment descriptor.
+     */
+    private FilterMap filterMaps[] = new FilterMap[0];
+
+
+    /**
+     * The set of classnames of InstanceListeners that will be added
+     * to each newly created Wrapper by <code>createWrapper()</code>.
+     */
+    private String instanceListeners[] = new String[0];
+
+
+    /**
+     * The login configuration descriptor for this web application.
+     */
+    private LoginConfig loginConfig = null;
+
+
+    /**
+     * The mapper associated with this context.
+     */
+    private org.apache.tomcat.util.http.mapper.Mapper mapper = 
+        new org.apache.tomcat.util.http.mapper.Mapper();
+
+
+    /**
+     * The naming context listener for this web application.
+     */
+    private transient NamingContextListener namingContextListener = null;
+
+
+    /**
+     * The naming resources for this web application.
+     */
+    private NamingResources namingResources = null;
+
+
+    /**
+     * The message destinations for this web application.
+     */
+    private HashMap messageDestinations = new HashMap();
+
+
+    /**
+     * The MIME mappings for this web application, keyed by extension.
+     */
+    private HashMap mimeMappings = new HashMap();
+
+
+     /**
+      * Special case: error page for status 200.
+      */
+     private ErrorPage okErrorPage = null;
+
+
+    /**
+     * The context initialization parameters for this web application,
+     * keyed by name.
+     */
+    private HashMap parameters = new HashMap();
+
+
+    /**
+     * The request processing pause flag (while reloading occurs)
+     */
+    private boolean paused = false;
+
+
+    /**
+     * The public identifier of the DTD for the web application deployment
+     * descriptor version we are currently parsing.  This is used to support
+     * relaxed validation rules when processing version 2.2 web.xml files.
+     */
+    private String publicId = null;
+
+
+    /**
+     * The reloadable flag for this web application.
+     */
+    private boolean reloadable = false;
+
+
+    /**
+     * Unpack WAR property.
+     */
+    private boolean unpackWAR = true;
+
+
+    /**
+     * The DefaultContext override flag for this web application.
+     */
+    private boolean override = false;
+
+
+    /**
+     * The privileged flag for this web application.
+     */
+    private boolean privileged = false;
+
+
+    /**
+     * Should the next call to <code>addWelcomeFile()</code> cause replacement
+     * of any existing welcome files?  This will be set before processing the
+     * web application's deployment descriptor, so that application specified
+     * choices <strong>replace</strong>, rather than append to, those defined
+     * in the global descriptor.
+     */
+    private boolean replaceWelcomeFiles = false;
+
+
+    /**
+     * The security role mappings for this application, keyed by role
+     * name (as used within the application).
+     */
+    private HashMap roleMappings = new HashMap();
+
+
+    /**
+     * The security roles for this application, keyed by role name.
+     */
+    private String securityRoles[] = new String[0];
+
+
+    /**
+     * The servlet mappings for this web application, keyed by
+     * matching pattern.
+     */
+    private HashMap servletMappings = new HashMap();
+
+
+    /**
+     * The session timeout (in minutes) for this web application.
+     */
+    private int sessionTimeout = 30;
+
+    /**
+     * The notification sequence number.
+     */
+    private long sequenceNumber = 0;
+    
+    /**
+     * The status code error pages for this web application, keyed by
+     * HTTP status code (as an Integer).
+     */
+    private HashMap statusPages = new HashMap();
+
+
+    /**
+     * Set flag to true to cause the system.out and system.err to be redirected
+     * to the logger when executing a servlet.
+     */
+    private boolean swallowOutput = false;
+
+
+    /**
+     * The JSP tag libraries for this web application, keyed by URI
+     */
+    private HashMap taglibs = new HashMap();
+
+
+    /**
+     * The watched resources for this application.
+     */
+    private String watchedResources[] = new String[0];
+
+
+    /**
+     * The welcome files for this application.
+     */
+    private String welcomeFiles[] = new String[0];
+
+
+    /**
+     * The set of classnames of LifecycleListeners that will be added
+     * to each newly created Wrapper by <code>createWrapper()</code>.
+     */
+    private String wrapperLifecycles[] = new String[0];
+
+
+    /**
+     * The set of classnames of ContainerListeners that will be added
+     * to each newly created Wrapper by <code>createWrapper()</code>.
+     */
+    private String wrapperListeners[] = new String[0];
+
+
+    /**
+     * The pathname to the work directory for this context (relative to
+     * the server's home if not absolute).
+     */
+    private String workDir = null;
+
+
+    /**
+     * Java class name of the Wrapper class implementation we use.
+     */
+    private String wrapperClassName = StandardWrapper.class.getName();
+    private Class wrapperClass = null;
+
+
+    /**
+     * JNDI use flag.
+     */
+    private boolean useNaming = true;
+
+
+    /**
+     * Filesystem based flag.
+     */
+    private boolean filesystemBased = false;
+
+
+    /**
+     * Name of the associated naming context.
+     */
+    private String namingContextName = null;
+
+
+    /**
+     * Caching allowed flag.
+     */
+    private boolean cachingAllowed = true;
+
+
+    /**
+     * Case sensitivity.
+     */
+    protected boolean caseSensitive = true;
+
+
+    /**
+     * Allow linking.
+     */
+    protected boolean allowLinking = false;
+
+
+    /**
+     * Cache max size in KB.
+     */
+    protected int cacheMaxSize = 10240; // 10 MB
+
+
+    /**
+     * Cache TTL in ms.
+     */
+    protected int cacheTTL = 5000;
+
+
+    private boolean lazy=true;
+
+    /**
+     * Non proxied resources.
+     */
+    private transient DirContext webappResources = null;
+
+    private long startupTime;
+    private long startTime;
+    private long tldScanTime;
+
+    /** 
+     * Name of the engine. If null, the domain is used.
+     */ 
+    private String engineName = null;
+    private String j2EEApplication="none";
+    private String j2EEServer="none";
+
+
+    /**
+     * Attribute value used to turn on/off XML validation
+     */
+     private boolean webXmlValidation = false;
+
+
+    /**
+     * Attribute value used to turn on/off XML namespace validation
+     */
+     private boolean webXmlNamespaceAware = false;
+
+    /**
+     * Attribute value used to turn on/off TLD processing
+     */
+    private boolean processTlds = true;
+
+    /**
+     * Attribute value used to turn on/off XML validation
+     */
+     private boolean tldValidation = false;
+
+
+    /**
+     * Attribute value used to turn on/off TLD XML namespace validation
+     */
+     private boolean tldNamespaceAware = false;
+
+
+    /**
+     * Should we save the configuration.
+     */
+    private boolean saveConfig = true;
+
+
+    // ----------------------------------------------------- Context Properties
+
+
+    public String getEncodedPath() {
+        return encodedPath;
+    }
+
+
+    public void setName( String name ) {
+        super.setName( name );
+        encodedPath = urlEncoder.encode(name);
+    }
+
+
+    /**
+     * Is caching allowed ?
+     */
+    public boolean isCachingAllowed() {
+        return cachingAllowed;
+    }
+
+
+    /**
+     * Set caching allowed flag.
+     */
+    public void setCachingAllowed(boolean cachingAllowed) {
+        this.cachingAllowed = cachingAllowed;
+    }
+
+
+    /**
+     * Set case sensitivity.
+     */
+    public void setCaseSensitive(boolean caseSensitive) {
+        this.caseSensitive = caseSensitive;
+    }
+
+
+    /**
+     * Is case sensitive ?
+     */
+    public boolean isCaseSensitive() {
+        return caseSensitive;
+    }
+
+
+    /**
+     * Set allow linking.
+     */
+    public void setAllowLinking(boolean allowLinking) {
+        this.allowLinking = allowLinking;
+    }
+
+
+    /**
+     * Is linking allowed.
+     */
+    public boolean isAllowLinking() {
+        return allowLinking;
+    }
+
+
+    /**
+     * Set cache TTL.
+     */
+    public void setCacheTTL(int cacheTTL) {
+        this.cacheTTL = cacheTTL;
+    }
+
+
+    /**
+     * Get cache TTL.
+     */
+    public int getCacheTTL() {
+        return cacheTTL;
+    }
+
+
+    /**
+     * Return the maximum size of the cache in KB.
+     */
+    public int getCacheMaxSize() {
+        return cacheMaxSize;
+    }
+
+
+    /**
+     * Set the maximum size of the cache in KB.
+     */
+    public void setCacheMaxSize(int cacheMaxSize) {
+        this.cacheMaxSize = cacheMaxSize;
+    }
+
+
+    /**
+     * Return the "follow standard delegation model" flag used to configure
+     * our ClassLoader.
+     */
+    public boolean getDelegate() {
+
+        return (this.delegate);
+
+    }
+
+
+    /**
+     * Set the "follow standard delegation model" flag used to configure
+     * our ClassLoader.
+     *
+     * @param delegate The new flag
+     */
+    public void setDelegate(boolean delegate) {
+
+        boolean oldDelegate = this.delegate;
+        this.delegate = delegate;
+        support.firePropertyChange("delegate", new Boolean(oldDelegate),
+                                   new Boolean(this.delegate));
+
+    }
+
+
+    /**
+     * Returns true if the internal naming support is used.
+     */
+    public boolean isUseNaming() {
+
+        return (useNaming);
+
+    }
+
+
+    /**
+     * Enables or disables naming.
+     */
+    public void setUseNaming(boolean useNaming) {
+        this.useNaming = useNaming;
+    }
+
+
+    /**
+     * Returns true if the resources associated with this context are
+     * filesystem based.
+     */
+    public boolean isFilesystemBased() {
+
+        return (filesystemBased);
+
+    }
+
+
+    /**
+     * Return the set of initialized application event listener objects,
+     * in the order they were specified in the web application deployment
+     * descriptor, for this application.
+     *
+     * @exception IllegalStateException if this method is called before
+     *  this application has started, or after it has been stopped
+     */
+    public Object[] getApplicationEventListeners() {
+        return (applicationEventListenersObjects);
+    }
+
+
+    /**
+     * Store the set of initialized application event listener objects,
+     * in the order they were specified in the web application deployment
+     * descriptor, for this application.
+     *
+     * @param listeners The set of instantiated listener objects.
+     */
+    public void setApplicationEventListeners(Object listeners[]) {
+        applicationEventListenersObjects = listeners;
+    }
+
+
+    /**
+     * Return the set of initialized application lifecycle listener objects,
+     * in the order they were specified in the web application deployment
+     * descriptor, for this application.
+     *
+     * @exception IllegalStateException if this method is called before
+     *  this application has started, or after it has been stopped
+     */
+    public Object[] getApplicationLifecycleListeners() {
+        return (applicationLifecycleListenersObjects);
+    }
+
+
+    /**
+     * Store the set of initialized application lifecycle listener objects,
+     * in the order they were specified in the web application deployment
+     * descriptor, for this application.
+     *
+     * @param listeners The set of instantiated listener objects.
+     */
+    public void setApplicationLifecycleListeners(Object listeners[]) {
+        applicationLifecycleListenersObjects = listeners;
+    }
+
+
+    /**
+     * Return the antiJARLocking flag for this Context.
+     */
+    public boolean getAntiJARLocking() {
+
+        return (this.antiJARLocking);
+
+    }
+
+
+    /**
+     * Return the antiResourceLocking flag for this Context.
+     */
+    public boolean getAntiResourceLocking() {
+
+        return (this.antiResourceLocking);
+
+    }
+
+
+    /**
+     * Set the antiJARLocking feature for this Context.
+     *
+     * @param antiJARLocking The new flag value
+     */
+    public void setAntiJARLocking(boolean antiJARLocking) {
+
+        boolean oldAntiJARLocking = this.antiJARLocking;
+        this.antiJARLocking = antiJARLocking;
+        support.firePropertyChange("antiJARLocking",
+                                   new Boolean(oldAntiJARLocking),
+                                   new Boolean(this.antiJARLocking));
+
+    }
+
+
+    /**
+     * Set the antiResourceLocking feature for this Context.
+     *
+     * @param antiResourceLocking The new flag value
+     */
+    public void setAntiResourceLocking(boolean antiResourceLocking) {
+
+        boolean oldAntiResourceLocking = this.antiResourceLocking;
+        this.antiResourceLocking = antiResourceLocking;
+        support.firePropertyChange("antiResourceLocking",
+                                   new Boolean(oldAntiResourceLocking),
+                                   new Boolean(this.antiResourceLocking));
+
+    }
+
+
+    /**
+     * Return the application available flag for this Context.
+     */
+    public boolean getAvailable() {
+
+        return (this.available);
+
+    }
+
+
+    /**
+     * Set the application available flag for this Context.
+     *
+     * @param available The new application available flag
+     */
+    public void setAvailable(boolean available) {
+
+        boolean oldAvailable = this.available;
+        this.available = available;
+        support.firePropertyChange("available",
+                                   new Boolean(oldAvailable),
+                                   new Boolean(this.available));
+
+    }
+
+
+    /**
+     * Return the Locale to character set mapper for this Context.
+     */
+    public CharsetMapper getCharsetMapper() {
+
+        // Create a mapper the first time it is requested
+        if (this.charsetMapper == null) {
+            try {
+                Class clazz = Class.forName(charsetMapperClass);
+                this.charsetMapper =
+                  (CharsetMapper) clazz.newInstance();
+            } catch (Throwable t) {
+                this.charsetMapper = new CharsetMapper();
+            }
+        }
+
+        return (this.charsetMapper);
+
+    }
+
+
+    /**
+     * Set the Locale to character set mapper for this Context.
+     *
+     * @param mapper The new mapper
+     */
+    public void setCharsetMapper(CharsetMapper mapper) {
+
+        CharsetMapper oldCharsetMapper = this.charsetMapper;
+        this.charsetMapper = mapper;
+        if( mapper != null )
+            this.charsetMapperClass= mapper.getClass().getName();
+        support.firePropertyChange("charsetMapper", oldCharsetMapper,
+                                   this.charsetMapper);
+
+    }
+
+    /**
+     * Return the path to a file to save this Context information.
+     */
+    public String getConfigFile() {
+
+        return (this.configFile);
+
+    }
+
+
+    /**
+     * Set the path to a file to save this Context information.
+     *
+     * @param configFile The path to a file to save this Context information.
+     */
+    public void setConfigFile(String configFile) {
+
+        this.configFile = configFile;
+    }
+
+
+    /**
+     * Return the "correctly configured" flag for this Context.
+     */
+    public boolean getConfigured() {
+
+        return (this.configured);
+
+    }
+
+
+    /**
+     * Set the "correctly configured" flag for this Context.  This can be
+     * set to false by startup listeners that detect a fatal configuration
+     * error to avoid the application from being made available.
+     *
+     * @param configured The new correctly configured flag
+     */
+    public void setConfigured(boolean configured) {
+
+        boolean oldConfigured = this.configured;
+        this.configured = configured;
+        support.firePropertyChange("configured",
+                                   new Boolean(oldConfigured),
+                                   new Boolean(this.configured));
+
+    }
+
+
+    /**
+     * Return the "use cookies for session ids" flag.
+     */
+    public boolean getCookies() {
+
+        return (this.cookies);
+
+    }
+
+
+    /**
+     * Set the "use cookies for session ids" flag.
+     *
+     * @param cookies The new flag
+     */
+    public void setCookies(boolean cookies) {
+
+        boolean oldCookies = this.cookies;
+        this.cookies = cookies;
+        support.firePropertyChange("cookies",
+                                   new Boolean(oldCookies),
+                                   new Boolean(this.cookies));
+
+    }
+
+
+    /**
+     * Return the "allow crossing servlet contexts" flag.
+     */
+    public boolean getCrossContext() {
+
+        return (this.crossContext);
+
+    }
+
+
+    /**
+     * Set the "allow crossing servlet contexts" flag.
+     *
+     * @param crossContext The new cross contexts flag
+     */
+    public void setCrossContext(boolean crossContext) {
+
+        boolean oldCrossContext = this.crossContext;
+        this.crossContext = crossContext;
+        support.firePropertyChange("crossContext",
+                                   new Boolean(oldCrossContext),
+                                   new Boolean(this.crossContext));
+
+    }
+
+    public String getDefaultContextXml() {
+        return defaultContextXml;
+    }
+
+    /** 
+     * Set the location of the default context xml that will be used.
+     * If not absolute, it'll be made relative to the engine's base dir
+     * ( which defaults to catalina.base system property ).
+     *
+     * @param defaultContextXml The default web xml 
+     */
+    public void setDefaultContextXml(String defaultContextXml) {
+        this.defaultContextXml = defaultContextXml;
+    }
+
+    public String getDefaultWebXml() {
+        return defaultWebXml;
+    }
+
+    /** 
+     * Set the location of the default web xml that will be used.
+     * If not absolute, it'll be made relative to the engine's base dir
+     * ( which defaults to catalina.base system property ).
+     *
+     * @param defaultWebXml The default web xml 
+     */
+    public void setDefaultWebXml(String defaultWebXml) {
+        this.defaultWebXml = defaultWebXml;
+    }
+
+    /**
+     * Gets the time (in milliseconds) it took to start this context.
+     *
+     * @return Time (in milliseconds) it took to start this context.
+     */
+    public long getStartupTime() {
+        return startupTime;
+    }
+
+    public void setStartupTime(long startupTime) {
+        this.startupTime = startupTime;
+    }
+
+    public long getTldScanTime() {
+        return tldScanTime;
+    }
+
+    public void setTldScanTime(long tldScanTime) {
+        this.tldScanTime = tldScanTime;
+    }
+
+    /**
+     * Return the display name of this web application.
+     */
+    public String getDisplayName() {
+
+        return (this.displayName);
+
+    }
+
+
+    /**
+     * Return the alternate Deployment Descriptor name.
+     */
+    public String getAltDDName(){
+        return altDDName;
+    }
+
+
+    /**
+     * Set an alternate Deployment Descriptor name.
+     */
+    public void setAltDDName(String altDDName) {
+        this.altDDName = altDDName;
+        if (context != null) {
+            context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
+        }
+    }
+
+
+    /**
+     * Return the compiler classpath.
+     */
+    public String getCompilerClasspath(){
+        return compilerClasspath;
+    }
+
+
+    /**
+     * Set the compiler classpath.
+     */
+    public void setCompilerClasspath(String compilerClasspath) {
+        this.compilerClasspath = compilerClasspath;
+    }
+
+
+    /**
+     * Set the display name of this web application.
+     *
+     * @param displayName The new display name
+     */
+    public void setDisplayName(String displayName) {
+
+        String oldDisplayName = this.displayName;
+        this.displayName = displayName;
+        support.firePropertyChange("displayName", oldDisplayName,
+                                   this.displayName);
+    }
+
+
+    /**
+     * Return the distributable flag for this web application.
+     */
+    public boolean getDistributable() {
+
+        return (this.distributable);
+
+    }
+
+    /**
+     * Set the distributable flag for this web application.
+     *
+     * @param distributable The new distributable flag
+     */
+    public void setDistributable(boolean distributable) {
+        boolean oldDistributable = this.distributable;
+        this.distributable = distributable;
+        support.firePropertyChange("distributable",
+                                   new Boolean(oldDistributable),
+                                   new Boolean(this.distributable));
+
+        // Bugzilla 32866
+        if(getManager() != null) {
+            if(log.isDebugEnabled()) {
+                log.debug("Propagating distributable=" + distributable
+                          + " to manager");
+            }
+            getManager().setDistributable(distributable);
+        }
+    }
+
+
+    /**
+     * Return the document root for this Context.  This can be an absolute
+     * pathname, a relative pathname, or a URL.
+     */
+    public String getDocBase() {
+
+        return (this.docBase);
+
+    }
+
+
+    /**
+     * Set the document root for this Context.  This can be an absolute
+     * pathname, a relative pathname, or a URL.
+     *
+     * @param docBase The new document root
+     */
+    public void setDocBase(String docBase) {
+
+        this.docBase = docBase;
+
+    }
+
+    // experimental
+    public boolean isLazy() {
+        return lazy;
+    }
+
+    public void setLazy(boolean lazy) {
+        this.lazy = lazy;
+    }
+
+
+    /**
+     * 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);
+
+    }
+
+    public String getEngineName() {
+        if( engineName != null ) return engineName;
+        return domain;
+    }
+
+    public void setEngineName(String engineName) {
+        this.engineName = engineName;
+    }
+
+    public String getJ2EEApplication() {
+        return j2EEApplication;
+    }
+
+    public void setJ2EEApplication(String j2EEApplication) {
+        this.j2EEApplication = j2EEApplication;
+    }
+
+    public String getJ2EEServer() {
+        return j2EEServer;
+    }
+
+    public void setJ2EEServer(String j2EEServer) {
+        this.j2EEServer = j2EEServer;
+    }
+
+
+    /**
+     * Set the Loader with which this Context is associated.
+     *
+     * @param loader The newly associated loader
+     */
+    public synchronized void setLoader(Loader loader) {
+
+        super.setLoader(loader);
+
+    }
+
+
+    /**
+     * Return the login configuration descriptor for this web application.
+     */
+    public LoginConfig getLoginConfig() {
+
+        return (this.loginConfig);
+
+    }
+
+
+    /**
+     * Set the login configuration descriptor for this web application.
+     *
+     * @param config The new login configuration
+     */
+    public void setLoginConfig(LoginConfig config) {
+
+        // Validate the incoming property value
+        if (config == null)
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.loginConfig.required"));
+        String loginPage = config.getLoginPage();
+        if ((loginPage != null) && !loginPage.startsWith("/")) {
+            if (isServlet22()) {
+                if(log.isDebugEnabled())
+                    log.debug(sm.getString("standardContext.loginConfig.loginWarning",
+                                 loginPage));
+                config.setLoginPage("/" + loginPage);
+            } else {
+                throw new IllegalArgumentException
+                    (sm.getString("standardContext.loginConfig.loginPage",
+                                  loginPage));
+            }
+        }
+        String errorPage = config.getErrorPage();
+        if ((errorPage != null) && !errorPage.startsWith("/")) {
+            if (isServlet22()) {
+                if(log.isDebugEnabled())
+                    log.debug(sm.getString("standardContext.loginConfig.errorWarning",
+                                 errorPage));
+                config.setErrorPage("/" + errorPage);
+            } else {
+                throw new IllegalArgumentException
+                    (sm.getString("standardContext.loginConfig.errorPage",
+                                  errorPage));
+            }
+        }
+
+        // Process the property setting change
+        LoginConfig oldLoginConfig = this.loginConfig;
+        this.loginConfig = config;
+        support.firePropertyChange("loginConfig",
+                                   oldLoginConfig, this.loginConfig);
+
+    }
+
+
+    /**
+     * Get the mapper associated with the context.
+     */
+    public org.apache.tomcat.util.http.mapper.Mapper getMapper() {
+        return (mapper);
+    }
+
+
+    /**
+     * Return the naming resources associated with this web application.
+     */
+    public NamingResources getNamingResources() {
+
+        if (namingResources == null) {
+            setNamingResources(new NamingResources());
+        }
+        return (namingResources);
+
+    }
+
+
+    /**
+     * Set the naming resources for this web application.
+     *
+     * @param namingResources The new naming resources
+     */
+    public void setNamingResources(NamingResources namingResources) {
+
+        // Process the property setting change
+        NamingResources oldNamingResources = this.namingResources;
+        this.namingResources = namingResources;
+        namingResources.setContainer(this);
+        support.firePropertyChange("namingResources",
+                                   oldNamingResources, this.namingResources);
+
+    }
+
+
+    /**
+     * 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) {
+        // XXX Use host in name
+        setName(RequestUtil.URLDecode(path));
+
+    }
+
+
+    /**
+     * Return the public identifier of the deployment descriptor DTD that is
+     * currently being parsed.
+     */
+    public String getPublicId() {
+
+        return (this.publicId);
+
+    }
+
+
+    /**
+     * Set the public identifier of the deployment descriptor DTD that is
+     * currently being parsed.
+     *
+     * @param publicId The public identifier
+     */
+    public void setPublicId(String publicId) {
+
+        if (log.isDebugEnabled())
+            log.debug("Setting deployment descriptor public ID to '" +
+                publicId + "'");
+
+        String oldPublicId = this.publicId;
+        this.publicId = publicId;
+        support.firePropertyChange("publicId", oldPublicId, publicId);
+
+    }
+
+
+    /**
+     * Return the reloadable flag for this web application.
+     */
+    public boolean getReloadable() {
+
+        return (this.reloadable);
+
+    }
+
+
+    /**
+     * Return the DefaultContext override flag for this web application.
+     */
+    public boolean getOverride() {
+
+        return (this.override);
+
+    }
+
+
+    /**
+     * Return the privileged flag for this web application.
+     */
+    public boolean getPrivileged() {
+
+        return (this.privileged);
+
+    }
+
+
+    /**
+     * Set the privileged flag for this web application.
+     *
+     * @param privileged The new privileged flag
+     */
+    public void setPrivileged(boolean privileged) {
+
+        boolean oldPrivileged = this.privileged;
+        this.privileged = privileged;
+        support.firePropertyChange("privileged",
+                                   new Boolean(oldPrivileged),
+                                   new Boolean(this.privileged));
+
+    }
+
+
+    /**
+     * Set the reloadable flag for this web application.
+     *
+     * @param reloadable The new reloadable flag
+     */
+    public void setReloadable(boolean reloadable) {
+
+        boolean oldReloadable = this.reloadable;
+        this.reloadable = reloadable;
+        support.firePropertyChange("reloadable",
+                                   new Boolean(oldReloadable),
+                                   new Boolean(this.reloadable));
+
+    }
+
+
+    /**
+     * Set the DefaultContext override flag for this web application.
+     *
+     * @param override The new override flag
+     */
+    public void setOverride(boolean override) {
+
+        boolean oldOverride = this.override;
+        this.override = override;
+        support.firePropertyChange("override",
+                                   new Boolean(oldOverride),
+                                   new Boolean(this.override));
+
+    }
+
+
+    /**
+     * Return the "replace welcome files" property.
+     */
+    public boolean isReplaceWelcomeFiles() {
+
+        return (this.replaceWelcomeFiles);
+
+    }
+
+
+    /**
+     * Set the "replace welcome files" property.
+     *
+     * @param replaceWelcomeFiles The new property value
+     */
+    public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
+
+        boolean oldReplaceWelcomeFiles = this.replaceWelcomeFiles;
+        this.replaceWelcomeFiles = replaceWelcomeFiles;
+        support.firePropertyChange("replaceWelcomeFiles",
+                                   new Boolean(oldReplaceWelcomeFiles),
+                                   new Boolean(this.replaceWelcomeFiles));
+
+    }
+
+
+    /**
+     * Return the servlet context for which this Context is a facade.
+     */
+    public ServletContext getServletContext() {
+
+        if (context == null) {
+            context = new ApplicationContext(getBasePath(), this);
+            if (altDDName != null)
+                context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
+        }
+        return (context.getFacade());
+
+    }
+
+
+    /**
+     * Return the default session timeout (in minutes) for this
+     * web application.
+     */
+    public int getSessionTimeout() {
+
+        return (this.sessionTimeout);
+
+    }
+
+
+    /**
+     * Set the default session timeout (in minutes) for this
+     * web application.
+     *
+     * @param timeout The new default session timeout
+     */
+    public void setSessionTimeout(int timeout) {
+
+        int oldSessionTimeout = this.sessionTimeout;
+        /*
+         * SRV.13.4 ("Deployment Descriptor"):
+         * If the timeout is 0 or less, the container ensures the default
+         * behaviour of sessions is never to time out.
+         */
+        this.sessionTimeout = (timeout == 0) ? -1 : timeout;
+        support.firePropertyChange("sessionTimeout",
+                                   new Integer(oldSessionTimeout),
+                                   new Integer(this.sessionTimeout));
+
+    }
+
+
+    /**
+     * Return the value of the swallowOutput flag.
+     */
+    public boolean getSwallowOutput() {
+
+        return (this.swallowOutput);
+
+    }
+
+
+    /**
+     * Set the value of the swallowOutput flag. If set to true, the system.out
+     * and system.err will be redirected to the logger during a servlet
+     * execution.
+     *
+     * @param swallowOutput The new value
+     */
+    public void setSwallowOutput(boolean swallowOutput) {
+
+        boolean oldSwallowOutput = this.swallowOutput;
+        this.swallowOutput = swallowOutput;
+        support.firePropertyChange("swallowOutput",
+                                   new Boolean(oldSwallowOutput),
+                                   new Boolean(this.swallowOutput));
+
+    }
+
+
+    /**
+     * Unpack WAR flag accessor.
+     */
+    public boolean getUnpackWAR() {
+
+        return (unpackWAR);
+
+    }
+
+
+    /**
+     * Unpack WAR flag mutator.
+     */
+    public void setUnpackWAR(boolean unpackWAR) {
+
+        this.unpackWAR = unpackWAR;
+
+    }
+
+    /**
+     * Return the Java class name of the Wrapper implementation used
+     * for servlets registered in this Context.
+     */
+    public String getWrapperClass() {
+
+        return (this.wrapperClassName);
+
+    }
+
+
+    /**
+     * Set the Java class name of the Wrapper implementation used
+     * for servlets registered in this Context.
+     *
+     * @param wrapperClassName The new wrapper class name
+     *
+     * @throws IllegalArgumentException if the specified wrapper class
+     * cannot be found or is not a subclass of StandardWrapper
+     */
+    public void setWrapperClass(String wrapperClassName) {
+
+        this.wrapperClassName = wrapperClassName;
+
+        try {
+            wrapperClass = Class.forName(wrapperClassName);         
+            if (!StandardWrapper.class.isAssignableFrom(wrapperClass)) {
+                throw new IllegalArgumentException(
+                    sm.getString("standardContext.invalidWrapperClass",
+                                 wrapperClassName));
+            }
+        } catch (ClassNotFoundException cnfe) {
+            throw new IllegalArgumentException(cnfe.getMessage());
+        }
+    }
+
+
+    /**
+     * Set the resources DirContext object with which this Container is
+     * associated.
+     *
+     * @param resources The newly associated DirContext
+     */
+    public synchronized void setResources(DirContext resources) {
+
+        if (started) {
+            throw new IllegalStateException
+                (sm.getString("standardContext.resources.started"));
+        }
+
+        DirContext oldResources = this.webappResources;
+        if (oldResources == resources)
+            return;
+
+        if (resources instanceof BaseDirContext) {
+            ((BaseDirContext) resources).setCached(isCachingAllowed());
+            ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
+            ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
+        }
+        if (resources instanceof FileDirContext) {
+            filesystemBased = true;
+            ((FileDirContext) resources).setCaseSensitive(isCaseSensitive());
+            ((FileDirContext) resources).setAllowLinking(isAllowLinking());
+        }
+        this.webappResources = resources;
+
+        // The proxied resources will be refreshed on start
+        this.resources = null;
+
+        support.firePropertyChange("resources", oldResources,
+                                   this.webappResources);
+
+    }
+
+
+    // ------------------------------------------------------ Public Properties
+
+
+    /**
+     * Return the Locale to character set mapper class for this Context.
+     */
+    public String getCharsetMapperClass() {
+
+        return (this.charsetMapperClass);
+
+    }
+
+
+    /**
+     * Set the Locale to character set mapper class for this Context.
+     *
+     * @param mapper The new mapper class
+     */
+    public void setCharsetMapperClass(String mapper) {
+
+        String oldCharsetMapperClass = this.charsetMapperClass;
+        this.charsetMapperClass = mapper;
+        support.firePropertyChange("charsetMapperClass",
+                                   oldCharsetMapperClass,
+                                   this.charsetMapperClass);
+
+    }
+
+
+    /** Get the absolute path to the work dir.
+     *  To avoid duplication.
+     * 
+     * @return The work path
+     */ 
+    public String getWorkPath() {
+        File workDir = new File(getWorkDir());
+        if (!workDir.isAbsolute()) {
+            File catalinaHome = engineBase();
+            String catalinaHomePath = null;
+            try {
+                catalinaHomePath = catalinaHome.getCanonicalPath();
+                workDir = new File(catalinaHomePath,
+                        getWorkDir());
+            } catch (IOException e) {
+                log.warn("Exception obtaining work path for " + getPath());
+            }
+        }
+        return workDir.getAbsolutePath();
+    }
+    
+    /**
+     * Return the work directory for this Context.
+     */
+    public String getWorkDir() {
+
+        return (this.workDir);
+
+    }
+
+
+    /**
+     * Set the work directory for this Context.
+     *
+     * @param workDir The new work directory
+     */
+    public void setWorkDir(String workDir) {
+
+        this.workDir = workDir;
+
+        if (started) {
+            postWorkDirectory();
+        }
+    }
+
+
+    /**
+     * Save config ?
+     */
+    public boolean isSaveConfig() {
+        return saveConfig;
+    }
+
+
+    /**
+     * Set save config flag.
+     */
+    public void setSaveConfig(boolean saveConfig) {
+        this.saveConfig = saveConfig;
+    }
+
+
+    // -------------------------------------------------------- Context Methods
+
+
+    /**
+     * Add a new Listener class name to the set of Listeners
+     * configured for this application.
+     *
+     * @param listener Java class name of a listener class
+     */
+    public void addApplicationListener(String listener) {
+
+        synchronized (applicationListeners) {
+            String results[] =new String[applicationListeners.length + 1];
+            for (int i = 0; i < applicationListeners.length; i++) {
+                if (listener.equals(applicationListeners[i]))
+                    return;
+                results[i] = applicationListeners[i];
+            }
+            results[applicationListeners.length] = listener;
+            applicationListeners = results;
+        }
+        fireContainerEvent("addApplicationListener", listener);
+
+        // FIXME - add instance if already started?
+
+    }
+
+
+    /**
+     * Add a new application parameter for this application.
+     *
+     * @param parameter The new application parameter
+     */
+    public void addApplicationParameter(ApplicationParameter parameter) {
+
+        synchronized (applicationParameters) {
+            String newName = parameter.getName();
+            for (int i = 0; i < applicationParameters.length; i++) {
+                if (newName.equals(applicationParameters[i].getName()) &&
+                    !applicationParameters[i].getOverride())
+                    return;
+            }
+            ApplicationParameter results[] =
+                new ApplicationParameter[applicationParameters.length + 1];
+            System.arraycopy(applicationParameters, 0, results, 0,
+                             applicationParameters.length);
+            results[applicationParameters.length] = parameter;
+            applicationParameters = results;
+        }
+        fireContainerEvent("addApplicationParameter", parameter);
+
+    }
+
+
+    /**
+     * Add a child Container, only if the proposed child is an implementation
+     * of Wrapper.
+     *
+     * @param child Child container to be added
+     *
+     * @exception IllegalArgumentException if the proposed container is
+     *  not an implementation of Wrapper
+     */
+    public void addChild(Container child) {
+
+        // Global JspServlet
+        Wrapper oldJspServlet = null;
+
+        if (!(child instanceof Wrapper)) {
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.notWrapper"));
+        }
+
+        Wrapper wrapper = (Wrapper) child;
+        boolean isJspServlet = "jsp".equals(child.getName());
+
+        // Allow webapp to override JspServlet inherited from global web.xml.
+        if (isJspServlet) {
+            oldJspServlet = (Wrapper) findChild("jsp");
+            if (oldJspServlet != null) {
+                removeChild(oldJspServlet);
+            }
+        }
+
+        String jspFile = wrapper.getJspFile();
+        if ((jspFile != null) && !jspFile.startsWith("/")) {
+            if (isServlet22()) {
+                if(log.isDebugEnabled())
+                    log.debug(sm.getString("standardContext.wrapper.warning", 
+                                       jspFile));
+                wrapper.setJspFile("/" + jspFile);
+            } else {
+                throw new IllegalArgumentException
+                    (sm.getString("standardContext.wrapper.error", jspFile));
+            }
+        }
+
+        super.addChild(child);
+
+        if (isJspServlet && oldJspServlet != null) {
+            /*
+             * The webapp-specific JspServlet inherits all the mappings
+             * specified in the global web.xml, and may add additional ones.
+             */
+            String[] jspMappings = oldJspServlet.findMappings();
+            for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
+                addServletMapping(jspMappings[i], child.getName());
+            }
+        }
+    }
+
+
+    /**
+     * Add a security constraint to the set for this web application.
+     */
+    public void addConstraint(SecurityConstraint constraint) {
+
+        // Validate the proposed constraint
+        SecurityCollection collections[] = constraint.findCollections();
+        for (int i = 0; i < collections.length; i++) {
+            String patterns[] = collections[i].findPatterns();
+            for (int j = 0; j < patterns.length; j++) {
+                patterns[j] = adjustURLPattern(patterns[j]);
+                if (!validateURLPattern(patterns[j]))
+                    throw new IllegalArgumentException
+                        (sm.getString
+                         ("standardContext.securityConstraint.pattern",
+                          patterns[j]));
+            }
+        }
+
+        // Add this constraint to the set for our web application
+        synchronized (constraints) {
+            SecurityConstraint results[] =
+                new SecurityConstraint[constraints.length + 1];
+            for (int i = 0; i < constraints.length; i++)
+                results[i] = constraints[i];
+            results[constraints.length] = constraint;
+            constraints = results;
+        }
+
+    }
+
+
+
+    /**
+     * Add an error page for the specified error or Java exception.
+     *
+     * @param errorPage The error page definition to be added
+     */
+    public void addErrorPage(ErrorPage errorPage) {
+        // Validate the input parameters
+        if (errorPage == null)
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.errorPage.required"));
+        String location = errorPage.getLocation();
+        if ((location != null) && !location.startsWith("/")) {
+            if (isServlet22()) {
+                if(log.isDebugEnabled())
+                    log.debug(sm.getString("standardContext.errorPage.warning",
+                                 location));
+                errorPage.setLocation("/" + location);
+            } else {
+                throw new IllegalArgumentException
+                    (sm.getString("standardContext.errorPage.error",
+                                  location));
+            }
+        }
+
+        // Add the specified error page to our internal collections
+        String exceptionType = errorPage.getExceptionType();
+        if (exceptionType != null) {
+            synchronized (exceptionPages) {
+                exceptionPages.put(exceptionType, errorPage);
+            }
+        } else {
+            synchronized (statusPages) {
+                if (errorPage.getErrorCode() == 200) {
+                    this.okErrorPage = errorPage;
+                }
+                statusPages.put(new Integer(errorPage.getErrorCode()),
+                                errorPage);
+            }
+        }
+        fireContainerEvent("addErrorPage", errorPage);
+
+    }
+
+
+    /**
+     * Add a filter definition to this Context.
+     *
+     * @param filterDef The filter definition to be added
+     */
+    public void addFilterDef(FilterDef filterDef) {
+
+        synchronized (filterDefs) {
+            filterDefs.put(filterDef.getFilterName(), filterDef);
+        }
+        fireContainerEvent("addFilterDef", filterDef);
+
+    }
+
+
+    /**
+     * Add a filter mapping to this Context.
+     *
+     * @param filterMap The filter mapping to be added
+     *
+     * @exception IllegalArgumentException if the specified filter name
+     *  does not match an existing filter definition, or the filter mapping
+     *  is malformed
+     */
+    public void addFilterMap(FilterMap filterMap) {
+
+        // Validate the proposed filter mapping
+        String filterName = filterMap.getFilterName();
+        String servletName = filterMap.getServletName();
+        String urlPattern = filterMap.getURLPattern();
+        if (findFilterDef(filterName) == null)
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.filterMap.name", filterName));
+        if ((servletName == null) && (urlPattern == null))
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.filterMap.either"));
+        if ((servletName != null) && (urlPattern != null))
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.filterMap.either"));
+        // Because filter-pattern is new in 2.3, no need to adjust
+        // for 2.2 backwards compatibility
+        if ((urlPattern != null) && !validateURLPattern(urlPattern))
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.filterMap.pattern",
+                              urlPattern));
+
+        // Add this filter mapping to our registered set
+        synchronized (filterMaps) {
+            FilterMap results[] =new FilterMap[filterMaps.length + 1];
+            System.arraycopy(filterMaps, 0, results, 0, filterMaps.length);
+            results[filterMaps.length] = filterMap;
+            filterMaps = results;
+        }
+        fireContainerEvent("addFilterMap", filterMap);
+
+    }
+
+
+    /**
+     * Add the classname of an InstanceListener to be added to each
+     * Wrapper appended to this Context.
+     *
+     * @param listener Java class name of an InstanceListener class
+     */
+    public void addInstanceListener(String listener) {
+
+        synchronized (instanceListeners) {
+            String results[] =new String[instanceListeners.length + 1];
+            for (int i = 0; i < instanceListeners.length; i++)
+                results[i] = instanceListeners[i];
+            results[instanceListeners.length] = listener;
+            instanceListeners = results;
+        }
+        fireContainerEvent("addInstanceListener", listener);
+
+    }
+
+    /**
+     * Add the given URL pattern as a jsp-property-group.  This maps
+     * resources that match the given pattern so they will be passed
+     * to the JSP container.  Though there are other elements in the
+     * property group, we only care about the URL pattern here.  The
+     * JSP container will parse the rest.
+     *
+     * @param pattern URL pattern to be mapped
+     */
+    public void addJspMapping(String pattern) {
+        String servletName = findServletMapping("*.jsp");
+        if (servletName == null) {
+            servletName = "jsp";
+        }
+
+        if( findChild(servletName) != null) {
+            addServletMapping(pattern, servletName, true);
+        } else {
+            if(log.isDebugEnabled())
+                log.debug("Skiping " + pattern + " , no servlet " + servletName);
+        }
+    }
+
+
+    /**
+     * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
+     *
+     * @param locale locale to map an encoding for
+     * @param encoding encoding to be used for a give locale
+     */
+    public void addLocaleEncodingMappingParameter(String locale, String encoding){
+        getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
+    }
+
+
+    /**
+     * Add a message destination for this web application.
+     *
+     * @param md New message destination
+     */
+    public void addMessageDestination(MessageDestination md) {
+
+        synchronized (messageDestinations) {
+            messageDestinations.put(md.getName(), md);
+        }
+        fireContainerEvent("addMessageDestination", md.getName());
+
+    }
+
+
+    /**
+     * Add a message destination reference for this web application.
+     *
+     * @param mdr New message destination reference
+     */
+    public void addMessageDestinationRef
+        (MessageDestinationRef mdr) {
+
+        namingResources.addMessageDestinationRef(mdr);
+        fireContainerEvent("addMessageDestinationRef", mdr.getName());
+
+    }
+
+
+    /**
+     * Add a new MIME mapping, replacing any existing mapping for
+     * the specified extension.
+     *
+     * @param extension Filename extension being mapped
+     * @param mimeType Corresponding MIME type
+     */
+    public void addMimeMapping(String extension, String mimeType) {
+
+        synchronized (mimeMappings) {
+            mimeMappings.put(extension, mimeType);
+        }
+        fireContainerEvent("addMimeMapping", extension);
+
+    }
+
+
+    /**
+     * Add a new context initialization parameter.
+     *
+     * @param name Name of the new parameter
+     * @param value Value of the new  parameter
+     *
+     * @exception IllegalArgumentException if the name or value is missing,
+     *  or if this context initialization parameter has already been
+     *  registered
+     */
+    public void addParameter(String name, String value) {
+        // Validate the proposed context initialization parameter
+        if ((name == null) || (value == null))
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.parameter.required"));
+        if (parameters.get(name) != null)
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.parameter.duplicate", name));
+
+        // Add this parameter to our defined set
+        synchronized (parameters) {
+            parameters.put(name, value);
+        }
+        fireContainerEvent("addParameter", name);
+
+    }
+
+
+    /**
+     * Add a security role reference for this web application.
+     *
+     * @param role Security role used in the application
+     * @param link Actual security role to check for
+     */
+    public void addRoleMapping(String role, String link) {
+
+        synchronized (roleMappings) {
+            roleMappings.put(role, link);
+        }
+        fireContainerEvent("addRoleMapping", role);
+
+    }
+
+
+    /**
+     * Add a new security role for this web application.
+     *
+     * @param role New security role
+     */
+    public void addSecurityRole(String role) {
+
+        synchronized (securityRoles) {
+            String results[] =new String[securityRoles.length + 1];
+            for (int i = 0; i < securityRoles.length; i++)
+                results[i] = securityRoles[i];
+            results[securityRoles.length] = role;
+            securityRoles = results;
+        }
+        fireContainerEvent("addSecurityRole", role);
+
+    }
+
+
+    /**
+     * Add a new servlet mapping, replacing any existing mapping for
+     * the specified pattern.
+     *
+     * @param pattern URL pattern to be mapped
+     * @param name Name of the corresponding servlet to execute
+     *
+     * @exception IllegalArgumentException if the specified servlet name
+     *  is not known to this Context
+     */
+    public void addServletMapping(String pattern, String name) {
+        addServletMapping(pattern, name, false);
+    }
+
+
+    /**
+     * Add a new servlet mapping, replacing any existing mapping for
+     * the specified pattern.
+     *
+     * @param pattern URL pattern to be mapped
+     * @param name Name of the corresponding servlet to execute
+     * @param jspWildCard true if name identifies the JspServlet
+     * and pattern contains a wildcard; false otherwise
+     *
+     * @exception IllegalArgumentException if the specified servlet name
+     *  is not known to this Context
+     */
+    public void addServletMapping(String pattern, String name,
+                                  boolean jspWildCard) {
+        // Validate the proposed mapping
+        if (findChild(name) == null)
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.servletMap.name", name));
+        pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
+        if (!validateURLPattern(pattern))
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.servletMap.pattern", pattern));
+
+        // Add this mapping to our registered set
+        synchronized (servletMappings) {
+            String name2 = (String) servletMappings.get(pattern);
+            if (name2 != null) {
+                // Don't allow more than one servlet on the same pattern
+                Wrapper wrapper = (Wrapper) findChild(name2);
+                wrapper.removeMapping(pattern);
+                mapper.removeWrapper(pattern);
+            }
+            servletMappings.put(pattern, name);
+        }
+        Wrapper wrapper = (Wrapper) findChild(name);
+        wrapper.addMapping(pattern);
+
+        // Update context mapper
+        mapper.addWrapper(pattern, wrapper, jspWildCard);
+
+        fireContainerEvent("addServletMapping", pattern);
+
+    }
+
+
+    /**
+     * Add a JSP tag library for the specified URI.
+     *
+     * @param uri URI, relative to the web.xml file, of this tag library
+     * @param location Location of the tag library descriptor
+     */
+    public void addTaglib(String uri, String location) {
+
+        synchronized (taglibs) {
+            taglibs.put(uri, location);
+        }
+        fireContainerEvent("addTaglib", uri);
+
+    }
+
+
+    /**
+     * Add a new watched resource to the set recognized by this Context.
+     *
+     * @param name New watched resource file name
+     */
+    public void addWatchedResource(String name) {
+
+        synchronized (watchedResources) {
+            String results[] = new String[watchedResources.length + 1];
+            for (int i = 0; i < watchedResources.length; i++)
+                results[i] = watchedResources[i];
+            results[watchedResources.length] = name;
+            watchedResources = results;
+        }
+        fireContainerEvent("addWatchedResource", name);
+
+    }
+
+
+    /**
+     * Add a new welcome file to the set recognized by this Context.
+     *
+     * @param name New welcome file name
+     */
+    public void addWelcomeFile(String name) {
+
+        synchronized (welcomeFiles) {
+            // Welcome files from the application deployment descriptor
+            // completely replace those from the default conf/web.xml file
+            if (replaceWelcomeFiles) {
+                welcomeFiles = new String[0];
+                setReplaceWelcomeFiles(false);
+            }
+            String results[] =new String[welcomeFiles.length + 1];
+            for (int i = 0; i < welcomeFiles.length; i++)
+                results[i] = welcomeFiles[i];
+            results[welcomeFiles.length] = name;
+            welcomeFiles = results;
+        }
+        postWelcomeFiles();
+        fireContainerEvent("addWelcomeFile", name);
+
+    }
+
+
+    /**
+     * Add the classname of a LifecycleListener to be added to each
+     * Wrapper appended to this Context.
+     *
+     * @param listener Java class name of a LifecycleListener class
+     */
+    public void addWrapperLifecycle(String listener) {
+
+        synchronized (wrapperLifecycles) {
+            String results[] =new String[wrapperLifecycles.length + 1];
+            for (int i = 0; i < wrapperLifecycles.length; i++)
+                results[i] = wrapperLifecycles[i];
+            results[wrapperLifecycles.length] = listener;
+            wrapperLifecycles = results;
+        }
+        fireContainerEvent("addWrapperLifecycle", listener);
+
+    }
+
+
+    /**
+     * Add the classname of a ContainerListener to be added to each
+     * Wrapper appended to this Context.
+     *
+     * @param listener Java class name of a ContainerListener class
+     */
+    public void addWrapperListener(String listener) {
+
+        synchronized (wrapperListeners) {
+            String results[] =new String[wrapperListeners.length + 1];
+            for (int i = 0; i < wrapperListeners.length; i++)
+                results[i] = wrapperListeners[i];
+            results[wrapperListeners.length] = listener;
+            wrapperListeners = results;
+        }
+        fireContainerEvent("addWrapperListener", listener);
+
+    }
+
+
+    /**
+     * Factory method to create and return a new Wrapper instance, of
+     * the Java implementation class appropriate for this Context
+     * implementation.  The constructor of the instantiated Wrapper
+     * will have been called, but no properties will have been set.
+     */
+    public Wrapper createWrapper() {
+
+        Wrapper wrapper = null;
+        if (wrapperClass != null) {
+            try {
+                wrapper = (Wrapper) wrapperClass.newInstance();
+            } catch (Throwable t) {
+                log.error("createWrapper", t);
+                return (null);
+            }
+        } else {
+            wrapper = new StandardWrapper();
+        }
+
+        synchronized (instanceListeners) {
+            for (int i = 0; i < instanceListeners.length; i++) {
+                try {
+                    Class clazz = Class.forName(instanceListeners[i]);
+                    InstanceListener listener =
+                      (InstanceListener) clazz.newInstance();
+                    wrapper.addInstanceListener(listener);
+                } catch (Throwable t) {
+                    log.error("createWrapper", t);
+                    return (null);
+                }
+            }
+        }
+
+        synchronized (wrapperLifecycles) {
+            for (int i = 0; i < wrapperLifecycles.length; i++) {
+                try {
+                    Class clazz = Class.forName(wrapperLifecycles[i]);
+                    LifecycleListener listener =
+                      (LifecycleListener) clazz.newInstance();
+                    if (wrapper instanceof Lifecycle)
+                        ((Lifecycle) wrapper).addLifecycleListener(listener);
+                } catch (Throwable t) {
+                    log.error("createWrapper", t);
+                    return (null);
+                }
+            }
+        }
+
+        synchronized (wrapperListeners) {
+            for (int i = 0; i < wrapperListeners.length; i++) {
+                try {
+                    Class clazz = Class.forName(wrapperListeners[i]);
+                    ContainerListener listener =
+                      (ContainerListener) clazz.newInstance();
+                    wrapper.addContainerListener(listener);
+                } catch (Throwable t) {
+                    log.error("createWrapper", t);
+                    return (null);
+                }
+            }
+        }
+
+        return (wrapper);
+
+    }
+
+
+    /**
+     * Return the set of application listener class names configured
+     * for this application.
+     */
+    public String[] findApplicationListeners() {
+
+        return (applicationListeners);
+
+    }
+
+
+    /**
+     * Return the set of application parameters for this application.
+     */
+    public ApplicationParameter[] findApplicationParameters() {
+
+        return (applicationParameters);
+
+    }
+
+
+    /**
+     * Return the security constraints for this web application.
+     * If there are none, a zero-length array is returned.
+     */
+    public SecurityConstraint[] findConstraints() {
+
+        return (constraints);
+
+    }
+
+
+    /**
+     * Return the error page entry for the specified HTTP error code,
+     * if any; otherwise return <code>null</code>.
+     *
+     * @param errorCode Error code to look up
+     */
+    public ErrorPage findErrorPage(int errorCode) {
+        if (errorCode == 200) {
+            return (okErrorPage);
+        } else {
+            return ((ErrorPage) statusPages.get(new Integer(errorCode)));
+        }
+
+    }
+
+
+    /**
+     * Return the error page entry for the specified Java exception type,
+     * if any; otherwise return <code>null</code>.
+     *
+     * @param exceptionType Exception type to look up
+     */
+    public ErrorPage findErrorPage(String exceptionType) {
+
+        synchronized (exceptionPages) {
+            return ((ErrorPage) exceptionPages.get(exceptionType));
+        }
+
+    }
+
+
+    /**
+     * Return the set of defined error pages for all specified error codes
+     * and exception types.
+     */
+    public ErrorPage[] findErrorPages() {
+
+        synchronized(exceptionPages) {
+            synchronized(statusPages) {
+                ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
+                results1 =
+                    (ErrorPage[]) exceptionPages.values().toArray(results1);
+                ErrorPage results2[] = new ErrorPage[statusPages.size()];
+                results2 =
+                    (ErrorPage[]) statusPages.values().toArray(results2);
+                ErrorPage results[] =
+                    new ErrorPage[results1.length + results2.length];
+                for (int i = 0; i < results1.length; i++)
+                    results[i] = results1[i];
+                for (int i = results1.length; i < results.length; i++)
+                    results[i] = results2[i - results1.length];
+                return (results);
+            }
+        }
+
+    }
+
+
+    /**
+     * Return the filter definition for the specified filter name, if any;
+     * otherwise return <code>null</code>.
+     *
+     * @param filterName Filter name to look up
+     */
+    public FilterDef findFilterDef(String filterName) {
+
+        synchronized (filterDefs) {
+            return ((FilterDef) filterDefs.get(filterName));
+        }
+
+    }
+
+
+    /**
+     * Return the set of defined filters for this Context.
+     */
+    public FilterDef[] findFilterDefs() {
+
+        synchronized (filterDefs) {
+            FilterDef results[] = new FilterDef[filterDefs.size()];
+            return ((FilterDef[]) filterDefs.values().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return the set of filter mappings for this Context.
+     */
+    public FilterMap[] findFilterMaps() {
+
+        return (filterMaps);
+
+    }
+
+
+    /**
+     * Return the set of InstanceListener classes that will be added to
+     * newly created Wrappers automatically.
+     */
+    public String[] findInstanceListeners() {
+
+        return (instanceListeners);
+
+    }
+
+
+    /**
+     * FIXME: Fooling introspection ...
+     */
+    public Context findMappingObject() {
+        return (Context) getMappingObject();
+    }
+    
+    
+    /**
+     * Return the message destination with the specified name, if any;
+     * otherwise, return <code>null</code>.
+     *
+     * @param name Name of the desired message destination
+     */
+    public MessageDestination findMessageDestination(String name) {
+
+        synchronized (messageDestinations) {
+            return ((MessageDestination) messageDestinations.get(name));
+        }
+
+    }
+
+
+    /**
+     * Return the set of defined message destinations for this web
+     * application.  If none have been defined, a zero-length array
+     * is returned.
+     */
+    public MessageDestination[] findMessageDestinations() {
+
+        synchronized (messageDestinations) {
+            MessageDestination results[] =
+                new MessageDestination[messageDestinations.size()];
+            return ((MessageDestination[])
+                    messageDestinations.values().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return the message destination ref with the specified name, if any;
+     * otherwise, return <code>null</code>.
+     *
+     * @param name Name of the desired message destination ref
+     */
+    public MessageDestinationRef
+        findMessageDestinationRef(String name) {
+
+        return namingResources.findMessageDestinationRef(name);
+
+    }
+
+
+    /**
+     * Return the set of defined message destination refs for this web
+     * application.  If none have been defined, a zero-length array
+     * is returned.
+     */
+    public MessageDestinationRef[]
+        findMessageDestinationRefs() {
+
+        return namingResources.findMessageDestinationRefs();
+
+    }
+
+
+    /**
+     * Return the MIME type to which the specified extension is mapped,
+     * if any; otherwise return <code>null</code>.
+     *
+     * @param extension Extension to map to a MIME type
+     */
+    public String findMimeMapping(String extension) {
+
+        return ((String) mimeMappings.get(extension));
+
+    }
+
+
+    /**
+     * Return the extensions for which MIME mappings are defined.  If there
+     * are none, a zero-length array is returned.
+     */
+    public String[] findMimeMappings() {
+
+        synchronized (mimeMappings) {
+            String results[] = new String[mimeMappings.size()];
+            return
+                ((String[]) mimeMappings.keySet().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return the value for the specified context initialization
+     * parameter name, if any; otherwise return <code>null</code>.
+     *
+     * @param name Name of the parameter to return
+     */
+    public String findParameter(String name) {
+
+        synchronized (parameters) {
+            return ((String) parameters.get(name));
+        }
+
+    }
+
+
+    /**
+     * Return the names of all defined context initialization parameters
+     * for this Context.  If no parameters are defined, a zero-length
+     * array is returned.
+     */
+    public String[] findParameters() {
+
+        synchronized (parameters) {
+            String results[] = new String[parameters.size()];
+            return ((String[]) parameters.keySet().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * For the given security role (as used by an application), return the
+     * corresponding role name (as defined by the underlying Realm) if there
+     * is one.  Otherwise, return the specified role unchanged.
+     *
+     * @param role Security role to map
+     */
+    public String findRoleMapping(String role) {
+
+        String realRole = null;
+        synchronized (roleMappings) {
+            realRole = (String) roleMappings.get(role);
+        }
+        if (realRole != null)
+            return (realRole);
+        else
+            return (role);
+
+    }
+
+
+    /**
+     * Return <code>true</code> if the specified security role is defined
+     * for this application; otherwise return <code>false</code>.
+     *
+     * @param role Security role to verify
+     */
+    public boolean findSecurityRole(String role) {
+
+        synchronized (securityRoles) {
+            for (int i = 0; i < securityRoles.length; i++) {
+                if (role.equals(securityRoles[i]))
+                    return (true);
+            }
+        }
+        return (false);
+
+    }
+
+
+    /**
+     * Return the security roles defined for this application.  If none
+     * have been defined, a zero-length array is returned.
+     */
+    public String[] findSecurityRoles() {
+
+        return (securityRoles);
+
+    }
+
+
+    /**
+     * Return the servlet name mapped by the specified pattern (if any);
+     * otherwise return <code>null</code>.
+     *
+     * @param pattern Pattern for which a mapping is requested
+     */
+    public String findServletMapping(String pattern) {
+
+        synchronized (servletMappings) {
+            return ((String) servletMappings.get(pattern));
+        }
+
+    }
+
+
+    /**
+     * Return the patterns of all defined servlet mappings for this
+     * Context.  If no mappings are defined, a zero-length array is returned.
+     */
+    public String[] findServletMappings() {
+
+        synchronized (servletMappings) {
+            String results[] = new String[servletMappings.size()];
+            return
+               ((String[]) servletMappings.keySet().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return the context-relative URI of the error page for the specified
+     * HTTP status code, if any; otherwise return <code>null</code>.
+     *
+     * @param status HTTP status code to look up
+     */
+    public String findStatusPage(int status) {
+
+        return ((String) statusPages.get(new Integer(status)));
+
+    }
+
+
+    /**
+     * Return the set of HTTP status codes for which error pages have
+     * been specified.  If none are specified, a zero-length array
+     * is returned.
+     */
+    public int[] findStatusPages() {
+
+        synchronized (statusPages) {
+            int results[] = new int[statusPages.size()];
+            Iterator elements = statusPages.keySet().iterator();
+            int i = 0;
+            while (elements.hasNext())
+                results[i++] = ((Integer) elements.next()).intValue();
+            return (results);
+        }
+
+    }
+
+
+    /**
+     * Return the tag library descriptor location for the specified taglib
+     * URI, if any; otherwise, return <code>null</code>.
+     *
+     * @param uri URI, relative to the web.xml file
+     */
+    public String findTaglib(String uri) {
+
+        synchronized (taglibs) {
+            return ((String) taglibs.get(uri));
+        }
+
+    }
+
+
+    /**
+     * Return the URIs of all tag libraries for which a tag library
+     * descriptor location has been specified.  If none are specified,
+     * a zero-length array is returned.
+     */
+    public String[] findTaglibs() {
+
+        synchronized (taglibs) {
+            String results[] = new String[taglibs.size()];
+            return ((String[]) taglibs.keySet().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return <code>true</code> if the specified welcome file is defined
+     * for this Context; otherwise return <code>false</code>.
+     *
+     * @param name Welcome file to verify
+     */
+    public boolean findWelcomeFile(String name) {
+
+        synchronized (welcomeFiles) {
+            for (int i = 0; i < welcomeFiles.length; i++) {
+                if (name.equals(welcomeFiles[i]))
+                    return (true);
+            }
+        }
+        return (false);
+
+    }
+
+
+    /**
+     * Return the set of watched resources for this Context. If none are 
+     * defined, a zero length array will be returned.
+     */
+    public String[] findWatchedResources() {
+        return watchedResources;
+    }
+    
+    
+    /**
+     * Return the set of welcome files defined for this Context.  If none are
+     * defined, a zero-length array is returned.
+     */
+    public String[] findWelcomeFiles() {
+
+        return (welcomeFiles);
+
+    }
+
+
+    /**
+     * Return the set of LifecycleListener classes that will be added to
+     * newly created Wrappers automatically.
+     */
+    public String[] findWrapperLifecycles() {
+
+        return (wrapperLifecycles);
+
+    }
+
+
+    /**
+     * Return the set of ContainerListener classes that will be added to
+     * newly created Wrappers automatically.
+     */
+    public String[] findWrapperListeners() {
+
+        return (wrapperListeners);
+
+    }
+
+
+    /**
+     * Reload this web application, if reloading is supported.
+     * <p>
+     * <b>IMPLEMENTATION NOTE</b>:  This method is designed to deal with
+     * reloads required by changes to classes in the underlying repositories
+     * of our class loader.  It does not handle changes to the web application
+     * deployment descriptor.  If that has occurred, you should stop this
+     * Context and create (and start) a new Context instance instead.
+     *
+     * @exception IllegalStateException if the <code>reloadable</code>
+     *  property is set to <code>false</code>.
+     */
+    public synchronized void reload() {
+
+        // Validate our current component state
+        if (!started)
+            throw new IllegalStateException
+                (sm.getString("containerBase.notStarted", logName()));
+
+        // Make sure reloading is enabled
+        //      if (!reloadable)
+        //          throw new IllegalStateException
+        //              (sm.getString("standardContext.notReloadable"));
+        if(log.isInfoEnabled())
+            log.info(sm.getString("standardContext.reloadingStarted"));
+
+        // Stop accepting requests temporarily
+        setPaused(true);
+
+        try {
+            stop();
+        } catch (LifecycleException e) {
+            log.error(sm.getString("standardContext.stoppingContext"), e);
+        }
+
+        try {
+            start();
+        } catch (LifecycleException e) {
+            log.error(sm.getString("standardContext.startingContext"), e);
+        }
+
+        setPaused(false);
+
+    }
+
+
+    /**
+     * Remove the specified application listener class from the set of
+     * listeners for this application.
+     *
+     * @param listener Java class name of the listener to be removed
+     */
+    public void removeApplicationListener(String listener) {
+
+        synchronized (applicationListeners) {
+
+            // Make sure this welcome file is currently present
+            int n = -1;
+            for (int i = 0; i < applicationListeners.length; i++) {
+                if (applicationListeners[i].equals(listener)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            String results[] = new String[applicationListeners.length - 1];
+            for (int i = 0; i < applicationListeners.length; i++) {
+                if (i != n)
+                    results[j++] = applicationListeners[i];
+            }
+            applicationListeners = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeApplicationListener", listener);
+
+        // FIXME - behavior if already started?
+
+    }
+
+
+    /**
+     * Remove the application parameter with the specified name from
+     * the set for this application.
+     *
+     * @param name Name of the application parameter to remove
+     */
+    public void removeApplicationParameter(String name) {
+
+        synchronized (applicationParameters) {
+
+            // Make sure this parameter is currently present
+            int n = -1;
+            for (int i = 0; i < applicationParameters.length; i++) {
+                if (name.equals(applicationParameters[i].getName())) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified parameter
+            int j = 0;
+            ApplicationParameter results[] =
+                new ApplicationParameter[applicationParameters.length - 1];
+            for (int i = 0; i < applicationParameters.length; i++) {
+                if (i != n)
+                    results[j++] = applicationParameters[i];
+            }
+            applicationParameters = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeApplicationParameter", name);
+
+    }
+
+
+    /**
+     * Add a child Container, only if the proposed child is an implementation
+     * of Wrapper.
+     *
+     * @param child Child container to be added
+     *
+     * @exception IllegalArgumentException if the proposed container is
+     *  not an implementation of Wrapper
+     */
+    public void removeChild(Container child) {
+
+        if (!(child instanceof Wrapper)) {
+            throw new IllegalArgumentException
+                (sm.getString("standardContext.notWrapper"));
+        }
+
+        super.removeChild(child);
+
+    }
+
+
+    /**
+     * Remove the specified security constraint from this web application.
+     *
+     * @param constraint Constraint to be removed
+     */
+    public void removeConstraint(SecurityConstraint constraint) {
+
+        synchronized (constraints) {
+
+            // Make sure this constraint is currently present
+            int n = -1;
+            for (int i = 0; i < constraints.length; i++) {
+                if (constraints[i].equals(constraint)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            SecurityConstraint results[] =
+                new SecurityConstraint[constraints.length - 1];
+            for (int i = 0; i < constraints.length; i++) {
+                if (i != n)
+                    results[j++] = constraints[i];
+            }
+            constraints = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeConstraint", constraint);
+
+    }
+
+
+    /**
+     * Remove the error page for the specified error code or
+     * Java language exception, if it exists; otherwise, no action is taken.
+     *
+     * @param errorPage The error page definition to be removed
+     */
+    public void removeErrorPage(ErrorPage errorPage) {
+
+        String exceptionType = errorPage.getExceptionType();
+        if (exceptionType != null) {
+            synchronized (exceptionPages) {
+                exceptionPages.remove(exceptionType);
+            }
+        } else {
+            synchronized (statusPages) {
+                if (errorPage.getErrorCode() == 200) {
+                    this.okErrorPage = null;
+                }
+                statusPages.remove(new Integer(errorPage.getErrorCode()));
+            }
+        }
+        fireContainerEvent("removeErrorPage", errorPage);
+
+    }
+
+
+    /**
+     * Remove the specified filter definition from this Context, if it exists;
+     * otherwise, no action is taken.
+     *
+     * @param filterDef Filter definition to be removed
+     */
+    public void removeFilterDef(FilterDef filterDef) {
+
+        synchronized (filterDefs) {
+            filterDefs.remove(filterDef.getFilterName());
+        }
+        fireContainerEvent("removeFilterDef", filterDef);
+
+    }
+
+
+    /**
+     * Remove a filter mapping from this Context.
+     *
+     * @param filterMap The filter mapping to be removed
+     */
+    public void removeFilterMap(FilterMap filterMap) {
+
+        synchronized (filterMaps) {
+
+            // Make sure this filter mapping is currently present
+            int n = -1;
+            for (int i = 0; i < filterMaps.length; i++) {
+                if (filterMaps[i] == filterMap) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified filter mapping
+            FilterMap results[] = new FilterMap[filterMaps.length - 1];
+            System.arraycopy(filterMaps, 0, results, 0, n);
+            System.arraycopy(filterMaps, n + 1, results, n,
+                             (filterMaps.length - 1) - n);
+            filterMaps = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeFilterMap", filterMap);
+
+    }
+
+
+    /**
+     * Remove a class name from the set of InstanceListener classes that
+     * will be added to newly created Wrappers.
+     *
+     * @param listener Class name of an InstanceListener class to be removed
+     */
+    public void removeInstanceListener(String listener) {
+
+        synchronized (instanceListeners) {
+
+            // Make sure this welcome file is currently present
+            int n = -1;
+            for (int i = 0; i < instanceListeners.length; i++) {
+                if (instanceListeners[i].equals(listener)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            String results[] = new String[instanceListeners.length - 1];
+            for (int i = 0; i < instanceListeners.length; i++) {
+                if (i != n)
+                    results[j++] = instanceListeners[i];
+            }
+            instanceListeners = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeInstanceListener", listener);
+
+    }
+
+
+    /**
+     * Remove any message destination with the specified name.
+     *
+     * @param name Name of the message destination to remove
+     */
+    public void removeMessageDestination(String name) {
+
+        synchronized (messageDestinations) {
+            messageDestinations.remove(name);
+        }
+        fireContainerEvent("removeMessageDestination", name);
+
+    }
+
+
+    /**
+     * Remove any message destination ref with the specified name.
+     *
+     * @param name Name of the message destination ref to remove
+     */
+    public void removeMessageDestinationRef(String name) {
+
+        namingResources.removeMessageDestinationRef(name);
+        fireContainerEvent("removeMessageDestinationRef", name);
+
+    }
+
+
+    /**
+     * Remove the MIME mapping for the specified extension, if it exists;
+     * otherwise, no action is taken.
+     *
+     * @param extension Extension to remove the mapping for
+     */
+    public void removeMimeMapping(String extension) {
+
+        synchronized (mimeMappings) {
+            mimeMappings.remove(extension);
+        }
+        fireContainerEvent("removeMimeMapping", extension);
+
+    }
+
+
+    /**
+     * Remove the context initialization parameter with the specified
+     * name, if it exists; otherwise, no action is taken.
+     *
+     * @param name Name of the parameter to remove
+     */
+    public void removeParameter(String name) {
+
+        synchronized (parameters) {
+            parameters.remove(name);
+        }
+        fireContainerEvent("removeParameter", name);
+
+    }
+
+
+    /**
+     * Remove any security role reference for the specified name
+     *
+     * @param role Security role (as used in the application) to remove
+     */
+    public void removeRoleMapping(String role) {
+
+        synchronized (roleMappings) {
+            roleMappings.remove(role);
+        }
+        fireContainerEvent("removeRoleMapping", role);
+
+    }
+
+
+    /**
+     * Remove any security role with the specified name.
+     *
+     * @param role Security role to remove
+     */
+    public void removeSecurityRole(String role) {
+
+        synchronized (securityRoles) {
+
+            // Make sure this security role is currently present
+            int n = -1;
+            for (int i = 0; i < securityRoles.length; i++) {
+                if (role.equals(securityRoles[i])) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified security role
+            int j = 0;
+            String results[] = new String[securityRoles.length - 1];
+            for (int i = 0; i < securityRoles.length; i++) {
+                if (i != n)
+                    results[j++] = securityRoles[i];
+            }
+            securityRoles = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeSecurityRole", role);
+
+    }
+
+
+    /**
+     * Remove any servlet mapping for the specified pattern, if it exists;
+     * otherwise, no action is taken.
+     *
+     * @param pattern URL pattern of the mapping to remove
+     */
+    public void removeServletMapping(String pattern) {
+
+        String name = null;
+        synchronized (servletMappings) {
+            name = (String) servletMappings.remove(pattern);
+        }
+        Wrapper wrapper = (Wrapper) findChild(name);
+        if( wrapper != null ) {
+            wrapper.removeMapping(pattern);
+        }
+        mapper.removeWrapper(pattern);
+        fireContainerEvent("removeServletMapping", pattern);
+
+    }
+
+
+    /**
+     * Remove the tag library location forthe specified tag library URI.
+     *
+     * @param uri URI, relative to the web.xml file
+     */
+    public void removeTaglib(String uri) {
+
+        synchronized (taglibs) {
+            taglibs.remove(uri);
+        }
+        fireContainerEvent("removeTaglib", uri);
+    }
+
+
+    /**
+     * Remove the specified watched resource name from the list associated
+     * with this Context.
+     * 
+     * @param name Name of the watched resource to be removed
+     */
+    public void removeWatchedResource(String name) {
+        
+        synchronized (watchedResources) {
+
+            // Make sure this watched resource is currently present
+            int n = -1;
+            for (int i = 0; i < watchedResources.length; i++) {
+                if (watchedResources[i].equals(name)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified watched resource
+            int j = 0;
+            String results[] = new String[watchedResources.length - 1];
+            for (int i = 0; i < watchedResources.length; i++) {
+                if (i != n)
+                    results[j++] = watchedResources[i];
+            }
+            watchedResources = results;
+
+        }
+
+        fireContainerEvent("removeWatchedResource", name);
+
+    }
+    
+    
+    /**
+     * Remove the specified welcome file name from the list recognized
+     * by this Context.
+     *
+     * @param name Name of the welcome file to be removed
+     */
+    public void removeWelcomeFile(String name) {
+
+        synchronized (welcomeFiles) {
+
+            // Make sure this welcome file is currently present
+            int n = -1;
+            for (int i = 0; i < welcomeFiles.length; i++) {
+                if (welcomeFiles[i].equals(name)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            String results[] = new String[welcomeFiles.length - 1];
+            for (int i = 0; i < welcomeFiles.length; i++) {
+                if (i != n)
+                    results[j++] = welcomeFiles[i];
+            }
+            welcomeFiles = results;
+
+        }
+
+        // Inform interested listeners
+        postWelcomeFiles();
+        fireContainerEvent("removeWelcomeFile", name);
+
+    }
+
+
+    /**
+     * Remove a class name from the set of LifecycleListener classes that
+     * will be added to newly created Wrappers.
+     *
+     * @param listener Class name of a LifecycleListener class to be removed
+     */
+    public void removeWrapperLifecycle(String listener) {
+
+
+        synchronized (wrapperLifecycles) {
+
+            // Make sure this welcome file is currently present
+            int n = -1;
+            for (int i = 0; i < wrapperLifecycles.length; i++) {
+                if (wrapperLifecycles[i].equals(listener)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            String results[] = new String[wrapperLifecycles.length - 1];
+            for (int i = 0; i < wrapperLifecycles.length; i++) {
+                if (i != n)
+                    results[j++] = wrapperLifecycles[i];
+            }
+            wrapperLifecycles = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeWrapperLifecycle", listener);
+
+    }
+
+
+    /**
+     * Remove a class name from the set of ContainerListener classes that
+     * will be added to newly created Wrappers.
+     *
+     * @param listener Class name of a ContainerListener class to be removed
+     */
+    public void removeWrapperListener(String listener) {
+
+
+        synchronized (wrapperListeners) {
+
+            // Make sure this welcome file is currently present
+            int n = -1;
+            for (int i = 0; i < wrapperListeners.length; i++) {
+                if (wrapperListeners[i].equals(listener)) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+
+            // Remove the specified constraint
+            int j = 0;
+            String results[] = new String[wrapperListeners.length - 1];
+            for (int i = 0; i < wrapperListeners.length; i++) {
+                if (i != n)
+                    results[j++] = wrapperListeners[i];
+            }
+            wrapperListeners = results;
+
+        }
+
+        // Inform interested listeners
+        fireContainerEvent("removeWrapperListener", listener);
+
+    }
+
+
+    /**
+     * Gets the cumulative processing times of all servlets in this
+     * StandardContext.
+     *
+     * @return Cumulative processing times of all servlets in this
+     * StandardContext
+     */
+    public long getProcessingTime() {
+        
+        long result = 0;
+
+        Container[] children = findChildren();
+        if (children != null) {
+            for( int i=0; i< children.length; i++ ) {
+                result += ((StandardWrapper)children[i]).getProcessingTime();
+            }
+        }
+
+        return result;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Configure and initialize the set of filters for this Context.
+     * Return <code>true</code> if all filter initialization completed
+     * successfully, or <code>false</code> otherwise.
+     */
+    public boolean filterStart() {
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug("Starting filters");
+        // Instantiate and record a FilterConfig for each defined filter
+        boolean ok = true;
+        synchronized (filterConfigs) {
+            filterConfigs.clear();
+            Iterator names = filterDefs.keySet().iterator();
+            while (names.hasNext()) {
+                String name = (String) names.next();
+                if (getLogger().isDebugEnabled())
+                    getLogger().debug(" Starting filter '" + name + "'");
+                ApplicationFilterConfig filterConfig = null;
+                try {
+                    filterConfig = new ApplicationFilterConfig
+                      (this, (FilterDef) filterDefs.get(name));
+                    filterConfigs.put(name, filterConfig);
+                } catch (Throwable t) {
+                    getLogger().error
+                        (sm.getString("standardContext.filterStart", name), t);
+                    ok = false;
+                }
+            }
+        }
+
+        return (ok);
+
+    }
+
+
+    /**
+     * Finalize and release the set of filters for this Context.
+     * Return <code>true</code> if all filter finalization completed
+     * successfully, or <code>false</code> otherwise.
+     */
+    public boolean filterStop() {
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug("Stopping filters");
+
+        // Release all Filter and FilterConfig instances
+        synchronized (filterConfigs) {
+            Iterator names = filterConfigs.keySet().iterator();
+            while (names.hasNext()) {
+                String name = (String) names.next();
+                if (getLogger().isDebugEnabled())
+                    getLogger().debug(" Stopping filter '" + name + "'");
+                ApplicationFilterConfig filterConfig =
+                  (ApplicationFilterConfig) filterConfigs.get(name);
+                filterConfig.release();
+            }
+            filterConfigs.clear();
+        }
+        return (true);
+
+    }
+
+
+    /**
+     * Find and return the initialized <code>FilterConfig</code> for the
+     * specified filter name, if any; otherwise return <code>null</code>.
+     *
+     * @param name Name of the desired filter
+     */
+    public FilterConfig findFilterConfig(String name) {
+
+        return ((FilterConfig) filterConfigs.get(name));
+
+    }
+
+
+    /**
+     * Configure the set of instantiated application event listeners
+     * for this Context.  Return <code>true</code> if all listeners wre
+     * initialized successfully, or <code>false</code> otherwise.
+     */
+    public boolean listenerStart() {
+
+        if (log.isDebugEnabled())
+            log.debug("Configuring application event listeners");
+
+        // Instantiate the required listeners
+        ClassLoader loader = getLoader().getClassLoader();
+        String listeners[] = findApplicationListeners();
+        Object results[] = new Object[listeners.length];
+        boolean ok = true;
+        for (int i = 0; i < results.length; i++) {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug(" Configuring event listener class '" +
+                    listeners[i] + "'");
+            try {
+                Class clazz = loader.loadClass(listeners[i]);
+                results[i] = clazz.newInstance();
+            } catch (Throwable t) {
+                getLogger().error
+                    (sm.getString("standardContext.applicationListener",
+                                  listeners[i]), t);
+                ok = false;
+            }
+        }
+        if (!ok) {
+            getLogger().error(sm.getString("standardContext.applicationSkipped"));
+            return (false);
+        }
+
+        // Sort listeners in two arrays
+        ArrayList eventListeners = new ArrayList();
+        ArrayList lifecycleListeners = new ArrayList();
+        for (int i = 0; i < results.length; i++) {
+            if ((results[i] instanceof ServletContextAttributeListener)
+                || (results[i] instanceof ServletRequestAttributeListener)
+                || (results[i] instanceof ServletRequestListener)
+                || (results[i] instanceof HttpSessionAttributeListener)) {
+                eventListeners.add(results[i]);
+            }
+            if ((results[i] instanceof ServletContextListener)
+                || (results[i] instanceof HttpSessionListener)) {
+                lifecycleListeners.add(results[i]);
+            }
+        }
+
+        setApplicationEventListeners(eventListeners.toArray());
+        setApplicationLifecycleListeners(lifecycleListeners.toArray());
+
+        // Send application start events
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug("Sending application start events");
+
+        Object instances[] = getApplicationLifecycleListeners();
+        if (instances == null)
+            return (ok);
+        ServletContextEvent event =
+          new ServletContextEvent(getServletContext());
+        for (int i = 0; i < instances.length; i++) {
+            if (instances[i] == null)
+                continue;
+            if (!(instances[i] instanceof ServletContextListener))
+                continue;
+            ServletContextListener listener =
+                (ServletContextListener) instances[i];
+            try {
+                fireContainerEvent("beforeContextInitialized", listener);
+                listener.contextInitialized(event);
+                fireContainerEvent("afterContextInitialized", listener);
+            } catch (Throwable t) {
+                fireContainerEvent("afterContextInitialized", listener);
+                getLogger().error
+                    (sm.getString("standardContext.listenerStart",
+                                  instances[i].getClass().getName()), t);
+                ok = false;
+            }
+        }
+        return (ok);
+
+    }
+
+
+    /**
+     * Send an application stop event to all interested listeners.
+     * Return <code>true</code> if all events were sent successfully,
+     * or <code>false</code> otherwise.
+     */
+    public boolean listenerStop() {
+
+        if (log.isDebugEnabled())
+            log.debug("Sending application stop events");
+
+        boolean ok = true;
+        Object listeners[] = getApplicationLifecycleListeners();
+        if (listeners == null)
+            return (ok);
+        ServletContextEvent event =
+          new ServletContextEvent(getServletContext());
+        for (int i = 0; i < listeners.length; i++) {
+            int j = (listeners.length - 1) - i;
+            if (listeners[j] == null)
+                continue;
+            if (!(listeners[j] instanceof ServletContextListener))
+                continue;
+            ServletContextListener listener =
+                (ServletContextListener) listeners[j];
+            try {
+                fireContainerEvent("beforeContextDestroyed", listener);
+                listener.contextDestroyed(event);
+                fireContainerEvent("afterContextDestroyed", listener);
+            } catch (Throwable t) {
+                fireContainerEvent("afterContextDestroyed", listener);
+                getLogger().error
+                    (sm.getString("standardContext.listenerStop",
+                                  listeners[j].getClass().getName()), t);
+                ok = false;
+            }
+        }
+
+        setApplicationEventListeners(null);
+        setApplicationLifecycleListeners(null);
+
+        return (ok);
+
+    }
+
+
+    /**
+     * Allocate resources, including proxy.
+     * Return <code>true</code> if initialization was successfull,
+     * or <code>false</code> otherwise.
+     */
+    public boolean resourcesStart() {
+
+        boolean ok = true;
+
+        Hashtable env = new Hashtable();
+        if (getParent() != null)
+            env.put(ProxyDirContext.HOST, getParent().getName());
+        env.put(ProxyDirContext.CONTEXT, getName());
+
+        try {
+            ProxyDirContext proxyDirContext =
+                new ProxyDirContext(env, webappResources);
+            if (webappResources instanceof FileDirContext) {
+                filesystemBased = true;
+                ((FileDirContext) webappResources).setCaseSensitive
+                    (isCaseSensitive());
+                ((FileDirContext) webappResources).setAllowLinking
+                    (isAllowLinking());
+            }
+            if (webappResources instanceof BaseDirContext) {
+                ((BaseDirContext) webappResources).setDocBase(getBasePath());
+                ((BaseDirContext) webappResources).setCached
+                    (isCachingAllowed());
+                ((BaseDirContext) webappResources).setCacheTTL(getCacheTTL());
+                ((BaseDirContext) webappResources).setCacheMaxSize
+                    (getCacheMaxSize());
+                ((BaseDirContext) webappResources).allocate();
+            }
+            // Register the cache in JMX
+            if (isCachingAllowed()) {
+                ObjectName resourcesName = 
+                    new ObjectName(this.getDomain() + ":type=Cache,host=" 
+                                   + getHostname() + ",path=" 
+                                   + (("".equals(getPath()))?"/":getPath()));
+                Registry.getRegistry(null, null).registerComponent
+                    (proxyDirContext.getCache(), resourcesName, null);
+            }
+            this.resources = proxyDirContext;
+        } catch (Throwable t) {
+            log.error(sm.getString("standardContext.resourcesStart"), t);
+            ok = false;
+        }
+
+        return (ok);
+
+    }
+
+
+    /**
+     * Deallocate resources and destroy proxy.
+     */
+    public boolean resourcesStop() {
+
+        boolean ok = true;
+
+        try {
+            if (resources != null) {
+                if (resources instanceof Lifecycle) {
+                    ((Lifecycle) resources).stop();
+                }
+                if (webappResources instanceof BaseDirContext) {
+                    ((BaseDirContext) webappResources).release();
+                }
+                // Unregister the cache in JMX
+                if (isCachingAllowed()) {
+                    ObjectName resourcesName = 
+                        new ObjectName(this.getDomain()
+                                       + ":type=Cache,host=" 
+                                       + getHostname() + ",path=" 
+                                       + (("".equals(getPath()))?"/"
+                                          :getPath()));
+                    Registry.getRegistry(null, null)
+                        .unregisterComponent(resourcesName);
+                }
+            }
+        } catch (Throwable t) {
+            log.error(sm.getString("standardContext.resourcesStop"), t);
+            ok = false;
+        }
+
+        this.resources = null;
+
+        return (ok);
+
+    }
+
+
+    /**
+     * Load and initialize all servlets marked "load on startup" in the
+     * web application deployment descriptor.
+     *
+     * @param children Array of wrappers for all currently defined
+     *  servlets (including those not declared load on startup)
+     */
+    public void loadOnStartup(Container children[]) {
+
+        // Collect "load on startup" servlets that need to be initialized
+        TreeMap map = new TreeMap();
+        for (int i = 0; i < children.length; i++) {
+            Wrapper wrapper = (Wrapper) children[i];
+            int loadOnStartup = wrapper.getLoadOnStartup();
+            if (loadOnStartup < 0)
+                continue;
+            if (loadOnStartup == 0)     // Arbitrarily put them last
+                loadOnStartup = Integer.MAX_VALUE;
+            Integer key = new Integer(loadOnStartup);
+            ArrayList list = (ArrayList) map.get(key);
+            if (list == null) {
+                list = new ArrayList();
+                map.put(key, list);
+            }
+            list.add(wrapper);
+        }
+
+        // Load the collected "load on startup" servlets
+        Iterator keys = map.keySet().iterator();
+        while (keys.hasNext()) {
+            Integer key = (Integer) keys.next();
+            ArrayList list = (ArrayList) map.get(key);
+            Iterator wrappers = list.iterator();
+            while (wrappers.hasNext()) {
+                Wrapper wrapper = (Wrapper) wrappers.next();
+                try {
+                    wrapper.load();
+                } catch (ServletException e) {
+                    getLogger().error(sm.getString("standardWrapper.loadException",
+                                      getName()), StandardWrapper.getRootCause(e));
+                    // NOTE: load errors (including a servlet that throws
+                    // UnavailableException from tht init() method) are NOT
+                    // fatal to application startup
+                }
+            }
+        }
+
+    }
+
+
+    /**
+     * Start this Context component.
+     *
+     * @exception LifecycleException if a startup error occurs
+     */
+    public synchronized void start() throws LifecycleException {
+        //if (lazy ) return;
+        if (started) {
+            if(log.isInfoEnabled())
+                log.info(sm.getString("containerBase.alreadyStarted", logName()));
+            return;
+        }
+        if( !initialized ) { 
+            try {
+                init();
+            } catch( Exception ex ) {
+                throw new LifecycleException("Error initializaing ", ex);
+            }
+        }
+        if(log.isDebugEnabled())
+            log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName()));
+
+        // Set JMX object name for proper pipeline registration
+        preRegisterJMX();
+
+        if ((oname != null) && 
+            (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {
+            // As things depend on the JMX registration, the context
+            // must be reregistered again once properly initialized
+            Registry.getRegistry(null, null).unregisterComponent(oname);
+        }
+
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
+
+        setAvailable(false);
+        setConfigured(false);
+        boolean ok = true;
+
+        // Add missing components as necessary
+        if (webappResources == null) {   // (1) Required by Loader
+            if (log.isDebugEnabled())
+                log.debug("Configuring default Resources");
+            try {
+                if ((docBase != null) && (docBase.endsWith(".war")) && (!(new File(getBasePath())).isDirectory()))
+                    setResources(new WARDirContext());
+                else
+                    setResources(new FileDirContext());
+            } catch (IllegalArgumentException e) {
+                log.error("Error initializing resources: " + e.getMessage());
+                ok = false;
+            }
+        }
+        if (ok) {
+            if (!resourcesStart()) {
+                log.error( "Error in resourceStart()");
+                ok = false;
+            }
+        }
+
+        // Look for a realm - that may have been configured earlier. 
+        // If the realm is added after context - it'll set itself.
+        if( realm == null && mserver != null ) {
+            ObjectName realmName=null;
+            try {
+                realmName=new ObjectName( getEngineName() + ":type=Realm,host=" + 
+                        getHostname() + ",path=" + getPath());
+                if( mserver.isRegistered(realmName ) ) {
+                    mserver.invoke(realmName, "init", 
+                            new Object[] {},
+                            new String[] {}
+                    );            
+                }
+            } catch( Throwable t ) {
+                if(log.isDebugEnabled())
+                    log.debug("No realm for this host " + realmName);
+            }
+        }
+        
+        if (getLoader() == null) {
+            ClassLoader parent = null;
+            if (getPrivileged()) {
+                if (log.isDebugEnabled())
+                    log.debug("Configuring privileged default Loader");
+                parent = this.getClass().getClassLoader();
+            } else {
+                if (log.isDebugEnabled())
+                    log.debug("Configuring non-privileged default Loader");
+                parent = getParentClassLoader();
+            }
+            WebappLoader webappLoader = new WebappLoader(parent);
+            webappLoader.setDelegate(getDelegate());
+            setLoader(webappLoader);
+        }
+
+        // Initialize character set mapper
+        getCharsetMapper();
+
+        // Post work directory
+        postWorkDirectory();
+
+        // Validate required extensions
+        boolean dependencyCheck = true;
+        try {
+            dependencyCheck = ExtensionValidator.validateApplication
+                (getResources(), this);
+        } catch (IOException ioe) {
+            log.error("Error in dependencyCheck", ioe);
+            dependencyCheck = false;
+        }
+
+        if (!dependencyCheck) {
+            // do not make application available if depency check fails
+            ok = false;
+        }
+
+        // Reading the "catalina.useNaming" environment variable
+        String useNamingProperty = System.getProperty("catalina.useNaming");
+        if ((useNamingProperty != null)
+            && (useNamingProperty.equals("false"))) {
+            useNaming = false;
+        }
+
+        if (ok && isUseNaming()) {
+            if (namingContextListener == null) {
+                namingContextListener = new NamingContextListener();
+                namingContextListener.setName(getNamingContextName());
+                addLifecycleListener(namingContextListener);
+            }
+        }
+
+        // Binding thread
+        ClassLoader oldCCL = bindThread();
+
+        // Standard container startup
+        if (log.isDebugEnabled())
+            log.debug("Processing standard container startup");
+
+        if (ok) {
+
+            boolean mainOk = false;
+            try {
+
+                started = true;
+
+                // Start our subordinate components, if any
+                if ((loader != null) && (loader instanceof Lifecycle))
+                    ((Lifecycle) loader).start();
+
+                // Unbinding thread
+                unbindThread(oldCCL);
+
+                // Binding thread
+                oldCCL = bindThread();
+
+                if ((logger != null) && (logger instanceof Lifecycle))
+                    ((Lifecycle) logger).start();
+                if ((cluster != null) && (cluster instanceof Lifecycle))
+                    ((Lifecycle) cluster).start();
+                if ((realm != null) && (realm instanceof Lifecycle))
+                    ((Lifecycle) realm).start();
+                if ((resources != null) && (resources instanceof Lifecycle))
+                    ((Lifecycle) resources).start();
+
+                // Start our child containers, if any
+                Container children[] = findChildren();
+                for (int i = 0; i < children.length; i++) {
+                    if (children[i] instanceof Lifecycle)
+                        ((Lifecycle) children[i]).start();
+                }
+
+                // Start the Valves in our pipeline (including the basic),
+                // if any
+                if (pipeline instanceof Lifecycle) {
+                    ((Lifecycle) pipeline).start();
+                }
+                
+                if(getProcessTlds()) {
+                    processTlds();
+                }
+                
+                // Notify our interested LifecycleListeners
+                lifecycle.fireLifecycleEvent(START_EVENT, null);
+
+                // Start manager
+                if ((manager != null) && (manager instanceof Lifecycle)) {
+                    ((Lifecycle) getManager()).start();
+                }
+
+                // Start ContainerBackgroundProcessor thread
+                super.threadStart();
+
+                mainOk = true;
+
+            } finally {
+                // Unbinding thread
+                unbindThread(oldCCL);
+                if (!mainOk) {
+                    // An exception occurred
+                    // Register with JMX anyway, to allow management
+                    registerJMX();
+                }
+            }
+
+        }
+        if (!getConfigured()) {
+            log.error( "Error getConfigured");
+            ok = false;
+        }
+
+        // We put the resources into the servlet context
+        if (ok)
+            getServletContext().setAttribute
+                (Globals.RESOURCES_ATTR, getResources());
+
+        // Initialize associated mapper
+        mapper.setContext(getPath(), welcomeFiles, resources);
+
+        // Binding thread
+        oldCCL = bindThread();
+
+        // Create context attributes that will be required
+        if (ok) {
+            postWelcomeFiles();
+        }
+
+        if (ok) {
+            // Notify our interested LifecycleListeners
+            lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
+        }
+
+        // Configure and call application event listeners and filters
+        if (ok) {
+            if (!listenerStart()) {
+                log.error( "Error listenerStart");
+                ok = false;
+            }
+        }
+        if (ok) {
+            if (!filterStart()) {
+                log.error( "Error filterStart");
+                ok = false;
+            }
+        }
+
+        // Load and initialize all "load on startup" servlets
+        if (ok) {
+            loadOnStartup(findChildren());
+        }
+
+        // Unbinding thread
+        unbindThread(oldCCL);
+
+        // Set available status depending upon startup success
+        if (ok) {
+            if (log.isDebugEnabled())
+                log.debug("Starting completed");
+            setAvailable(true);
+        } else {
+            log.error(sm.getString("standardContext.startFailed", getName()));
+            try {
+                stop();
+            } catch (Throwable t) {
+                log.error(sm.getString("standardContext.startCleanup"), t);
+            }
+            setAvailable(false);
+        }
+
+        // JMX registration
+        registerJMX();
+
+        startTime=System.currentTimeMillis();
+        
+        // Send j2ee.state.running notification 
+        if (ok && (this.getObjectName() != null)) {
+            Notification notification = 
+                new Notification("j2ee.state.running", this.getObjectName(), 
+                                sequenceNumber++);
+            broadcaster.sendNotification(notification);
+        }
+
+        // Close all JARs right away to avoid always opening a peak number 
+        // of files on startup
+        if (getLoader() instanceof WebappLoader) {
+            ((WebappLoader) getLoader()).closeJARs(true);
+        }
+
+        // Reinitializing if something went wrong
+        if (!ok && started) {
+            stop();
+        }
+
+        //cacheContext();
+    }
+
+    /**
+     * Processes TLDs.
+     *
+     * @throws LifecycleException If an error occurs
+     */
+     protected void processTlds() throws LifecycleException {
+       TldConfig tldConfig = new TldConfig();
+       tldConfig.setContext(this);
+
+       // (1)  check if the attribute has been defined
+       //      on the context element.
+       tldConfig.setTldValidation(tldValidation);
+       tldConfig.setTldNamespaceAware(tldNamespaceAware);
+
+       // (2) if the attribute wasn't defined on the context
+       //     try the host.
+       if (!tldValidation) {
+         tldConfig.setTldValidation
+           (((StandardHost) getParent()).getXmlValidation());
+       }
+
+       if (!tldNamespaceAware) {
+         tldConfig.setTldNamespaceAware
+           (((StandardHost) getParent()).getXmlNamespaceAware());
+       }
+                    
+       try {
+         tldConfig.execute();
+       } catch (Exception ex) {
+         log.error("Error reading tld listeners " 
+                    + ex.toString(), ex); 
+       }
+     }
+    
+    private void cacheContext() {
+        try {
+            File workDir=new File( getWorkPath() );
+            
+            File ctxSer=new File( workDir, "_tomcat_context.ser");
+            FileOutputStream fos=new FileOutputStream( ctxSer );
+            ObjectOutputStream oos=new ObjectOutputStream( fos );
+            oos.writeObject(this);
+            oos.close();
+            fos.close();
+        } catch( Throwable t ) {
+            if(log.isInfoEnabled())
+                log.info("Error saving context.ser ", t);
+        }
+    }
+
+    
+    /**
+     * Stop this Context component.
+     *
+     * @exception LifecycleException if a shutdown error occurs
+     */
+    public synchronized void stop() throws LifecycleException {
+
+        // Validate and update our current component state
+        if (!started) {
+            if(log.isInfoEnabled())
+                log.info(sm.getString("containerBase.notStarted", logName()));
+            return;
+        }
+
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
+        
+        // Send j2ee.state.stopping notification 
+        if (this.getObjectName() != null) {
+            Notification notification = 
+                new Notification("j2ee.state.stopping", this.getObjectName(), 
+                                sequenceNumber++);
+            broadcaster.sendNotification(notification);
+        }
+        
+        // Mark this application as unavailable while we shut down
+        setAvailable(false);
+
+        // Binding thread
+        ClassLoader oldCCL = bindThread();
+
+        // Stop our filters
+        filterStop();
+
+        // Stop ContainerBackgroundProcessor thread
+        super.threadStop();
+
+        if ((manager != null) && (manager instanceof Lifecycle)) {
+            ((Lifecycle) manager).stop();
+        }
+
+        // Finalize our character set mapper
+        setCharsetMapper(null);
+
+        // Normal container shutdown processing
+        if (log.isDebugEnabled())
+            log.debug("Processing standard container shutdown");
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
+        started = false;
+
+        try {
+
+            // Stop the Valves in our pipeline (including the basic), if any
+            if (pipeline instanceof Lifecycle) {
+                ((Lifecycle) pipeline).stop();
+            }
+
+            // Stop our child containers, if any
+            Container[] children = findChildren();
+            for (int i = 0; i < children.length; i++) {
+                if (children[i] instanceof Lifecycle)
+                    ((Lifecycle) children[i]).stop();
+            }
+
+            // Stop our application listeners
+            listenerStop();
+
+            // Clear all application-originated servlet context attributes
+            if (context != null)
+                context.clearAttributes();
+
+            // Stop resources
+            resourcesStop();
+
+            if ((realm != null) && (realm instanceof Lifecycle)) {
+                ((Lifecycle) realm).stop();
+            }
+            if ((cluster != null) && (cluster instanceof Lifecycle)) {
+                ((Lifecycle) cluster).stop();
+            }
+            if ((logger != null) && (logger instanceof Lifecycle)) {
+                ((Lifecycle) logger).stop();
+            }
+            if ((loader != null) && (loader instanceof Lifecycle)) {
+                ((Lifecycle) loader).stop();
+            }
+
+        } finally {
+
+            // Unbinding thread
+            unbindThread(oldCCL);
+
+        }
+
+        // Send j2ee.state.stopped notification 
+        if (this.getObjectName() != null) {
+            Notification notification = 
+                new Notification("j2ee.state.stopped", this.getObjectName(), 
+                                sequenceNumber++);
+            broadcaster.sendNotification(notification);
+        }
+        
+        // Reset application context
+        context = null;
+
+        // This object will no longer be visible or used. 
+        try {
+            resetContext();
+        } catch( Exception ex ) {
+            log.error( "Error reseting context " + this + " " + ex, ex );
+        }
+        
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
+
+        if (log.isDebugEnabled())
+            log.debug("Stopping complete");
+
+    }
+
+    /** Destroy needs to clean up the context completely.
+     * 
+     * The problem is that undoing all the config in start() and restoring 
+     * a 'fresh' state is impossible. After stop()/destroy()/init()/start()
+     * we should have the same state as if a fresh start was done - i.e
+     * read modified web.xml, etc. This can only be done by completely 
+     * removing the context object and remapping a new one, or by cleaning
+     * up everything.
+     * 
+     * XXX Should this be done in stop() ?
+     * 
+     */ 
+    public void destroy() throws Exception {
+        if( oname != null ) { 
+            // Send j2ee.object.deleted notification 
+            Notification notification = 
+                new Notification("j2ee.object.deleted", this.getObjectName(), 
+                                sequenceNumber++);
+            broadcaster.sendNotification(notification);
+        } 
+        super.destroy();
+
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);
+
+        instanceListeners = new String[0];
+        applicationListeners = new String[0];
+    }
+    
+    private void resetContext() throws Exception, MBeanRegistrationException {
+        // Restore the original state ( pre reading web.xml in start )
+        // If you extend this - override this method and make sure to clean up
+        children=new HashMap();
+        startupTime = 0;
+        startTime = 0;
+        tldScanTime = 0;
+
+        // Bugzilla 32867
+        distributable = false;
+
+        if(log.isDebugEnabled())
+            log.debug("resetContext " + oname + " " + mserver);
+    }
+
+    /**
+     * Return a String representation of this component.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer();
+        if (getParent() != null) {
+            sb.append(getParent().toString());
+            sb.append(".");
+        }
+        sb.append("StandardContext[");
+        sb.append(getName());
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * Adjust the URL pattern to begin with a leading slash, if appropriate
+     * (i.e. we are running a servlet 2.2 application).  Otherwise, return
+     * the specified URL pattern unchanged.
+     *
+     * @param urlPattern The URL pattern to be adjusted (if needed)
+     *  and returned
+     */
+    protected String adjustURLPattern(String urlPattern) {
+
+        if (urlPattern == null)
+            return (urlPattern);
+        if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
+            return (urlPattern);
+        if (!isServlet22())
+            return (urlPattern);
+        if(log.isDebugEnabled())
+            log.debug(sm.getString("standardContext.urlPattern.patternWarning",
+                         urlPattern));
+        return ("/" + urlPattern);
+
+    }
+
+
+    /**
+     * Are we processing a version 2.2 deployment descriptor?
+     */
+    protected boolean isServlet22() {
+
+        if (this.publicId == null)
+            return (false);
+        if (this.publicId.equals
+            (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
+            return (true);
+        else
+            return (false);
+
+    }
+
+
+    /**
+     * Return a File object representing the base directory for the
+     * entire servlet container (i.e. the Engine container if present).
+     */
+    protected File engineBase() {
+        String base=System.getProperty("catalina.base");
+        if( base == null ) {
+            StandardEngine eng=(StandardEngine)this.getParent().getParent();
+            base=eng.getBaseDir();
+        }
+        return (new File(base));
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+
+    /**
+     * Bind current thread, both for CL purposes and for JNDI ENC support
+     * during : startup, shutdown and realoading of the context.
+     *
+     * @return the previous context class loader
+     */
+    private ClassLoader bindThread() {
+
+        ClassLoader oldContextClassLoader =
+            Thread.currentThread().getContextClassLoader();
+
+        if (getResources() == null)
+            return oldContextClassLoader;
+
+        if (getLoader().getClassLoader() != null) {
+            Thread.currentThread().setContextClassLoader
+                (getLoader().getClassLoader());
+        }
+
+        DirContextURLStreamHandler.bind(getResources());
+
+        if (isUseNaming()) {
+            try {
+                ContextBindings.bindThread(this, this);
+            } catch (NamingException e) {
+                // Silent catch, as this is a normal case during the early
+                // startup stages
+            }
+        }
+
+        return oldContextClassLoader;
+
+    }
+
+
+    /**
+     * Unbind thread.
+     */
+    private void unbindThread(ClassLoader oldContextClassLoader) {
+
+        Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+
+        oldContextClassLoader = null;
+
+        if (isUseNaming()) {
+            ContextBindings.unbindThread(this, this);
+        }
+
+        DirContextURLStreamHandler.unbind();
+
+    }
+
+
+
+    /**
+     * Get base path.
+     */
+    private String getBasePath() {
+        String docBase = null;
+        Container container = this;
+        while (container != null) {
+            if (container instanceof Host)
+                break;
+            container = container.getParent();
+        }
+        File file = new File(getDocBase());
+        if (!file.isAbsolute()) {
+            if (container == null) {
+                docBase = (new File(engineBase(), getDocBase())).getPath();
+            } else {
+                // Use the "appBase" property of this container
+                String appBase = ((Host) container).getAppBase();
+                file = new File(appBase);
+                if (!file.isAbsolute())
+                    file = new File(engineBase(), appBase);
+                docBase = (new File(file, getDocBase())).getPath();
+            }
+        } else {
+            docBase = file.getPath();
+        }
+        return docBase;
+    }
+
+
+    /**
+     * Get app base.
+     */
+    private String getAppBase() {
+        String appBase = null;
+        Container container = this;
+        while (container != null) {
+            if (container instanceof Host)
+                break;
+            container = container.getParent();
+        }
+        if (container != null) {
+            appBase = ((Host) container).getAppBase();
+        }
+        return appBase;
+    }
+
+
+    /**
+     * Get config base.
+     */
+    public File getConfigBase() {
+        File configBase = 
+            new File(System.getProperty("catalina.base"), "conf");
+        if (!configBase.exists()) {
+            return null;
+        }
+        Container container = this;
+        Container host = null;
+        Container engine = null;
+        while (container != null) {
+            if (container instanceof Host)
+                host = container;
+            if (container instanceof Engine)
+                engine = container;
+            container = container.getParent();
+        }
+        if (engine != null) {
+            configBase = new File(configBase, engine.getName());
+        }
+        if (host != null) {
+            configBase = new File(configBase, host.getName());
+        }
+        if (saveConfig) {
+            configBase.mkdirs();
+        }
+        return configBase;
+    }
+
+
+    /**
+     * Given a context path, get the config file name.
+     */
+    protected String getDefaultConfigFile() {
+        String basename = null;
+        String path = getPath();
+        if (path.equals("")) {
+            basename = "ROOT";
+        } else {
+            basename = path.substring(1).replace('/', '#');
+        }
+        return (basename + ".xml");
+    }
+
+
+    /**
+     * Copy a file.
+     */
+    private boolean copy(File src, File dest) {
+        FileInputStream is = null;
+        FileOutputStream os = null;
+        try {
+            is = new FileInputStream(src);
+            os = new FileOutputStream(dest);
+            byte[] buf = new byte[4096];
+            while (true) {
+                int len = is.read(buf);
+                if (len < 0)
+                    break;
+                os.write(buf, 0, len);
+            }
+            is.close();
+            os.close();
+        } catch (IOException e) {
+            return false;
+        } finally {
+            try {
+                if (is != null) {
+                    is.close();
+                }
+            } catch (Exception e) {
+                // Ignore
+            }
+            try {
+                if (os != null) {
+                    os.close();
+                }
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Get naming context full name.
+     */
+    private String getNamingContextName() {
+    if (namingContextName == null) {
+        Container parent = getParent();
+        if (parent == null) {
+        namingContextName = getName();
+        } else {
+        Stack stk = new Stack();
+        StringBuffer buff = new StringBuffer();
+        while (parent != null) {
+            stk.push(parent.getName());
+            parent = parent.getParent();
+        }
+        while (!stk.empty()) {
+            buff.append("/" + stk.pop());
+        }
+        buff.append(getName());
+        namingContextName = buff.toString();
+        }
+    }
+    return namingContextName;
+    }
+
+
+    /**
+     * Return the request processing paused flag for this Context.
+     */
+    public boolean getPaused() {
+
+        return (this.paused);
+
+    }
+
+
+    /**
+     * Post a copy of our web application resources as a servlet context
+     * attribute.
+     */
+    private void postResources() {
+
+        getServletContext().setAttribute
+            (Globals.RESOURCES_ATTR, getResources());
+
+    }
+
+
+    /**
+     * Post a copy of our current list of welcome files as a servlet context
+     * attribute, so that the default servlet can find them.
+     */
+    private void postWelcomeFiles() {
+
+        getServletContext().setAttribute("org.apache.catalina.WELCOME_FILES",
+                                         welcomeFiles);
+
+    }
+
+    public String getHostname() {
+        Container parentHost = getParent();
+        if (parentHost != null) {
+            hostName = parentHost.getName();
+        }
+        if ((hostName == null) || (hostName.length() < 1))
+            hostName = "_";
+        return hostName;
+    }
+
+    /**
+     * Set the appropriate context attribute for our work directory.
+     */
+    private void postWorkDirectory() {
+
+        // Acquire (or calculate) the work directory path
+        String workDir = getWorkDir();
+        if (workDir == null) {
+
+            // Retrieve our parent (normally a host) name
+            String hostName = null;
+            String engineName = null;
+            String hostWorkDir = null;
+            Container parentHost = getParent();
+            if (parentHost != null) {
+                hostName = parentHost.getName();
+                if (parentHost instanceof StandardHost) {
+                    hostWorkDir = ((StandardHost)parentHost).getWorkDir();
+                }
+                Container parentEngine = parentHost.getParent();
+                if (parentEngine != null) {
+                   engineName = parentEngine.getName();
+                }
+            }
+            if ((hostName == null) || (hostName.length() < 1))
+                hostName = "_";
+            if ((engineName == null) || (engineName.length() < 1))
+                engineName = "_";
+
+            String temp = getPath();
+            if (temp.startsWith("/"))
+                temp = temp.substring(1);
+            temp = temp.replace('/', '_');
+            temp = temp.replace('\\', '_');
+            if (temp.length() < 1)
+                temp = "_";
+            if (hostWorkDir != null ) {
+                workDir = hostWorkDir + File.separator + temp;
+            } else {
+                workDir = "work" + File.separator + engineName +
+                    File.separator + hostName + File.separator + temp;
+            }
+            setWorkDir(workDir);
+        }
+
+        // Create this directory if necessary
+        File dir = new File(workDir);
+        if (!dir.isAbsolute()) {
+            File catalinaHome = engineBase();
+            String catalinaHomePath = null;
+            try {
+                catalinaHomePath = catalinaHome.getCanonicalPath();
+                dir = new File(catalinaHomePath, workDir);
+            } catch (IOException e) {
+            }
+        }
+        dir.mkdirs();
+
+        // Set the appropriate servlet context attribute
+        getServletContext().setAttribute(Globals.WORK_DIR_ATTR, dir);
+        if (getServletContext() instanceof ApplicationContext)
+            ((ApplicationContext) getServletContext()).setAttributeReadOnly
+                (Globals.WORK_DIR_ATTR);
+
+    }
+
+
+    /**
+     * Set the request processing paused flag for this Context.
+     *
+     * @param paused The new request processing paused flag
+     */
+    private void setPaused(boolean paused) {
+
+        this.paused = paused;
+
+    }
+
+
+    /**
+     * Validate the syntax of a proposed <code>&lt;url-pattern&gt;</code>
+     * for conformance with specification requirements.
+     *
+     * @param urlPattern URL pattern to be validated
+     */
+    private boolean validateURLPattern(String urlPattern) {
+
+        if (urlPattern == null)
+            return (false);
+        if (urlPattern.indexOf('\n') >= 0 || urlPattern.indexOf('\r') >= 0) {
+            getLogger().warn(sm.getString("standardContext.crlfinurl",urlPattern));
+        }
+        if (urlPattern.startsWith("*.")) {
+            if (urlPattern.indexOf('/') < 0)
+                return (true);
+            else
+                return (false);
+        }
+        if ( (urlPattern.startsWith("/")) &&
+                (urlPattern.indexOf("*.") < 0))
+            return (true);
+        else
+            return (false);
+
+    }
+
+
+    // ------------------------------------------------------------- Operations
+
+
+    /**
+     * JSR77 deploymentDescriptor attribute
+     *
+     * @return string deployment descriptor 
+     */
+    public String getDeploymentDescriptor() {
+    
+        InputStream stream = null;
+        ServletContext servletContext = getServletContext();
+        if (servletContext != null) {
+            stream = servletContext.getResourceAsStream(
+                org.apache.catalina.startup.Constants.ApplicationWebXml);
+        }
+        if (stream == null) {
+            return "";
+        }
+        BufferedReader br = new BufferedReader(
+                                new InputStreamReader(stream));
+        StringBuffer sb = new StringBuffer();
+        String strRead = "";
+        try {
+            while (strRead != null) {
+                sb.append(strRead);
+                strRead = br.readLine();
+            }
+        } catch (IOException e) {
+            return "";
+        }
+
+        return sb.toString(); 
+    
+    }
+    
+    
+    /**
+     * JSR77 servlets attribute
+     *
+     * @return list of all servlets ( we know about )
+     */
+    public String[] getServlets() {
+        
+        String[] result = null;
+
+        Container[] children = findChildren();
+        if (children != null) {
+            result = new String[children.length];
+            for( int i=0; i< children.length; i++ ) {
+                result[i] = ((StandardWrapper)children[i]).getObjectName();
+            }
+        }
+
+        return result;
+    }
+    
+
+    public ObjectName createObjectName(String hostDomain, ObjectName parentName)
+            throws MalformedObjectNameException
+    {
+        String onameStr;
+        StandardHost hst=(StandardHost)getParent();
+        
+        String pathName=getName();
+        String hostName=getParent().getName();
+        String name= "//" + ((hostName==null)? "DEFAULT" : hostName) +
+                (("".equals(pathName))?"/":pathName );
+
+        String suffix=",J2EEApplication=" +
+                getJ2EEApplication() + ",J2EEServer=" +
+                getJ2EEServer();
+
+        onameStr="j2eeType=WebModule,name=" + name + suffix;
+        if( log.isDebugEnabled())
+            log.debug("Registering " + onameStr + " for " + oname);
+        
+        // default case - no domain explictely set.
+        if( getDomain() == null ) domain=hst.getDomain();
+
+        ObjectName oname=new ObjectName(getDomain() + ":" + onameStr);
+        return oname;        
+    }    
+    
+    private void preRegisterJMX() {
+        try {
+            StandardHost host = (StandardHost) getParent();
+            if ((oname == null) 
+                || (oname.getKeyProperty("j2eeType") == null)) {
+                oname = createObjectName(host.getDomain(), host.getJmxName());
+                controller = oname;
+            }
+        } catch(Exception ex) {
+            if(log.isInfoEnabled())
+                log.info("Error registering ctx with jmx " + this + " " +
+                     oname + " " + ex.toString(), ex );
+        }
+    }
+
+    private void registerJMX() {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Checking for " + oname );
+            }
+            if(! Registry.getRegistry(null, null)
+                .getMBeanServer().isRegistered(oname)) {
+                controller = oname;
+                Registry.getRegistry(null, null)
+                    .registerComponent(this, oname, null);
+                
+                // Send j2ee.object.created notification 
+                if (this.getObjectName() != null) {
+                    Notification notification = new Notification(
+                                                        "j2ee.object.created", 
+                                                        this.getObjectName(), 
+                                                        sequenceNumber++);
+                    broadcaster.sendNotification(notification);
+                }
+            }
+            Container children[] = findChildren();
+            for (int i=0; children!=null && i<children.length; i++) {
+                ((StandardWrapper)children[i]).registerJMX( this );
+            }
+        } catch (Exception ex) {
+            if(log.isInfoEnabled())
+                log.info("Error registering wrapper with jmx " + this + " " +
+                    oname + " " + ex.toString(), ex );
+        }
+    }
+
+    /** There are 2 cases:
+     *   1.The context is created and registered by internal APIS
+     *   2. The context is created by JMX, and it'll self-register.
+     *
+     * @param server The server
+     * @param name The object name
+     * @return ObjectName The name of the object
+     * @throws Exception If an error occurs
+     */
+    public ObjectName preRegister(MBeanServer server,
+                                  ObjectName name)
+            throws Exception
+    {
+        if( oname != null ) {
+            //log.info( "Already registered " + oname + " " + name);
+            // Temporary - /admin uses the old names
+            return name;
+        }
+        ObjectName result=super.preRegister(server,name);
+        return name;
+    }
+
+    public void preDeregister() throws Exception {
+        if( started ) {
+            try {
+                stop();
+            } catch( Exception ex ) {
+                log.error( "error stopping ", ex);
+            }
+        }
+    }
+
+    public void init() throws Exception {
+
+        if( this.getParent() == null ) {
+            ObjectName parentName=getParentName();
+            
+            if( ! mserver.isRegistered(parentName)) {
+                if(log.isDebugEnabled())
+                    log.debug("No host, creating one " + parentName);
+                StandardHost host=new StandardHost();
+                host.setName(hostName);
+                host.setAutoDeploy(false);
+                Registry.getRegistry(null, null)
+                    .registerComponent(host, parentName, null);
+                mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );
+            }
+            ContextConfig config = new ContextConfig();
+            this.addLifecycleListener(config);
+
+            if(log.isDebugEnabled())
+                 log.debug( "AddChild " + parentName + " " + this);
+            try {
+                mserver.invoke(parentName, "addChild", new Object[] { this },
+                               new String[] {"org.apache.catalina.Container"});
+            } catch (Exception e) {
+                destroy();
+                throw e;
+            }
+            // It's possible that addChild may have started us
+            if( initialized ) {
+                return;
+            }
+        }
+        super.init();
+        
+        // Notify our interested LifecycleListeners
+        lifecycle.fireLifecycleEvent(INIT_EVENT, null);
+
+        // Send j2ee.state.starting notification 
+        if (this.getObjectName() != null) {
+            Notification notification = new Notification("j2ee.state.starting", 
+                                                        this.getObjectName(), 
+                                                        sequenceNumber++);
+            broadcaster.sendNotification(notification);
+        }
+        
+    }
+
+    public ObjectName getParentName() throws MalformedObjectNameException {
+        // "Life" update
+        String path=oname.getKeyProperty("name");
+        if( path == null ) {
+            log.error( "No name attribute " +name );
+            return null;
+        }
+        if( ! path.startsWith( "//")) {
+            log.error("Invalid name " + name);
+        }
+        path=path.substring(2);
+        int delim=path.indexOf( "/" );
+        hostName="localhost"; // Should be default...
+        if( delim > 0 ) {
+            hostName=path.substring(0, delim);
+            path = path.substring(delim);
+            if (path.equals("/")) {
+                this.setName("");
+            } else {
+                this.setName(path);
+            }
+        } else {
+            if(log.isDebugEnabled())
+                log.debug("Setting path " +  path );
+            this.setName( path );
+        }
+        // XXX The service and domain should be the same.
+        String parentDomain=getEngineName();
+        if( parentDomain == null ) parentDomain=domain;
+        ObjectName parentName=new ObjectName( parentDomain + ":" +
+                "type=Host,host=" + hostName);
+        return parentName;
+    }
+    
+    public void create() throws Exception{
+        init();
+    }
+
+    /* Remove a JMX notficationListener 
+     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
+     */
+    public void removeNotificationListener(NotificationListener listener, 
+            NotificationFilter filter, Object object) throws ListenerNotFoundException {
+    	broadcaster.removeNotificationListener(listener,filter,object);
+    	
+    }
+    
+    private MBeanNotificationInfo[] notificationInfo;
+    
+    /* Get JMX Broadcaster Info
+     * @TODO use StringManager for international support!
+     * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
+     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+    	// FIXME: i18n
+    	if(notificationInfo == null) {
+    		notificationInfo = new MBeanNotificationInfo[]{
+    				new MBeanNotificationInfo(new String[] {
+    				"j2ee.object.created"},
+					Notification.class.getName(),
+					"web application is created"
+    				), 
+					new MBeanNotificationInfo(new String[] {
+					"j2ee.state.starting"},
+					Notification.class.getName(),
+					"change web application is starting"
+					),
+					new MBeanNotificationInfo(new String[] {
+					"j2ee.state.running"},
+					Notification.class.getName(),
+					"web application is running"
+					),
+					new MBeanNotificationInfo(new String[] {
+					"j2ee.state.stopped"},
+					Notification.class.getName(),
+					"web application start to stopped"
+					),
+					new MBeanNotificationInfo(new String[] {
+					"j2ee.object.stopped"},
+					Notification.class.getName(),
+					"web application is stopped"
+					),
+					new MBeanNotificationInfo(new String[] {
+					"j2ee.object.deleted"},
+					Notification.class.getName(),
+					"web application is deleted"
+					)
+    		};
+    		
+    	}
+    	
+    	return notificationInfo;
+    }
+    
+    
+    /* Add a JMX-NotificationListener
+     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
+     */
+    public void addNotificationListener(NotificationListener listener, 
+            NotificationFilter filter, Object object) throws IllegalArgumentException {
+    	broadcaster.addNotificationListener(listener,filter,object);
+    	
+    }
+    
+    
+    /**
+     * Remove a JMX-NotificationListener 
+     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
+     */
+    public void removeNotificationListener(NotificationListener listener) 
+    throws ListenerNotFoundException {
+    	broadcaster.removeNotificationListener(listener);
+    	
+    }
+    
+    
+    // ------------------------------------------------------------- Attributes
+
+
+    /**
+     * Return the naming resources associated with this web application.
+     */
+    public javax.naming.directory.DirContext getStaticResources() {
+
+        return getResources();
+
+    }
+
+
+    /**
+     * Return the naming resources associated with this web application.
+     * FIXME: Fooling introspection ... 
+     */
+    public javax.naming.directory.DirContext findStaticResources() {
+
+        return getResources();
+
+    }
+
+
+    /**
+     * Return the naming resources associated with this web application.
+     */
+    public String[] getWelcomeFiles() {
+
+        return findWelcomeFiles();
+
+    }
+
+     /**
+     * Set the validation feature of the XML parser used when
+     * parsing xml instances.
+     * @param webXmlValidation true to enable xml instance validation
+     */
+    public void setXmlValidation(boolean webXmlValidation){
+        
+        this.webXmlValidation = webXmlValidation;
+
+    }
+
+    /**
+     * Get the server.xml <context> attribute's xmlValidation.
+     * @return true if validation is enabled.
+     *
+     */
+    public boolean getXmlValidation(){
+        return webXmlValidation;
+    }
+
+
+    /**
+     * Get the server.xml <context> attribute's xmlNamespaceAware.
+     * @return true if namespace awarenes is enabled.
+     */
+    public boolean getXmlNamespaceAware(){
+        return webXmlNamespaceAware;
+    }
+
+
+    /**
+     * Set the namespace aware feature of the XML parser used when
+     * parsing xml instances.
+     * @param webXmlNamespaceAware true to enable namespace awareness
+     */
+    public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
+        this.webXmlNamespaceAware= webXmlNamespaceAware;
+    }    
+
+
+    /**
+     * Set the validation feature of the XML parser used when
+     * parsing tlds files. 
+     * @param tldValidation true to enable xml instance validation
+     */
+    public void setTldValidation(boolean tldValidation){
+        
+        this.tldValidation = tldValidation;
+
+    }
+
+    /**
+     * Get the server.xml <context> attribute's webXmlValidation.
+     * @return true if validation is enabled.
+     *
+     */
+    public boolean getTldValidation(){
+        return tldValidation;
+    }
+
+    /**
+     * Sets the process TLDs attribute.
+     *
+     * @param newProcessTlds The new value
+     */
+    public void setProcessTlds(boolean newProcessTlds) {
+	processTlds = newProcessTlds;
+    }
+
+    /**
+     * Returns the processTlds attribute value.
+     */
+    public boolean getProcessTlds() {
+	return processTlds;
+    }
+
+    /**
+     * Get the server.xml <host> attribute's xmlNamespaceAware.
+     * @return true if namespace awarenes is enabled.
+     */
+    public boolean getTldNamespaceAware(){
+        return tldNamespaceAware;
+    }
+
+
+    /**
+     * Set the namespace aware feature of the XML parser used when
+     * parsing xml instances.
+     * @param tldNamespaceAware true to enable namespace awareness
+     */
+    public void setTldNamespaceAware(boolean tldNamespaceAware){
+        this.tldNamespaceAware= tldNamespaceAware;
+    }    
+
+
+    /** 
+     * Support for "stateManageable" JSR77 
+     */
+    public boolean isStateManageable() {
+        return true;
+    }
+    
+    public void startRecursive() throws LifecycleException {
+        // nothing to start recursive, the servlets will be started by load-on-startup
+        start();
+    }
+    
+    public int getState() {
+        if( started ) {
+            return 1; // RUNNING
+        }
+        if( initialized ) {
+            return 0; // starting ? 
+        }
+        if( ! available ) { 
+            return 4; //FAILED
+        }
+        // 2 - STOPPING
+        return 3; // STOPPED
+    }
+    
+    /**
+     * The J2EE Server ObjectName this module is deployed on.
+     */     
+    private String server = null;
+    
+    /**
+     * The Java virtual machines on which this module is running.
+     */       
+    private String[] javaVMs = null;
+    
+    public String getServer() {
+        return server;
+    }
+        
+    public String setServer(String server) {
+        return this.server=server;
+    }
+        
+    public String[] getJavaVMs() {
+        return javaVMs;
+    }
+        
+    public String[] setJavaVMs(String[] javaVMs) {
+        return this.javaVMs = javaVMs;
+    }
+    
+    /**
+     * Gets the time this context was started.
+     *
+     * @return Time (in milliseconds since January 1, 1970, 00:00:00) when this
+     * context was started 
+     */
+    public long getStartTime() {
+        return startTime;
+    }
+    
+    public boolean isEventProvider() {
+        return false;
+    }
+    
+    public boolean isStatisticsProvider() {
+        return false;
+    }
+    
+}
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml	2005-09-26 01:21:13.000000000 -0400
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+  <component name="ModuleRootManager" />
+  <component name="NewModuleRootManager">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/catalina/src/share" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/catalina/src/test" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+</module>
+
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml	2005-09-26 01:21:13.000000000 -0400
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+  <component name="ModuleRootManager" />
+  <component name="NewModuleRootManager">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/coyote/src/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/coyote/src/test" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/http11/src/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/http11/src/test/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jk/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jk/jkant/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jk/test" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jni/examples" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jni/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jni/test" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/juli/src/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/naming/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/util/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/util/loader" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+</module>
+
diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml
--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml	2005-09-26 00:02:02.000000000 -0400
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+  <component name="ModuleRootManager" />
+  <component name="NewModuleRootManager">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/jasper2/src/share" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntryProperties />
+  </component>
+</module>
+
diff -Nru upstream/jakarta-tomcat-5.5.9-src/LICENSE jakarta-tomcat-5.5.9-src/LICENSE
--- upstream/jakarta-tomcat-5.5.9-src/LICENSE	1969-12-31 19:00:00.000000000 -0500
+++ jakarta-tomcat-5.5.9-src/LICENSE	2005-09-26 00:05:01.000000000 -0400
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
