diff --git a/java/org/apache/catalina/Container.java b/java/org/apache/catalina/Container.java
index 73b265e..5ca3c09 100644
--- a/java/org/apache/catalina/Container.java
+++ b/java/org/apache/catalina/Container.java
@@ -1,479 +1,496 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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;
-
-
-import java.beans.PropertyChangeListener;
-import java.io.IOException;
-
-import javax.management.ObjectName;
-import javax.naming.directory.DirContext;
-import javax.servlet.ServletException;
-
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.juli.logging.Log;
-
-
-/**
- * A Container is an object that can execute requests received from
- * a client, and return responses based on those requests. A Container may
- * optionally support a pipeline of Valves that process the request in an
- * order configured at runtime, by implementing the Pipeline interface
- * as well.
- *
- * Containers will exist at several conceptual levels within Catalina. The
- * following examples represent common cases:
- *
- *
Engine - Representation of the entire Catalina servlet engine,
- * most likely containing one or more subcontainers that are either Host
- * or Context implementations, or other custom groups.
- *
Host - Representation of a virtual host containing a number
- * of Contexts.
- *
Context - Representation of a single ServletContext, which will
- * typically contain one or more Wrappers for the supported servlets.
- *
Wrapper - Representation of an individual servlet definition
- * (which may support multiple servlet instances if the servlet itself
- * implements SingleThreadModel).
- *
- * A given deployment of Catalina need not include Containers at all of the
- * levels described above. For example, an administration application
- * embedded within a network device (such as a router) might only contain
- * a single Context and a few Wrappers, or even a single Wrapper if the
- * application is relatively small. Therefore, Container implementations
- * need to be designed so that they will operate correctly in the absence
- * of parent Containers in a given deployment.
- *
- * A Container may also be associated with a number of support components
- * that provide functionality which might be shared (by attaching it to a
- * parent Container) or individually customized. The following support
- * components are currently recognized:
- *
- *
Loader - Class loader to use for integrating new Java classes
- * for this Container into the JVM in which Catalina is running.
- *
Logger - Implementation of the log() method
- * signatures of the ServletContext interface.
- *
Manager - Manager for the pool of Sessions associated with
- * this Container.
- *
Realm - Read-only interface to a security domain, for
- * authenticating user identities and their corresponding roles.
- *
Resources - JNDI directory context enabling access to static
- * resources, enabling custom linkages to existing server components when
- * Catalina is embedded in a larger server.
- *
- *
- * @author Craig R. McClanahan
- * @author Remy Maucherat
- * @version $Id$
- */
-
-public interface Container extends Lifecycle {
-
-
- // ----------------------------------------------------- Manifest Constants
-
-
- /**
- * The ContainerEvent event type sent when a child container is added
- * by addChild().
- */
- public static final String ADD_CHILD_EVENT = "addChild";
-
-
- /**
- * The ContainerEvent event type sent when a Mapper is added
- * by addMapper().
- */
- public static final String ADD_MAPPER_EVENT = "addMapper";
-
-
- /**
- * The ContainerEvent event type sent when a valve is added
- * by addValve(), if this Container supports pipelines.
- */
- public static final String ADD_VALVE_EVENT = "addValve";
-
-
- /**
- * The ContainerEvent event type sent when a child container is removed
- * by removeChild().
- */
- public static final String REMOVE_CHILD_EVENT = "removeChild";
-
-
- /**
- * The ContainerEvent event type sent when a Mapper is removed
- * by removeMapper().
- */
- public static final String REMOVE_MAPPER_EVENT = "removeMapper";
-
-
- /**
- * The ContainerEvent event type sent when a valve is removed
- * by removeValve(), if this Container supports pipelines.
- */
- public static final String REMOVE_VALVE_EVENT = "removeValve";
-
-
- // ------------------------------------------------------------- Properties
-
-
- /**
- * Return descriptive information about this Container implementation and
- * the corresponding version number, in the format
- * <description>/<version>.
- */
- public String getInfo();
-
-
- /**
- * Return the Loader with which this Container is associated. If there is
- * no associated Loader, return the Loader associated with our parent
- * Container (if any); otherwise, return null.
- */
- public Loader getLoader();
-
-
- /**
- * Set the Loader with which this Container is associated.
- *
- * @param loader The newly associated loader
- */
- public void setLoader(Loader loader);
-
-
- /**
- * Return the Logger with which this Container is associated. If there is
- * no associated Logger, return the Logger associated with our parent
- * Container (if any); otherwise return null.
- */
- public Log getLogger();
-
-
- /**
- * Return the Manager with which this Container is associated. If there is
- * no associated Manager, return the Manager associated with our parent
- * Container (if any); otherwise return null.
- */
- public Manager getManager();
-
-
- /**
- * Set the Manager with which this Container is associated.
- *
- * @param manager The newly associated Manager
- */
- public void setManager(Manager manager);
-
-
- /**
- * Return an object which may be utilized for mapping to this component.
- */
- public Object getMappingObject();
-
-
- /**
- * Return the JMX name associated with this container.
- */
- public ObjectName getObjectName();
-
- /**
- * Return the Pipeline object that manages the Valves associated with
- * this Container.
- */
- public Pipeline getPipeline();
-
-
- /**
- * Return the Cluster with which this Container is associated. If there is
- * no associated Cluster, return the Cluster associated with our parent
- * Container (if any); otherwise return null.
- */
- public Cluster getCluster();
-
-
- /**
- * Set the Cluster with which this Container is associated.
- *
- * @param cluster the Cluster with which this Container is associated.
- */
- public void setCluster(Cluster cluster);
-
-
- /**
- * Get the delay between the invocation of the backgroundProcess method on
- * this container and its children. Child containers will not be invoked
- * if their delay value is not negative (which would mean they are using
- * their own thread). Setting this to a positive value will cause
- * a thread to be spawn. After waiting the specified amount of time,
- * the thread will invoke the executePeriodic method on this container
- * and all its children.
- */
- public int getBackgroundProcessorDelay();
-
-
- /**
- * Set the delay between the invocation of the execute method on this
- * container and its children.
- *
- * @param delay The delay in seconds between the invocation of
- * backgroundProcess methods
- */
- public void setBackgroundProcessorDelay(int delay);
-
-
- /**
- * Return a name string (suitable for use by humans) that describes this
- * Container. Within the set of child containers belonging to a particular
- * parent, Container names must be unique.
- */
- public String getName();
-
-
- /**
- * Set a name string (suitable for use by humans) that describes this
- * Container. Within the set of child containers belonging to a particular
- * parent, Container names must be unique.
- *
- * @param name New name of this container
- *
- * @exception IllegalStateException if this Container has already been
- * added to the children of a parent Container (after which the name
- * may not be changed)
- */
- public void setName(String name);
-
-
- /**
- * Return the Container for which this Container is a child, if there is
- * one. If there is no defined parent, return null.
- */
- public Container getParent();
-
-
- /**
- * Set the parent Container to which this Container is being added as a
- * child. This Container may refuse to become attached to the specified
- * Container by throwing an exception.
- *
- * @param container Container to which this Container is being added
- * as a child
- *
- * @exception IllegalArgumentException if this Container refuses to become
- * attached to the specified Container
- */
- public void setParent(Container container);
-
-
- /**
- * Return the parent class loader for this component. If not set, return
- * {@link #getParent()} {@link #getParentClassLoader()}. If no parent has
- * been set, return the system class loader.
- */
- public ClassLoader getParentClassLoader();
-
-
- /**
- * Set the parent class loader for this component. For {@link Context}s
- * this call is meaningful only before a Loader has
- * been configured, and the specified value (if non-null) should be
- * passed as an argument to the class loader constructor.
- *
- * @param parent The new parent class loader
- */
- public void setParentClassLoader(ClassLoader parent);
-
-
- /**
- * Return the Realm with which this Container is associated. If there is
- * no associated Realm, return the Realm associated with our parent
- * Container (if any); otherwise return null.
- */
- public Realm getRealm();
-
-
- /**
- * Set the Realm with which this Container is associated.
- *
- * @param realm The newly associated Realm
- */
- public void setRealm(Realm realm);
-
-
- /**
- * Return the Resources with which this Container is associated. If there
- * is no associated Resources object, return the Resources associated with
- * our parent Container (if any); otherwise return null.
- */
- public DirContext getResources();
-
-
- /**
- * Set the Resources object with which this Container is associated.
- *
- * @param resources The newly associated Resources
- */
- public void setResources(DirContext resources);
-
-
- // --------------------------------------------------------- Public Methods
-
-
- /**
- * Execute a periodic task, such as reloading, etc. This method will be
- * invoked inside the classloading context of this container. Unexpected
- * throwables will be caught and logged.
- */
- public void backgroundProcess();
-
-
- /**
- * Add a new child Container to those associated with this Container,
- * if supported. Prior to adding this Container to the set of children,
- * the child's setParent() method must be called, with this
- * Container as an argument. This method may thrown an
- * IllegalArgumentException if this Container chooses not
- * to be attached to the specified Container, in which case it is not added
- *
- * @param child New child Container to be added
- *
- * @exception IllegalArgumentException if this exception is thrown by
- * the setParent() method of the child Container
- * @exception IllegalArgumentException if the new child does not have
- * a name unique from that of existing children of this Container
- * @exception IllegalStateException if this Container does not support
- * child Containers
- */
- public void addChild(Container child);
-
-
- /**
- * Add a container event listener to this component.
- *
- * @param listener The listener to add
- */
- public void addContainerListener(ContainerListener listener);
-
-
- /**
- * Add a property change listener to this component.
- *
- * @param listener The listener to add
- */
- public void addPropertyChangeListener(PropertyChangeListener listener);
-
-
- /**
- * Return the child Container, associated with this Container, with
- * the specified name (if any); otherwise, return null
- *
- * @param name Name of the child Container to be retrieved
- */
- public Container findChild(String name);
-
-
- /**
- * Return the set of children Containers associated with this Container.
- * If this Container has no children, a zero-length array is returned.
- */
- public Container[] findChildren();
-
-
- /**
- * Return the set of container listeners associated with this Container.
- * If this Container has no registered container listeners, a zero-length
- * array is returned.
- */
- public ContainerListener[] findContainerListeners();
-
-
- /**
- * Process the specified Request, and generate the corresponding Response,
- * according to the design of this particular Container.
- *
- * @param request Request to be processed
- * @param response Response to be produced
- *
- * @exception IOException if an input/output error occurred while
- * processing
- * @exception ServletException if a ServletException was thrown
- * while processing this request
- */
- public void invoke(Request request, Response response)
- throws IOException, ServletException;
-
-
- /**
- * Remove an existing child Container from association with this parent
- * Container.
- *
- * @param child Existing child Container to be removed
- */
- public void removeChild(Container child);
-
-
- /**
- * Remove a container event listener from this component.
- *
- * @param listener The listener to remove
- */
- public void removeContainerListener(ContainerListener listener);
-
-
- /**
- * Remove a property change listener from this component.
- *
- * @param listener The listener to remove
- */
- public void removePropertyChangeListener(PropertyChangeListener listener);
-
-
- /**
- * Notify all container event listeners that a particular event has
- * occurred for this Container. The default implementation performs
- * this notification synchronously using the calling thread.
- *
- * @param type Event type
- * @param data Event data
- */
- public void fireContainerEvent(String type, Object data);
-
-
- /**
- * Log a request/response that was destined for this container but has been
- * handled earlier in the processing chain so that the request/response
- * still appears in the correct access logs.
- * @param request Request (associated with the response) to log
- * @param response Response (associated with the request) to log
- * @param time Time taken to process the request/response in
- * milliseconds (use 0 if not known)
- * @param useDefault Flag that indicates that the request/response should
- * be logged in the engine's default access log
- */
- public void logAccess(Request request, Response response, long time,
- boolean useDefault);
-
-
- /**
- * Identify the AccessLog to use to log a request/response that was destined
- * for this container but was handled earlier in the processing chain so
- * that the request/response still appears in the correct access logs.
- */
- public AccessLog getAccessLog();
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+
+import javax.management.ObjectName;
+import javax.naming.directory.DirContext;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.juli.logging.Log;
+
+
+/**
+ * A Container is an object that can execute requests received from
+ * a client, and return responses based on those requests. A Container may
+ * optionally support a pipeline of Valves that process the request in an
+ * order configured at runtime, by implementing the Pipeline interface
+ * as well.
+ *
+ * Containers will exist at several conceptual levels within Catalina. The
+ * following examples represent common cases:
+ *
+ *
Engine - Representation of the entire Catalina servlet engine,
+ * most likely containing one or more subcontainers that are either Host
+ * or Context implementations, or other custom groups.
+ *
Host - Representation of a virtual host containing a number
+ * of Contexts.
+ *
Context - Representation of a single ServletContext, which will
+ * typically contain one or more Wrappers for the supported servlets.
+ *
Wrapper - Representation of an individual servlet definition
+ * (which may support multiple servlet instances if the servlet itself
+ * implements SingleThreadModel).
+ *
+ * A given deployment of Catalina need not include Containers at all of the
+ * levels described above. For example, an administration application
+ * embedded within a network device (such as a router) might only contain
+ * a single Context and a few Wrappers, or even a single Wrapper if the
+ * application is relatively small. Therefore, Container implementations
+ * need to be designed so that they will operate correctly in the absence
+ * of parent Containers in a given deployment.
+ *
+ * A Container may also be associated with a number of support components
+ * that provide functionality which might be shared (by attaching it to a
+ * parent Container) or individually customized. The following support
+ * components are currently recognized:
+ *
+ *
Loader - Class loader to use for integrating new Java classes
+ * for this Container into the JVM in which Catalina is running.
+ *
Logger - Implementation of the log() method
+ * signatures of the ServletContext interface.
+ *
Manager - Manager for the pool of Sessions associated with
+ * this Container.
+ *
Realm - Read-only interface to a security domain, for
+ * authenticating user identities and their corresponding roles.
+ *
Resources - JNDI directory context enabling access to static
+ * resources, enabling custom linkages to existing server components when
+ * Catalina is embedded in a larger server.
+ *
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+ * @version $Id$
+ */
+
+public interface Container extends Lifecycle {
+
+
+ // ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The ContainerEvent event type sent when a child container is added
+ * by addChild().
+ */
+ public static final String ADD_CHILD_EVENT = "addChild";
+
+
+ /**
+ * The ContainerEvent event type sent when a Mapper is added
+ * by addMapper().
+ */
+ public static final String ADD_MAPPER_EVENT = "addMapper";
+
+
+ /**
+ * The ContainerEvent event type sent when a valve is added
+ * by addValve(), if this Container supports pipelines.
+ */
+ public static final String ADD_VALVE_EVENT = "addValve";
+
+
+ /**
+ * The ContainerEvent event type sent when a child container is removed
+ * by removeChild().
+ */
+ public static final String REMOVE_CHILD_EVENT = "removeChild";
+
+
+ /**
+ * The ContainerEvent event type sent when a Mapper is removed
+ * by removeMapper().
+ */
+ public static final String REMOVE_MAPPER_EVENT = "removeMapper";
+
+
+ /**
+ * The ContainerEvent event type sent when a valve is removed
+ * by removeValve(), if this Container supports pipelines.
+ */
+ public static final String REMOVE_VALVE_EVENT = "removeValve";
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Return descriptive information about this Container implementation and
+ * the corresponding version number, in the format
+ * <description>/<version>.
+ */
+ public String getInfo();
+
+
+ /**
+ * Return the Loader with which this Container is associated. If there is
+ * no associated Loader, return the Loader associated with our parent
+ * Container (if any); otherwise, return null.
+ */
+ public Loader getLoader();
+
+
+ /**
+ * Set the Loader with which this Container is associated.
+ *
+ * @param loader The newly associated loader
+ */
+ public void setLoader(Loader loader);
+
+
+ /**
+ * Return the Logger with which this Container is associated. If there is
+ * no associated Logger, return the Logger associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ public Log getLogger();
+
+
+ /**
+ * Return the Manager with which this Container is associated. If there is
+ * no associated Manager, return the Manager associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ public Manager getManager();
+
+
+ /**
+ * Set the Manager with which this Container is associated.
+ *
+ * @param manager The newly associated Manager
+ */
+ public void setManager(Manager manager);
+
+
+ /**
+ * Return an object which may be utilized for mapping to this component.
+ */
+ public Object getMappingObject();
+
+
+ /**
+ * Return the JMX name associated with this container.
+ */
+ public ObjectName getObjectName();
+
+ /**
+ * Return the Pipeline object that manages the Valves associated with
+ * this Container.
+ */
+ public Pipeline getPipeline();
+
+
+ /**
+ * Return the Cluster with which this Container is associated. If there is
+ * no associated Cluster, return the Cluster associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ public Cluster getCluster();
+
+
+ /**
+ * Set the Cluster with which this Container is associated.
+ *
+ * @param cluster the Cluster with which this Container is associated.
+ */
+ public void setCluster(Cluster cluster);
+
+
+ /**
+ * Get the delay between the invocation of the backgroundProcess method on
+ * this container and its children. Child containers will not be invoked
+ * if their delay value is not negative (which would mean they are using
+ * their own thread). Setting this to a positive value will cause
+ * a thread to be spawn. After waiting the specified amount of time,
+ * the thread will invoke the executePeriodic method on this container
+ * and all its children.
+ */
+ public int getBackgroundProcessorDelay();
+
+
+ /**
+ * Set the delay between the invocation of the execute method on this
+ * container and its children.
+ *
+ * @param delay The delay in seconds between the invocation of
+ * backgroundProcess methods
+ */
+ public void setBackgroundProcessorDelay(int delay);
+
+
+ /**
+ * Return a name string (suitable for use by humans) that describes this
+ * Container. Within the set of child containers belonging to a particular
+ * parent, Container names must be unique.
+ */
+ public String getName();
+
+
+ /**
+ * Set a name string (suitable for use by humans) that describes this
+ * Container. Within the set of child containers belonging to a particular
+ * parent, Container names must be unique.
+ *
+ * @param name New name of this container
+ *
+ * @exception IllegalStateException if this Container has already been
+ * added to the children of a parent Container (after which the name
+ * may not be changed)
+ */
+ public void setName(String name);
+
+
+ /**
+ * Return the Container for which this Container is a child, if there is
+ * one. If there is no defined parent, return null.
+ */
+ public Container getParent();
+
+
+ /**
+ * Set the parent Container to which this Container is being added as a
+ * child. This Container may refuse to become attached to the specified
+ * Container by throwing an exception.
+ *
+ * @param container Container to which this Container is being added
+ * as a child
+ *
+ * @exception IllegalArgumentException if this Container refuses to become
+ * attached to the specified Container
+ */
+ public void setParent(Container container);
+
+
+ /**
+ * Return the parent class loader for this component. If not set, return
+ * {@link #getParent()} {@link #getParentClassLoader()}. If no parent has
+ * been set, return the system class loader.
+ */
+ public ClassLoader getParentClassLoader();
+
+
+ /**
+ * Set the parent class loader for this component. For {@link Context}s
+ * this call is meaningful only before a Loader has
+ * been configured, and the specified value (if non-null) should be
+ * passed as an argument to the class loader constructor.
+ *
+ * @param parent The new parent class loader
+ */
+ public void setParentClassLoader(ClassLoader parent);
+
+
+ /**
+ * Return the Realm with which this Container is associated. If there is
+ * no associated Realm, return the Realm associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ public Realm getRealm();
+
+
+ /**
+ * Set the Realm with which this Container is associated.
+ *
+ * @param realm The newly associated Realm
+ */
+ public void setRealm(Realm realm);
+
+
+ /**
+ * Return the Resources with which this Container is associated. If there
+ * is no associated Resources object, return the Resources associated with
+ * our parent Container (if any); otherwise return null.
+ */
+ public DirContext getResources();
+
+
+ /**
+ * Set the Resources object with which this Container is associated.
+ *
+ * @param resources The newly associated Resources
+ */
+ public void setResources(DirContext resources);
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Execute a periodic task, such as reloading, etc. This method will be
+ * invoked inside the classloading context of this container. Unexpected
+ * throwables will be caught and logged.
+ */
+ public void backgroundProcess();
+
+
+ /**
+ * Add a new child Container to those associated with this Container,
+ * if supported. Prior to adding this Container to the set of children,
+ * the child's setParent() method must be called, with this
+ * Container as an argument. This method may thrown an
+ * IllegalArgumentException if this Container chooses not
+ * to be attached to the specified Container, in which case it is not added
+ *
+ * @param child New child Container to be added
+ *
+ * @exception IllegalArgumentException if this exception is thrown by
+ * the setParent() method of the child Container
+ * @exception IllegalArgumentException if the new child does not have
+ * a name unique from that of existing children of this Container
+ * @exception IllegalStateException if this Container does not support
+ * child Containers
+ */
+ public void addChild(Container child);
+
+
+ /**
+ * Add a container event listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ public void addContainerListener(ContainerListener listener);
+
+
+ /**
+ * Add a property change listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ public void addPropertyChangeListener(PropertyChangeListener listener);
+
+
+ /**
+ * Return the child Container, associated with this Container, with
+ * the specified name (if any); otherwise, return null
+ *
+ * @param name Name of the child Container to be retrieved
+ */
+ public Container findChild(String name);
+
+
+ /**
+ * Return the set of children Containers associated with this Container.
+ * If this Container has no children, a zero-length array is returned.
+ */
+ public Container[] findChildren();
+
+
+ /**
+ * Return the set of container listeners associated with this Container.
+ * If this Container has no registered container listeners, a zero-length
+ * array is returned.
+ */
+ public ContainerListener[] findContainerListeners();
+
+
+ /**
+ * Process the specified Request, and generate the corresponding Response,
+ * according to the design of this particular Container.
+ *
+ * @param request Request to be processed
+ * @param response Response to be produced
+ *
+ * @exception IOException if an input/output error occurred while
+ * processing
+ * @exception ServletException if a ServletException was thrown
+ * while processing this request
+ */
+ public void invoke(Request request, Response response)
+ throws IOException, ServletException;
+
+
+ /**
+ * Remove an existing child Container from association with this parent
+ * Container.
+ *
+ * @param child Existing child Container to be removed
+ */
+ public void removeChild(Container child);
+
+
+ /**
+ * Remove a container event listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ public void removeContainerListener(ContainerListener listener);
+
+
+ /**
+ * Remove a property change listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ public void removePropertyChangeListener(PropertyChangeListener listener);
+
+
+ /**
+ * Notify all container event listeners that a particular event has
+ * occurred for this Container. The default implementation performs
+ * this notification synchronously using the calling thread.
+ *
+ * @param type Event type
+ * @param data Event data
+ */
+ public void fireContainerEvent(String type, Object data);
+
+
+ /**
+ * Log a request/response that was destined for this container but has been
+ * handled earlier in the processing chain so that the request/response
+ * still appears in the correct access logs.
+ * @param request Request (associated with the response) to log
+ * @param response Response (associated with the request) to log
+ * @param time Time taken to process the request/response in
+ * milliseconds (use 0 if not known)
+ * @param useDefault Flag that indicates that the request/response should
+ * be logged in the engine's default access log
+ */
+ public void logAccess(Request request, Response response, long time,
+ boolean useDefault);
+
+
+ /**
+ * Identify the AccessLog to use to log a request/response that was destined
+ * for this container but was handled earlier in the processing chain so
+ * that the request/response still appears in the correct access logs.
+ */
+ public AccessLog getAccessLog();
+
+
+ /**
+ * Returns the number of threads available for starting and stopping any
+ * children associated with this container. This allows start/stop calls to
+ * children to be processed in parallel.
+ */
+ public int getStartStopThreads();
+
+
+ /**
+ * Sets the number of threads available for starting and stopping any
+ * children associated with this container. This allows start/stop calls to
+ * children to be processed in parallel.
+ * @param startStopThreads The new number of threads to be used
+ */
+ public void setStartStopThreads(int startStopThreads);
+}
diff --git a/java/org/apache/catalina/Host.java b/java/org/apache/catalina/Host.java
index 72f5dc2..9d27191 100644
--- a/java/org/apache/catalina/Host.java
+++ b/java/org/apache/catalina/Host.java
@@ -1,220 +1,228 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-
-/**
- * A Host is a Container that represents a virtual host in the
- * Catalina servlet engine. It is useful in the following types of scenarios:
- *
- *
You wish to use Interceptors that see every single request processed
- * by this particular virtual host.
- *
You wish to run Catalina in with a standalone HTTP connector, but still
- * want support for multiple virtual hosts.
- *
- * In general, you would not use a Host when deploying Catalina connected
- * to a web server (such as Apache), because the Connector will have
- * utilized the web server's facilities to determine which Context (or
- * perhaps even which Wrapper) should be utilized to process this request.
- *
- * The parent Container attached to a Host is generally an Engine, but may
- * be some other implementation, or may be omitted if it is not necessary.
- *
- * The child containers attached to a Host are generally implementations
- * of Context (representing an individual servlet context).
- *
- * @author Craig R. McClanahan
- * @version $Id$
- */
-
-public interface Host extends Container {
-
-
- // ----------------------------------------------------- Manifest Constants
-
-
- /**
- * The ContainerEvent event type sent when a new alias is added
- * by addAlias().
- */
- public static final String ADD_ALIAS_EVENT = "addAlias";
-
-
- /**
- * The ContainerEvent event type sent when an old alias is removed
- * by removeAlias().
- */
- public static final String REMOVE_ALIAS_EVENT = "removeAlias";
-
-
- // ------------------------------------------------------------- Properties
-
-
- /**
- * Return the XML root for this Host. This can be an absolute
- * pathname, a relative pathname, or a URL.
- * If null, defaults to
- * ${catalina.base}/conf/<engine name>/<host name> directory
- */
- public String getXmlBase();
-
- /**
- * Set the Xml root for this Host. This can be an absolute
- * pathname, a relative pathname, or a URL.
- * If null, defaults to
- * ${catalina.base}/conf/<engine name>/<host name> directory
- * @param xmlBase The new XML root
- */
- public void setXmlBase(String xmlBase);
-
- /**
- * Return the application root for this Host. This can be an absolute
- * pathname, a relative pathname, or a URL.
- */
- public String getAppBase();
-
-
- /**
- * Return an absolute {@link File} for the appBase of this Host. The file
- * will be canonical if possible. There is no guarantee that that the
- * appBase exists.
- */
- public File getAppBaseFile();
-
-
- /**
- * Set the application root for this Host. This can be an absolute
- * pathname, a relative pathname, or a URL.
- *
- * @param appBase The new application root
- */
- public void setAppBase(String appBase);
-
-
- /**
- * Return the value of the auto deploy flag. If true, it indicates that
- * this host's child webapps should be discovered and automatically
- * deployed dynamically.
- */
- public boolean getAutoDeploy();
-
-
- /**
- * Set the auto deploy flag value for this host.
- *
- * @param autoDeploy The new auto deploy flag
- */
- public void setAutoDeploy(boolean autoDeploy);
-
-
- /**
- * Return the Java class name of the context configuration class
- * for new web applications.
- */
- public String getConfigClass();
-
-
- /**
- * Set the Java class name of the context configuration class
- * for new web applications.
- *
- * @param configClass The new context configuration class
- */
- public void setConfigClass(String configClass);
-
-
- /**
- * Return the value of the deploy on startup flag. If true, it indicates
- * that this host's child webapps should be discovered and automatically
- * deployed.
- */
- public boolean getDeployOnStartup();
-
-
- /**
- * Set the deploy on startup flag value for this host.
- *
- * @param deployOnStartup The new deploy on startup flag
- */
- public void setDeployOnStartup(boolean deployOnStartup);
-
-
- /**
- * Return the regular expression that defines the files and directories in
- * the host's appBase that will be ignored by the automatic deployment
- * process.
- */
- public String getDeployIgnore();
-
-
- /**
- * Return the compiled regular expression that defines the files and
- * directories in the host's appBase that will be ignored by the automatic
- * deployment process.
- */
- public Pattern getDeployIgnorePattern();
-
-
- /**
- * Set the regular expression that defines the files and directories in
- * the host's appBase that will be ignored by the automatic deployment
- * process.
- */
- public void setDeployIgnore(String deployIgnore);
-
-
- // --------------------------------------------------------- Public Methods
-
-
- /**
- * Add an alias name that should be mapped to this same Host.
- *
- * @param alias The alias to be added
- */
- public void addAlias(String alias);
-
-
- /**
- * Return the set of alias names for this Host. If none are defined,
- * a zero length array is returned.
- */
- public String[] findAliases();
-
-
- /**
- * Remove the specified alias name from the aliases for this Host.
- *
- * @param alias Alias name to be removed
- */
- public void removeAlias(String alias);
-
- /**
- * Returns true if the Host will attempt to create directories for appBase and xmlBase
- * unless they already exist.
- * @return true if the Host will attempt to create directories
- */
- public boolean getCreateDirs();
- /**
- * Set to true if the Host should attempt to create directories for xmlBase and appBase upon startup
- * @param createDirs
- */
- public void setCreateDirs(boolean createDirs);
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import java.io.File;
+import java.util.concurrent.ExecutorService;
+import java.util.regex.Pattern;
+
+
+/**
+ * A Host is a Container that represents a virtual host in the
+ * Catalina servlet engine. It is useful in the following types of scenarios:
+ *
+ *
You wish to use Interceptors that see every single request processed
+ * by this particular virtual host.
+ *
You wish to run Catalina in with a standalone HTTP connector, but still
+ * want support for multiple virtual hosts.
+ *
+ * In general, you would not use a Host when deploying Catalina connected
+ * to a web server (such as Apache), because the Connector will have
+ * utilized the web server's facilities to determine which Context (or
+ * perhaps even which Wrapper) should be utilized to process this request.
+ *
+ * The parent Container attached to a Host is generally an Engine, but may
+ * be some other implementation, or may be omitted if it is not necessary.
+ *
+ * The child containers attached to a Host are generally implementations
+ * of Context (representing an individual servlet context).
+ *
+ * @author Craig R. McClanahan
+ * @version $Id$
+ */
+
+public interface Host extends Container {
+
+
+ // ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The ContainerEvent event type sent when a new alias is added
+ * by addAlias().
+ */
+ public static final String ADD_ALIAS_EVENT = "addAlias";
+
+
+ /**
+ * The ContainerEvent event type sent when an old alias is removed
+ * by removeAlias().
+ */
+ public static final String REMOVE_ALIAS_EVENT = "removeAlias";
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Return the XML root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ * If null, defaults to
+ * ${catalina.base}/conf/<engine name>/<host name> directory
+ */
+ public String getXmlBase();
+
+ /**
+ * Set the Xml root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ * If null, defaults to
+ * ${catalina.base}/conf/<engine name>/<host name> directory
+ * @param xmlBase The new XML root
+ */
+ public void setXmlBase(String xmlBase);
+
+ /**
+ * Return the application root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ */
+ public String getAppBase();
+
+
+ /**
+ * Return an absolute {@link File} for the appBase of this Host. The file
+ * will be canonical if possible. There is no guarantee that that the
+ * appBase exists.
+ */
+ public File getAppBaseFile();
+
+
+ /**
+ * Set the application root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ *
+ * @param appBase The new application root
+ */
+ public void setAppBase(String appBase);
+
+
+ /**
+ * Return the value of the auto deploy flag. If true, it indicates that
+ * this host's child webapps should be discovered and automatically
+ * deployed dynamically.
+ */
+ public boolean getAutoDeploy();
+
+
+ /**
+ * Set the auto deploy flag value for this host.
+ *
+ * @param autoDeploy The new auto deploy flag
+ */
+ public void setAutoDeploy(boolean autoDeploy);
+
+
+ /**
+ * Return the Java class name of the context configuration class
+ * for new web applications.
+ */
+ public String getConfigClass();
+
+
+ /**
+ * Set the Java class name of the context configuration class
+ * for new web applications.
+ *
+ * @param configClass The new context configuration class
+ */
+ public void setConfigClass(String configClass);
+
+
+ /**
+ * Return the value of the deploy on startup flag. If true, it indicates
+ * that this host's child webapps should be discovered and automatically
+ * deployed.
+ */
+ public boolean getDeployOnStartup();
+
+
+ /**
+ * Set the deploy on startup flag value for this host.
+ *
+ * @param deployOnStartup The new deploy on startup flag
+ */
+ public void setDeployOnStartup(boolean deployOnStartup);
+
+
+ /**
+ * Return the regular expression that defines the files and directories in
+ * the host's appBase that will be ignored by the automatic deployment
+ * process.
+ */
+ public String getDeployIgnore();
+
+
+ /**
+ * Return the compiled regular expression that defines the files and
+ * directories in the host's appBase that will be ignored by the automatic
+ * deployment process.
+ */
+ public Pattern getDeployIgnorePattern();
+
+
+ /**
+ * Set the regular expression that defines the files and directories in
+ * the host's appBase that will be ignored by the automatic deployment
+ * process.
+ */
+ public void setDeployIgnore(String deployIgnore);
+
+
+ /**
+ * Return the executor that is used for starting and stopping contexts. This
+ * is primarily for use by components deploying contexts that want to do
+ * this in a multi-threaded manner.
+ */
+ public ExecutorService getStartStopExecutor();
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Add an alias name that should be mapped to this same Host.
+ *
+ * @param alias The alias to be added
+ */
+ public void addAlias(String alias);
+
+
+ /**
+ * Return the set of alias names for this Host. If none are defined,
+ * a zero length array is returned.
+ */
+ public String[] findAliases();
+
+
+ /**
+ * Remove the specified alias name from the aliases for this Host.
+ *
+ * @param alias Alias name to be removed
+ */
+ public void removeAlias(String alias);
+
+ /**
+ * Returns true if the Host will attempt to create directories for appBase and xmlBase
+ * unless they already exist.
+ * @return true if the Host will attempt to create directories
+ */
+ public boolean getCreateDirs();
+ /**
+ * Set to true if the Host should attempt to create directories for xmlBase and appBase upon startup
+ * @param createDirs
+ */
+ public void setCreateDirs(boolean createDirs);
+
+}
diff --git a/java/org/apache/catalina/core/ContainerBase.java b/java/org/apache/catalina/core/ContainerBase.java
index 4a736a6..0a8edfc 100644
--- a/java/org/apache/catalina/core/ContainerBase.java
+++ b/java/org/apache/catalina/core/ContainerBase.java
@@ -1,1415 +1,1546 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-
-import javax.management.ObjectName;
-import javax.naming.directory.DirContext;
-import javax.servlet.ServletException;
-
-import org.apache.catalina.AccessLog;
-import org.apache.catalina.CatalinaFactory;
-import org.apache.catalina.Cluster;
-import org.apache.catalina.Container;
-import org.apache.catalina.ContainerEvent;
-import org.apache.catalina.ContainerListener;
-import org.apache.catalina.Globals;
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleState;
-import org.apache.catalina.Loader;
-import org.apache.catalina.Manager;
-import org.apache.catalina.Pipeline;
-import org.apache.catalina.Realm;
-import org.apache.catalina.Valve;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.mbeans.MBeanUtils;
-import org.apache.catalina.util.LifecycleMBeanBase;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.naming.resources.ProxyDirContext;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.res.StringManager;
-
-
-/**
- * Abstract implementation of the Container interface, providing common
- * functionality required by nearly every implementation. Classes extending
- * this base class must implement getInfo(), and may implement
- * a replacement for invoke().
- *
- * All subclasses of this abstract base class will include support for a
- * Pipeline object that defines the processing to be performed for each request
- * received by the invoke() method of this class, utilizing the
- * "Chain of Responsibility" design pattern. A subclass should encapsulate its
- * own processing functionality as a Valve, and configure this
- * Valve into the pipeline by calling setBasic().
- *
- * This implementation fires property change events, per the JavaBeans design
- * pattern, for changes in singleton properties. In addition, it fires the
- * following ContainerEvent events to listeners who register
- * themselves with addContainerListener():
- *
- *
- *
Type
- *
Data
- *
Description
- *
- *
- *
addChild
- *
Container
- *
Child container added to this Container.
- *
- *
- *
addValve
- *
Valve
- *
Valve added to this Container.
- *
- *
- *
removeChild
- *
Container
- *
Child container removed from this Container.
- *
- *
- *
removeValve
- *
Valve
- *
Valve removed from this Container.
- *
- *
- *
start
- *
null
- *
Container was started.
- *
- *
- *
stop
- *
null
- *
Container was stopped.
- *
- *
- * Subclasses that fire additional events should document them in the
- * class comments of the implementation class.
- *
- * TODO: Review synchronisation around background processing. See bug 47024.
- *
- * @author Craig R. McClanahan
- */
-public abstract class ContainerBase extends LifecycleMBeanBase
- implements Container {
-
- private static final org.apache.juli.logging.Log log=
- org.apache.juli.logging.LogFactory.getLog( ContainerBase.class );
-
- /**
- * Perform addChild with the permissions of this class.
- * addChild can be called with the XML parser on the stack,
- * this allows the XML parser to have fewer privileges than
- * Tomcat.
- */
- protected class PrivilegedAddChild
- implements PrivilegedAction {
-
- private Container child;
-
- PrivilegedAddChild(Container child) {
- this.child = child;
- }
-
- @Override
- public Void run() {
- addChildInternal(child);
- return null;
- }
-
- }
-
-
- // ----------------------------------------------------- Instance Variables
-
-
- /**
- * The child Containers belonging to this Container, keyed by name.
- */
- protected HashMap children =
- new HashMap();
-
-
- /**
- * The processor delay for this component.
- */
- protected int backgroundProcessorDelay = -1;
-
-
- /**
- * The container event listeners for this Container.
- */
- protected ArrayList listeners = new ArrayList();
-
-
- /**
- * The Loader implementation with which this Container is associated.
- */
- protected Loader loader = null;
-
-
- /**
- * The Logger implementation with which this Container is associated.
- */
- protected Log logger = null;
-
-
- /**
- * Associated logger name.
- */
- protected String logName = null;
-
-
- /**
- * The Manager implementation with which this Container is associated.
- */
- protected Manager manager = null;
-
-
- /**
- * The cluster with which this Container is associated.
- */
- protected Cluster cluster = null;
-
-
- /**
- * The human-readable name of this Container.
- */
- protected String name = null;
-
-
- /**
- * The parent Container to which this Container is a child.
- */
- protected Container parent = null;
-
-
- /**
- * The parent class loader to be configured when we install a Loader.
- */
- protected ClassLoader parentClassLoader = null;
-
-
- /**
- * The Pipeline object with which this Container is associated.
- */
- protected Pipeline pipeline =
- CatalinaFactory.getFactory().createPipeline(this);
-
-
- /**
- * The Realm with which this Container is associated.
- */
- protected Realm realm = null;
-
-
- /**
- * The resources DirContext object with which this Container is associated.
- */
- protected DirContext resources = null;
-
-
- /**
- * The string manager for this package.
- */
- protected static final StringManager sm =
- StringManager.getManager(Constants.Package);
-
-
- /**
- * Will children be started automatically when they are added.
- */
- protected boolean startChildren = true;
-
- /**
- * The property change support for this component.
- */
- protected PropertyChangeSupport support = new PropertyChangeSupport(this);
-
-
- /**
- * The background thread.
- */
- private Thread thread = null;
-
-
- /**
- * The background thread completion semaphore.
- */
- private volatile boolean threadDone = false;
-
-
- /**
- * The access log to use for requests normally handled by this container
- * that have been handled earlier in the processing chain.
- */
- protected volatile AccessLog accessLog = null;
- private volatile boolean accessLogScanComplete = false;
-
- // ------------------------------------------------------------- Properties
-
-
- /**
- * Get the delay between the invocation of the backgroundProcess method on
- * this container and its children. Child containers will not be invoked
- * if their delay value is not negative (which would mean they are using
- * their own thread). Setting this to a positive value will cause
- * a thread to be spawn. After waiting the specified amount of time,
- * the thread will invoke the executePeriodic method on this container
- * and all its children.
- */
- @Override
- public int getBackgroundProcessorDelay() {
- return backgroundProcessorDelay;
- }
-
-
- /**
- * Set the delay between the invocation of the execute method on this
- * container and its children.
- *
- * @param delay The delay in seconds between the invocation of
- * backgroundProcess methods
- */
- @Override
- public void setBackgroundProcessorDelay(int delay) {
- backgroundProcessorDelay = delay;
- }
-
-
- /**
- * Return descriptive information about this Container implementation and
- * the corresponding version number, in the format
- * <description>/<version>.
- */
- @Override
- public String getInfo() {
- return this.getClass().getName();
- }
-
-
- /**
- * Return the Loader with which this Container is associated. If there is
- * no associated Loader, return the Loader associated with our parent
- * Container (if any); otherwise, return null.
- */
- @Override
- public Loader getLoader() {
-
- if (loader != null)
- return (loader);
- if (parent != null)
- return (parent.getLoader());
- return (null);
-
- }
-
-
- /**
- * Set the Loader with which this Container is associated.
- *
- * @param loader The newly associated loader
- */
- @Override
- public synchronized void setLoader(Loader loader) {
-
- // Change components if necessary
- Loader oldLoader = this.loader;
- if (oldLoader == loader)
- return;
- this.loader = loader;
-
- // Stop the old component if necessary
- if (getState().isAvailable() && (oldLoader != null) &&
- (oldLoader instanceof Lifecycle)) {
- try {
- ((Lifecycle) oldLoader).stop();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setLoader: stop: ", e);
- }
- }
-
- // Start the new component if necessary
- if (loader != null)
- loader.setContainer(this);
- if (getState().isAvailable() && (loader != null) &&
- (loader instanceof Lifecycle)) {
- try {
- ((Lifecycle) loader).start();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setLoader: start: ", e);
- }
- }
-
- // Report this property change to interested listeners
- support.firePropertyChange("loader", oldLoader, this.loader);
-
- }
-
-
- /**
- * Return the Logger for this Container.
- */
- @Override
- public Log getLogger() {
-
- if (logger != null)
- return (logger);
- logger = LogFactory.getLog(logName());
- return (logger);
-
- }
-
-
- /**
- * Return the Manager with which this Container is associated. If there is
- * no associated Manager, return the Manager associated with our parent
- * Container (if any); otherwise return null.
- */
- @Override
- public Manager getManager() {
-
- if (manager != null)
- return (manager);
- if (parent != null)
- return (parent.getManager());
- return (null);
-
- }
-
-
- /**
- * Set the Manager with which this Container is associated.
- *
- * @param manager The newly associated Manager
- */
- @Override
- public synchronized void setManager(Manager manager) {
-
- // Change components if necessary
- Manager oldManager = this.manager;
- if (oldManager == manager)
- return;
- this.manager = manager;
-
- // Stop the old component if necessary
- if (getState().isAvailable() && (oldManager != null) &&
- (oldManager instanceof Lifecycle)) {
- try {
- ((Lifecycle) oldManager).stop();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setManager: stop: ", e);
- }
- }
-
- // Start the new component if necessary
- if (manager != null)
- manager.setContainer(this);
- if (getState().isAvailable() && (manager != null) &&
- (manager instanceof Lifecycle)) {
- try {
- ((Lifecycle) manager).start();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setManager: start: ", e);
- }
- }
-
- // Report this property change to interested listeners
- support.firePropertyChange("manager", oldManager, this.manager);
-
- }
-
-
- /**
- * Return an object which may be utilized for mapping to this component.
- */
- @Override
- public Object getMappingObject() {
- return this;
- }
-
-
- /**
- * Return the Cluster with which this Container is associated. If there is
- * no associated Cluster, return the Cluster associated with our parent
- * Container (if any); otherwise return null.
- */
- @Override
- public Cluster getCluster() {
- if (cluster != null)
- return (cluster);
-
- if (parent != null)
- return (parent.getCluster());
-
- return (null);
- }
-
-
- /**
- * Set the Cluster with which this Container is associated.
- *
- * @param cluster The newly associated Cluster
- */
- @Override
- public synchronized void setCluster(Cluster cluster) {
- // Change components if necessary
- Cluster oldCluster = this.cluster;
- if (oldCluster == cluster)
- return;
- this.cluster = cluster;
-
- // Stop the old component if necessary
- if (getState().isAvailable() && (oldCluster != null) &&
- (oldCluster instanceof Lifecycle)) {
- try {
- ((Lifecycle) oldCluster).stop();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setCluster: stop: ", e);
- }
- }
-
- // Start the new component if necessary
- if (cluster != null)
- cluster.setContainer(this);
-
- if (getState().isAvailable() && (cluster != null) &&
- (cluster instanceof Lifecycle)) {
- try {
- ((Lifecycle) cluster).start();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setCluster: start: ", e);
- }
- }
-
- // Report this property change to interested listeners
- support.firePropertyChange("cluster", oldCluster, this.cluster);
- }
-
-
- /**
- * Return a name string (suitable for use by humans) that describes this
- * Container. Within the set of child containers belonging to a particular
- * parent, Container names must be unique.
- */
- @Override
- public String getName() {
-
- return (name);
-
- }
-
-
- /**
- * Set a name string (suitable for use by humans) that describes this
- * Container. Within the set of child containers belonging to a particular
- * parent, Container names must be unique.
- *
- * @param name New name of this container
- *
- * @exception IllegalStateException if this Container has already been
- * added to the children of a parent Container (after which the name
- * may not be changed)
- */
- @Override
- public void setName(String name) {
-
- String oldName = this.name;
- this.name = name;
- support.firePropertyChange("name", oldName, this.name);
- }
-
-
- /**
- * Return if children of this container will be started automatically when
- * they are added to this container.
- */
- public boolean getStartChildren() {
-
- return (startChildren);
-
- }
-
-
- /**
- * Set if children of this container will be started automatically when
- * they are added to this container.
- *
- * @param startChildren New value of the startChildren flag
- */
- public void setStartChildren(boolean startChildren) {
-
- boolean oldStartChildren = this.startChildren;
- this.startChildren = startChildren;
- support.firePropertyChange("startChildren", oldStartChildren, this.startChildren);
- }
-
-
- /**
- * Return the Container for which this Container is a child, if there is
- * one. If there is no defined parent, return null.
- */
- @Override
- public Container getParent() {
-
- return (parent);
-
- }
-
-
- /**
- * Set the parent Container to which this Container is being added as a
- * child. This Container may refuse to become attached to the specified
- * Container by throwing an exception.
- *
- * @param container Container to which this Container is being added
- * as a child
- *
- * @exception IllegalArgumentException if this Container refuses to become
- * attached to the specified Container
- */
- @Override
- public void setParent(Container container) {
-
- Container oldParent = this.parent;
- this.parent = container;
- support.firePropertyChange("parent", oldParent, this.parent);
-
- }
-
-
- /**
- * Return the parent class loader (if any) for this web application.
- * This call is meaningful only after a Loader has
- * been configured.
- */
- @Override
- public ClassLoader getParentClassLoader() {
- if (parentClassLoader != null)
- return (parentClassLoader);
- if (parent != null) {
- return (parent.getParentClassLoader());
- }
- return (ClassLoader.getSystemClassLoader());
-
- }
-
-
- /**
- * Set the parent class loader (if any) for this web application.
- * This call is meaningful only before a Loader has
- * been configured, and the specified value (if non-null) should be
- * passed as an argument to the class loader constructor.
- *
- *
- * @param parent The new parent class loader
- */
- @Override
- public void setParentClassLoader(ClassLoader parent) {
- ClassLoader oldParentClassLoader = this.parentClassLoader;
- this.parentClassLoader = parent;
- support.firePropertyChange("parentClassLoader", oldParentClassLoader,
- this.parentClassLoader);
-
- }
-
-
- /**
- * Return the Pipeline object that manages the Valves associated with
- * this Container.
- */
- @Override
- public Pipeline getPipeline() {
-
- return (this.pipeline);
-
- }
-
-
- /**
- * Return the Realm with which this Container is associated. If there is
- * no associated Realm, return the Realm associated with our parent
- * Container (if any); otherwise return null.
- */
- @Override
- public Realm getRealm() {
-
- if (realm != null)
- return (realm);
- if (parent != null)
- return (parent.getRealm());
- return (null);
-
- }
-
-
- /**
- * Set the Realm with which this Container is associated.
- *
- * @param realm The newly associated Realm
- */
- @Override
- public synchronized void setRealm(Realm realm) {
-
- // Change components if necessary
- Realm oldRealm = this.realm;
- if (oldRealm == realm)
- return;
- this.realm = realm;
-
- // Stop the old component if necessary
- if (getState().isAvailable() && (oldRealm != null) &&
- (oldRealm instanceof Lifecycle)) {
- try {
- ((Lifecycle) oldRealm).stop();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setRealm: stop: ", e);
- }
- }
-
- // Start the new component if necessary
- if (realm != null)
- realm.setContainer(this);
- if (getState().isAvailable() && (realm != null) &&
- (realm instanceof Lifecycle)) {
- try {
- ((Lifecycle) realm).start();
- } catch (LifecycleException e) {
- log.error("ContainerBase.setRealm: start: ", e);
- }
- }
-
- // Report this property change to interested listeners
- support.firePropertyChange("realm", oldRealm, this.realm);
-
- }
-
-
- /**
- * Return the resources DirContext object with which this Container is
- * associated. If there is no associated resources object, return the
- * resources associated with our parent Container (if any); otherwise
- * return null.
- */
- @Override
- public DirContext getResources() {
- if (resources != null)
- return (resources);
- if (parent != null)
- return (parent.getResources());
- return (null);
-
- }
-
-
- /**
- * Set the resources DirContext object with which this Container is
- * associated.
- *
- * @param resources The newly associated DirContext
- */
- @Override
- public synchronized void setResources(DirContext resources) {
- // Called from StandardContext.setResources()
- // <- StandardContext.start()
- // <- ContainerBase.addChildInternal()
-
- // Change components if necessary
- DirContext oldResources = this.resources;
- if (oldResources == resources)
- return;
- Hashtable env = new Hashtable();
- if (getParent() != null)
- env.put(ProxyDirContext.HOST, getParent().getName());
- env.put(ProxyDirContext.CONTEXT, getName());
- this.resources = new ProxyDirContext(env, resources);
- // Report this property change to interested listeners
- support.firePropertyChange("resources", oldResources, this.resources);
-
- }
-
-
- // ------------------------------------------------------ Container Methods
-
-
- /**
- * Add a new child Container to those associated with this Container,
- * if supported. Prior to adding this Container to the set of children,
- * the child's setParent() method must be called, with this
- * Container as an argument. This method may thrown an
- * IllegalArgumentException if this Container chooses not
- * to be attached to the specified Container, in which case it is not added
- *
- * @param child New child Container to be added
- *
- * @exception IllegalArgumentException if this exception is thrown by
- * the setParent() method of the child Container
- * @exception IllegalArgumentException if the new child does not have
- * a name unique from that of existing children of this Container
- * @exception IllegalStateException if this Container does not support
- * child Containers
- */
- @Override
- public void addChild(Container child) {
- if (Globals.IS_SECURITY_ENABLED) {
- PrivilegedAction dp =
- new PrivilegedAddChild(child);
- AccessController.doPrivileged(dp);
- } else {
- addChildInternal(child);
- }
- }
-
- private void addChildInternal(Container child) {
-
- if( log.isDebugEnabled() )
- log.debug("Add child " + child + " " + this);
- synchronized(children) {
- if (children.get(child.getName()) != null)
- throw new IllegalArgumentException("addChild: Child name '" +
- child.getName() +
- "' is not unique");
- child.setParent(this); // May throw IAE
- children.put(child.getName(), child);
- }
-
- // Start child
- // Don't do this inside sync block - start can be a slow process and
- // locking the children object can cause problems elsewhere
- if ((getState().isAvailable() ||
- LifecycleState.STARTING_PREP.equals(getState())) &&
- startChildren) {
- boolean success = false;
- try {
- child.start();
- success = true;
- } catch (LifecycleException e) {
- log.error("ContainerBase.addChild: start: ", e);
- throw new IllegalStateException
- ("ContainerBase.addChild: start: " + e);
- } finally {
- if (!success) {
- synchronized (children) {
- children.remove(child.getName());
- }
- }
- }
- }
-
- fireContainerEvent(ADD_CHILD_EVENT, child);
- }
-
-
- /**
- * Add a container event listener to this component.
- *
- * @param listener The listener to add
- */
- @Override
- public void addContainerListener(ContainerListener listener) {
-
- synchronized (listeners) {
- listeners.add(listener);
- }
-
- }
-
-
- /**
- * Add a property change listener to this component.
- *
- * @param listener The listener to add
- */
- @Override
- public void addPropertyChangeListener(PropertyChangeListener listener) {
-
- support.addPropertyChangeListener(listener);
-
- }
-
-
- /**
- * Return the child Container, associated with this Container, with
- * the specified name (if any); otherwise, return null
- *
- * @param name Name of the child Container to be retrieved
- */
- @Override
- public Container findChild(String name) {
-
- if (name == null)
- return (null);
- synchronized (children) {
- return children.get(name);
- }
-
- }
-
-
- /**
- * Return the set of children Containers associated with this Container.
- * If this Container has no children, a zero-length array is returned.
- */
- @Override
- public Container[] findChildren() {
-
- synchronized (children) {
- Container results[] = new Container[children.size()];
- return children.values().toArray(results);
- }
-
- }
-
-
- /**
- * Return the set of container listeners associated with this Container.
- * If this Container has no registered container listeners, a zero-length
- * array is returned.
- */
- @Override
- public ContainerListener[] findContainerListeners() {
-
- synchronized (listeners) {
- ContainerListener[] results =
- new ContainerListener[listeners.size()];
- return listeners.toArray(results);
- }
-
- }
-
-
- /**
- * Process the specified Request, to produce the corresponding Response,
- * by invoking the first Valve in our pipeline (if any), or the basic
- * Valve otherwise.
- *
- * @param request Request to be processed
- * @param response Response to be produced
- *
- * @exception IllegalStateException if neither a pipeline or a basic
- * Valve have been configured for this Container
- * @exception IOException if an input/output error occurred while
- * processing
- * @exception ServletException if a ServletException was thrown
- * while processing this request
- */
- @Override
- public void invoke(Request request, Response response)
- throws IOException, ServletException {
-
- pipeline.getFirst().invoke(request, response);
-
- }
-
-
- /**
- * Remove an existing child Container from association with this parent
- * Container.
- *
- * @param child Existing child Container to be removed
- */
- @Override
- public void removeChild(Container child) {
-
- if (child == null) {
- return;
- }
-
- synchronized(children) {
- if (children.get(child.getName()) == null)
- return;
- children.remove(child.getName());
- }
-
- try {
- if (child.getState().isAvailable()) {
- child.stop();
- }
- } catch (LifecycleException e) {
- log.error("ContainerBase.removeChild: stop: ", e);
- }
-
- fireContainerEvent(REMOVE_CHILD_EVENT, child);
-
- try {
- // child.destroy() may have already been called which would have
- // triggered this call. If that is the case, no need to destroy the
- // child again.
- if (!LifecycleState.DESTROYING.equals(child.getState())) {
- child.destroy();
- }
- } catch (LifecycleException e) {
- log.error("ContainerBase.removeChild: destroy: ", e);
- }
-
- }
-
-
- /**
- * Remove a container event listener from this component.
- *
- * @param listener The listener to remove
- */
- @Override
- public void removeContainerListener(ContainerListener listener) {
-
- synchronized (listeners) {
- listeners.remove(listener);
- }
-
- }
-
-
- /**
- * Remove a property change listener from this component.
- *
- * @param listener The listener to remove
- */
- @Override
- public void removePropertyChangeListener(PropertyChangeListener listener) {
-
- support.removePropertyChangeListener(listener);
-
- }
-
-
- /**
- * Start this component and implement the requirements
- * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
- *
- * @exception LifecycleException if this component detects a fatal error
- * that prevents this component from being used
- */
- @Override
- protected synchronized void startInternal() throws LifecycleException {
-
- // Start our subordinate components, if any
- if ((loader != null) && (loader instanceof Lifecycle))
- ((Lifecycle) loader).start();
- logger = null;
- getLogger();
- if ((logger != null) && (logger instanceof Lifecycle))
- ((Lifecycle) logger).start();
- if ((manager != null) && (manager instanceof Lifecycle))
- ((Lifecycle) manager).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++) {
- children[i].start();
- }
-
- // Start the Valves in our pipeline (including the basic), if any
- if (pipeline instanceof Lifecycle)
- ((Lifecycle) pipeline).start();
-
-
- setState(LifecycleState.STARTING);
-
- // Start our thread
- threadStart();
-
- }
-
-
- /**
- * Stop this component and implement the requirements
- * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
- *
- * @exception LifecycleException if this component detects a fatal error
- * that prevents this component from being used
- */
- @Override
- protected synchronized void stopInternal() throws LifecycleException {
-
- // Stop our thread
- threadStop();
-
- setState(LifecycleState.STOPPING);
-
- // Stop the Valves in our pipeline (including the basic), if any
- if (pipeline instanceof Lifecycle &&
- ((Lifecycle) pipeline).getState().isAvailable()) {
- ((Lifecycle) pipeline).stop();
- }
-
- // Stop our child containers, if any
- Container children[] = findChildren();
- for (int i = 0; i < children.length; i++) {
- children[i].stop();
- }
-
- // Stop our subordinate components, if any
- if ((resources != null) && (resources instanceof Lifecycle)) {
- ((Lifecycle) resources).stop();
- }
- if ((realm != null) && (realm instanceof Lifecycle)) {
- ((Lifecycle) realm).stop();
- }
- if ((cluster != null) && (cluster instanceof Lifecycle)) {
- ((Lifecycle) cluster).stop();
- }
- if ((manager != null) && (manager instanceof Lifecycle) &&
- ((Lifecycle) manager).getState().isAvailable() ) {
- ((Lifecycle) manager).stop();
- }
- if ((logger != null) && (logger instanceof Lifecycle)) {
- ((Lifecycle) logger).stop();
- }
- if ((loader != null) && (loader instanceof Lifecycle)) {
- ((Lifecycle) loader).stop();
- }
- }
-
- @Override
- protected void destroyInternal() throws LifecycleException {
-
- // Stop the Valves in our pipeline (including the basic), if any
- if (pipeline instanceof Lifecycle) {
- ((Lifecycle) pipeline).destroy();
- }
-
- // Remove children now this container is being destroyed
- for (Container child : findChildren()) {
- removeChild(child);
- }
-
- // Required if the child is destroyed directly.
- if (parent != null) {
- parent.removeChild(this);
- }
-
- super.destroyInternal();
- }
-
-
- /**
- * Check this container for an access log and if none is found, look to the
- * parent. If there is no parent and still none is found, use the NoOp
- * access log.
- */
- @Override
- public void logAccess(Request request, Response response, long time,
- boolean useDefault) {
-
- boolean logged = false;
-
- if (getAccessLog() != null) {
- getAccessLog().log(request, response, time);
- logged = true;
- }
-
- if (getParent() != null) {
- // No need to use default logger once request/response has been logged
- // once
- getParent().logAccess(request, response, time, (useDefault && !logged));
- }
- }
-
- @Override
- public AccessLog getAccessLog() {
-
- if (accessLogScanComplete) {
- return accessLog;
- }
-
- AccessLogAdapter adapter = null;
- Valve valves[] = getPipeline().getValves();
- for (Valve valve : valves) {
- if (valve instanceof AccessLog) {
- if (adapter == null) {
- adapter = new AccessLogAdapter((AccessLog) valve);
- } else {
- adapter.add((AccessLog) valve);
- }
- }
- }
- if (adapter != null) {
- accessLog = adapter;
- }
- accessLogScanComplete = true;
- return accessLog;
- }
-
- // ------------------------------------------------------- Pipeline Methods
-
-
- /**
- * Convenience method, intended for use by the digester to simplify the
- * process of adding Valves to containers. See
- * {@link Pipeline#addValve(Valve)} for full details. Components other than
- * the digester should use {@link #getPipeline()}.{@link #addValve(Valve)} in case a
- * future implementation provides an alternative method for the digester to
- * use.
- *
- * @param valve Valve to be added
- *
- * @exception IllegalArgumentException if this Container refused to
- * accept the specified Valve
- * @exception IllegalArgumentException if the specified Valve refuses to be
- * associated with this Container
- * @exception IllegalStateException if the specified Valve is already
- * associated with a different Container
- */
- public synchronized void addValve(Valve valve) {
-
- pipeline.addValve(valve);
- }
-
-
- /**
- * Execute a periodic task, such as reloading, etc. This method will be
- * invoked inside the classloading context of this container. Unexpected
- * throwables will be caught and logged.
- */
- @Override
- public void backgroundProcess() {
-
- if (!getState().isAvailable())
- return;
-
- if (cluster != null) {
- try {
- cluster.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);
- }
- }
- if (loader != null) {
- try {
- loader.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e);
- }
- }
- if (manager != null) {
- try {
- manager.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e);
- }
- }
- if (realm != null) {
- try {
- realm.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);
- }
- }
- Valve current = pipeline.getFirst();
- while (current != null) {
- try {
- current.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);
- }
- current = current.getNext();
- }
- fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
- }
-
-
- // ------------------------------------------------------ Protected Methods
-
-
- /**
- * Notify all container event listeners that a particular event has
- * occurred for this Container. The default implementation performs
- * this notification synchronously using the calling thread.
- *
- * @param type Event type
- * @param data Event data
- */
- @Override
- public void fireContainerEvent(String type, Object data) {
-
- if (listeners.size() < 1)
- return;
- ContainerEvent event = new ContainerEvent(this, type, data);
- ContainerListener list[] = new ContainerListener[0];
- synchronized (listeners) {
- list = listeners.toArray(list);
- }
- for (int i = 0; i < list.length; i++)
- list[i].containerEvent(event);
-
- }
-
-
- /**
- * Return the abbreviated name of this container for logging messages
- */
- protected String logName() {
-
- if (logName != null) {
- return logName;
- }
- String loggerName = null;
- Container current = this;
- while (current != null) {
- String name = current.getName();
- if ((name == null) || (name.equals(""))) {
- name = "/";
- } else if (name.startsWith("##")) {
- name = "/" + name;
- }
- loggerName = "[" + name + "]"
- + ((loggerName != null) ? ("." + loggerName) : "");
- current = current.getParent();
- }
- logName = ContainerBase.class.getName() + "." + loggerName;
- return logName;
-
- }
-
-
- // -------------------- JMX and Registration --------------------
-
- @Override
- protected String getDomainInternal() {
- return MBeanUtils.getDomain(this);
- }
-
- public ObjectName[] getChildren() {
- ObjectName result[]=new ObjectName[children.size()];
- Iterator it=children.values().iterator();
- int i=0;
- while( it.hasNext() ) {
- Object next=it.next();
- if( next instanceof ContainerBase ) {
- result[i++]=((ContainerBase)next).getObjectName();
- }
- }
- return result;
- }
-
-
- // -------------------- Background Thread --------------------
-
- /**
- * Start the background thread that will periodically check for
- * session timeouts.
- */
- protected void threadStart() {
-
- if (thread != null)
- return;
- if (backgroundProcessorDelay <= 0)
- return;
-
- threadDone = false;
- String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
- thread = new Thread(new ContainerBackgroundProcessor(), threadName);
- thread.setDaemon(true);
- thread.start();
-
- }
-
-
- /**
- * Stop the background thread that is periodically checking for
- * session timeouts.
- */
- protected void threadStop() {
-
- if (thread == null)
- return;
-
- threadDone = true;
- thread.interrupt();
- try {
- thread.join();
- } catch (InterruptedException e) {
- // Ignore
- }
-
- thread = null;
-
- }
-
-
- // -------------------------------------- ContainerExecuteDelay Inner Class
-
-
- /**
- * Private thread class to invoke the backgroundProcess method
- * of this container and its children after a fixed delay.
- */
- protected class ContainerBackgroundProcessor implements Runnable {
-
- @Override
- public void run() {
- while (!threadDone) {
- try {
- Thread.sleep(backgroundProcessorDelay * 1000L);
- } catch (InterruptedException e) {
- // Ignore
- }
- if (!threadDone) {
- Container parent = (Container) getMappingObject();
- ClassLoader cl =
- Thread.currentThread().getContextClassLoader();
- if (parent.getLoader() != null) {
- cl = parent.getLoader().getClassLoader();
- }
- processChildren(parent, cl);
- }
- }
- }
-
- protected void processChildren(Container container, ClassLoader cl) {
- try {
- if (container.getLoader() != null) {
- Thread.currentThread().setContextClassLoader
- (container.getLoader().getClassLoader());
- }
- container.backgroundProcess();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error("Exception invoking periodic operation: ", t);
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
- Container[] children = container.findChildren();
- for (int i = 0; i < children.length; i++) {
- if (children[i].getBackgroundProcessorDelay() <= 0) {
- processChildren(children[i], cl);
- }
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.ObjectName;
+import javax.naming.directory.DirContext;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.AccessLog;
+import org.apache.catalina.CatalinaFactory;
+import org.apache.catalina.Cluster;
+import org.apache.catalina.Container;
+import org.apache.catalina.ContainerEvent;
+import org.apache.catalina.ContainerListener;
+import org.apache.catalina.Globals;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Loader;
+import org.apache.catalina.Manager;
+import org.apache.catalina.Pipeline;
+import org.apache.catalina.Realm;
+import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.mbeans.MBeanUtils;
+import org.apache.catalina.util.LifecycleMBeanBase;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.naming.resources.ProxyDirContext;
+import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.res.StringManager;
+
+
+/**
+ * Abstract implementation of the Container interface, providing common
+ * functionality required by nearly every implementation. Classes extending
+ * this base class must implement getInfo(), and may implement
+ * a replacement for invoke().
+ *
+ * All subclasses of this abstract base class will include support for a
+ * Pipeline object that defines the processing to be performed for each request
+ * received by the invoke() method of this class, utilizing the
+ * "Chain of Responsibility" design pattern. A subclass should encapsulate its
+ * own processing functionality as a Valve, and configure this
+ * Valve into the pipeline by calling setBasic().
+ *
+ * This implementation fires property change events, per the JavaBeans design
+ * pattern, for changes in singleton properties. In addition, it fires the
+ * following ContainerEvent events to listeners who register
+ * themselves with addContainerListener():
+ *
+ *
+ *
Type
+ *
Data
+ *
Description
+ *
+ *
+ *
addChild
+ *
Container
+ *
Child container added to this Container.
+ *
+ *
+ *
addValve
+ *
Valve
+ *
Valve added to this Container.
+ *
+ *
+ *
removeChild
+ *
Container
+ *
Child container removed from this Container.
+ *
+ *
+ *
removeValve
+ *
Valve
+ *
Valve removed from this Container.
+ *
+ *
+ *
start
+ *
null
+ *
Container was started.
+ *
+ *
+ *
stop
+ *
null
+ *
Container was stopped.
+ *
+ *
+ * Subclasses that fire additional events should document them in the
+ * class comments of the implementation class.
+ *
+ * TODO: Review synchronisation around background processing. See bug 47024.
+ *
+ * @author Craig R. McClanahan
+ */
+public abstract class ContainerBase extends LifecycleMBeanBase
+ implements Container {
+
+ private static final org.apache.juli.logging.Log log=
+ org.apache.juli.logging.LogFactory.getLog( ContainerBase.class );
+
+ /**
+ * Perform addChild with the permissions of this class.
+ * addChild can be called with the XML parser on the stack,
+ * this allows the XML parser to have fewer privileges than
+ * Tomcat.
+ */
+ protected class PrivilegedAddChild
+ implements PrivilegedAction {
+
+ private Container child;
+
+ PrivilegedAddChild(Container child) {
+ this.child = child;
+ }
+
+ @Override
+ public Void run() {
+ addChildInternal(child);
+ return null;
+ }
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The child Containers belonging to this Container, keyed by name.
+ */
+ protected HashMap children =
+ new HashMap();
+
+
+ /**
+ * The processor delay for this component.
+ */
+ protected int backgroundProcessorDelay = -1;
+
+
+ /**
+ * The container event listeners for this Container.
+ */
+ protected ArrayList listeners = new ArrayList();
+
+
+ /**
+ * The Loader implementation with which this Container is associated.
+ */
+ protected Loader loader = null;
+
+
+ /**
+ * The Logger implementation with which this Container is associated.
+ */
+ protected Log logger = null;
+
+
+ /**
+ * Associated logger name.
+ */
+ protected String logName = null;
+
+
+ /**
+ * The Manager implementation with which this Container is associated.
+ */
+ protected Manager manager = null;
+
+
+ /**
+ * The cluster with which this Container is associated.
+ */
+ protected Cluster cluster = null;
+
+
+ /**
+ * The human-readable name of this Container.
+ */
+ protected String name = null;
+
+
+ /**
+ * The parent Container to which this Container is a child.
+ */
+ protected Container parent = null;
+
+
+ /**
+ * The parent class loader to be configured when we install a Loader.
+ */
+ protected ClassLoader parentClassLoader = null;
+
+
+ /**
+ * The Pipeline object with which this Container is associated.
+ */
+ protected Pipeline pipeline =
+ CatalinaFactory.getFactory().createPipeline(this);
+
+
+ /**
+ * The Realm with which this Container is associated.
+ */
+ protected Realm realm = null;
+
+
+ /**
+ * The resources DirContext object with which this Container is associated.
+ */
+ protected DirContext resources = null;
+
+
+ /**
+ * The string manager for this package.
+ */
+ protected static final StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ /**
+ * Will children be started automatically when they are added.
+ */
+ protected boolean startChildren = true;
+
+ /**
+ * The property change support for this component.
+ */
+ protected PropertyChangeSupport support = new PropertyChangeSupport(this);
+
+
+ /**
+ * The background thread.
+ */
+ private Thread thread = null;
+
+
+ /**
+ * The background thread completion semaphore.
+ */
+ private volatile boolean threadDone = false;
+
+
+ /**
+ * The access log to use for requests normally handled by this container
+ * that have been handled earlier in the processing chain.
+ */
+ protected volatile AccessLog accessLog = null;
+ private volatile boolean accessLogScanComplete = false;
+
+
+ /**
+ * The number of threads available to process start and stop events for any
+ * children associated with this container.
+ */
+ private int startStopThreads = 1;
+ protected ThreadPoolExecutor startStopExecutor;
+
+ // ------------------------------------------------------------- Properties
+
+ @Override
+ public int getStartStopThreads() {
+ return startStopThreads;
+ }
+
+ /**
+ * Handles the special values.
+ */
+ private int getStartStopThreadsInternal() {
+ int result = getStartStopThreads();
+
+ // Positive values are unchanged
+ if (result > 0) {
+ return result;
+ }
+
+ // Zero == Runtime.getRuntime().availableProcessors()
+ // -ve == Runtime.getRuntime().availableProcessors() + value
+ // These two are the same
+ result = Runtime.getRuntime().availableProcessors() + result;
+ if (result < 1) {
+ result = 1;
+ }
+ return result;
+ }
+
+ @Override
+ public void setStartStopThreads(int startStopThreads) {
+ this.startStopThreads = startStopThreads;
+
+ // Use local copies to ensure thread safety
+ ThreadPoolExecutor executor = startStopExecutor;
+ if (executor != null) {
+ int newThreads = getStartStopThreadsInternal();
+ executor.setMaximumPoolSize(newThreads);
+ executor.setCorePoolSize(newThreads);
+ }
+ }
+
+
+ /**
+ * Get the delay between the invocation of the backgroundProcess method on
+ * this container and its children. Child containers will not be invoked
+ * if their delay value is not negative (which would mean they are using
+ * their own thread). Setting this to a positive value will cause
+ * a thread to be spawn. After waiting the specified amount of time,
+ * the thread will invoke the executePeriodic method on this container
+ * and all its children.
+ */
+ @Override
+ public int getBackgroundProcessorDelay() {
+ return backgroundProcessorDelay;
+ }
+
+
+ /**
+ * Set the delay between the invocation of the execute method on this
+ * container and its children.
+ *
+ * @param delay The delay in seconds between the invocation of
+ * backgroundProcess methods
+ */
+ @Override
+ public void setBackgroundProcessorDelay(int delay) {
+ backgroundProcessorDelay = delay;
+ }
+
+
+ /**
+ * Return descriptive information about this Container implementation and
+ * the corresponding version number, in the format
+ * <description>/<version>.
+ */
+ @Override
+ public String getInfo() {
+ return this.getClass().getName();
+ }
+
+
+ /**
+ * Return the Loader with which this Container is associated. If there is
+ * no associated Loader, return the Loader associated with our parent
+ * Container (if any); otherwise, return null.
+ */
+ @Override
+ public Loader getLoader() {
+
+ if (loader != null)
+ return (loader);
+ if (parent != null)
+ return (parent.getLoader());
+ return (null);
+
+ }
+
+
+ /**
+ * Set the Loader with which this Container is associated.
+ *
+ * @param loader The newly associated loader
+ */
+ @Override
+ public synchronized void setLoader(Loader loader) {
+
+ // Change components if necessary
+ Loader oldLoader = this.loader;
+ if (oldLoader == loader)
+ return;
+ this.loader = loader;
+
+ // Stop the old component if necessary
+ if (getState().isAvailable() && (oldLoader != null) &&
+ (oldLoader instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) oldLoader).stop();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setLoader: stop: ", e);
+ }
+ }
+
+ // Start the new component if necessary
+ if (loader != null)
+ loader.setContainer(this);
+ if (getState().isAvailable() && (loader != null) &&
+ (loader instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) loader).start();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setLoader: start: ", e);
+ }
+ }
+
+ // Report this property change to interested listeners
+ support.firePropertyChange("loader", oldLoader, this.loader);
+
+ }
+
+
+ /**
+ * Return the Logger for this Container.
+ */
+ @Override
+ public Log getLogger() {
+
+ if (logger != null)
+ return (logger);
+ logger = LogFactory.getLog(logName());
+ return (logger);
+
+ }
+
+
+ /**
+ * Return the Manager with which this Container is associated. If there is
+ * no associated Manager, return the Manager associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ @Override
+ public Manager getManager() {
+
+ if (manager != null)
+ return (manager);
+ if (parent != null)
+ return (parent.getManager());
+ return (null);
+
+ }
+
+
+ /**
+ * Set the Manager with which this Container is associated.
+ *
+ * @param manager The newly associated Manager
+ */
+ @Override
+ public synchronized void setManager(Manager manager) {
+
+ // Change components if necessary
+ Manager oldManager = this.manager;
+ if (oldManager == manager)
+ return;
+ this.manager = manager;
+
+ // Stop the old component if necessary
+ if (getState().isAvailable() && (oldManager != null) &&
+ (oldManager instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) oldManager).stop();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setManager: stop: ", e);
+ }
+ }
+
+ // Start the new component if necessary
+ if (manager != null)
+ manager.setContainer(this);
+ if (getState().isAvailable() && (manager != null) &&
+ (manager instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) manager).start();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setManager: start: ", e);
+ }
+ }
+
+ // Report this property change to interested listeners
+ support.firePropertyChange("manager", oldManager, this.manager);
+
+ }
+
+
+ /**
+ * Return an object which may be utilized for mapping to this component.
+ */
+ @Override
+ public Object getMappingObject() {
+ return this;
+ }
+
+
+ /**
+ * Return the Cluster with which this Container is associated. If there is
+ * no associated Cluster, return the Cluster associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ @Override
+ public Cluster getCluster() {
+ if (cluster != null)
+ return (cluster);
+
+ if (parent != null)
+ return (parent.getCluster());
+
+ return (null);
+ }
+
+
+ /**
+ * Set the Cluster with which this Container is associated.
+ *
+ * @param cluster The newly associated Cluster
+ */
+ @Override
+ public synchronized void setCluster(Cluster cluster) {
+ // Change components if necessary
+ Cluster oldCluster = this.cluster;
+ if (oldCluster == cluster)
+ return;
+ this.cluster = cluster;
+
+ // Stop the old component if necessary
+ if (getState().isAvailable() && (oldCluster != null) &&
+ (oldCluster instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) oldCluster).stop();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setCluster: stop: ", e);
+ }
+ }
+
+ // Start the new component if necessary
+ if (cluster != null)
+ cluster.setContainer(this);
+
+ if (getState().isAvailable() && (cluster != null) &&
+ (cluster instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) cluster).start();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setCluster: start: ", e);
+ }
+ }
+
+ // Report this property change to interested listeners
+ support.firePropertyChange("cluster", oldCluster, this.cluster);
+ }
+
+
+ /**
+ * Return a name string (suitable for use by humans) that describes this
+ * Container. Within the set of child containers belonging to a particular
+ * parent, Container names must be unique.
+ */
+ @Override
+ public String getName() {
+
+ return (name);
+
+ }
+
+
+ /**
+ * Set a name string (suitable for use by humans) that describes this
+ * Container. Within the set of child containers belonging to a particular
+ * parent, Container names must be unique.
+ *
+ * @param name New name of this container
+ *
+ * @exception IllegalStateException if this Container has already been
+ * added to the children of a parent Container (after which the name
+ * may not be changed)
+ */
+ @Override
+ public void setName(String name) {
+
+ String oldName = this.name;
+ this.name = name;
+ support.firePropertyChange("name", oldName, this.name);
+ }
+
+
+ /**
+ * Return if children of this container will be started automatically when
+ * they are added to this container.
+ */
+ public boolean getStartChildren() {
+
+ return (startChildren);
+
+ }
+
+
+ /**
+ * Set if children of this container will be started automatically when
+ * they are added to this container.
+ *
+ * @param startChildren New value of the startChildren flag
+ */
+ public void setStartChildren(boolean startChildren) {
+
+ boolean oldStartChildren = this.startChildren;
+ this.startChildren = startChildren;
+ support.firePropertyChange("startChildren", oldStartChildren, this.startChildren);
+ }
+
+
+ /**
+ * Return the Container for which this Container is a child, if there is
+ * one. If there is no defined parent, return null.
+ */
+ @Override
+ public Container getParent() {
+
+ return (parent);
+
+ }
+
+
+ /**
+ * Set the parent Container to which this Container is being added as a
+ * child. This Container may refuse to become attached to the specified
+ * Container by throwing an exception.
+ *
+ * @param container Container to which this Container is being added
+ * as a child
+ *
+ * @exception IllegalArgumentException if this Container refuses to become
+ * attached to the specified Container
+ */
+ @Override
+ public void setParent(Container container) {
+
+ Container oldParent = this.parent;
+ this.parent = container;
+ support.firePropertyChange("parent", oldParent, this.parent);
+
+ }
+
+
+ /**
+ * Return the parent class loader (if any) for this web application.
+ * This call is meaningful only after a Loader has
+ * been configured.
+ */
+ @Override
+ public ClassLoader getParentClassLoader() {
+ if (parentClassLoader != null)
+ return (parentClassLoader);
+ if (parent != null) {
+ return (parent.getParentClassLoader());
+ }
+ return (ClassLoader.getSystemClassLoader());
+
+ }
+
+
+ /**
+ * Set the parent class loader (if any) for this web application.
+ * This call is meaningful only before a Loader has
+ * been configured, and the specified value (if non-null) should be
+ * passed as an argument to the class loader constructor.
+ *
+ *
+ * @param parent The new parent class loader
+ */
+ @Override
+ public void setParentClassLoader(ClassLoader parent) {
+ ClassLoader oldParentClassLoader = this.parentClassLoader;
+ this.parentClassLoader = parent;
+ support.firePropertyChange("parentClassLoader", oldParentClassLoader,
+ this.parentClassLoader);
+
+ }
+
+
+ /**
+ * Return the Pipeline object that manages the Valves associated with
+ * this Container.
+ */
+ @Override
+ public Pipeline getPipeline() {
+
+ return (this.pipeline);
+
+ }
+
+
+ /**
+ * Return the Realm with which this Container is associated. If there is
+ * no associated Realm, return the Realm associated with our parent
+ * Container (if any); otherwise return null.
+ */
+ @Override
+ public Realm getRealm() {
+
+ if (realm != null)
+ return (realm);
+ if (parent != null)
+ return (parent.getRealm());
+ return (null);
+
+ }
+
+
+ /**
+ * Set the Realm with which this Container is associated.
+ *
+ * @param realm The newly associated Realm
+ */
+ @Override
+ public synchronized void setRealm(Realm realm) {
+
+ // Change components if necessary
+ Realm oldRealm = this.realm;
+ if (oldRealm == realm)
+ return;
+ this.realm = realm;
+
+ // Stop the old component if necessary
+ if (getState().isAvailable() && (oldRealm != null) &&
+ (oldRealm instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) oldRealm).stop();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setRealm: stop: ", e);
+ }
+ }
+
+ // Start the new component if necessary
+ if (realm != null)
+ realm.setContainer(this);
+ if (getState().isAvailable() && (realm != null) &&
+ (realm instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) realm).start();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setRealm: start: ", e);
+ }
+ }
+
+ // Report this property change to interested listeners
+ support.firePropertyChange("realm", oldRealm, this.realm);
+
+ }
+
+
+ /**
+ * Return the resources DirContext object with which this Container is
+ * associated. If there is no associated resources object, return the
+ * resources associated with our parent Container (if any); otherwise
+ * return null.
+ */
+ @Override
+ public DirContext getResources() {
+ if (resources != null)
+ return (resources);
+ if (parent != null)
+ return (parent.getResources());
+ return (null);
+
+ }
+
+
+ /**
+ * Set the resources DirContext object with which this Container is
+ * associated.
+ *
+ * @param resources The newly associated DirContext
+ */
+ @Override
+ public synchronized void setResources(DirContext resources) {
+ // Called from StandardContext.setResources()
+ // <- StandardContext.start()
+ // <- ContainerBase.addChildInternal()
+
+ // Change components if necessary
+ DirContext oldResources = this.resources;
+ if (oldResources == resources)
+ return;
+ Hashtable env = new Hashtable();
+ if (getParent() != null)
+ env.put(ProxyDirContext.HOST, getParent().getName());
+ env.put(ProxyDirContext.CONTEXT, getName());
+ this.resources = new ProxyDirContext(env, resources);
+ // Report this property change to interested listeners
+ support.firePropertyChange("resources", oldResources, this.resources);
+
+ }
+
+
+ // ------------------------------------------------------ Container Methods
+
+
+ /**
+ * Add a new child Container to those associated with this Container,
+ * if supported. Prior to adding this Container to the set of children,
+ * the child's setParent() method must be called, with this
+ * Container as an argument. This method may thrown an
+ * IllegalArgumentException if this Container chooses not
+ * to be attached to the specified Container, in which case it is not added
+ *
+ * @param child New child Container to be added
+ *
+ * @exception IllegalArgumentException if this exception is thrown by
+ * the setParent() method of the child Container
+ * @exception IllegalArgumentException if the new child does not have
+ * a name unique from that of existing children of this Container
+ * @exception IllegalStateException if this Container does not support
+ * child Containers
+ */
+ @Override
+ public void addChild(Container child) {
+ if (Globals.IS_SECURITY_ENABLED) {
+ PrivilegedAction dp =
+ new PrivilegedAddChild(child);
+ AccessController.doPrivileged(dp);
+ } else {
+ addChildInternal(child);
+ }
+ }
+
+ private void addChildInternal(Container child) {
+
+ if( log.isDebugEnabled() )
+ log.debug("Add child " + child + " " + this);
+ synchronized(children) {
+ if (children.get(child.getName()) != null)
+ throw new IllegalArgumentException("addChild: Child name '" +
+ child.getName() +
+ "' is not unique");
+ child.setParent(this); // May throw IAE
+ children.put(child.getName(), child);
+ }
+
+ // Start child
+ // Don't do this inside sync block - start can be a slow process and
+ // locking the children object can cause problems elsewhere
+ if ((getState().isAvailable() ||
+ LifecycleState.STARTING_PREP.equals(getState())) &&
+ startChildren) {
+ boolean success = false;
+ try {
+ child.start();
+ success = true;
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.addChild: start: ", e);
+ throw new IllegalStateException
+ ("ContainerBase.addChild: start: " + e);
+ } finally {
+ if (!success) {
+ synchronized (children) {
+ children.remove(child.getName());
+ }
+ }
+ }
+ }
+
+ fireContainerEvent(ADD_CHILD_EVENT, child);
+ }
+
+
+ /**
+ * Add a container event listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ @Override
+ public void addContainerListener(ContainerListener listener) {
+
+ synchronized (listeners) {
+ listeners.add(listener);
+ }
+
+ }
+
+
+ /**
+ * Add a property change listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+
+ support.addPropertyChangeListener(listener);
+
+ }
+
+
+ /**
+ * Return the child Container, associated with this Container, with
+ * the specified name (if any); otherwise, return null
+ *
+ * @param name Name of the child Container to be retrieved
+ */
+ @Override
+ public Container findChild(String name) {
+
+ if (name == null)
+ return (null);
+ synchronized (children) {
+ return children.get(name);
+ }
+
+ }
+
+
+ /**
+ * Return the set of children Containers associated with this Container.
+ * If this Container has no children, a zero-length array is returned.
+ */
+ @Override
+ public Container[] findChildren() {
+
+ synchronized (children) {
+ Container results[] = new Container[children.size()];
+ return children.values().toArray(results);
+ }
+
+ }
+
+
+ /**
+ * Return the set of container listeners associated with this Container.
+ * If this Container has no registered container listeners, a zero-length
+ * array is returned.
+ */
+ @Override
+ public ContainerListener[] findContainerListeners() {
+
+ synchronized (listeners) {
+ ContainerListener[] results =
+ new ContainerListener[listeners.size()];
+ return listeners.toArray(results);
+ }
+
+ }
+
+
+ /**
+ * Process the specified Request, to produce the corresponding Response,
+ * by invoking the first Valve in our pipeline (if any), or the basic
+ * Valve otherwise.
+ *
+ * @param request Request to be processed
+ * @param response Response to be produced
+ *
+ * @exception IllegalStateException if neither a pipeline or a basic
+ * Valve have been configured for this Container
+ * @exception IOException if an input/output error occurred while
+ * processing
+ * @exception ServletException if a ServletException was thrown
+ * while processing this request
+ */
+ @Override
+ public void invoke(Request request, Response response)
+ throws IOException, ServletException {
+
+ pipeline.getFirst().invoke(request, response);
+
+ }
+
+
+ /**
+ * Remove an existing child Container from association with this parent
+ * Container.
+ *
+ * @param child Existing child Container to be removed
+ */
+ @Override
+ public void removeChild(Container child) {
+
+ if (child == null) {
+ return;
+ }
+
+ synchronized(children) {
+ if (children.get(child.getName()) == null)
+ return;
+ children.remove(child.getName());
+ }
+
+ try {
+ if (child.getState().isAvailable()) {
+ child.stop();
+ }
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.removeChild: stop: ", e);
+ }
+
+ fireContainerEvent(REMOVE_CHILD_EVENT, child);
+
+ try {
+ // child.destroy() may have already been called which would have
+ // triggered this call. If that is the case, no need to destroy the
+ // child again.
+ if (!LifecycleState.DESTROYING.equals(child.getState())) {
+ child.destroy();
+ }
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.removeChild: destroy: ", e);
+ }
+
+ }
+
+
+ /**
+ * Remove a container event listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ @Override
+ public void removeContainerListener(ContainerListener listener) {
+
+ synchronized (listeners) {
+ listeners.remove(listener);
+ }
+
+ }
+
+
+ /**
+ * Remove a property change listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+
+ support.removePropertyChangeListener(listener);
+
+ }
+
+
+ @Override
+ protected void initInternal() throws LifecycleException {
+ BlockingQueue startStopQueue =
+ new LinkedBlockingQueue();
+ startStopExecutor = new ThreadPoolExecutor(0,
+ getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
+ startStopQueue);
+ super.initInternal();
+ }
+
+
+ /**
+ * Start this component and implement the requirements
+ * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents this component from being used
+ */
+ @Override
+ protected synchronized void startInternal() throws LifecycleException {
+
+ // Start our subordinate components, if any
+ if ((loader != null) && (loader instanceof Lifecycle))
+ ((Lifecycle) loader).start();
+ logger = null;
+ getLogger();
+ if ((logger != null) && (logger instanceof Lifecycle))
+ ((Lifecycle) logger).start();
+ if ((manager != null) && (manager instanceof Lifecycle))
+ ((Lifecycle) manager).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();
+ List> results = new ArrayList>();
+ for (int i = 0; i < children.length; i++) {
+ results.add(startStopExecutor.submit(new StartChild(children[i])));
+ }
+
+ boolean fail = false;
+ for (Future result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString("containerBase.threadedStartFailed"), e);
+ fail = true;
+ }
+
+ }
+ if (fail) {
+ throw new LifecycleException(
+ sm.getString("containerBase.threadedStartFailed"));
+ }
+
+ // Start the Valves in our pipeline (including the basic), if any
+ if (pipeline instanceof Lifecycle)
+ ((Lifecycle) pipeline).start();
+
+
+ setState(LifecycleState.STARTING);
+
+ // Start our thread
+ threadStart();
+
+ }
+
+
+ /**
+ * Stop this component and implement the requirements
+ * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents this component from being used
+ */
+ @Override
+ protected synchronized void stopInternal() throws LifecycleException {
+
+ // Stop our thread
+ threadStop();
+
+ setState(LifecycleState.STOPPING);
+
+ // Stop the Valves in our pipeline (including the basic), if any
+ if (pipeline instanceof Lifecycle &&
+ ((Lifecycle) pipeline).getState().isAvailable()) {
+ ((Lifecycle) pipeline).stop();
+ }
+
+ // Stop our child containers, if any
+ Container children[] = findChildren();
+ List> results = new ArrayList>();
+ for (int i = 0; i < children.length; i++) {
+ results.add(startStopExecutor.submit(new StopChild(children[i])));
+ }
+
+ boolean fail = false;
+ for (Future result : results) {
+ try {
+ result.get();
+ } catch (Exception e) {
+ log.error(sm.getString("containerBase.threadedStopFailed"), e);
+ fail = true;
+ }
+ }
+ if (fail) {
+ throw new LifecycleException(
+ sm.getString("containerBase.threadedStopFailed"));
+ }
+
+ // Stop our subordinate components, if any
+ if ((resources != null) && (resources instanceof Lifecycle)) {
+ ((Lifecycle) resources).stop();
+ }
+ if ((realm != null) && (realm instanceof Lifecycle)) {
+ ((Lifecycle) realm).stop();
+ }
+ if ((cluster != null) && (cluster instanceof Lifecycle)) {
+ ((Lifecycle) cluster).stop();
+ }
+ if ((manager != null) && (manager instanceof Lifecycle) &&
+ ((Lifecycle) manager).getState().isAvailable() ) {
+ ((Lifecycle) manager).stop();
+ }
+ if ((logger != null) && (logger instanceof Lifecycle)) {
+ ((Lifecycle) logger).stop();
+ }
+ if ((loader != null) && (loader instanceof Lifecycle)) {
+ ((Lifecycle) loader).stop();
+ }
+ }
+
+ @Override
+ protected void destroyInternal() throws LifecycleException {
+
+ // Stop the Valves in our pipeline (including the basic), if any
+ if (pipeline instanceof Lifecycle) {
+ ((Lifecycle) pipeline).destroy();
+ }
+
+ // Remove children now this container is being destroyed
+ for (Container child : findChildren()) {
+ removeChild(child);
+ }
+
+ // Required if the child is destroyed directly.
+ if (parent != null) {
+ parent.removeChild(this);
+ }
+
+ startStopExecutor.shutdownNow();
+
+ super.destroyInternal();
+ }
+
+
+ /**
+ * Check this container for an access log and if none is found, look to the
+ * parent. If there is no parent and still none is found, use the NoOp
+ * access log.
+ */
+ @Override
+ public void logAccess(Request request, Response response, long time,
+ boolean useDefault) {
+
+ boolean logged = false;
+
+ if (getAccessLog() != null) {
+ getAccessLog().log(request, response, time);
+ logged = true;
+ }
+
+ if (getParent() != null) {
+ // No need to use default logger once request/response has been logged
+ // once
+ getParent().logAccess(request, response, time, (useDefault && !logged));
+ }
+ }
+
+ @Override
+ public AccessLog getAccessLog() {
+
+ if (accessLogScanComplete) {
+ return accessLog;
+ }
+
+ AccessLogAdapter adapter = null;
+ Valve valves[] = getPipeline().getValves();
+ for (Valve valve : valves) {
+ if (valve instanceof AccessLog) {
+ if (adapter == null) {
+ adapter = new AccessLogAdapter((AccessLog) valve);
+ } else {
+ adapter.add((AccessLog) valve);
+ }
+ }
+ }
+ if (adapter != null) {
+ accessLog = adapter;
+ }
+ accessLogScanComplete = true;
+ return accessLog;
+ }
+
+ // ------------------------------------------------------- Pipeline Methods
+
+
+ /**
+ * Convenience method, intended for use by the digester to simplify the
+ * process of adding Valves to containers. See
+ * {@link Pipeline#addValve(Valve)} for full details. Components other than
+ * the digester should use {@link #getPipeline()}.{@link #addValve(Valve)} in case a
+ * future implementation provides an alternative method for the digester to
+ * use.
+ *
+ * @param valve Valve to be added
+ *
+ * @exception IllegalArgumentException if this Container refused to
+ * accept the specified Valve
+ * @exception IllegalArgumentException if the specified Valve refuses to be
+ * associated with this Container
+ * @exception IllegalStateException if the specified Valve is already
+ * associated with a different Container
+ */
+ public synchronized void addValve(Valve valve) {
+
+ pipeline.addValve(valve);
+ }
+
+
+ /**
+ * Execute a periodic task, such as reloading, etc. This method will be
+ * invoked inside the classloading context of this container. Unexpected
+ * throwables will be caught and logged.
+ */
+ @Override
+ public void backgroundProcess() {
+
+ if (!getState().isAvailable())
+ return;
+
+ if (cluster != null) {
+ try {
+ cluster.backgroundProcess();
+ } catch (Exception e) {
+ log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);
+ }
+ }
+ if (loader != null) {
+ try {
+ loader.backgroundProcess();
+ } catch (Exception e) {
+ log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e);
+ }
+ }
+ if (manager != null) {
+ try {
+ manager.backgroundProcess();
+ } catch (Exception e) {
+ log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e);
+ }
+ }
+ if (realm != null) {
+ try {
+ realm.backgroundProcess();
+ } catch (Exception e) {
+ log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);
+ }
+ }
+ Valve current = pipeline.getFirst();
+ while (current != null) {
+ try {
+ current.backgroundProcess();
+ } catch (Exception e) {
+ log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);
+ }
+ current = current.getNext();
+ }
+ fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Notify all container event listeners that a particular event has
+ * occurred for this Container. The default implementation performs
+ * this notification synchronously using the calling thread.
+ *
+ * @param type Event type
+ * @param data Event data
+ */
+ @Override
+ public void fireContainerEvent(String type, Object data) {
+
+ if (listeners.size() < 1)
+ return;
+ ContainerEvent event = new ContainerEvent(this, type, data);
+ ContainerListener list[] = new ContainerListener[0];
+ synchronized (listeners) {
+ list = listeners.toArray(list);
+ }
+ for (int i = 0; i < list.length; i++)
+ list[i].containerEvent(event);
+
+ }
+
+
+ /**
+ * Return the abbreviated name of this container for logging messages
+ */
+ protected String logName() {
+
+ if (logName != null) {
+ return logName;
+ }
+ String loggerName = null;
+ Container current = this;
+ while (current != null) {
+ String name = current.getName();
+ if ((name == null) || (name.equals(""))) {
+ name = "/";
+ } else if (name.startsWith("##")) {
+ name = "/" + name;
+ }
+ loggerName = "[" + name + "]"
+ + ((loggerName != null) ? ("." + loggerName) : "");
+ current = current.getParent();
+ }
+ logName = ContainerBase.class.getName() + "." + loggerName;
+ return logName;
+
+ }
+
+
+ // -------------------- JMX and Registration --------------------
+
+ @Override
+ protected String getDomainInternal() {
+ return MBeanUtils.getDomain(this);
+ }
+
+ public ObjectName[] getChildren() {
+ ObjectName result[]=new ObjectName[children.size()];
+ Iterator it=children.values().iterator();
+ int i=0;
+ while( it.hasNext() ) {
+ Object next=it.next();
+ if( next instanceof ContainerBase ) {
+ result[i++]=((ContainerBase)next).getObjectName();
+ }
+ }
+ return result;
+ }
+
+
+ // -------------------- Background Thread --------------------
+
+ /**
+ * Start the background thread that will periodically check for
+ * session timeouts.
+ */
+ protected void threadStart() {
+
+ if (thread != null)
+ return;
+ if (backgroundProcessorDelay <= 0)
+ return;
+
+ threadDone = false;
+ String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
+ thread = new Thread(new ContainerBackgroundProcessor(), threadName);
+ thread.setDaemon(true);
+ thread.start();
+
+ }
+
+
+ /**
+ * Stop the background thread that is periodically checking for
+ * session timeouts.
+ */
+ protected void threadStop() {
+
+ if (thread == null)
+ return;
+
+ threadDone = true;
+ thread.interrupt();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+
+ thread = null;
+
+ }
+
+
+ // -------------------------------------- ContainerExecuteDelay Inner Class
+
+
+ /**
+ * Private thread class to invoke the backgroundProcess method
+ * of this container and its children after a fixed delay.
+ */
+ protected class ContainerBackgroundProcessor implements Runnable {
+
+ @Override
+ public void run() {
+ while (!threadDone) {
+ try {
+ Thread.sleep(backgroundProcessorDelay * 1000L);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ if (!threadDone) {
+ Container parent = (Container) getMappingObject();
+ ClassLoader cl =
+ Thread.currentThread().getContextClassLoader();
+ if (parent.getLoader() != null) {
+ cl = parent.getLoader().getClassLoader();
+ }
+ processChildren(parent, cl);
+ }
+ }
+ }
+
+ protected void processChildren(Container container, ClassLoader cl) {
+ try {
+ if (container.getLoader() != null) {
+ Thread.currentThread().setContextClassLoader
+ (container.getLoader().getClassLoader());
+ }
+ container.backgroundProcess();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ log.error("Exception invoking periodic operation: ", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ Container[] children = container.findChildren();
+ for (int i = 0; i < children.length; i++) {
+ if (children[i].getBackgroundProcessorDelay() <= 0) {
+ processChildren(children[i], cl);
+ }
+ }
+ }
+ }
+
+
+ // ----------------------------- Inner classes used with start/stop Executor
+
+ private static class StartChild implements Callable {
+
+ private Container child;
+
+ public StartChild(Container child) {
+ this.child = child;
+ }
+
+ @Override
+ public Void call() throws LifecycleException {
+ child.start();
+ return null;
+ }
+ }
+
+ private static class StopChild implements Callable {
+
+ private Container child;
+
+ public StopChild(Container child) {
+ this.child = child;
+ }
+
+ @Override
+ public Void call() throws LifecycleException {
+ child.stop();
+ return null;
+ }
+ }
+}
diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties
index 839005c..f51c19e 100644
--- a/java/org/apache/catalina/core/LocalStrings.properties
+++ b/java/org/apache/catalina/core/LocalStrings.properties
@@ -1,255 +1,257 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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.
-
-applicationContext.addFilter.ise=Filters can not be added to context {0} as the context has been initialised
-applicationContext.addListener.iae.cnfe=Unable to create an instance of type [{0}]
-applicationContext.addListener.iae.wrongType=The type specified [{0}] is not one of the expected listener types
-applicationContext.addListener.iae.sclNotAllowed=Once the first ServletContextListener has been called, no more ServletContextListeners may be added.
-applicationContext.addListener.ise=Listeners can not be added to context {0} as the context has been initialised
-applicationContext.addRole.ise=Roles can not be added to context {0} as the context has been initialised
-applicationContext.addServlet.ise=Servlets can not be added to context {0} as the context has been initialised
-applicationContext.attributeEvent=Exception thrown by attributes event listener
-applicationContext.mapping.error=Error during mapping
-applicationContext.requestDispatcher.iae=Path {0} does not start with a "/" character
-applicationContext.resourcePaths.iae=Path {0} does not start with a "/" character
-applicationContext.role.iae=An individual role to declare for context [{0}] may not be null nor the empty string
-applicationContext.roles.iae=Array of roles to declare for context [{0}] cannot be null
-applicationContext.setAttribute.namenull=Name cannot be null
-applicationContext.addSessionCookieConfig.ise=Session Cookie configuration cannot be set for context {0} as the context has been initialised
-applicationContext.setSessionTracking.ise=The session tracking modes for context {0} cannot be set whilst the context is running
-applicationContext.setSessionTracking.iae.invalid=The session tracking mode {0} requested for context {1} is not supported by that context
-applicationContext.setSessionTracking.iae.ssl=The session tracking modes requested for context {1} included SSL and at least one other mode. SSL may not be configured with other modes.
-applicationContext.lookup.error=Failed to locate resource [{0}] in context [{1}]
-applicationDispatcher.allocateException=Allocate exception for servlet {0}
-applicationDispatcher.deallocateException=Deallocate exception for servlet {0}
-applicationDispatcher.forward.ise=Cannot forward after response has been committed
-applicationDispatcher.forward.throw=Forwarded resource threw an exception
-applicationDispatcher.include.throw=Included resource threw an exception
-applicationDispatcher.isUnavailable=Servlet {0} is currently unavailable
-applicationDispatcher.serviceException=Servlet.service() for servlet {0} threw exception
-applicationDispatcher.specViolation.request=Original SevletRequest or wrapped original ServletRequest not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
-applicationDispatcher.specViolation.response=Original SevletResponse or wrapped original ServletResponse not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
-applicationFilterConfig.jmxRegisterFail=JMX registration failed for filter of type [{0}] and name [{1}]
-applicationFilterConfig.jmxUnregister=JMX de-registration complete for filter of type [{0}] and name [{1}]
-applicationFilterConfig.jmxUnregisterFail=JMX de-registration failed for filter of type [{0}] and name [{1}]
-applicationFilterRegistration.nullInitParam=Unable to set initialisation parameter for filter due to null name and/or value. Name [{0}], Value [{1}]
-applicationFilterRegistration.nullInitParams=Unable to set initialisation parameters for filter due to null name and/or value. Name [{0}], Value [{1}]
-applicationRequest.badParent=Cannot locate parent Request implementation
-applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper
-applicationResponse.badParent=Cannot locate parent Response implementation
-applicationResponse.badResponse=Response is not a javax.servlet.ServletResponseWrapper
-applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with name [{1}]
-applicationServletRegistration.setServletSecurity.ise=Security constraints can't be added to servlet [{0}] deployed to context with name [{1}] as the context has already been initialised
-aprListener.aprInit=The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: {0}
-aprListener.tcnInvalid=An incompatible version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat requires version {1}
-aprListener.tcnVersion=An older version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of {1}
-aprListener.aprDestroy=Failed shutdown of APR based Apache Tomcat Native library
-aprListener.sslInit=Failed to initialize the SSLEngine.
-aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0}.
-aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}].
-asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing.
-containerBase.alreadyStarted=Container {0} has already been started
-containerBase.notConfigured=No basic Valve has been configured
-containerBase.notStarted=Container {0} has not been started
-containerBase.backgroundProcess.cluster=Exception processing cluster {0} background process
-containerBase.backgroundProcess.loader=Exception processing loader {0} background process
-containerBase.backgroundProcess.manager=Exception processing manager {0} background process
-containerBase.backgroundProcess.realm=Exception processing realm {0} background process
-containerBase.backgroundProcess.valve=Exception processing valve {0} background process
-fastEngineMapper.alreadyStarted=FastEngineMapper {0} has already been started
-fastEngineMapper.notStarted=FastEngineMapper {0} has not yet been started
-filterChain.filter=Filter execution threw an exception
-filterChain.servlet=Servlet execution threw an exception
-httpContextMapper.container=This container is not a StandardContext
-httpEngineMapper.container=This container is not a StandardEngine
-httpHostMapper.container=This container is not a StandardHost
-interceptorValve.alreadyStarted=InterceptorValve has already been started
-interceptorValve.notStarted=InterceptorValve has not yet been started
-jreLeakListener.keepAliveFail=Failed to trigger creation of the sun.net.www.http.HttpClient class during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
-jreLeakListener.gcDaemonFail=Failed to trigger creation of the GC Daemon thread during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
-jreLeakListener.jarUrlConnCacheFail=Failed to disable Jar URL connection caching by default
-jreLeakListener.xmlParseFail=Error whilst attempting to prevent memory leaks during XML parsing
-jreLeakListener.authPolicyFail=Error whilst attempting to prevent memory leak in javax.security.auth.Policy class
-jreLeakListener.ldapPoolManagerFail=Failed to trigger creation of the com.sun.jndi.ldap.LdapPoolManager class during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
-jreLeakListener.classToInitializeFail=Failed to load class {0} during Tomcat start to prevent possible memory leaks.
-naming.wsdlFailed=Failed to find wsdl file: {0}
-naming.bindFailed=Failed to bind object: {0}
-naming.jmxRegistrationFailed=Failed to register in JMX: {0}
-naming.unbindFailed=Failed to unbind object: {0}
-naming.invalidEnvEntryType=Environment entry {0} has an invalid type
-naming.invalidEnvEntryValue=Environment entry {0} has an invalid value
-naming.namingContextCreationFailed=Creation of the naming context failed: {0}
-standardContext.invalidWrapperClass={0} is not a subclass of StandardWrapper
-standardContext.alreadyStarted=Context has already been started
-standardContext.applicationListener=Error configuring application listener of class {0}
-standardContext.applicationSkipped=Skipped installing application listeners due to previous error(s)
-standardContext.badRequest=Invalid request path ({0}).
-standardContext.cluster.noManager=No manager found. Checking if cluster manager should be used. Cluster configured: [{0}], Application distributable: [{1}]
-standardContext.crlfinurl=The URL pattern "{0}" contains a CR or LF and so can never be matched.
-standardContext.duplicateListener=The listener "{0}" is already configured for this context. The duplicate definition has been ignored.
-standardContext.errorPage.error=Error page location {0} must start with a ''/''
-standardContext.errorPage.required=ErrorPage cannot be null
-standardContext.errorPage.warning=WARNING: Error page location {0} must start with a ''/'' in Servlet 2.4
-standardContext.filterMap.either=Filter mapping must specify either a or a
-standardContext.filterMap.name=Filter mapping specifies an unknown filter name {0}
-standardContext.filterMap.pattern=Invalid {0} in filter mapping
-standardContext.filterStart=Exception starting filter {0}
-standardContext.filterStartFailed=Failed to start application Filters successfully
-standardContext.requestListener.requestInit=Exception sending request initialized lifecycle event to listener instance of class {0}
-standardContext.requestListener.requestDestroy=Exception sending request destroyed lifecycle event to listener instance of class {0}
-standardContext.requestListenerStartFailed=Failed to start request listener valve successfully
-standardContext.requestListenerConfig.added=Added request listener Valve
-standardContext.requestListenerConfig.error=Exception adding request listener Valve: {0}
-standardContext.isUnavailable=This application is not currently available
-standardContext.listenerStart=Exception sending context initialized event to listener instance of class {0}
-standardContext.listenerStartFailed=Failed to start application Listeners successfully
-standardContext.listenerStop=Exception sending context destroyed event to listener instance of class {0}
-standardContext.loginConfig.errorPage=Form error page {0} must start with a ''/'
-standardContext.loginConfig.errorWarning=WARNING: Form error page {0} must start with a ''/'' in Servlet 2.4
-standardContext.loginConfig.loginPage=Form login page {0} must start with a ''/'
-standardContext.loginConfig.loginWarning=WARNING: Form login page {0} must start with a ''/'' in Servlet 2.4
-standardContext.loginConfig.required=LoginConfig cannot be null
-standardContext.manager=Configured a manager of class [{0}]
-standardContext.mappingError=MAPPING configuration error for relative URI {0}
-standardContext.namingResource.init.fail=Failed to init new naming resources
-standardContext.namingResource.destroy.fail=Failed to destroy old naming resources
-standardContext.noResourceJar=Resource JARs are not supported. The JAR found at [{0}] will not be used to provide static content for context with name [{1}]
-standardContext.notFound=The requested resource ({0}) is not available.
-standardContext.notReloadable=Reloading is disabled on this Context
-standardContext.notStarted=Context with name [{0}] has not yet been started
-standardContext.notWrapper=Child of a Context must be a Wrapper
-standardContext.parameter.duplicate=Duplicate context initialization parameter {0}
-standardContext.parameter.required=Both parameter name and parameter value are required
-standardContext.pathInvalid=A context path must either be an empty string or start with a ''/''. The path [{0}] does not meet these criteria and has been changed to [{1}]
-standardContext.reloadingCompleted=Reloading Context with name [{0}] is completed
-standardContext.reloadingFailed=Reloading this Context failed due to previous errors
-standardContext.reloadingStarted=Reloading Context with name [{0}] has started
-standardContext.resourcesStart=Error starting static Resources
-standardContext.securityConstraint.mixHttpMethod=It is not permitted to mix and in the same web resource collection
-standardContext.securityConstraint.pattern=Invalid {0} in security constraint
-standardContext.servletMap.name=Servlet mapping specifies an unknown servlet name {0}
-standardContext.servletMap.pattern=Invalid {0} in servlet mapping
-standardContext.startCleanup=Exception during cleanup after start failed
-standardContext.startFailed=Context [{0}] startup failed due to previous errors
-standardContext.startingContext=Exception starting Context with name [{0}]
-standardContext.startingLoader=Exception starting Loader
-standardContext.startingManager=Exception starting Manager
-standardContext.startingWrapper=Exception starting Wrapper for servlet {0}
-standardContext.stoppingContext=Exception stopping Context with name [{0}]
-standardContext.stoppingLoader=Exception stopping Loader
-standardContext.stoppingManager=Exception stopping Manager
-standardContext.stoppingWrapper=Exception stopping Wrapper for servlet {0}
-standardContext.urlDecode=Cannot URL decode request path {0}
-standardContext.urlPattern.patternWarning=WARNING: URL pattern {0} must start with a ''/'' in Servlet 2.4
-standardContext.urlValidate=Cannot validate URL decoded request path {0}
-standardContext.workPath=Exception obtaining work path for context [{0}]
-standardContext.workCreateException=Failed to determine absolute work directory from directory [{0}] and CATALINA_HOME [{1}] for context [{2}]
-standardContext.workCreateFail=Failed to create work directory [{0}] for context [{1}]
-standardContextValve.acknowledgeException=Failed to acknowledge request with a 100 (Continue) response
-standardEngine.alreadyStarted=Engine has already been started
-standardEngine.jvmRouteFail=Failed to set Engine's jvmRoute attribute from system property
-standardEngine.mappingError=MAPPING configuration error for server name {0}
-standardEngine.noHost=No Host matches server name {0}
-standardEngine.noHostHeader=HTTP/1.1 request with no Host: header
-standardEngine.notHost=Child of an Engine must be a Host
-standardEngine.notParent=Engine cannot have a parent Container
-standardEngine.notStarted=Engine has not yet been started
-standardEngine.unfoundHost=Virtual host {0} not found
-standardEngine.unknownHost=No server host specified in this request
-standardEngine.unregister.mbeans.failed=Error in destroy() for mbean file {0}
-standardHost.accessBase=Cannot access document base directory {0}
-standardHost.alreadyStarted=Host has already been started
-standardHost.appBase=Application base directory {0} does not exist
-standardHost.clientAbort=Remote Client Aborted Request, IOException: {0}
-standardHost.configRequired=URL to configuration file is required
-standardHost.configNotAllowed=Use of configuration file is not allowed
-standardHost.installBase=Only web applications in the Host web application directory can be installed
-standardHost.installing=Installing web application at context path {0} from URL {1}
-standardHost.installingWAR=Installing web application from URL {0}
-standardHost.installingXML=Processing Context configuration file URL {0}
-standardHost.installError=Error deploying application at context path {0}
-standardHost.invalidErrorReportValveClass=Couldn''t load specified error report valve class: {0}
-standardHost.docBase=Document base directory {0} already exists
-standardHost.mappingError=MAPPING configuration error for request URI {0}
-standardHost.noContext=No Context configured to process this request
-standardHost.noHost=No Host configured to process this request
-standardHost.notContext=Child of a Host must be a Context
-standardHost.notStarted=Host has not yet been started
-standardHost.nullName=Host name is required
-standardHost.pathFormat=Invalid context path: {0}
-standardHost.pathMatch=Context path {0} must match the directory or WAR file name: {1}
-standardHost.pathMissing=Context path {0} is not currently in use
-standardHost.pathRequired=Context path is required
-standardHost.pathUsed=Context path {0} is already in use
-standardHost.removing=Removing web application at context path {0}
-standardHost.removeError=Error removing application at context path {0}
-standardHost.start=Starting web application at context path {0}
-standardHost.stop=Stopping web application at context path {0}
-standardHost.unfoundContext=Cannot find context for request URI {0}
-standardHost.warRequired=URL to web application archive is required
-standardHost.warURL=Invalid URL for web application archive: {0}
-standardServer.onameFail=MBean name specified for Server [{0}] is not valid
-standardServer.shutdownViaPort=A valid shutdown command was received via the shutdown port. Stopping the Server instance.
-standardService.connector.initFailed=Failed to initialize connector [{0}]
-standardService.connector.destroyFailed=Failed to destroy connector [{0}]
-standardService.connector.pauseFailed=Failed to pause connector [{0}]
-standardService.connector.startFailed=Failed to start connector [{0}]
-standardService.connector.stopFailed=Failed to stop connector [{0}]
-standardService.initialize.failed=Service initializing at {0} failed
-standardService.onameFail=MBean name specified for Service [{0}] is not valid
-standardService.register.failed=Error registering Service at domain {0}
-standardService.start.name=Starting service {0}
-standardService.stop.name=Stopping service {0}
-standardThreadExecutor.onameFail=MBean name specified for Thread Executor [{0}] is not valid
-standardWrapper.allocate=Error allocating a servlet instance
-standardWrapper.allocateException=Allocate exception for servlet {0}
-standardWrapper.containerServlet=Loading container servlet {0}
-standardWrapper.createFilters=Create filters exception for servlet {0}
-standardWrapper.deallocateException=Deallocate exception for servlet {0}
-standardWrapper.destroyException=Servlet.destroy() for servlet {0} threw exception
-standardWrapper.exception0=Tomcat Exception Report
-standardWrapper.exception1=A Servlet Exception Has Occurred
-standardWrapper.exception2=Exception Report:
-standardWrapper.exception3=Root Cause:
-standardWrapper.initException=Servlet.init() for servlet {0} threw exception
-standardWrapper.instantiate=Error instantiating servlet class {0}
-standardWrapper.isUnavailable=Servlet {0} is currently unavailable
-standardWrapper.jasperLoader=Using Jasper classloader for servlet {0}
-standardWrapper.jspFile.format=JSP file {0} does not start with a ''/'' character
-standardWrapper.loadException=Servlet {0} threw load() exception
-standardWrapper.missingClass=Wrapper cannot find servlet class {0} or a class it depends on
-standardWrapper.missingLoader=Wrapper cannot find Loader for servlet {0}
-standardWrapper.notChild=Wrapper container may not have child containers
-standardWrapper.notClass=No servlet class has been specified for servlet {0}
-standardWrapper.notContext=Parent container of a Wrapper must be a Context
-standardWrapper.notFound=Servlet {0} is not available
-standardWrapper.notServlet=Class {0} is not a Servlet
-standardWrapper.releaseFilters=Release filters exception for servlet {0}
-standardWrapper.serviceException=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception
-standardWrapper.serviceExceptionRoot=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception [{2}] with root cause
-standardWrapper.statusHeader=HTTP Status {0} - {1}
-standardWrapper.statusTitle=Tomcat Error Report
-standardWrapper.unavailable=Marking servlet {0} as unavailable
-standardWrapper.unloadException=Servlet {0} threw unload() exception
-standardWrapper.unloading=Cannot allocate servlet {0} because it is being unloaded
-standardWrapper.waiting=Waiting for {0} instance(s) to be deallocated
-threadLocalLeakPreventionListener.lifecycleEvent.error=Exception processing lifecycle event {0}
-threadLocalLeakPreventionListener.containerEvent.error=Exception processing container event {0}
-
-defaultInstanceManager.restrictedServletsResource=Restricted servlets property file not found
-defaultInstanceManager.privilegedServlet=Servlet of class {0} is privileged and cannot be loaded by this web application
-defaultInstanceManager.restrictedFiltersResource=Restricted filters property file not found
-defaultInstanceManager.privilegedFilter=Filter of class {0} is privileged and cannot be loaded by this web application
-defaultInstanceManager.restrictedListenersResources="Restricted listeners property file not found
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+applicationContext.addFilter.ise=Filters can not be added to context {0} as the context has been initialised
+applicationContext.addListener.iae.cnfe=Unable to create an instance of type [{0}]
+applicationContext.addListener.iae.wrongType=The type specified [{0}] is not one of the expected listener types
+applicationContext.addListener.iae.sclNotAllowed=Once the first ServletContextListener has been called, no more ServletContextListeners may be added.
+applicationContext.addListener.ise=Listeners can not be added to context {0} as the context has been initialised
+applicationContext.addRole.ise=Roles can not be added to context {0} as the context has been initialised
+applicationContext.addServlet.ise=Servlets can not be added to context {0} as the context has been initialised
+applicationContext.attributeEvent=Exception thrown by attributes event listener
+applicationContext.mapping.error=Error during mapping
+applicationContext.requestDispatcher.iae=Path {0} does not start with a "/" character
+applicationContext.resourcePaths.iae=Path {0} does not start with a "/" character
+applicationContext.role.iae=An individual role to declare for context [{0}] may not be null nor the empty string
+applicationContext.roles.iae=Array of roles to declare for context [{0}] cannot be null
+applicationContext.setAttribute.namenull=Name cannot be null
+applicationContext.addSessionCookieConfig.ise=Session Cookie configuration cannot be set for context {0} as the context has been initialised
+applicationContext.setSessionTracking.ise=The session tracking modes for context {0} cannot be set whilst the context is running
+applicationContext.setSessionTracking.iae.invalid=The session tracking mode {0} requested for context {1} is not supported by that context
+applicationContext.setSessionTracking.iae.ssl=The session tracking modes requested for context {1} included SSL and at least one other mode. SSL may not be configured with other modes.
+applicationContext.lookup.error=Failed to locate resource [{0}] in context [{1}]
+applicationDispatcher.allocateException=Allocate exception for servlet {0}
+applicationDispatcher.deallocateException=Deallocate exception for servlet {0}
+applicationDispatcher.forward.ise=Cannot forward after response has been committed
+applicationDispatcher.forward.throw=Forwarded resource threw an exception
+applicationDispatcher.include.throw=Included resource threw an exception
+applicationDispatcher.isUnavailable=Servlet {0} is currently unavailable
+applicationDispatcher.serviceException=Servlet.service() for servlet {0} threw exception
+applicationDispatcher.specViolation.request=Original SevletRequest or wrapped original ServletRequest not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
+applicationDispatcher.specViolation.response=Original SevletResponse or wrapped original ServletResponse not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
+applicationFilterConfig.jmxRegisterFail=JMX registration failed for filter of type [{0}] and name [{1}]
+applicationFilterConfig.jmxUnregister=JMX de-registration complete for filter of type [{0}] and name [{1}]
+applicationFilterConfig.jmxUnregisterFail=JMX de-registration failed for filter of type [{0}] and name [{1}]
+applicationFilterRegistration.nullInitParam=Unable to set initialisation parameter for filter due to null name and/or value. Name [{0}], Value [{1}]
+applicationFilterRegistration.nullInitParams=Unable to set initialisation parameters for filter due to null name and/or value. Name [{0}], Value [{1}]
+applicationRequest.badParent=Cannot locate parent Request implementation
+applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper
+applicationResponse.badParent=Cannot locate parent Response implementation
+applicationResponse.badResponse=Response is not a javax.servlet.ServletResponseWrapper
+applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with name [{1}]
+applicationServletRegistration.setServletSecurity.ise=Security constraints can't be added to servlet [{0}] deployed to context with name [{1}] as the context has already been initialised
+aprListener.aprInit=The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: {0}
+aprListener.tcnInvalid=An incompatible version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat requires version {1}
+aprListener.tcnVersion=An older version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of {1}
+aprListener.aprDestroy=Failed shutdown of APR based Apache Tomcat Native library
+aprListener.sslInit=Failed to initialize the SSLEngine.
+aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0}.
+aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}].
+asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing.
+containerBase.alreadyStarted=Container {0} has already been started
+containerBase.notConfigured=No basic Valve has been configured
+containerBase.notStarted=Container {0} has not been started
+containerBase.threadedStartFailed=A child container failed during start
+containerBase.threadedStopFailed=A child container failed during stop
+containerBase.backgroundProcess.cluster=Exception processing cluster {0} background process
+containerBase.backgroundProcess.loader=Exception processing loader {0} background process
+containerBase.backgroundProcess.manager=Exception processing manager {0} background process
+containerBase.backgroundProcess.realm=Exception processing realm {0} background process
+containerBase.backgroundProcess.valve=Exception processing valve {0} background process
+fastEngineMapper.alreadyStarted=FastEngineMapper {0} has already been started
+fastEngineMapper.notStarted=FastEngineMapper {0} has not yet been started
+filterChain.filter=Filter execution threw an exception
+filterChain.servlet=Servlet execution threw an exception
+httpContextMapper.container=This container is not a StandardContext
+httpEngineMapper.container=This container is not a StandardEngine
+httpHostMapper.container=This container is not a StandardHost
+interceptorValve.alreadyStarted=InterceptorValve has already been started
+interceptorValve.notStarted=InterceptorValve has not yet been started
+jreLeakListener.keepAliveFail=Failed to trigger creation of the sun.net.www.http.HttpClient class during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
+jreLeakListener.gcDaemonFail=Failed to trigger creation of the GC Daemon thread during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
+jreLeakListener.jarUrlConnCacheFail=Failed to disable Jar URL connection caching by default
+jreLeakListener.xmlParseFail=Error whilst attempting to prevent memory leaks during XML parsing
+jreLeakListener.authPolicyFail=Error whilst attempting to prevent memory leak in javax.security.auth.Policy class
+jreLeakListener.ldapPoolManagerFail=Failed to trigger creation of the com.sun.jndi.ldap.LdapPoolManager class during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
+jreLeakListener.classToInitializeFail=Failed to load class {0} during Tomcat start to prevent possible memory leaks.
+naming.wsdlFailed=Failed to find wsdl file: {0}
+naming.bindFailed=Failed to bind object: {0}
+naming.jmxRegistrationFailed=Failed to register in JMX: {0}
+naming.unbindFailed=Failed to unbind object: {0}
+naming.invalidEnvEntryType=Environment entry {0} has an invalid type
+naming.invalidEnvEntryValue=Environment entry {0} has an invalid value
+naming.namingContextCreationFailed=Creation of the naming context failed: {0}
+standardContext.invalidWrapperClass={0} is not a subclass of StandardWrapper
+standardContext.alreadyStarted=Context has already been started
+standardContext.applicationListener=Error configuring application listener of class {0}
+standardContext.applicationSkipped=Skipped installing application listeners due to previous error(s)
+standardContext.badRequest=Invalid request path ({0}).
+standardContext.cluster.noManager=No manager found. Checking if cluster manager should be used. Cluster configured: [{0}], Application distributable: [{1}]
+standardContext.crlfinurl=The URL pattern "{0}" contains a CR or LF and so can never be matched.
+standardContext.duplicateListener=The listener "{0}" is already configured for this context. The duplicate definition has been ignored.
+standardContext.errorPage.error=Error page location {0} must start with a ''/''
+standardContext.errorPage.required=ErrorPage cannot be null
+standardContext.errorPage.warning=WARNING: Error page location {0} must start with a ''/'' in Servlet 2.4
+standardContext.filterMap.either=Filter mapping must specify either a or a
+standardContext.filterMap.name=Filter mapping specifies an unknown filter name {0}
+standardContext.filterMap.pattern=Invalid {0} in filter mapping
+standardContext.filterStart=Exception starting filter {0}
+standardContext.filterStartFailed=Failed to start application Filters successfully
+standardContext.requestListener.requestInit=Exception sending request initialized lifecycle event to listener instance of class {0}
+standardContext.requestListener.requestDestroy=Exception sending request destroyed lifecycle event to listener instance of class {0}
+standardContext.requestListenerStartFailed=Failed to start request listener valve successfully
+standardContext.requestListenerConfig.added=Added request listener Valve
+standardContext.requestListenerConfig.error=Exception adding request listener Valve: {0}
+standardContext.isUnavailable=This application is not currently available
+standardContext.listenerStart=Exception sending context initialized event to listener instance of class {0}
+standardContext.listenerStartFailed=Failed to start application Listeners successfully
+standardContext.listenerStop=Exception sending context destroyed event to listener instance of class {0}
+standardContext.loginConfig.errorPage=Form error page {0} must start with a ''/'
+standardContext.loginConfig.errorWarning=WARNING: Form error page {0} must start with a ''/'' in Servlet 2.4
+standardContext.loginConfig.loginPage=Form login page {0} must start with a ''/'
+standardContext.loginConfig.loginWarning=WARNING: Form login page {0} must start with a ''/'' in Servlet 2.4
+standardContext.loginConfig.required=LoginConfig cannot be null
+standardContext.manager=Configured a manager of class [{0}]
+standardContext.mappingError=MAPPING configuration error for relative URI {0}
+standardContext.namingResource.init.fail=Failed to init new naming resources
+standardContext.namingResource.destroy.fail=Failed to destroy old naming resources
+standardContext.noResourceJar=Resource JARs are not supported. The JAR found at [{0}] will not be used to provide static content for context with name [{1}]
+standardContext.notFound=The requested resource ({0}) is not available.
+standardContext.notReloadable=Reloading is disabled on this Context
+standardContext.notStarted=Context with name [{0}] has not yet been started
+standardContext.notWrapper=Child of a Context must be a Wrapper
+standardContext.parameter.duplicate=Duplicate context initialization parameter {0}
+standardContext.parameter.required=Both parameter name and parameter value are required
+standardContext.pathInvalid=A context path must either be an empty string or start with a ''/''. The path [{0}] does not meet these criteria and has been changed to [{1}]
+standardContext.reloadingCompleted=Reloading Context with name [{0}] is completed
+standardContext.reloadingFailed=Reloading this Context failed due to previous errors
+standardContext.reloadingStarted=Reloading Context with name [{0}] has started
+standardContext.resourcesStart=Error starting static Resources
+standardContext.securityConstraint.mixHttpMethod=It is not permitted to mix and in the same web resource collection
+standardContext.securityConstraint.pattern=Invalid {0} in security constraint
+standardContext.servletMap.name=Servlet mapping specifies an unknown servlet name {0}
+standardContext.servletMap.pattern=Invalid {0} in servlet mapping
+standardContext.startCleanup=Exception during cleanup after start failed
+standardContext.startFailed=Context [{0}] startup failed due to previous errors
+standardContext.startingContext=Exception starting Context with name [{0}]
+standardContext.startingLoader=Exception starting Loader
+standardContext.startingManager=Exception starting Manager
+standardContext.startingWrapper=Exception starting Wrapper for servlet {0}
+standardContext.stoppingContext=Exception stopping Context with name [{0}]
+standardContext.stoppingLoader=Exception stopping Loader
+standardContext.stoppingManager=Exception stopping Manager
+standardContext.stoppingWrapper=Exception stopping Wrapper for servlet {0}
+standardContext.urlDecode=Cannot URL decode request path {0}
+standardContext.urlPattern.patternWarning=WARNING: URL pattern {0} must start with a ''/'' in Servlet 2.4
+standardContext.urlValidate=Cannot validate URL decoded request path {0}
+standardContext.workPath=Exception obtaining work path for context [{0}]
+standardContext.workCreateException=Failed to determine absolute work directory from directory [{0}] and CATALINA_HOME [{1}] for context [{2}]
+standardContext.workCreateFail=Failed to create work directory [{0}] for context [{1}]
+standardContextValve.acknowledgeException=Failed to acknowledge request with a 100 (Continue) response
+standardEngine.alreadyStarted=Engine has already been started
+standardEngine.jvmRouteFail=Failed to set Engine's jvmRoute attribute from system property
+standardEngine.mappingError=MAPPING configuration error for server name {0}
+standardEngine.noHost=No Host matches server name {0}
+standardEngine.noHostHeader=HTTP/1.1 request with no Host: header
+standardEngine.notHost=Child of an Engine must be a Host
+standardEngine.notParent=Engine cannot have a parent Container
+standardEngine.notStarted=Engine has not yet been started
+standardEngine.unfoundHost=Virtual host {0} not found
+standardEngine.unknownHost=No server host specified in this request
+standardEngine.unregister.mbeans.failed=Error in destroy() for mbean file {0}
+standardHost.accessBase=Cannot access document base directory {0}
+standardHost.alreadyStarted=Host has already been started
+standardHost.appBase=Application base directory {0} does not exist
+standardHost.clientAbort=Remote Client Aborted Request, IOException: {0}
+standardHost.configRequired=URL to configuration file is required
+standardHost.configNotAllowed=Use of configuration file is not allowed
+standardHost.installBase=Only web applications in the Host web application directory can be installed
+standardHost.installing=Installing web application at context path {0} from URL {1}
+standardHost.installingWAR=Installing web application from URL {0}
+standardHost.installingXML=Processing Context configuration file URL {0}
+standardHost.installError=Error deploying application at context path {0}
+standardHost.invalidErrorReportValveClass=Couldn''t load specified error report valve class: {0}
+standardHost.docBase=Document base directory {0} already exists
+standardHost.mappingError=MAPPING configuration error for request URI {0}
+standardHost.noContext=No Context configured to process this request
+standardHost.noHost=No Host configured to process this request
+standardHost.notContext=Child of a Host must be a Context
+standardHost.notStarted=Host has not yet been started
+standardHost.nullName=Host name is required
+standardHost.pathFormat=Invalid context path: {0}
+standardHost.pathMatch=Context path {0} must match the directory or WAR file name: {1}
+standardHost.pathMissing=Context path {0} is not currently in use
+standardHost.pathRequired=Context path is required
+standardHost.pathUsed=Context path {0} is already in use
+standardHost.removing=Removing web application at context path {0}
+standardHost.removeError=Error removing application at context path {0}
+standardHost.start=Starting web application at context path {0}
+standardHost.stop=Stopping web application at context path {0}
+standardHost.unfoundContext=Cannot find context for request URI {0}
+standardHost.warRequired=URL to web application archive is required
+standardHost.warURL=Invalid URL for web application archive: {0}
+standardServer.onameFail=MBean name specified for Server [{0}] is not valid
+standardServer.shutdownViaPort=A valid shutdown command was received via the shutdown port. Stopping the Server instance.
+standardService.connector.initFailed=Failed to initialize connector [{0}]
+standardService.connector.destroyFailed=Failed to destroy connector [{0}]
+standardService.connector.pauseFailed=Failed to pause connector [{0}]
+standardService.connector.startFailed=Failed to start connector [{0}]
+standardService.connector.stopFailed=Failed to stop connector [{0}]
+standardService.initialize.failed=Service initializing at {0} failed
+standardService.onameFail=MBean name specified for Service [{0}] is not valid
+standardService.register.failed=Error registering Service at domain {0}
+standardService.start.name=Starting service {0}
+standardService.stop.name=Stopping service {0}
+standardThreadExecutor.onameFail=MBean name specified for Thread Executor [{0}] is not valid
+standardWrapper.allocate=Error allocating a servlet instance
+standardWrapper.allocateException=Allocate exception for servlet {0}
+standardWrapper.containerServlet=Loading container servlet {0}
+standardWrapper.createFilters=Create filters exception for servlet {0}
+standardWrapper.deallocateException=Deallocate exception for servlet {0}
+standardWrapper.destroyException=Servlet.destroy() for servlet {0} threw exception
+standardWrapper.exception0=Tomcat Exception Report
+standardWrapper.exception1=A Servlet Exception Has Occurred
+standardWrapper.exception2=Exception Report:
+standardWrapper.exception3=Root Cause:
+standardWrapper.initException=Servlet.init() for servlet {0} threw exception
+standardWrapper.instantiate=Error instantiating servlet class {0}
+standardWrapper.isUnavailable=Servlet {0} is currently unavailable
+standardWrapper.jasperLoader=Using Jasper classloader for servlet {0}
+standardWrapper.jspFile.format=JSP file {0} does not start with a ''/'' character
+standardWrapper.loadException=Servlet {0} threw load() exception
+standardWrapper.missingClass=Wrapper cannot find servlet class {0} or a class it depends on
+standardWrapper.missingLoader=Wrapper cannot find Loader for servlet {0}
+standardWrapper.notChild=Wrapper container may not have child containers
+standardWrapper.notClass=No servlet class has been specified for servlet {0}
+standardWrapper.notContext=Parent container of a Wrapper must be a Context
+standardWrapper.notFound=Servlet {0} is not available
+standardWrapper.notServlet=Class {0} is not a Servlet
+standardWrapper.releaseFilters=Release filters exception for servlet {0}
+standardWrapper.serviceException=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception
+standardWrapper.serviceExceptionRoot=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception [{2}] with root cause
+standardWrapper.statusHeader=HTTP Status {0} - {1}
+standardWrapper.statusTitle=Tomcat Error Report
+standardWrapper.unavailable=Marking servlet {0} as unavailable
+standardWrapper.unloadException=Servlet {0} threw unload() exception
+standardWrapper.unloading=Cannot allocate servlet {0} because it is being unloaded
+standardWrapper.waiting=Waiting for {0} instance(s) to be deallocated
+threadLocalLeakPreventionListener.lifecycleEvent.error=Exception processing lifecycle event {0}
+threadLocalLeakPreventionListener.containerEvent.error=Exception processing container event {0}
+
+defaultInstanceManager.restrictedServletsResource=Restricted servlets property file not found
+defaultInstanceManager.privilegedServlet=Servlet of class {0} is privileged and cannot be loaded by this web application
+defaultInstanceManager.restrictedFiltersResource=Restricted filters property file not found
+defaultInstanceManager.privilegedFilter=Filter of class {0} is privileged and cannot be loaded by this web application
+defaultInstanceManager.restrictedListenersResources="Restricted listeners property file not found
diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java
index a408da0..8e7b971 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -1,6544 +1,6462 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import java.util.TreeMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanNotificationInfo;
-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.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContainerInitializer;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestEvent;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.ServletSecurityElement;
-import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionListener;
-
-import org.apache.catalina.Authenticator;
-import org.apache.catalina.Container;
-import org.apache.catalina.ContainerListener;
-import org.apache.catalina.Context;
-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.LifecycleState;
-import org.apache.catalina.Loader;
-import org.apache.catalina.Manager;
-import org.apache.catalina.Pipeline;
-import org.apache.catalina.Valve;
-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.Injectable;
-import org.apache.catalina.deploy.InjectionTarget;
-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.session.StandardManager;
-import org.apache.catalina.startup.TldConfig;
-import org.apache.catalina.util.CharsetMapper;
-import org.apache.catalina.util.ContextName;
-import org.apache.catalina.util.ExtensionValidator;
-import org.apache.catalina.util.RequestUtil;
-import org.apache.catalina.util.URLEncoder;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-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.InstanceManager;
-import org.apache.tomcat.JarScanner;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.modeler.Registry;
-import org.apache.tomcat.util.scan.StandardJarScanner;
-import org.apache.tomcat.util.threads.DedicatedThreadExecutor;
-
-/**
- * Standard implementation of the Context 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 $Id$
- */
-
-public class StandardContext extends ContainerBase
- implements Context, NotificationEmitter {
-
- private static final 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();
- // Set defaults
- if (!Globals.STRICT_SERVLET_COMPLIANCE) {
- // Strict servlet compliance requires all extension mapped servlets
- // to be checked against welcome files
- resourceOnlyServlets.add("jsp");
- }
- }
-
-
- // ----------------------------------------------------- Class Variables
-
-
- /**
- * The descriptive information string for this implementation.
- */
- private static final String info =
- "org.apache.catalina.core.StandardContext/1.0";
-
-
- /**
- * 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
-
-
- /**
- * Allow multipart/form-data requests to be parsed even when the
- * target servlet doesn't specify @MultipartConfig or have a
- * <multipart-config> element.
- */
- protected boolean allowCasualMultipartParsing = false;
-
- /**
- * Control whether remaining request data will be read
- * (swallowed) even if the request violates a data size constraint.
- */
- private boolean swallowAbortedUploads = true;
-
- /**
- * The alternate deployment descriptor name.
- */
- private String altDDName = null;
-
-
- /**
- * Lifecycle provider.
- */
- private InstanceManager instanceManager = 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];
-
- private final Object applicationListenersLock = new Object();
-
-
- /**
- * The set of instantiated application event listener objects.
- */
- private Object applicationEventListenersObjects[] =
- new Object[0];
-
-
- /**
- * The set of instantiated application lifecycle listener objects.
- */
- private Object applicationLifecycleListenersObjects[] =
- new Object[0];
-
-
- /**
- * The ordered set of ServletContainerInitializers for this web application.
- */
- private Map>> initializers =
- new LinkedHashMap>>();
-
-
- /**
- * The set of application parameters defined for this application.
- */
- private ApplicationParameter applicationParameters[] =
- new ApplicationParameter[0];
-
- private final Object applicationParametersLock = new Object();
-
-
- /**
- * The broadcaster that sends j2ee notifications.
- */
- private NotificationBroadcasterSupport broadcaster = null;
-
- /**
- * The Locale to character set mapper for this application.
- */
- private CharsetMapper charsetMapper = null;
-
-
- /**
- * The Java class name of the CharsetMapper class to be created.
- */
- private String charsetMapperClass =
- "org.apache.catalina.util.CharsetMapper";
-
-
- /**
- * The URL of the XML descriptor for this context.
- */
- private URL configFile = null;
-
-
- /**
- * The "correctly configured" flag for this Context.
- */
- private boolean configured = false;
-
-
- /**
- * The security constraints for this web application.
- */
- private volatile SecurityConstraint constraints[] =
- new SecurityConstraint[0];
-
- private final Object constraintsLock = new Object();
-
-
- /**
- * The ServletContext implementation associated with this Context.
- */
- protected 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 ServletContext.getContext() method
- * to access the context of other web applications in this server?
- */
- private boolean crossContext = false;
-
-
- /**
- * Encoded path.
- */
- private String encodedPath = null;
-
-
- /**
- * Unencoded path for this web application.
- */
- private String path = 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 with additional mappings
- * added via the {@link ServletContext} possibly both before and after those
- * defined in the deployment descriptor.
- */
- private final ContextFilterMaps filterMaps = new ContextFilterMaps();
-
- /**
- * Ignore annotations.
- */
- private boolean ignoreAnnotations = false;
-
-
- /**
- * The set of classnames of InstanceListeners that will be added
- * to each newly created Wrapper by createWrapper().
- */
- private String instanceListeners[] = new String[0];
-
- private final Object instanceListenersLock = new Object();
-
-
- /**
- * 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 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 default context override flag for this web application.
- */
- private boolean override = false;
-
-
- /**
- * The original document root for this web application.
- */
- private String originalDocBase = null;
-
-
- /**
- * The privileged flag for this web application.
- */
- private boolean privileged = false;
-
-
- /**
- * Should the next call to addWelcomeFile() cause replacement
- * of any existing welcome files? This will be set before processing the
- * web application's deployment descriptor, so that application specified
- * choices replace, 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];
-
- private final Object securityRolesLock = new Object();
-
-
- /**
- * The servlet mappings for this web application, keyed by
- * matching pattern.
- */
- private HashMap servletMappings =
- new HashMap();
-
- private final Object servletMappingsLock = new Object();
-
-
- /**
- * The session timeout (in minutes) for this web application.
- */
- private int sessionTimeout = 30;
-
- /**
- * The notification sequence number.
- */
- private AtomicLong sequenceNumber = new AtomicLong(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;
-
-
- /**
- * Amount of ms that the container will wait for servlets to unload.
- */
- private long unloadDelay = 2000;
-
-
- /**
- * The watched resources for this application.
- */
- private String watchedResources[] = new String[0];
-
- private final Object watchedResourcesLock = new Object();
-
-
- /**
- * The welcome files for this application.
- */
- private String welcomeFiles[] = new String[0];
-
- private final Object welcomeFilesLock = new Object();
-
-
- /**
- * The set of classnames of LifecycleListeners that will be added
- * to each newly created Wrapper by createWrapper().
- */
- private String wrapperLifecycles[] = new String[0];
-
- private final Object wrapperLifecyclesLock = new Object();
-
- /**
- * The set of classnames of ContainerListeners that will be added
- * to each newly created Wrapper by createWrapper().
- */
- private String wrapperListeners[] = new String[0];
-
- private final Object wrapperListenersLock = new Object();
-
- /**
- * 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;
-
-
- /**
- * Allow linking.
- */
- protected boolean allowLinking = false;
-
-
- /**
- * Cache max size in KB.
- */
- protected int cacheMaxSize = 10240; // 10 MB
-
-
- /**
- * Cache object max size in KB.
- */
- protected int cacheObjectMaxSize = 512; // 512K
-
-
- /**
- * Cache TTL in ms.
- */
- protected int cacheTTL = 5000;
-
-
- /**
- * List of resource aliases.
- */
- private String aliases = null;
-
-
- /**
- * Non proxied resources.
- */
- private DirContext webappResources = null;
-
- private long startupTime;
- private long startTime;
- private long tldScanTime;
-
- /**
- * Name of the engine. If null, the domain is used.
- */
- private String j2EEApplication="none";
- private String j2EEServer="none";
-
-
- /**
- * Attribute value used to turn on/off XML validation
- */
- private boolean webXmlValidation = Globals.STRICT_SERVLET_COMPLIANCE;
-
-
- /**
- * Attribute value used to turn on/off XML namespace validation
- */
- private boolean webXmlNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;
-
- /**
- * 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 = Globals.STRICT_SERVLET_COMPLIANCE;
-
-
- /**
- * Attribute value used to turn on/off TLD XML namespace validation
- */
- private boolean tldNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;
-
-
- /**
- * Should we save the configuration.
- */
- private boolean saveConfig = true;
-
-
- /**
- * The name to use for session cookies. null indicates that
- * the name is controlled by the application.
- */
- private String sessionCookieName;
-
-
- /**
- * The flag that indicates that session cookies should use HttpOnly
- */
- private boolean useHttpOnly = true;
-
-
- /**
- * The domain to use for session cookies. null indicates that
- * the domain is controlled by the application.
- */
- private String sessionCookieDomain;
-
-
- /**
- * The path to use for session cookies. null indicates that
- * the path is controlled by the application.
- */
- private String sessionCookiePath;
-
-
- /**
- * Is a / added to the end of the session cookie path to ensure browsers,
- * particularly IE, don't send a session cookie for context /foo with
- * requests intended for context /foobar.
- */
- private boolean sessionCookiePathUsesTrailingSlash = true;
-
-
- /**
- * The Jar scanner to use to search for Jars that might contain
- * configuration information such as TLDs or web-fragment.xml files.
- */
- private JarScanner jarScanner = null;
-
- /**
- * Should Tomcat attempt to null out any static or final fields from loaded
- * classes when a web application is stopped as a work around for apparent
- * garbage collection bugs and application coding errors? There have been
- * some issues reported with log4j when this option is true. Applications
- * without memory leaks using recent JVMs should operate correctly with this
- * option set to false. If not specified, the default value of
- * false will be used.
- */
- private boolean clearReferencesStatic = false;
-
- /**
- * Should Tomcat attempt to terminate threads that have been started by the
- * web application? Stopping threads is performed via the deprecated (for
- * good reason) Thread.stop() method and is likely to result in
- * instability. As such, enabling this should be viewed as an option of last
- * resort in a development environment and is not recommended in a
- * production environment. If not specified, the default value of
- * false will be used.
- */
- private boolean clearReferencesStopThreads = false;
-
- /**
- * Should Tomcat attempt to terminate any {@link java.util.TimerThread}s
- * that have been started by the web application? If not specified, the
- * default value of false will be used.
- */
- private boolean clearReferencesStopTimerThreads = false;
-
- /**
- * If an HttpClient keep-alive timer thread has been started by this web
- * application and is still running, should Tomcat change the context class
- * loader from the current {@link WebappClassLoader} to
- * {@link WebappClassLoader#parent} to prevent a memory leak? Note that the
- * keep-alive timer thread will stop on its own once the keep-alives all
- * expire however, on a busy system that might not happen for some time.
- */
- private boolean clearReferencesHttpClientKeepAliveThread = true;
-
- /**
- * Should Tomcat renew the threads of the thread pool when the application
- * is stopped to avoid memory leaks because of uncleaned ThreadLocal
- * variables. This also requires that the threadRenewalDelay property of the
- * StandardThreadExecutor of ThreadPoolExecutor be set to a positive value.
- */
- private boolean renewThreadsWhenStoppingContext = true;
-
- /**
- * Should the effective web.xml be logged when the context starts?
- */
- private boolean logEffectiveWebXml = false;
-
- private int effectiveMajorVersion = 3;
-
- private int effectiveMinorVersion = 0;
-
- private JspConfigDescriptor jspConfigDescriptor =
- new ApplicationJspConfigDescriptor();
-
- private Set resourceOnlyServlets = new HashSet();
-
- private String webappVersion = "";
-
- private boolean addWebinfClassesResources = false;
-
- private boolean fireRequestListenersOnForwards = false;
-
- /**
- * Servlets created via {@link ApplicationContext#createServlet(Class)} for
- * tracking purposes.
- */
- private Set createdServlets = new HashSet();
-
- private boolean preemptiveAuthentication = false;
-
- private boolean sendRedirectBody = false;
-
-
- // ----------------------------------------------------- Context Properties
-
- @Override
- public boolean getSendRedirectBody() {
- return sendRedirectBody;
- }
-
-
- @Override
- public void setSendRedirectBody(boolean sendRedirectBody) {
- this.sendRedirectBody = sendRedirectBody;
- }
-
-
- @Override
- public boolean getPreemptiveAuthentication() {
- return preemptiveAuthentication;
- }
-
-
- @Override
- public void setPreemptiveAuthentication(boolean preemptiveAuthentication) {
- this.preemptiveAuthentication = preemptiveAuthentication;
- }
-
-
- @Override
- public void setFireRequestListenersOnForwards(boolean enable) {
- fireRequestListenersOnForwards = enable;
- }
-
-
- @Override
- public boolean getFireRequestListenersOnForwards() {
- return fireRequestListenersOnForwards;
- }
-
-
- public void setAddWebinfClassesResources(
- boolean addWebinfClassesResources) {
- this.addWebinfClassesResources = addWebinfClassesResources;
- }
-
-
- public boolean getAddWebinfClassesResources() {
- return addWebinfClassesResources;
- }
-
-
- @Override
- public void setWebappVersion(String webappVersion) {
- if (null == webappVersion) {
- this.webappVersion = "";
- } else {
- this.webappVersion = webappVersion;
- }
- }
-
-
- @Override
- public String getWebappVersion() {
- return webappVersion;
- }
-
-
- @Override
- public String getBaseName() {
- return new ContextName(path, webappVersion).getBaseName();
- }
-
-
- @Override
- public String getResourceOnlyServlets() {
- StringBuilder result = new StringBuilder();
- boolean first = true;
- for (String servletName : resourceOnlyServlets) {
- if (!first) {
- result.append(',');
- }
- result.append(servletName);
- }
- return result.toString();
- }
-
-
- @Override
- public void setResourceOnlyServlets(String resourceOnlyServlets) {
- this.resourceOnlyServlets.clear();
- if (resourceOnlyServlets == null) {
- return;
- }
- for (String servletName : resourceOnlyServlets.split(",")) {
- servletName = servletName.trim();
- if (servletName.length()>0) {
- this.resourceOnlyServlets.add(servletName);
- }
- }
- }
-
-
- @Override
- public boolean isResourceOnlyServlet(String servletName) {
- return resourceOnlyServlets.contains(servletName);
- }
-
-
- @Override
- public int getEffectiveMajorVersion() {
- return effectiveMajorVersion;
- }
-
- @Override
- public void setEffectiveMajorVersion(int effectiveMajorVersion) {
- this.effectiveMajorVersion = effectiveMajorVersion;
- }
-
- @Override
- public int getEffectiveMinorVersion() {
- return effectiveMinorVersion;
- }
-
- @Override
- public void setEffectiveMinorVersion(int effectiveMinorVersion) {
- this.effectiveMinorVersion = effectiveMinorVersion;
- }
-
- @Override
- public void setLogEffectiveWebXml(boolean logEffectiveWebXml) {
- this.logEffectiveWebXml = logEffectiveWebXml;
- }
-
- @Override
- public boolean getLogEffectiveWebXml() {
- return logEffectiveWebXml;
- }
-
- @Override
- public Authenticator getAuthenticator() {
- if (this instanceof Authenticator)
- return (Authenticator) this;
-
- Pipeline pipeline = getPipeline();
- if (pipeline != null) {
- Valve basic = pipeline.getBasic();
- if ((basic != null) && (basic instanceof Authenticator))
- return (Authenticator) basic;
- Valve valves[] = pipeline.getValves();
- for (int i = 0; i < valves.length; i++) {
- if (valves[i] instanceof Authenticator)
- return (Authenticator) valves[i];
- }
- }
- return null;
- }
-
- @Override
- public JarScanner getJarScanner() {
- if (jarScanner == null) {
- jarScanner = new StandardJarScanner();
- }
- return jarScanner;
- }
-
-
- @Override
- public void setJarScanner(JarScanner jarScanner) {
- this.jarScanner = jarScanner;
- }
-
-
- public InstanceManager getInstanceManager() {
- return instanceManager;
- }
-
-
- public void setInstanceManager(InstanceManager instanceManager) {
- this.instanceManager = instanceManager;
- }
-
-
- @Override
- public String getEncodedPath() {
- return encodedPath;
- }
-
-
- /**
- * Is caching allowed ?
- */
- public boolean isCachingAllowed() {
- return cachingAllowed;
- }
-
-
- /**
- * Set caching allowed flag.
- */
- public void setCachingAllowed(boolean cachingAllowed) {
- this.cachingAllowed = cachingAllowed;
- }
-
-
- /**
- * Set allow linking.
- */
- public void setAllowLinking(boolean allowLinking) {
- this.allowLinking = allowLinking;
- }
-
-
- /**
- * Is linking allowed.
- */
- public boolean isAllowLinking() {
- return allowLinking;
- }
-
- /**
- * Set to true to allow requests mapped to servlets that
- * do not explicitly declare @MultipartConfig or have
- * <multipart-config> specified in web.xml to parse
- * multipart/form-data requests.
- *
- * @param allowCasualMultipartParsing true to allow such
- * casual parsing, false otherwise.
- */
- @Override
- public void setAllowCasualMultipartParsing(
- boolean allowCasualMultipartParsing) {
- this.allowCasualMultipartParsing = allowCasualMultipartParsing;
- }
-
- /**
- * Returns true if requests mapped to servlets without
- * "multipart config" to parse multipart/form-data requests anyway.
- *
- * @return true if requests mapped to servlets without
- * "multipart config" to parse multipart/form-data requests,
- * false otherwise.
- */
- @Override
- public boolean getAllowCasualMultipartParsing() {
- return this.allowCasualMultipartParsing;
- }
-
- /**
- * Set to false to disable request data swallowing
- * after an upload was aborted due to size constraints.
- *
- * @param swallowAbortedUploads false to disable
- * swallowing, true otherwise (default).
- */
- @Override
- public void setSwallowAbortedUploads(boolean swallowAbortedUploads) {
- this.swallowAbortedUploads = swallowAbortedUploads;
- }
-
- /**
- * Returns true if remaining request data will be read
- * (swallowed) even the request violates a data size constraint.
- *
- * @return true if data will be swallowed (default),
- * false otherwise.
- */
- @Override
- public boolean getSwallowAbortedUploads() {
- return this.swallowAbortedUploads;
- }
-
- /**
- * 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 maximum size of objects to be cached in KB.
- */
- public int getCacheObjectMaxSize() {
- return cacheObjectMaxSize;
- }
-
-
- /**
- * Set the maximum size of objects to be placed the cache in KB.
- */
- public void setCacheObjectMaxSize(int cacheObjectMaxSize) {
- this.cacheObjectMaxSize = cacheObjectMaxSize;
- }
-
-
- /**
- * Return the list of resource aliases.
- */
- public String getAliases() {
- return this.aliases;
- }
-
-
- /**
- * Add a URL for a JAR that contains static resources in a
- * META-INF/resources directory that should be included in the static
- * resources for this context.
- */
- @Override
- public void addResourceJarUrl(URL url) {
- if (webappResources instanceof BaseDirContext) {
- ((BaseDirContext) webappResources).addResourcesJar(url);
- } else {
- log.error(sm.getString("standardContext.noResourceJar", url,
- getName()));
- }
- }
-
-
- /**
- * Set the current alias configuration. The list of aliases should be of the
- * form "/aliasPath1=docBase1,/aliasPath2=docBase2" where aliasPathN must
- * include a leading '/' and docBaseN must be an absolute path to either a
- * .war file or a directory.
- */
- public void setAliases(String aliases) {
- this.aliases = aliases;
- }
-
-
- /**
- * Add a ServletContainerInitializer instance to this web application.
- *
- * @param sci The instance to add
- * @param classes The classes in which the initializer expressed an
- * interest
- */
- @Override
- public void addServletContainerInitializer(
- ServletContainerInitializer sci, Set> classes) {
- initializers.put(sci, classes);
- }
-
-
- /**
- * 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", oldDelegate,
- 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
- */
- @Override
- 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.
- */
- @Override
- public void setApplicationEventListeners(Object listeners[]) {
- applicationEventListenersObjects = listeners;
- }
-
-
- /**
- * Add a listener to the end of the list of initialized application event
- * listeners.
- */
- public void addApplicationEventListener(Object listener) {
- int len = applicationEventListenersObjects.length;
- Object[] newListeners = Arrays.copyOf(applicationEventListenersObjects,
- len + 1);
- newListeners[len] = listener;
- applicationEventListenersObjects = newListeners;
- }
-
-
- /**
- * 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
- */
- @Override
- 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.
- */
- @Override
- public void setApplicationLifecycleListeners(Object listeners[]) {
- applicationLifecycleListenersObjects = listeners;
- }
-
-
- /**
- * Add a listener to the end of the list of initialized application
- * lifecycle listeners.
- */
- public void addApplicationLifecycleListener(Object listener) {
- int len = applicationLifecycleListenersObjects.length;
- Object[] newListeners = Arrays.copyOf(
- applicationLifecycleListenersObjects, len + 1);
- newListeners[len] = listener;
- applicationLifecycleListenersObjects = newListeners;
- }
-
-
- /**
- * 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",
- oldAntiJARLocking,
- 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",
- oldAntiResourceLocking,
- this.antiResourceLocking);
-
- }
-
-
- /**
- * Return the application available flag for this Context.
- */
- @Override
- public boolean getAvailable() {
-
- // TODO Remove this method entirely
- return getState().isAvailable();
-
- }
-
-
- /**
- * Return the Locale to character set mapper for this Context.
- */
- @Override
- 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) {
- ExceptionUtils.handleThrowable(t);
- this.charsetMapper = new CharsetMapper();
- }
- }
-
- return (this.charsetMapper);
-
- }
-
-
- /**
- * Set the Locale to character set mapper for this Context.
- *
- * @param mapper The new mapper
- */
- @Override
- 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 URL of the XML descriptor for this context.
- */
- @Override
- public URL getConfigFile() {
-
- return (this.configFile);
-
- }
-
-
- /**
- * Set the URL of the XML descriptor for this context.
- *
- * @param configFile The URL of the XML descriptor for this context.
- */
- @Override
- public void setConfigFile(URL configFile) {
-
- this.configFile = configFile;
- }
-
-
- /**
- * Return the "correctly configured" flag for this Context.
- */
- @Override
- 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
- */
- @Override
- public void setConfigured(boolean configured) {
-
- boolean oldConfigured = this.configured;
- this.configured = configured;
- support.firePropertyChange("configured",
- oldConfigured,
- this.configured);
-
- }
-
-
- /**
- * Return the "use cookies for session ids" flag.
- */
- @Override
- public boolean getCookies() {
-
- return (this.cookies);
-
- }
-
-
- /**
- * Set the "use cookies for session ids" flag.
- *
- * @param cookies The new flag
- */
- @Override
- public void setCookies(boolean cookies) {
-
- boolean oldCookies = this.cookies;
- this.cookies = cookies;
- support.firePropertyChange("cookies",
- oldCookies,
- this.cookies);
-
- }
-
-
- /**
- * Gets the name to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @return The value of the default session cookie name or null if not
- * specified
- */
- @Override
- public String getSessionCookieName() {
- return sessionCookieName;
- }
-
-
- /**
- * Sets the name to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @param sessionCookieName The name to use
- */
- @Override
- public void setSessionCookieName(String sessionCookieName) {
- String oldSessionCookieName = this.sessionCookieName;
- this.sessionCookieName = sessionCookieName;
- support.firePropertyChange("sessionCookieName",
- oldSessionCookieName, sessionCookieName);
- }
-
-
- /**
- * Gets the value of the use HttpOnly cookies for session cookies flag.
- *
- * @return true if the HttpOnly flag should be set on session
- * cookies
- */
- @Override
- public boolean getUseHttpOnly() {
- return useHttpOnly;
- }
-
-
- /**
- * Sets the use HttpOnly cookies for session cookies flag.
- *
- * @param useHttpOnly Set to true to use HttpOnly cookies
- * for session cookies
- */
- @Override
- public void setUseHttpOnly(boolean useHttpOnly) {
- boolean oldUseHttpOnly = this.useHttpOnly;
- this.useHttpOnly = useHttpOnly;
- support.firePropertyChange("useHttpOnly",
- oldUseHttpOnly,
- this.useHttpOnly);
- }
-
-
- /**
- * Gets the domain to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @return The value of the default session cookie domain or null if not
- * specified
- */
- @Override
- public String getSessionCookieDomain() {
- return sessionCookieDomain;
- }
-
-
- /**
- * Sets the domain to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @param sessionCookieDomain The domain to use
- */
- @Override
- public void setSessionCookieDomain(String sessionCookieDomain) {
- String oldSessionCookieDomain = this.sessionCookieDomain;
- this.sessionCookieDomain = sessionCookieDomain;
- support.firePropertyChange("sessionCookieDomain",
- oldSessionCookieDomain, sessionCookieDomain);
- }
-
-
- /**
- * Gets the path to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @return The value of the default session cookie path or null if not
- * specified
- */
- @Override
- public String getSessionCookiePath() {
- return sessionCookiePath;
- }
-
-
- /**
- * Sets the path to use for session cookies. Overrides any setting that
- * may be specified by the application.
- *
- * @param sessionCookiePath The path to use
- */
- @Override
- public void setSessionCookiePath(String sessionCookiePath) {
- String oldSessionCookiePath = this.sessionCookiePath;
- this.sessionCookiePath = sessionCookiePath;
- support.firePropertyChange("sessionCookiePath",
- oldSessionCookiePath, sessionCookiePath);
- }
-
-
- @Override
- public boolean getSessionCookiePathUsesTrailingSlash() {
- return sessionCookiePathUsesTrailingSlash;
- }
-
-
- @Override
- public void setSessionCookiePathUsesTrailingSlash(
- boolean sessionCookiePathUsesTrailingSlash) {
- this.sessionCookiePathUsesTrailingSlash =
- sessionCookiePathUsesTrailingSlash;
- }
-
-
- /**
- * Return the "allow crossing servlet contexts" flag.
- */
- @Override
- public boolean getCrossContext() {
-
- return (this.crossContext);
-
- }
-
-
- /**
- * Set the "allow crossing servlet contexts" flag.
- *
- * @param crossContext The new cross contexts flag
- */
- @Override
- public void setCrossContext(boolean crossContext) {
-
- boolean oldCrossContext = this.crossContext;
- this.crossContext = crossContext;
- support.firePropertyChange("crossContext",
- oldCrossContext,
- 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.
- */
- @Override
- public String getDisplayName() {
-
- return (this.displayName);
-
- }
-
-
- /**
- * Return the alternate Deployment Descriptor name.
- */
- @Override
- public String getAltDDName(){
- return altDDName;
- }
-
-
- /**
- * Set an alternate Deployment Descriptor name.
- */
- @Override
- 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
- */
- @Override
- 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.
- */
- @Override
- public boolean getDistributable() {
-
- return (this.distributable);
-
- }
-
- /**
- * Set the distributable flag for this web application.
- *
- * @param distributable The new distributable flag
- */
- @Override
- public void setDistributable(boolean distributable) {
- boolean oldDistributable = this.distributable;
- this.distributable = distributable;
- support.firePropertyChange("distributable",
- oldDistributable,
- 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.
- */
- @Override
- 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
- */
- @Override
- public void setDocBase(String docBase) {
-
- this.docBase = docBase;
-
- }
-
- /**
- * Return descriptive information about this Container implementation and
- * the corresponding version number, in the format
- * <description>/<version>.
- */
- @Override
- public String getInfo() {
-
- return (info);
-
- }
-
- 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
- */
- @Override
- public synchronized void setLoader(Loader loader) {
-
- super.setLoader(loader);
-
- }
-
-
- /**
- * Return the boolean on the annotations parsing.
- */
- @Override
- public boolean getIgnoreAnnotations() {
- return this.ignoreAnnotations;
- }
-
-
- /**
- * Set the boolean on the annotations parsing for this web
- * application.
- *
- * @param ignoreAnnotations The boolean on the annotations parsing
- */
- @Override
- public void setIgnoreAnnotations(boolean ignoreAnnotations) {
- boolean oldIgnoreAnnotations = this.ignoreAnnotations;
- this.ignoreAnnotations = ignoreAnnotations;
- support.firePropertyChange("ignoreAnnotations", oldIgnoreAnnotations,
- this.ignoreAnnotations);
- }
-
-
- /**
- * Return the login configuration descriptor for this web application.
- */
- @Override
- public LoginConfig getLoginConfig() {
-
- return (this.loginConfig);
-
- }
-
-
- /**
- * Set the login configuration descriptor for this web application.
- *
- * @param config The new login configuration
- */
- @Override
- 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.
- */
- @Override
- public org.apache.tomcat.util.http.mapper.Mapper getMapper() {
- return (mapper);
- }
-
-
- /**
- * Return the naming resources associated with this web application.
- */
- @Override
- 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
- */
- @Override
- public void setNamingResources(NamingResources namingResources) {
-
- // Process the property setting change
- NamingResources oldNamingResources = this.namingResources;
- this.namingResources = namingResources;
- if (namingResources != null) {
- namingResources.setContainer(this);
- }
- support.firePropertyChange("namingResources",
- oldNamingResources, this.namingResources);
-
- if (getState() == LifecycleState.NEW ||
- getState() == LifecycleState.INITIALIZING ||
- getState() == LifecycleState.INITIALIZED) {
- // NEW will occur if Context is defined in server.xml
- // At this point getObjectKeyPropertiesNameOnly() will trigger an
- // NPE.
- // INITIALIZED will occur if the Context is defined in a context.xml
- // file
- // If started now, a second start will be attempted when the context
- // starts
-
- // In both cases, return and let context init the namingResources
- // when it starts
- return;
- }
-
- if (oldNamingResources != null) {
- try {
- oldNamingResources.stop();
- oldNamingResources.destroy();
- } catch (LifecycleException e) {
- log.warn("standardContext.namingResource.destroy.fail", e);
- }
- }
- if (namingResources != null) {
- try {
- namingResources.init();
- namingResources.start();
- } catch (LifecycleException e) {
- log.warn("standardContext.namingResource.init.fail", e);
- }
- }
- }
-
-
- /**
- * Return the context path for this Context.
- */
- @Override
- public String getPath() {
- return (path);
- }
-
-
- /**
- * Set the context path for this Context.
- *
- * @param path The new context path
- */
- @Override
- public void setPath(String path) {
- if (path == null || (!path.equals("") && !path.startsWith("/"))) {
- this.path = "/" + path;
- log.warn(sm.getString(
- "standardContext.pathInvalid", path, this.path));
- } else {
- this.path = path;
- }
- encodedPath = urlEncoder.encode(this.path);
- if (getName() == null) {
- setName(this.path);
- }
- }
-
-
- /**
- * Return the public identifier of the deployment descriptor DTD that is
- * currently being parsed.
- */
- @Override
- 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
- */
- @Override
- 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.
- */
- @Override
- public boolean getReloadable() {
-
- return (this.reloadable);
-
- }
-
-
- /**
- * Return the default context override flag for this web application.
- */
- @Override
- public boolean getOverride() {
-
- return (this.override);
-
- }
-
-
- /**
- * Return the original document root for this Context. This can be an absolute
- * pathname, a relative pathname, or a URL.
- * Is only set as deployment has change docRoot!
- */
- public String getOriginalDocBase() {
-
- return (this.originalDocBase);
-
- }
-
- /**
- * Set the original document root for this Context. This can be an absolute
- * pathname, a relative pathname, or a URL.
- *
- * @param docBase The original document root
- */
- public void setOriginalDocBase(String docBase) {
-
- this.originalDocBase = docBase;
- }
-
-
- /**
- * Return the parent class loader (if any) for this web application.
- * This call is meaningful only after a Loader has
- * been configured.
- */
- @Override
- public ClassLoader getParentClassLoader() {
- if (parentClassLoader != null)
- return (parentClassLoader);
- if (getPrivileged()) {
- return this.getClass().getClassLoader();
- } else if (parent != null) {
- return (parent.getParentClassLoader());
- }
- return (ClassLoader.getSystemClassLoader());
- }
-
-
- /**
- * Return the privileged flag for this web application.
- */
- @Override
- public boolean getPrivileged() {
-
- return (this.privileged);
-
- }
-
-
- /**
- * Set the privileged flag for this web application.
- *
- * @param privileged The new privileged flag
- */
- @Override
- public void setPrivileged(boolean privileged) {
-
- boolean oldPrivileged = this.privileged;
- this.privileged = privileged;
- support.firePropertyChange("privileged",
- oldPrivileged,
- this.privileged);
-
- }
-
-
- /**
- * Set the reloadable flag for this web application.
- *
- * @param reloadable The new reloadable flag
- */
- @Override
- public void setReloadable(boolean reloadable) {
-
- boolean oldReloadable = this.reloadable;
- this.reloadable = reloadable;
- support.firePropertyChange("reloadable",
- oldReloadable,
- this.reloadable);
-
- }
-
-
- /**
- * Set the default context override flag for this web application.
- *
- * @param override The new override flag
- */
- @Override
- public void setOverride(boolean override) {
-
- boolean oldOverride = this.override;
- this.override = override;
- support.firePropertyChange("override",
- oldOverride,
- 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",
- oldReplaceWelcomeFiles,
- this.replaceWelcomeFiles);
-
- }
-
-
- /**
- * Return the servlet context for which this Context is a facade.
- */
- @Override
- public ServletContext getServletContext() {
-
- if (context == null) {
- context = new ApplicationContext(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.
- */
- @Override
- public int getSessionTimeout() {
-
- return (this.sessionTimeout);
-
- }
-
-
- /**
- * Set the default session timeout (in minutes) for this
- * web application.
- *
- * @param timeout The new default session timeout
- */
- @Override
- 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",
- oldSessionTimeout,
- this.sessionTimeout);
-
- }
-
-
- /**
- * Return the value of the swallowOutput flag.
- */
- @Override
- 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
- */
- @Override
- public void setSwallowOutput(boolean swallowOutput) {
-
- boolean oldSwallowOutput = this.swallowOutput;
- this.swallowOutput = swallowOutput;
- support.firePropertyChange("swallowOutput",
- oldSwallowOutput,
- this.swallowOutput);
-
- }
-
-
- /**
- * Return the value of the unloadDelay flag.
- */
- public long getUnloadDelay() {
-
- return (this.unloadDelay);
-
- }
-
-
- /**
- * Set the value of the unloadDelay flag, which represents the amount
- * of ms that the container will wait when unloading servlets.
- * Setting this to a small value may cause more requests to fail
- * to complete when stopping a web application.
- *
- * @param unloadDelay The new value
- */
- public void setUnloadDelay(long unloadDelay) {
-
- long oldUnloadDelay = this.unloadDelay;
- this.unloadDelay = unloadDelay;
- support.firePropertyChange("unloadDelay",
- Long.valueOf(oldUnloadDelay),
- Long.valueOf(this.unloadDelay));
-
- }
-
-
- /**
- * 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.
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- public synchronized void setResources(DirContext resources) {
-
- if (getState().isAvailable()) {
- throw new IllegalStateException
- (sm.getString("standardContext.resources.started"));
- }
-
- DirContext oldResources = this.webappResources;
- if (oldResources == resources)
- return;
-
- if (resources instanceof BaseDirContext) {
- // Caching
- ((BaseDirContext) resources).setCached(isCachingAllowed());
- ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
- ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
- ((BaseDirContext) resources).setCacheObjectMaxSize(
- getCacheObjectMaxSize());
- // Alias support
- ((BaseDirContext) resources).setAliases(getAliases());
- }
- if (resources instanceof FileDirContext) {
- filesystemBased = true;
- ((FileDirContext) resources).setAllowLinking(isAllowLinking());
- }
- this.webappResources = resources;
-
- // The proxied resources will be refreshed on start
- this.resources = null;
-
- support.firePropertyChange("resources", oldResources,
- this.webappResources);
-
- }
-
-
- @Override
- public JspConfigDescriptor getJspConfigDescriptor() {
- return jspConfigDescriptor;
- }
-
-
- // ------------------------------------------------------ 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() {
- if (getWorkDir() == null) {
- return null;
- }
- 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(sm.getString("standardContext.workPath", getName()),
- e);
- }
- }
- 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 (getState().isAvailable()) {
- postWorkDirectory();
- }
- }
-
-
- /**
- * Save config ?
- */
- public boolean isSaveConfig() {
- return saveConfig;
- }
-
-
- /**
- * Set save config flag.
- */
- public void setSaveConfig(boolean saveConfig) {
- this.saveConfig = saveConfig;
- }
-
-
- /**
- * Return the clearReferencesStatic flag for this Context.
- */
- public boolean getClearReferencesStatic() {
-
- return (this.clearReferencesStatic);
-
- }
-
-
- /**
- * Set the clearReferencesStatic feature for this Context.
- *
- * @param clearReferencesStatic The new flag value
- */
- public void setClearReferencesStatic(boolean clearReferencesStatic) {
-
- boolean oldClearReferencesStatic = this.clearReferencesStatic;
- this.clearReferencesStatic = clearReferencesStatic;
- support.firePropertyChange("clearReferencesStatic",
- oldClearReferencesStatic,
- this.clearReferencesStatic);
-
- }
-
-
- /**
- * Return the clearReferencesStopThreads flag for this Context.
- */
- public boolean getClearReferencesStopThreads() {
-
- return (this.clearReferencesStopThreads);
-
- }
-
-
- /**
- * Set the clearReferencesStopThreads feature for this Context.
- *
- * @param clearReferencesStopThreads The new flag value
- */
- public void setClearReferencesStopThreads(
- boolean clearReferencesStopThreads) {
-
- boolean oldClearReferencesStopThreads = this.clearReferencesStopThreads;
- this.clearReferencesStopThreads = clearReferencesStopThreads;
- support.firePropertyChange("clearReferencesStopThreads",
- oldClearReferencesStopThreads,
- this.clearReferencesStopThreads);
-
- }
-
-
- /**
- * Return the clearReferencesStopTimerThreads flag for this Context.
- */
- public boolean getClearReferencesStopTimerThreads() {
- return (this.clearReferencesStopTimerThreads);
- }
-
-
- /**
- * Set the clearReferencesStopTimerThreads feature for this Context.
- *
- * @param clearReferencesStopTimerThreads The new flag value
- */
- public void setClearReferencesStopTimerThreads(
- boolean clearReferencesStopTimerThreads) {
-
- boolean oldClearReferencesStopTimerThreads =
- this.clearReferencesStopTimerThreads;
- this.clearReferencesStopTimerThreads = clearReferencesStopTimerThreads;
- support.firePropertyChange("clearReferencesStopTimerThreads",
- oldClearReferencesStopTimerThreads,
- this.clearReferencesStopTimerThreads);
- }
-
-
- /**
- * Return the clearReferencesHttpClientKeepAliveThread flag for this
- * Context.
- */
- public boolean getClearReferencesHttpClientKeepAliveThread() {
- return (this.clearReferencesHttpClientKeepAliveThread);
- }
-
-
- /**
- * Set the clearReferencesHttpClientKeepAliveThread feature for this
- * Context.
- *
- * @param clearReferencesHttpClientKeepAliveThread The new flag value
- */
- public void setClearReferencesHttpClientKeepAliveThread(
- boolean clearReferencesHttpClientKeepAliveThread) {
- this.clearReferencesHttpClientKeepAliveThread =
- clearReferencesHttpClientKeepAliveThread;
- }
-
-
- public boolean getRenewThreadsWhenStoppingContext() {
- return this.renewThreadsWhenStoppingContext;
- }
-
- public void setRenewThreadsWhenStoppingContext(
- boolean renewThreadsWhenStoppingContext) {
- boolean oldRenewThreadsWhenStoppingContext =
- this.renewThreadsWhenStoppingContext;
- this.renewThreadsWhenStoppingContext = renewThreadsWhenStoppingContext;
- support.firePropertyChange("renewThreadsWhenStoppingContext",
- oldRenewThreadsWhenStoppingContext,
- this.renewThreadsWhenStoppingContext);
- }
-
- // -------------------------------------------------------- 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
- */
- @Override
- public void addApplicationListener(String listener) {
-
- synchronized (applicationListenersLock) {
- String results[] =new String[applicationListeners.length + 1];
- for (int i = 0; i < applicationListeners.length; i++) {
- if (listener.equals(applicationListeners[i])) {
- log.info(sm.getString(
- "standardContext.duplicateListener",listener));
- 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
- */
- @Override
- public void addApplicationParameter(ApplicationParameter parameter) {
-
- synchronized (applicationParametersLock) {
- String newName = parameter.getName();
- for (ApplicationParameter p : applicationParameters) {
- if (newName.equals(p.getName()) && !p.getOverride())
- return;
- }
- ApplicationParameter results[] = Arrays.copyOf(
- applicationParameters, applicationParameters.length + 1);
- 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
- */
- @Override
- public void addChild(Container child) {
-
- // Global JspServlet
- Wrapper oldJspServlet = null;
-
- if (!(child instanceof Wrapper)) {
- throw new IllegalArgumentException
- (sm.getString("standardContext.notWrapper"));
- }
-
- 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);
- }
- }
-
- 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 0 &&
- collections[i].findOmittedMethods().length > 0) {
- throw new IllegalArgumentException(sm.getString(
- "standardContext.securityConstraint.mixHttpMethod"));
- }
- }
-
- // Add this constraint to the set for our web application
- synchronized (constraintsLock) {
- 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
- */
- @Override
- 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(Integer.valueOf(errorPage.getErrorCode()),
- errorPage);
- }
- }
- fireContainerEvent("addErrorPage", errorPage);
-
- }
-
-
- /**
- * Add a filter definition to this Context.
- *
- * @param filterDef The filter definition to be added
- */
- @Override
- public void addFilterDef(FilterDef filterDef) {
-
- synchronized (filterDefs) {
- filterDefs.put(filterDef.getFilterName(), filterDef);
- }
- fireContainerEvent("addFilterDef", filterDef);
-
- }
-
-
- /**
- * Add a filter mapping to this Context at the end of the current set
- * of filter mappings.
- *
- * @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
- */
- @Override
- public void addFilterMap(FilterMap filterMap) {
- validateFilterMap(filterMap);
- // Add this filter mapping to our registered set
- filterMaps.add(filterMap);
- fireContainerEvent("addFilterMap", filterMap);
- }
-
-
- /**
- * Add a filter mapping to this Context before the mappings defined in the
- * deployment descriptor but after any other mappings added via this method.
- *
- * @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
- */
- @Override
- public void addFilterMapBefore(FilterMap filterMap) {
- validateFilterMap(filterMap);
- // Add this filter mapping to our registered set
- filterMaps.addBefore(filterMap);
- fireContainerEvent("addFilterMap", filterMap);
- }
-
-
- /**
- * Validate the supplied FilterMap.
- */
- private void validateFilterMap(FilterMap filterMap) {
- // Validate the proposed filter mapping
- String filterName = filterMap.getFilterName();
- String[] servletNames = filterMap.getServletNames();
- String[] urlPatterns = filterMap.getURLPatterns();
- if (findFilterDef(filterName) == null)
- throw new IllegalArgumentException
- (sm.getString("standardContext.filterMap.name", filterName));
-
- if (!filterMap.getMatchAllServletNames() &&
- !filterMap.getMatchAllUrlPatterns() &&
- (servletNames.length == 0) && (urlPatterns.length == 0))
- throw new IllegalArgumentException
- (sm.getString("standardContext.filterMap.either"));
- // FIXME: Older spec revisions may still check this
- /*
- if ((servletNames.length != 0) && (urlPatterns.length != 0))
- throw new IllegalArgumentException
- (sm.getString("standardContext.filterMap.either"));
- */
- for (int i = 0; i < urlPatterns.length; i++) {
- if (!validateURLPattern(urlPatterns[i])) {
- throw new IllegalArgumentException
- (sm.getString("standardContext.filterMap.pattern",
- urlPatterns[i]));
- }
- }
- }
-
- /**
- * 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
- */
- @Override
- public void addInstanceListener(String listener) {
-
- synchronized (instanceListenersLock) {
- 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 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
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- public void addSecurityRole(String role) {
-
- synchronized (securityRolesLock) {
- 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
- */
- @Override
- 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
- */
- @Override
- 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));
- String decodedPattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
- if (!validateURLPattern(decodedPattern))
- throw new IllegalArgumentException
- (sm.getString("standardContext.servletMap.pattern", decodedPattern));
-
- // Add this mapping to our registered set
- synchronized (servletMappingsLock) {
- String name2 = servletMappings.get(decodedPattern);
- if (name2 != null) {
- // Don't allow more than one servlet on the same pattern
- Wrapper wrapper = (Wrapper) findChild(name2);
- wrapper.removeMapping(decodedPattern);
- mapper.removeWrapper(decodedPattern);
- }
- servletMappings.put(decodedPattern, name);
- }
- Wrapper wrapper = (Wrapper) findChild(name);
- wrapper.addMapping(decodedPattern);
-
- // Update context mapper
- mapper.addWrapper(decodedPattern, wrapper, jspWildCard,
- resourceOnlyServlets.contains(name));
-
- fireContainerEvent("addServletMapping", decodedPattern);
-
- }
-
-
- /**
- * Add a new watched resource to the set recognized by this Context.
- *
- * @param name New watched resource file name
- */
- @Override
- public void addWatchedResource(String name) {
-
- synchronized (watchedResourcesLock) {
- 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
- */
- @Override
- public void addWelcomeFile(String name) {
-
- synchronized (welcomeFilesLock) {
- // Welcome files from the application deployment descriptor
- // completely replace those from the default conf/web.xml file
- if (replaceWelcomeFiles) {
- fireContainerEvent(CLEAR_WELCOME_FILES_EVENT, null);
- 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;
- }
- if(this.getState().equals(LifecycleState.STARTED))
- fireContainerEvent(ADD_WELCOME_FILE_EVENT, 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
- */
- @Override
- public void addWrapperLifecycle(String listener) {
-
- synchronized (wrapperLifecyclesLock) {
- 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
- */
- @Override
- public void addWrapperListener(String listener) {
-
- synchronized (wrapperListenersLock) {
- 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.
- */
- @Override
- public Wrapper createWrapper() {
-
- Wrapper wrapper = null;
- if (wrapperClass != null) {
- try {
- wrapper = (Wrapper) wrapperClass.newInstance();
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error("createWrapper", t);
- return (null);
- }
- } else {
- wrapper = new StandardWrapper();
- }
-
- synchronized (instanceListenersLock) {
- 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) {
- ExceptionUtils.handleThrowable(t);
- log.error("createWrapper", t);
- return (null);
- }
- }
- }
-
- synchronized (wrapperLifecyclesLock) {
- for (int i = 0; i < wrapperLifecycles.length; i++) {
- try {
- Class> clazz = Class.forName(wrapperLifecycles[i]);
- LifecycleListener listener =
- (LifecycleListener) clazz.newInstance();
- wrapper.addLifecycleListener(listener);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- log.error("createWrapper", t);
- return (null);
- }
- }
- }
-
- synchronized (wrapperListenersLock) {
- 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) {
- ExceptionUtils.handleThrowable(t);
- log.error("createWrapper", t);
- return (null);
- }
- }
- }
-
- return (wrapper);
-
- }
-
-
- /**
- * Return the set of application listener class names configured
- * for this application.
- */
- @Override
- public String[] findApplicationListeners() {
-
- return (applicationListeners);
-
- }
-
-
- /**
- * Return the set of application parameters for this application.
- */
- @Override
- public ApplicationParameter[] findApplicationParameters() {
-
- synchronized (applicationParametersLock) {
- return (applicationParameters);
- }
-
- }
-
-
- /**
- * Return the security constraints for this web application.
- * If there are none, a zero-length array is returned.
- */
- @Override
- public SecurityConstraint[] findConstraints() {
-
- return (constraints);
-
- }
-
-
- /**
- * Return the error page entry for the specified HTTP error code,
- * if any; otherwise return null.
- *
- * @param errorCode Error code to look up
- */
- @Override
- public ErrorPage findErrorPage(int errorCode) {
- if (errorCode == 200) {
- return (okErrorPage);
- } else {
- return (statusPages.get(Integer.valueOf(errorCode)));
- }
-
- }
-
-
- /**
- * Return the error page entry for the specified Java exception type,
- * if any; otherwise return null.
- *
- * @param exceptionType Exception type to look up
- */
- @Override
- public ErrorPage findErrorPage(String exceptionType) {
-
- synchronized (exceptionPages) {
- return (exceptionPages.get(exceptionType));
- }
-
- }
-
-
- /**
- * Return the set of defined error pages for all specified error codes
- * and exception types.
- */
- @Override
- public ErrorPage[] findErrorPages() {
-
- synchronized(exceptionPages) {
- synchronized(statusPages) {
- ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
- results1 = exceptionPages.values().toArray(results1);
- ErrorPage results2[] = new ErrorPage[statusPages.size()];
- results2 = 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 null.
- *
- * @param filterName Filter name to look up
- */
- @Override
- public FilterDef findFilterDef(String filterName) {
-
- synchronized (filterDefs) {
- return (filterDefs.get(filterName));
- }
-
- }
-
-
- /**
- * Return the set of defined filters for this Context.
- */
- @Override
- public FilterDef[] findFilterDefs() {
-
- synchronized (filterDefs) {
- FilterDef results[] = new FilterDef[filterDefs.size()];
- return (filterDefs.values().toArray(results));
- }
-
- }
-
-
- /**
- * Return the set of filter mappings for this Context.
- */
- @Override
- public FilterMap[] findFilterMaps() {
- return filterMaps.asArray();
- }
-
-
- /**
- * Return the set of InstanceListener classes that will be added to
- * newly created Wrappers automatically.
- */
- @Override
- public String[] findInstanceListeners() {
-
- synchronized (instanceListenersLock) {
- return (instanceListeners);
- }
-
- }
-
-
- /**
- * FIXME: Fooling introspection ...
- */
- public Context findMappingObject() {
- return (Context) getMappingObject();
- }
-
-
- /**
- * Return the message destination with the specified name, if any;
- * otherwise, return null.
- *
- * @param name Name of the desired message destination
- */
- public MessageDestination findMessageDestination(String name) {
-
- synchronized (messageDestinations) {
- return (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 (messageDestinations.values().toArray(results));
- }
-
- }
-
-
- /**
- * Return the message destination ref with the specified name, if any;
- * otherwise, return null.
- *
- * @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 null.
- *
- * @param extension Extension to map to a MIME type
- */
- @Override
- public String findMimeMapping(String extension) {
-
- return (mimeMappings.get(extension));
-
- }
-
-
- /**
- * Return the extensions for which MIME mappings are defined. If there
- * are none, a zero-length array is returned.
- */
- @Override
- public String[] findMimeMappings() {
-
- synchronized (mimeMappings) {
- String results[] = new String[mimeMappings.size()];
- return
- (mimeMappings.keySet().toArray(results));
- }
-
- }
-
-
- /**
- * Return the value for the specified context initialization
- * parameter name, if any; otherwise return null.
- *
- * @param name Name of the parameter to return
- */
- @Override
- public String findParameter(String name) {
-
- synchronized (parameters) {
- return (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.
- */
- @Override
- public String[] findParameters() {
-
- synchronized (parameters) {
- String results[] = new String[parameters.size()];
- return (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
- */
- @Override
- public String findRoleMapping(String role) {
-
- String realRole = null;
- synchronized (roleMappings) {
- realRole = roleMappings.get(role);
- }
- if (realRole != null)
- return (realRole);
- else
- return (role);
-
- }
-
-
- /**
- * Return true if the specified security role is defined
- * for this application; otherwise return false.
- *
- * @param role Security role to verify
- */
- @Override
- public boolean findSecurityRole(String role) {
-
- synchronized (securityRolesLock) {
- 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.
- */
- @Override
- public String[] findSecurityRoles() {
-
- synchronized (securityRolesLock) {
- return (securityRoles);
- }
-
- }
-
-
- /**
- * Return the servlet name mapped by the specified pattern (if any);
- * otherwise return null.
- *
- * @param pattern Pattern for which a mapping is requested
- */
- @Override
- public String findServletMapping(String pattern) {
-
- synchronized (servletMappingsLock) {
- return (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.
- */
- @Override
- public String[] findServletMappings() {
-
- synchronized (servletMappingsLock) {
- String results[] = new String[servletMappings.size()];
- return
- (servletMappings.keySet().toArray(results));
- }
-
- }
-
-
- /**
- * Return the context-relative URI of the error page for the specified
- * HTTP status code, if any; otherwise return null.
- *
- * @param status HTTP status code to look up
- */
- @Override
- public String findStatusPage(int status) {
-
- ErrorPage errorPage = statusPages.get(Integer.valueOf(status));
- if (errorPage!=null) {
- return errorPage.getLocation();
- }
- return null;
-
- }
-
-
- /**
- * Return the set of HTTP status codes for which error pages have
- * been specified. If none are specified, a zero-length array
- * is returned.
- */
- @Override
- public int[] findStatusPages() {
-
- synchronized (statusPages) {
- int results[] = new int[statusPages.size()];
- Iterator elements = statusPages.keySet().iterator();
- int i = 0;
- while (elements.hasNext())
- results[i++] = elements.next().intValue();
- return (results);
- }
-
- }
-
-
- /**
- * Return true if the specified welcome file is defined
- * for this Context; otherwise return false.
- *
- * @param name Welcome file to verify
- */
- @Override
- public boolean findWelcomeFile(String name) {
-
- synchronized (welcomeFilesLock) {
- 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.
- */
- @Override
- public String[] findWatchedResources() {
- synchronized (watchedResourcesLock) {
- return watchedResources;
- }
- }
-
-
- /**
- * Return the set of welcome files defined for this Context. If none are
- * defined, a zero-length array is returned.
- */
- @Override
- public String[] findWelcomeFiles() {
-
- synchronized (welcomeFilesLock) {
- return (welcomeFiles);
- }
-
- }
-
-
- /**
- * Return the set of LifecycleListener classes that will be added to
- * newly created Wrappers automatically.
- */
- @Override
- public String[] findWrapperLifecycles() {
-
- synchronized (wrapperLifecyclesLock) {
- return (wrapperLifecycles);
- }
-
- }
-
-
- /**
- * Return the set of ContainerListener classes that will be added to
- * newly created Wrappers automatically.
- */
- @Override
- public String[] findWrapperListeners() {
-
- synchronized (wrapperListenersLock) {
- return (wrapperListeners);
- }
-
- }
-
-
- /**
- * Reload this web application, if reloading is supported.
- *
- * IMPLEMENTATION NOTE: 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 reloadable
- * property is set to false.
- */
- @Override
- public synchronized void reload() {
-
- // Validate our current component state
- if (!getState().isAvailable())
- throw new IllegalStateException
- (sm.getString("standardContext.notStarted", getName()));
-
- if(log.isInfoEnabled())
- log.info(sm.getString("standardContext.reloadingStarted",
- getName()));
-
- // Stop accepting requests temporarily
- setPaused(true);
-
- try {
- stop();
- } catch (LifecycleException e) {
- log.error(
- sm.getString("standardContext.stoppingContext", getName()), e);
- }
-
- try {
- start();
- } catch (LifecycleException e) {
- log.error(
- sm.getString("standardContext.startingContext", getName()), e);
- }
-
- setPaused(false);
-
- if(log.isInfoEnabled())
- log.info(sm.getString("standardContext.reloadingCompleted",
- getName()));
-
- }
-
-
- /**
- * 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
- */
- @Override
- public void removeApplicationListener(String listener) {
-
- synchronized (applicationListenersLock) {
-
- // 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
- */
- @Override
- public void removeApplicationParameter(String name) {
-
- synchronized (applicationParametersLock) {
-
- // 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
- */
- @Override
- 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
- */
- @Override
- public void removeConstraint(SecurityConstraint constraint) {
-
- synchronized (constraintsLock) {
-
- // 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
- */
- @Override
- 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(Integer.valueOf(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
- */
- @Override
- 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
- */
- @Override
- public void removeFilterMap(FilterMap filterMap) {
- filterMaps.remove(filterMap);
- // 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
- */
- @Override
- public void removeInstanceListener(String listener) {
-
- synchronized (instanceListenersLock) {
-
- // 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
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- 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
- */
- @Override
- public void removeSecurityRole(String role) {
-
- synchronized (securityRolesLock) {
-
- // 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
- */
- @Override
- public void removeServletMapping(String pattern) {
-
- String name = null;
- synchronized (servletMappingsLock) {
- name = servletMappings.remove(pattern);
- }
- Wrapper wrapper = (Wrapper) findChild(name);
- if( wrapper != null ) {
- wrapper.removeMapping(pattern);
- }
- mapper.removeWrapper(pattern);
- fireContainerEvent("removeServletMapping", pattern);
-
- }
-
-
- /**
- * Remove the specified watched resource name from the list associated
- * with this Context.
- *
- * @param name Name of the watched resource to be removed
- */
- @Override
- public void removeWatchedResource(String name) {
-
- synchronized (watchedResourcesLock) {
-
- // 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
- */
- @Override
- public void removeWelcomeFile(String name) {
-
- synchronized (welcomeFilesLock) {
-
- // 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
- if(this.getState().equals(LifecycleState.STARTED))
- fireContainerEvent(REMOVE_WELCOME_FILE_EVENT, 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
- */
- @Override
- public void removeWrapperLifecycle(String listener) {
-
-
- synchronized (wrapperLifecyclesLock) {
-
- // 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
- */
- @Override
- public void removeWrapperListener(String listener) {
-
-
- synchronized (wrapperListenersLock) {
-
- // 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;
- }
-
-
- /**
- * Return the real path for a given virtual path, if possible; otherwise
- * return null.
- *
- * @param path The path to the desired resource
- */
- @Override
- public String getRealPath(String path) {
- if (webappResources instanceof BaseDirContext) {
- return ((BaseDirContext) webappResources).getRealPath(path);
- }
- return null;
- }
-
- /**
- * hook to register that we need to scan for security annotations.
- * @param wrapper The wrapper for the Servlet that was added
- */
- public ServletRegistration.Dynamic dynamicServletAdded(Wrapper wrapper) {
- Servlet s = wrapper.getServlet();
- if (s != null && createdServlets.contains(s)) {
- // Mark the wrapper to indicate annotations need to be scanned
- wrapper.setServletSecurityAnnotationScanRequired(true);
- }
- return new ApplicationServletRegistration(wrapper, this);
- }
-
- /**
- * hook to track which registrations need annotation scanning
- * @param servlet
- */
- public void dynamicServletCreated(Servlet servlet) {
- createdServlets.add(servlet);
- }
-
-
- /**
- * A helper class to manage the filter mappings in a Context.
- */
- private static final class ContextFilterMaps {
- private final Object lock = new Object();
-
- /**
- * The set of filter mappings for this application, in the order they
- * were defined in the deployment descriptor with additional mappings
- * added via the {@link ServletContext} possibly both before and after
- * those defined in the deployment descriptor.
- */
- private FilterMap[] array = new FilterMap[0];
-
- /**
- * Filter mappings added via {@link ServletContext} may have to be
- * inserted before the mappings in the deployment descriptor but must be
- * inserted in the order the {@link ServletContext} methods are called.
- * This isn't an issue for the mappings added after the deployment
- * descriptor - they are just added to the end - but correctly the
- * adding mappings before the deployment descriptor mappings requires
- * knowing where the last 'before' mapping was added.
- */
- private int insertPoint = 0;
-
- /**
- * Return the set of filter mappings.
- */
- public FilterMap[] asArray() {
- synchronized (lock) {
- return array;
- }
- }
-
- /**
- * Add a filter mapping at the end of the current set of filter
- * mappings.
- *
- * @param filterMap
- * The filter mapping to be added
- */
- public void add(FilterMap filterMap) {
- synchronized (lock) {
- FilterMap results[] = Arrays.copyOf(array, array.length + 1);
- results[array.length] = filterMap;
- array = results;
- }
- }
-
- /**
- * Add a filter mapping before the mappings defined in the deployment
- * descriptor but after any other mappings added via this method.
- *
- * @param filterMap
- * The filter mapping to be added
- */
- public void addBefore(FilterMap filterMap) {
- synchronized (lock) {
- FilterMap results[] = new FilterMap[array.length + 1];
- System.arraycopy(array, 0, results, 0, insertPoint);
- System.arraycopy(array, insertPoint, results, insertPoint + 1,
- array.length - insertPoint);
- results[insertPoint] = filterMap;
- array = results;
- insertPoint++;
- }
- }
-
- /**
- * Remove a filter mapping.
- *
- * @param filterMap The filter mapping to be removed
- */
- public void remove(FilterMap filterMap) {
- synchronized (lock) {
- // Make sure this filter mapping is currently present
- int n = -1;
- for (int i = 0; i < array.length; i++) {
- if (array[i] == filterMap) {
- n = i;
- break;
- }
- }
- if (n < 0)
- return;
-
- // Remove the specified filter mapping
- FilterMap results[] = new FilterMap[array.length - 1];
- System.arraycopy(array, 0, results, 0, n);
- System.arraycopy(array, n + 1, results, n, (array.length - 1)
- - n);
- array = results;
- if (n < insertPoint) {
- insertPoint--;
- }
- }
- }
- }
-
- // --------------------------------------------------------- Public Methods
-
-
- /**
- * Configure and initialize the set of filters for this Context.
- * Return true if all filter initialization completed
- * successfully, or false 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 = names.next();
- if (getLogger().isDebugEnabled())
- getLogger().debug(" Starting filter '" + name + "'");
- ApplicationFilterConfig filterConfig = null;
- try {
- filterConfig =
- new ApplicationFilterConfig(this, filterDefs.get(name));
- filterConfigs.put(name, filterConfig);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(t);
- getLogger().error
- (sm.getString("standardContext.filterStart", name), t);
- ok = false;
- }
- }
- }
-
- return (ok);
-
- }
-
-
- /**
- * Finalize and release the set of filters for this Context.
- * Return true if all filter finalization completed
- * successfully, or false 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 = names.next();
- if (getLogger().isDebugEnabled())
- getLogger().debug(" Stopping filter '" + name + "'");
- ApplicationFilterConfig filterConfig = filterConfigs.get(name);
- filterConfig.release();
- }
- filterConfigs.clear();
- }
- return (true);
-
- }
-
-
- /**
- * Find and return the initialized FilterConfig for the
- * specified filter name, if any; otherwise return null.
- *
- * @param name Name of the desired filter
- */
- public FilterConfig findFilterConfig(String name) {
-
- return (filterConfigs.get(name));
-
- }
-
-
- /**
- * Configure the set of instantiated application event listeners
- * for this Context. Return true if all listeners wre
- * initialized successfully, or false otherwise.
- */
- public boolean listenerStart() {
-
- if (log.isDebugEnabled())
- log.debug("Configuring application event listeners");
-
- // Instantiate the required listeners
- 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 {
- results[i] = instanceManager.newInstance(listeners[i]);
- } catch (Throwable t) {
- ExceptionUtils.handleThrowable(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
+
+
When using automatic deployment, the docBase defined by
+ an XML Context file should be outside of the
+ appBase directory. If this is not the case, difficulties
+ may be experienced deploying the web application or the application may
+ be deployed twice. The deployIgnore attribute can be used
+ to avoid this situation.
+
+
Finally, note that if you are defining contexts explicitly in server.xml,
+ you should probably turn off automatic application deployment or specify
+ deployIgnore carefully. Otherwise, the web applications
+ will each be deployed twice, and that may cause problems for the
+ applications.
+
+
+
+
+
+
+
In many server environments, Network Administrators have configured
+ more than one network name (in the Domain Name Service (DNS)
+ server), that resolve to the IP address of the same server. Normally,
+ each such network name would be configured as a separate
+ Host element in conf/server.xml, each
+ with its own set of web applications.
+
+
However, in some circumstances, it is desirable that two or more
+ network names should resolve to the same virtual host,
+ running the same set of applications. A common use case for this
+ scenario is a corporate web site, where it is desirable that users
+ be able to utilize either www.mycompany.com or
+ company.com to access exactly the same content and
+ applications.
+
+
This is accomplished by utilizing one or more Alias
+ elements nested inside your Host element. For
+ example:
+
+
+
In order for this strategy to be effective, all of the network names
+ involved must be registered in your DNS server to resolve to the
+ same computer that is running this instance of Catalina.
+
+
+
+
+
+
+
If you have implemented a Java object that needs to know when this
+ Host is started or stopped, you can declare it by
+ nesting a Listener element inside this element. The
+ class name you specify must implement the
+ org.apache.catalina.LifecycleListener interface, and
+ it will be notified about the occurrence of the corresponding
+ lifecycle events. Configuration of such a listener looks like this:
+
+
+
+
Note that a Listener can have any number of additional properties
+ that may be configured from this element. Attribute names are matched
+ to corresponding JavaBean property names using the standard property
+ method naming patterns.
+
+
+
+
+
+
+
You can ask Catalina to check the IP address, or host name, on every
+ incoming request directed to the surrounding
+ Engine, Host, or
+ Context element. The remote address or name
+ will be checked against configured "accept" and/or "deny"
+ filters, which are defined using java.util.regex Regular
+ Expression syntax. Requests that come from locations that are
+ not accepted will be rejected with an HTTP "Forbidden" error.
+ Example filter declarations:
In many environments, but particularly in portal environments, it
+ is desireable to have a user challenged to authenticate themselves only
+ once over a set of web applications deployed on a particular virtual
+ host. This can be accomplished by nesting an element like this inside
+ the Host element for this virtual host:
+
+
+
+
The Single Sign On facility operates according to the following rules:
+
+
+
All web applications configured for this virtual host must share the
+ same Realm. In practice, that means you can
+ nest the Realm element inside this Host element (or the surrounding
+ Engine element), but not inside a
+ Context element for one of the involved
+ web applications.
+
As long as the user accesses only unprotected resources in any of the
+ web applications on this virtual host, they will not be challenged
+ to authenticate themselves.
+
As soon as the user accesses a protected resource in
+ any web application associated with this virtual
+ host, the user will be challenged to authenticate himself or herself,
+ using the login method defined for the web application currently
+ being accessed.
+
Once authenticated, the roles associated with this user will be
+ utilized for access control decisions across all
+ of the associated web applications, without challenging the user
+ to authenticate themselves to each application individually.
+
As soon as the user logs out of one web application (for example,
+ by invalidating the corresponding session if form
+ based login is used), the user's sessions in all
+ web applications will be invalidated. Any subsequent attempt to
+ access a protected resource in any application will require the
+ user to authenticate himself or herself again.
+
The Single Sign On feature utilizes HTTP cookies to transmit a token
+ that associates each request with the saved user identity, so it can
+ only be utilized in client environments that support cookies.
+
+
+
+
+
+
+
+
Many web servers can automatically map a request URI starting with
+ a tilde character ("~") and a username to a directory (commonly named
+ public_html) in that user's home directory on the server.
+ You can accomplish the same thing in Catalina by using a special
+ Listener element like this (on a Unix system that
+ uses the /etc/passwd file to identify valid users):
+
+
+
+
On a server where /etc/passwd is not in use, you can
+ request Catalina to consider all directories found in a specified base
+ directory (such as c:\Homes in this example) to be
+ considered "user home" directories for the purposes of this directive:
+
+
+
+
If a user home directory has been set up for a user named
+ craigmcc, then its contents will be visible from a
+ client browser by making a request to a URL like:
+
+
+
+
Successful use of this feature requires recognition of the following
+ considerations:
+
+
Each user web application will be deployed with characteristics
+ established by the global and host level default context settings.
+
It is legal to include more than one instance of this Listener
+ element. This would only be useful, however, in circumstances
+ where you wanted to configure more than one "homeBase" directory.
+
The operating system username under which Catalina is executed
+ MUST have read access to each user's web application directory,
+ and all of its contents.