/*
 * 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.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

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.naming.NamingException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.FilterRegistration;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextAttributeListener;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.ServletRegistration.Dynamic;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletRequestAttributeListener;
import jakarta.servlet.ServletRequestEvent;
import jakarta.servlet.ServletRequestListener;
import jakarta.servlet.ServletSecurityElement;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.SessionTrackingMode;
import jakarta.servlet.descriptor.JspConfigDescriptor;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionIdListener;
import jakarta.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.CredentialHandler;
import org.apache.catalina.Globals;
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.Realm;
import org.apache.catalina.ThreadBindingListener;
import org.apache.catalina.Valve;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.Wrapper;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.util.CharsetMapper;
import org.apache.catalina.util.ContextName;
import org.apache.catalina.util.ErrorPageSupport;
import org.apache.catalina.util.ExtensionValidator;
import org.apache.catalina.util.URLEncoder;
import org.apache.catalina.webresources.StandardRoot;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.naming.ContextBindings;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.InstanceManagerBindings;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.buf.StringUtils;
import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.descriptor.XmlIdentifiers;
import org.apache.tomcat.util.descriptor.web.ApplicationParameter;
import org.apache.tomcat.util.descriptor.web.ErrorPage;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.Injectable;
import org.apache.tomcat.util.descriptor.web.InjectionTarget;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.MessageDestination;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.http.Rfc6265CookieProcessor;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.apache.tomcat.util.security.PrivilegedGetTccl;
import org.apache.tomcat.util.security.PrivilegedSetTccl;

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, Remy Maucherat
/** * Standard implementation of the <b>Context</b> interface. Each * child container must be a Wrapper implementation to process the * requests directed to a particular servlet. * * @author Craig R. McClanahan * @author Remy Maucherat */
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.
/** * 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"); } } // ----------------------------------------------------- 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.
/** * Allow multipart/form-data requests to be parsed even when the * target servlet doesn't specify @MultipartConfig or have a * &lt;multipart-config&gt; element. */
protected boolean allowCasualMultipartParsing = false;
Control whether remaining request data will be read (swallowed) even if the request violates a data size constraint.
/** * 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.
/** * The alternate deployment descriptor name. */
private String altDDName = null;
Lifecycle provider.
/** * Lifecycle provider. */
private InstanceManager instanceManager = null;
The antiResourceLocking flag for this Context.
/** * 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 resulting merged web.xml file.
/** * The set of application listener class names configured for this * application, in the order they were encountered in the resulting merged * web.xml file. */
private String applicationListeners[] = new String[0]; private final Object applicationListenersLock = new Object();
The set of application listeners that are required to have limited access to ServletContext methods. See Servlet 3.1 section 4.4.
/** * The set of application listeners that are required to have limited access * to ServletContext methods. See Servlet 3.1 section 4.4. */
private final Set<Object> noPluggabilityListeners = new HashSet<>();
The list of instantiated application event listener objects. Note that SCIs and other code may use the pluggability APIs to add listener instances directly to this list before the application starts.
/** * The list of instantiated application event listener objects. Note that * SCIs and other code may use the pluggability APIs to add listener * instances directly to this list before the application starts. */
private List<Object> applicationEventListenersList = new CopyOnWriteArrayList<>();
The set of instantiated application lifecycle listener objects. Note that SCIs and other code may use the pluggability APIs to add listener instances directly to this list before the application starts.
/** * The set of instantiated application lifecycle listener objects. Note that * SCIs and other code may use the pluggability APIs to add listener * instances directly to this list before the application starts. */
private Object applicationLifecycleListenersObjects[] = new Object[0];
The ordered set of ServletContainerInitializers for this web application.
/** * The ordered set of ServletContainerInitializers for this web application. */
private Map<ServletContainerInitializer,Set<Class<?>>> initializers = new LinkedHashMap<>();
The set of application parameters defined for this application.
/** * 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.
/** * The broadcaster that sends j2ee notifications. */
private NotificationBroadcasterSupport broadcaster = null;
The Locale to character set mapper for this application.
/** * The Locale to character set mapper for this application. */
private CharsetMapper charsetMapper = null;
The Java class name of the CharsetMapper class to be created.
/** * 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.
/** * The URL of the XML descriptor for this context. */
private URL configFile = null;
The "correctly configured" flag for this Context.
/** * The "correctly configured" flag for this Context. */
private boolean configured = false;
The security constraints for this web application.
/** * 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.
/** * The ServletContext implementation associated with this Context. */
protected ApplicationContext context = null;
The wrapped version of the associated ServletContext that is presented to listeners that are required to have limited access to ServletContext methods. See Servlet 3.1 section 4.4.
/** * The wrapped version of the associated ServletContext that is presented * to listeners that are required to have limited access to ServletContext * methods. See Servlet 3.1 section 4.4. */
private NoPluggabilityServletContext noPluggabilityServletContext = null;
Should we attempt to use cookies for session id communication?
/** * 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?
/** * Should we allow the <code>ServletContext.getContext()</code> method * to access the context of other web applications in this server? */
private boolean crossContext = false;
Encoded path.
/** * Encoded path. */
private String encodedPath = null;
Unencoded path for this web application.
/** * Unencoded path for this web application. */
private String path = null;
The "follow standard delegation model" flag that will be used to configure our ClassLoader. Graal cannot actually load a class from the webapp classloader, so delegate by default.
/** * The "follow standard delegation model" flag that will be used to * configure our ClassLoader. * Graal cannot actually load a class from the webapp classloader, * so delegate by default. */
private boolean delegate = JreCompat.isGraalAvailable(); private boolean denyUncoveredHttpMethods;
The display name of this web application.
/** * The display name of this web application. */
private String displayName = null;
Override the default context xml location.
/** * Override the default context xml location. */
private String defaultContextXml;
Override the default web xml location.
/** * Override the default web xml location. */
private String defaultWebXml;
The distributable flag for this web application.
/** * The distributable flag for this web application. */
private boolean distributable = false;
The document root for this web application.
/** * The document root for this web application. */
private String docBase = null; private final ErrorPageSupport errorPageSupport = new ErrorPageSupport();
The set of filter configurations (and associated filter instances) we have initialized, keyed by filter name.
/** * The set of filter configurations (and associated filter instances) we * have initialized, keyed by filter name. */
private Map<String, ApplicationFilterConfig> filterConfigs = new HashMap<>();
The set of filter definitions for this application, keyed by filter name.
/** * The set of filter definitions for this application, keyed by * filter name. */
private Map<String, FilterDef> 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 ServletContext possibly both before and after those defined in the deployment descriptor.
/** * 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.
/** * Ignore annotations. */
private boolean ignoreAnnotations = false;
The Loader implementation with which this Container is associated.
/** * The Loader implementation with which this Container is associated. */
private Loader loader = null; private final ReadWriteLock loaderLock = new ReentrantReadWriteLock();
The login configuration descriptor for this web application.
/** * The login configuration descriptor for this web application. */
private LoginConfig loginConfig = null;
The Manager implementation with which this Container is associated.
/** * The Manager implementation with which this Container is associated. */
protected Manager manager = null; private final ReadWriteLock managerLock = new ReentrantReadWriteLock();
The naming context listener for this web application.
/** * The naming context listener for this web application. */
private NamingContextListener namingContextListener = null;
The naming resources for this web application.
/** * The naming resources for this web application. */
private NamingResourcesImpl namingResources = null;
The message destinations for this web application.
/** * The message destinations for this web application. */
private HashMap<String, MessageDestination> messageDestinations = new HashMap<>();
The MIME mappings for this web application, keyed by extension.
/** * The MIME mappings for this web application, keyed by extension. */
private Map<String, String> mimeMappings = new HashMap<>();
The context initialization parameters for this web application, keyed by name.
/** * The context initialization parameters for this web application, * keyed by name. */
private final Map<String, String> parameters = new ConcurrentHashMap<>();
The request processing pause flag (while reloading occurs)
/** * The request processing pause flag (while reloading occurs) */
private volatile 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.
/** * 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.
/** * The reloadable flag for this web application. */
private boolean reloadable = false;
Unpack WAR property.
/** * Unpack WAR property. */
private boolean unpackWAR = true;
Context level override for default StandardHost.isCopyXML().
/** * Context level override for default {@link StandardHost#isCopyXML()}. */
private boolean copyXML = false;
The default context override flag for this web application.
/** * The default context override flag for this web application. */
private boolean override = false;
The original document root for this web application.
/** * The original document root for this web application. */
private String originalDocBase = null;
The privileged flag for this web application.
/** * 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.
/** * Should the next call to <code>addWelcomeFile()</code> cause replacement * of any existing welcome files? This will be set before processing the * web application's deployment descriptor, so that application specified * choices <strong>replace</strong>, rather than append to, those defined * in the global descriptor. */
private boolean replaceWelcomeFiles = false;
The security role mappings for this application, keyed by role name (as used within the application).
/** * The security role mappings for this application, keyed by role * name (as used within the application). */
private Map<String, String> roleMappings = new HashMap<>();
The security roles for this application, keyed by role name.
/** * 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.
/** * The servlet mappings for this web application, keyed by * matching pattern. */
private Map<String, String> servletMappings = new HashMap<>(); private final Object servletMappingsLock = new Object();
The session timeout (in minutes) for this web application.
/** * The session timeout (in minutes) for this web application. */
private int sessionTimeout = 30;
The notification sequence number.
/** * The notification sequence number. */
private AtomicLong sequenceNumber = new AtomicLong(0);
Set flag to true to cause the system.out and system.err to be redirected to the logger when executing a servlet.
/** * 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.
/** * Amount of ms that the container will wait for servlets to unload. */
private long unloadDelay = 2000;
The watched resources for this application.
/** * The watched resources for this application. */
private String watchedResources[] = new String[0]; private final Object watchedResourcesLock = new Object();
The welcome files for this application.
/** * 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().
/** * The set of classnames of LifecycleListeners that will be added * to each newly created Wrapper by <code>createWrapper()</code>. */
private String wrapperLifecycles[] = new String[0]; private final Object wrapperLifecyclesLock = new Object();
The set of classnames of ContainerListeners that will be added to each newly created Wrapper by createWrapper().
/** * The set of classnames of ContainerListeners that will be added * to each newly created Wrapper by <code>createWrapper()</code>. */
private String wrapperListeners[] = new String[0]; private final Object wrapperListenersLock = new Object();
The pathname to the work directory for this context (relative to the server's home if not absolute).
/** * 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.
/** * Java class name of the Wrapper class implementation we use. */
private String wrapperClassName = StandardWrapper.class.getName(); private Class<?> wrapperClass = null;
JNDI use flag.
/** * JNDI use flag. */
private boolean useNaming = true;
Name of the associated naming context.
/** * Name of the associated naming context. */
private String namingContextName = null; private WebResourceRoot resources; private final ReadWriteLock resourcesLock = new ReentrantReadWriteLock(); private long startupTime; private long startTime; private long tldScanTime;
Name of the engine. If null, the domain is used.
/** * 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 for web.xml and web-fragment.xml files.
/** * Attribute value used to turn on/off XML validation for web.xml and * web-fragment.xml files. */
private boolean webXmlValidation = Globals.STRICT_SERVLET_COMPLIANCE;
Attribute value used to turn on/off XML namespace validation
/** * Attribute value used to turn on/off XML namespace validation */
private boolean webXmlNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;
Attribute used to turn on/off the use of external entities.
/** * Attribute used to turn on/off the use of external entities. */
private boolean xmlBlockExternal = true;
Attribute value used to turn on/off XML validation
/** * Attribute value used to turn on/off XML validation */
private boolean tldValidation = Globals.STRICT_SERVLET_COMPLIANCE;
The name to use for session cookies. null indicates that the name is controlled by the application.
/** * The name to use for session cookies. <code>null</code> indicates that * the name is controlled by the application. */
private String sessionCookieName;
The flag that indicates that session cookies should use HttpOnly
/** * 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.
/** * The domain to use for session cookies. <code>null</code> 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.
/** * The path to use for session cookies. <code>null</code> 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.
/** * 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 = false;
The Jar scanner to use to search for Jars that might contain configuration information such as TLDs or web-fragment.xml files.
/** * 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;
Enables the RMI Target memory leak detection to be controlled. This is necessary since the detection can only work on Java 9 if some of the modularity checks are disabled.
/** * Enables the RMI Target memory leak detection to be controlled. This is * necessary since the detection can only work on Java 9 if some of the * modularity checks are disabled. */
private boolean clearReferencesRmiTargets = true;
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.
/** * Should Tomcat attempt to terminate threads that have been started by the * web application? Stopping threads is performed via the deprecated (for * good reason) <code>Thread.stop()</code> 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 * <code>false</code> will be used. */
private boolean clearReferencesStopThreads = false;
Should Tomcat attempt to terminate any TimerThreads that have been started by the web application? If not specified, the default value of false will be used.
/** * 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 <code>false</code> 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 ClassLoader to ClassLoader.getParent() 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.
/** * 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 ClassLoader} to * {@link ClassLoader#getParent()} 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 or ThreadPoolExecutor be set to a positive value.
/** * 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 or ThreadPoolExecutor be set to a positive value. */
private boolean renewThreadsWhenStoppingContext = true;
Should Tomcat attempt to clear references to classes loaded by the web application class loader from the ObjectStreamClass caches?
/** * Should Tomcat attempt to clear references to classes loaded by the web * application class loader from the ObjectStreamClass caches? */
private boolean clearReferencesObjectStreamClassCaches = true;
Should Tomcat attempt to clear references to classes loaded by this class loader from ThreadLocals?
/** * Should Tomcat attempt to clear references to classes loaded by this class * loader from ThreadLocals? */
private boolean clearReferencesThreadLocals = true;
Should Tomcat skip the memory leak checks when the web application is stopped as part of the process of shutting down the JVM?
/** * Should Tomcat skip the memory leak checks when the web application is * stopped as part of the process of shutting down the JVM? */
private boolean skipMemoryLeakChecksOnJvmShutdown = false;
Should the effective web.xml be logged when the context starts?
/** * 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 = null; private Set<String> resourceOnlyServlets = new HashSet<>(); private String webappVersion = ""; private boolean addWebinfClassesResources = false; private boolean fireRequestListenersOnForwards = false;
Servlets created via ApplicationContext.createServlet(Class<Servlet>) for tracking purposes.
/** * Servlets created via {@link ApplicationContext#createServlet(Class)} for * tracking purposes. */
private Set<Servlet> createdServlets = new HashSet<>(); private boolean preemptiveAuthentication = false; private boolean sendRedirectBody = false; private boolean jndiExceptionOnFailedWrite = true; private Map<String, String> postConstructMethods = new HashMap<>(); private Map<String, String> preDestroyMethods = new HashMap<>(); private String containerSciFilter; private Boolean failCtxIfServletStartFails; protected static final ThreadBindingListener DEFAULT_NAMING_LISTENER = (new ThreadBindingListener() { @Override public void bind() {} @Override public void unbind() {} }); protected ThreadBindingListener threadBindingListener = DEFAULT_NAMING_LISTENER; private final Object namingToken = new Object(); private CookieProcessor cookieProcessor; private boolean validateClientProvidedNewSessionId = true; private boolean mapperContextRootRedirectEnabled = true; private boolean mapperDirectoryRedirectEnabled = false; private boolean useRelativeRedirects = !Globals.STRICT_SERVLET_COMPLIANCE; private boolean dispatchersUseEncodedPaths = true; private String requestEncoding = null; private String responseEncoding = null; private boolean allowMultipleLeadingForwardSlashInPath = false; private final AtomicLong inProgressAsyncCount = new AtomicLong(0); private boolean createUploadTargets = false; private boolean alwaysAccessSession = Globals.STRICT_SERVLET_COMPLIANCE; private boolean contextGetResourceRequiresSlash = Globals.STRICT_SERVLET_COMPLIANCE; private boolean dispatcherWrapsSameObject = Globals.STRICT_SERVLET_COMPLIANCE; private boolean parallelAnnotationScanning = false; private boolean useBloomFilterForArchives = false; // ----------------------------------------------------- Context Properties @Override public void setCreateUploadTargets(boolean createUploadTargets) { this.createUploadTargets = createUploadTargets; } @Override public boolean getCreateUploadTargets() { return createUploadTargets; } @Override public void incrementInProgressAsyncCount() { inProgressAsyncCount.incrementAndGet(); } @Override public void decrementInProgressAsyncCount() { inProgressAsyncCount.decrementAndGet(); } public long getInProgressAsyncCount() { return inProgressAsyncCount.get(); } @Override public void setAllowMultipleLeadingForwardSlashInPath( boolean allowMultipleLeadingForwardSlashInPath) { this.allowMultipleLeadingForwardSlashInPath = allowMultipleLeadingForwardSlashInPath; } @Override public boolean getAllowMultipleLeadingForwardSlashInPath() { return allowMultipleLeadingForwardSlashInPath; } @Override public boolean getAlwaysAccessSession() { return alwaysAccessSession; } @Override public void setAlwaysAccessSession(boolean alwaysAccessSession) { this.alwaysAccessSession = alwaysAccessSession; } @Override public boolean getContextGetResourceRequiresSlash() { return contextGetResourceRequiresSlash; } @Override public void setContextGetResourceRequiresSlash( boolean contextGetResourceRequiresSlash) { this.contextGetResourceRequiresSlash = contextGetResourceRequiresSlash; } @Override public boolean getDispatcherWrapsSameObject() { return dispatcherWrapsSameObject; } @Override public void setDispatcherWrapsSameObject( boolean dispatcherWrapsSameObject) { this.dispatcherWrapsSameObject = dispatcherWrapsSameObject; } @Override public String getRequestCharacterEncoding() { return requestEncoding; } @Override public void setRequestCharacterEncoding(String requestEncoding) { this.requestEncoding = requestEncoding; } @Override public String getResponseCharacterEncoding() { return responseEncoding; } @Override public void setResponseCharacterEncoding(String responseEncoding) { /* * This ensures that the context response encoding is represented by a * unique String object. This enables the Default Servlet to * differentiate between a Response using this default encoding and one * that has been explicitly configured. */ if (responseEncoding == null) { this.responseEncoding = null; } else { this.responseEncoding = new String(responseEncoding); } } @Override public void setDispatchersUseEncodedPaths(boolean dispatchersUseEncodedPaths) { this.dispatchersUseEncodedPaths = dispatchersUseEncodedPaths; }
{@inheritDoc}

The default value for this implementation is true.

/** * {@inheritDoc} * <p> * The default value for this implementation is {@code true}. */
@Override public boolean getDispatchersUseEncodedPaths() { return dispatchersUseEncodedPaths; } @Override public void setUseRelativeRedirects(boolean useRelativeRedirects) { this.useRelativeRedirects = useRelativeRedirects; }
{@inheritDoc}

The default value for this implementation is true.

/** * {@inheritDoc} * <p> * The default value for this implementation is {@code true}. */
@Override public boolean getUseRelativeRedirects() { return useRelativeRedirects; } @Override public void setMapperContextRootRedirectEnabled(boolean mapperContextRootRedirectEnabled) { this.mapperContextRootRedirectEnabled = mapperContextRootRedirectEnabled; }
{@inheritDoc}

The default value for this implementation is false.

/** * {@inheritDoc} * <p> * The default value for this implementation is {@code false}. */
@Override public boolean getMapperContextRootRedirectEnabled() { return mapperContextRootRedirectEnabled; } @Override public void setMapperDirectoryRedirectEnabled(boolean mapperDirectoryRedirectEnabled) { this.mapperDirectoryRedirectEnabled = mapperDirectoryRedirectEnabled; }
{@inheritDoc}

The default value for this implementation is false.

/** * {@inheritDoc} * <p> * The default value for this implementation is {@code false}. */
@Override public boolean getMapperDirectoryRedirectEnabled() { return mapperDirectoryRedirectEnabled; } @Override public void setValidateClientProvidedNewSessionId(boolean validateClientProvidedNewSessionId) { this.validateClientProvidedNewSessionId = validateClientProvidedNewSessionId; }
{@inheritDoc}

The default value for this implementation is true.

/** * {@inheritDoc} * <p> * The default value for this implementation is {@code true}. */
@Override public boolean getValidateClientProvidedNewSessionId() { return validateClientProvidedNewSessionId; } @Override public void setCookieProcessor(CookieProcessor cookieProcessor) { if (cookieProcessor == null) { throw new IllegalArgumentException( sm.getString("standardContext.cookieProcessor.null")); } this.cookieProcessor = cookieProcessor; } @Override public CookieProcessor getCookieProcessor() { return cookieProcessor; } @Override public Object getNamingToken() { return namingToken; } @Override public void setContainerSciFilter(String containerSciFilter) { this.containerSciFilter = containerSciFilter; } @Override public String getContainerSciFilter() { return containerSciFilter; } @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; } @Override public void setAddWebinfClassesResources( boolean addWebinfClassesResources) { this.addWebinfClassesResources = addWebinfClassesResources; } @Override 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() { return StringUtils.join(resourceOnlyServlets); } @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() { Pipeline pipeline = getPipeline(); if (pipeline != null) { Valve basic = pipeline.getBasic(); if (basic instanceof Authenticator) return (Authenticator) basic; for (Valve valve : pipeline.getValves()) { if (valve instanceof Authenticator) { return (Authenticator) valve; } } } return null; } @Override public JarScanner getJarScanner() { if (jarScanner == null) { jarScanner = new StandardJarScanner(); } return jarScanner; } @Override public void setJarScanner(JarScanner jarScanner) { this.jarScanner = jarScanner; } @Override public InstanceManager getInstanceManager() { return instanceManager; } @Override public void setInstanceManager(InstanceManager instanceManager) { this.instanceManager = instanceManager; } @Override public String getEncodedPath() { return encodedPath; }
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.
Params:
  • allowCasualMultipartParsing – true to allow such casual parsing, false otherwise.
/** * Set to <code>true</code> to allow requests mapped to servlets that * do not explicitly declare @MultipartConfig or have * &lt;multipart-config&gt; specified in web.xml to parse * multipart/form-data requests. * * @param allowCasualMultipartParsing <code>true</code> to allow such * casual parsing, <code>false</code> 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.
Returns:true if requests mapped to servlets without "multipart config" to parse multipart/form-data requests, false otherwise.
/** * Returns <code>true</code> if requests mapped to servlets without * "multipart config" to parse multipart/form-data requests anyway. * * @return <code>true</code> if requests mapped to servlets without * "multipart config" to parse multipart/form-data requests, * <code>false</code> 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.
Params:
  • swallowAbortedUploads – false to disable swallowing, true otherwise (default).
/** * Set to <code>false</code> to disable request data swallowing * after an upload was aborted due to size constraints. * * @param swallowAbortedUploads <code>false</code> to disable * swallowing, <code>true</code> 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.
Returns:true if data will be swallowed (default), false otherwise.
/** * Returns <code>true</code> if remaining request data will be read * (swallowed) even the request violates a data size constraint. * * @return <code>true</code> if data will be swallowed (default), * <code>false</code> otherwise. */
@Override public boolean getSwallowAbortedUploads() { return this.swallowAbortedUploads; }
Add a ServletContainerInitializer instance to this web application.
Params:
  • sci – The instance to add
  • classes – The classes in which the initializer expressed an interest
/** * 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<Class<?>> classes) { initializers.put(sci, classes); }
Return the "follow standard delegation model" flag used to configure our ClassLoader.
Returns:true if classloading delegates to the parent classloader first
/** * Return the "follow standard delegation model" flag used to configure * our ClassLoader. * * @return <code>true</code> if classloading delegates to the parent classloader first */
public boolean getDelegate() { return this.delegate; }
Set the "follow standard delegation model" flag used to configure our ClassLoader.
Params:
  • delegate – The new flag
/** * 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.
/** * @return true if the internal naming support is used. */
public boolean isUseNaming() { return useNaming; }
Enables or disables naming.
Params:
  • useNaming – true to enable the naming environment
/** * Enables or disables naming. * * @param useNaming <code>true</code> to enable the naming environment */
public void setUseNaming(boolean useNaming) { this.useNaming = useNaming; } @Override public Object[] getApplicationEventListeners() { return applicationEventListenersList.toArray(); }
{@inheritDoc} Note that this implementation is not thread safe. If two threads call this method concurrently, the result may be either set of listeners or a the union of both.
/** * {@inheritDoc} * * Note that this implementation is not thread safe. If two threads call * this method concurrently, the result may be either set of listeners or a * the union of both. */
@Override public void setApplicationEventListeners(Object listeners[]) { applicationEventListenersList.clear(); if (listeners != null && listeners.length > 0) { applicationEventListenersList.addAll(Arrays.asList(listeners)); } }
Add a listener to the end of the list of initialized application event listeners.
Params:
  • listener – The listener to add
/** * Add a listener to the end of the list of initialized application event * listeners. * * @param listener The listener to add */
public void addApplicationEventListener(Object listener) { applicationEventListenersList.add(listener); } @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.
Params:
  • listeners – The set of instantiated listener objects.
/** * 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.
Params:
  • listener – The listener to add
/** * Add a listener to the end of the list of initialized application * lifecycle listeners. * * @param listener The listener to add */
public void addApplicationLifecycleListener(Object listener) { int len = applicationLifecycleListenersObjects.length; Object[] newListeners = Arrays.copyOf( applicationLifecycleListenersObjects, len + 1); newListeners[len] = listener; applicationLifecycleListenersObjects = newListeners; }
Returns:the antiResourceLocking flag for this Context.
/** * @return the antiResourceLocking flag for this Context. */
public boolean getAntiResourceLocking() { return this.antiResourceLocking; }
Set the antiResourceLocking feature for this Context.
Params:
  • antiResourceLocking – The new flag value
/** * 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); } @Override public boolean getUseBloomFilterForArchives() { return this.useBloomFilterForArchives; } @Override public void setUseBloomFilterForArchives(boolean useBloomFilterForArchives) { boolean oldUseBloomFilterForArchives = this.useBloomFilterForArchives; this.useBloomFilterForArchives = useBloomFilterForArchives; support.firePropertyChange("useBloomFilterForArchives", oldUseBloomFilterForArchives, this.useBloomFilterForArchives); } @Override public void setParallelAnnotationScanning(boolean parallelAnnotationScanning) { boolean oldParallelAnnotationScanning = this.parallelAnnotationScanning; this.parallelAnnotationScanning = parallelAnnotationScanning; support.firePropertyChange("parallelAnnotationScanning", oldParallelAnnotationScanning, this.parallelAnnotationScanning); } @Override public boolean isParallelAnnotationScanning() { return this.parallelAnnotationScanning; }
Returns:the Locale to character set mapper for this Context.
/** * @return the Locale to character set mapper for this Context. */
public CharsetMapper getCharsetMapper() { // Create a mapper the first time it is requested if (this.charsetMapper == null) { try { Class<?> clazz = Class.forName(charsetMapperClass); this.charsetMapper = (CharsetMapper) clazz.getConstructor().newInstance(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); this.charsetMapper = new CharsetMapper(); } } return this.charsetMapper; }
Set the Locale to character set mapper for this Context.
Params:
  • mapper – The new mapper
/** * Set the Locale to character set mapper for this Context. * * @param mapper The new mapper */
public void setCharsetMapper(CharsetMapper mapper) { CharsetMapper oldCharsetMapper = this.charsetMapper; this.charsetMapper = mapper; if( mapper != null ) this.charsetMapperClass= mapper.getClass().getName(); support.firePropertyChange("charsetMapper", oldCharsetMapper, this.charsetMapper); } @Override public String getCharset(Locale locale) { return getCharsetMapper().getCharset(locale); } @Override public URL getConfigFile() { return this.configFile; } @Override public void setConfigFile(URL configFile) { this.configFile = configFile; } @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.
Params:
  • configured – The new correctly configured flag
/** * 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); } @Override public boolean getCookies() { return this.cookies; }
Set the "use cookies for session ids" flag.
Params:
  • cookies – The new flag
/** * 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.
Returns: The value of the default session cookie name or null if not specified
/** * 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.
Params:
  • sessionCookieName – The name to use
/** * 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.
Returns:true if the HttpOnly flag should be set on session cookies
/** * Gets the value of the use HttpOnly cookies for session cookies flag. * * @return <code>true</code> 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.
Params:
  • useHttpOnly – Set to true to use HttpOnly cookies for session cookies
/** * Sets the use HttpOnly cookies for session cookies flag. * * @param useHttpOnly Set to <code>true</code> 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.
Returns: The value of the default session cookie domain or null if not specified
/** * 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.
Params:
  • sessionCookieDomain – The domain to use
/** * 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.
Returns: The value of the default session cookie path or null if not specified
/** * 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.
Params:
  • sessionCookiePath – The path to use
/** * 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; } @Override public boolean getCrossContext() { return this.crossContext; }
Set the "allow crossing servlet contexts" flag.
Params:
  • crossContext – The new cross contexts flag
/** * 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 ).
Params:
  • defaultContextXml – The default web xml
/** * 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 ).
Params:
  • defaultWebXml – The default web xml
/** * 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.
Returns:Time (in milliseconds) it took to start this context.
/** * 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; } @Override public boolean getDenyUncoveredHttpMethods() { return denyUncoveredHttpMethods; } @Override public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) { this.denyUncoveredHttpMethods = denyUncoveredHttpMethods; }
Returns:the display name of this web application.
/** * @return the display name of this web application. */
@Override public String getDisplayName() { return this.displayName; }
Returns:the alternate Deployment Descriptor name.
/** * @return the alternate Deployment Descriptor name. */
@Override public String getAltDDName(){ return altDDName; }
Set an alternate Deployment Descriptor name.
Params:
  • altDDName – The new name
/** * Set an alternate Deployment Descriptor name. * * @param altDDName The new name */
@Override public void setAltDDName(String altDDName) { this.altDDName = altDDName; if (context != null) { context.setAttribute(Globals.ALT_DD_ATTR,altDDName); } }
Set the display name of this web application.
Params:
  • displayName – The new display name
/** * 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); }
Returns:the distributable flag for this web application.
/** * @return the distributable flag for this web application. */
@Override public boolean getDistributable() { return this.distributable; }
Set the distributable flag for this web application.
Params:
  • distributable – The new distributable flag
/** * 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); } @Override public String getDocBase() { return this.docBase; } @Override public void setDocBase(String docBase) { this.docBase = docBase; } 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; } @Override public Loader getLoader() { Lock readLock = loaderLock.readLock(); readLock.lock(); try { return loader; } finally { readLock.unlock(); } } @Override public void setLoader(Loader loader) { Lock writeLock = loaderLock.writeLock(); writeLock.lock(); Loader oldLoader = null; try { // Change components if necessary 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(sm.getString("standardContext.setLoader.stop"), e); } } // Start the new component if necessary if (loader != null) loader.setContext(this); if (getState().isAvailable() && (loader != null) && (loader instanceof Lifecycle)) { try { ((Lifecycle) loader).start(); } catch (LifecycleException e) { log.error(sm.getString("standardContext.setLoader.start"), e); } } } finally { writeLock.unlock(); } // Report this property change to interested listeners support.firePropertyChange("loader", oldLoader, loader); } @Override public Manager getManager() { Lock readLock = managerLock.readLock(); readLock.lock(); try { return manager; } finally { readLock.unlock(); } } @Override public void setManager(Manager manager) { Lock writeLock = managerLock.writeLock(); writeLock.lock(); Manager oldManager = null; try { // Change components if necessary oldManager = this.manager; if (oldManager == manager) return; this.manager = manager; // Stop the old component if necessary if (oldManager instanceof Lifecycle) { try { ((Lifecycle) oldManager).stop(); ((Lifecycle) oldManager).destroy(); } catch (LifecycleException e) { log.error(sm.getString("standardContext.setManager.stop"), e); } } // Start the new component if necessary if (manager != null) { manager.setContext(this); } if (getState().isAvailable() && manager instanceof Lifecycle) { try { ((Lifecycle) manager).start(); } catch (LifecycleException e) { log.error(sm.getString("standardContext.setManager.start"), e); } } } finally { writeLock.unlock(); } // Report this property change to interested listeners support.firePropertyChange("manager", oldManager, manager); }
Returns:the boolean on the annotations parsing.
/** * @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.
Params:
  • ignoreAnnotations – The boolean on the annotations parsing
/** * 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); }
Returns:the login configuration descriptor for this web application.
/** * @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.
Params:
  • config – The new login configuration
/** * 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); }
Returns:the naming resources associated with this web application.
/** * @return the naming resources associated with this web application. */
@Override public NamingResourcesImpl getNamingResources() { if (namingResources == null) { setNamingResources(new NamingResourcesImpl()); } return namingResources; }
Set the naming resources for this web application.
Params:
  • namingResources – The new naming resources
/** * Set the naming resources for this web application. * * @param namingResources The new naming resources */
@Override public void setNamingResources(NamingResourcesImpl namingResources) { // Process the property setting change NamingResourcesImpl 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.error(sm.getString("standardContext.namingResource.destroy.fail"), e); } } if (namingResources != null) { try { namingResources.init(); namingResources.start(); } catch (LifecycleException e) { log.error(sm.getString("standardContext.namingResource.init.fail"), e); } } }
Returns:the context path for this Context.
/** * @return the context path for this Context. */
@Override public String getPath() { return path; }
Set the context path for this Context.
Params:
  • path – The new context path
/** * Set the context path for this Context. * * @param path The new context path */
@Override public void setPath(String path) { boolean invalid = false; if (path == null || path.equals("/")) { invalid = true; this.path = ""; } else if (path.isEmpty() || path.startsWith("/")) { this.path = path; } else { invalid = true; this.path = "/" + path; } if (this.path.endsWith("/")) { invalid = true; this.path = this.path.substring(0, this.path.length() - 1); } if (invalid) { log.warn(sm.getString( "standardContext.pathInvalid", path, this.path)); } encodedPath = URLEncoder.DEFAULT.encode(this.path, StandardCharsets.UTF_8); if (getName() == null) { setName(this.path); } }
Returns:the public identifier of the deployment descriptor DTD that is currently being parsed.
/** * @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.
Params:
  • publicId – The public identifier
/** * 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); }
Returns:the reloadable flag for this web application.
/** * @return the reloadable flag for this web application. */
@Override public boolean getReloadable() { return this.reloadable; }
Returns:the default context override flag for this web application.
/** * @return the default context override flag for this web application. */
@Override public boolean getOverride() { return this.override; }
Returns: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!
/** * @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.
Params:
  • docBase – The original document root
/** * 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; }
Returns:the parent class loader (if any) for this web application. This call is meaningful only after a Loader has been configured.
/** * @return the parent class loader (if any) for this web application. * This call is meaningful only <strong>after</strong> 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(); }
Returns:the privileged flag for this web application.
/** * @return the privileged flag for this web application. */
@Override public boolean getPrivileged() { return this.privileged; }
Set the privileged flag for this web application.
Params:
  • privileged – The new privileged flag
/** * 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.
Params:
  • reloadable – The new reloadable flag
/** * 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.
Params:
  • override – The new override flag
/** * 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); }
Set the "replace welcome files" property.
Params:
  • replaceWelcomeFiles – The new property value
/** * 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); }
Returns:the servlet context for which this Context is a facade.
/** * @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(); }
Returns:the default session timeout (in minutes) for this web application.
/** * @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.
Params:
  • timeout – The new default session timeout
/** * 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); }
Returns:the value of the swallowOutput flag.
/** * @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.
Params:
  • swallowOutput – The new value
/** * 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); }
Returns:the value of the unloadDelay flag.
/** * @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.
Params:
  • unloadDelay – The new value
/** * 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)); }
Returns:unpack WAR flag.
/** * @return unpack WAR flag. */
public boolean getUnpackWAR() { return unpackWAR; }
Unpack WAR flag mutator.
Params:
  • unpackWAR – true to unpack WARs on deployment
/** * Unpack WAR flag mutator. * * @param unpackWAR <code>true</code> to unpack WARs on deployment */
public void setUnpackWAR(boolean unpackWAR) { this.unpackWAR = unpackWAR; }
Flag which indicates if bundled context.xml files should be copied to the config folder. The doesn't occur by default.
Returns:true if the META-INF/context.xml file included in a WAR will be copied to the host configuration base folder on deployment
/** * Flag which indicates if bundled context.xml files should be copied to the * config folder. The doesn't occur by default. * * @return <code>true</code> if the <code>META-INF/context.xml</code> file included * in a WAR will be copied to the host configuration base folder on deployment */
public boolean getCopyXML() { return copyXML; }
Allows copying a bundled context.xml file to the host configuration base folder on deployment.
Params:
  • copyXML – the new flag value
/** * Allows copying a bundled context.xml file to the host configuration base * folder on deployment. * * @param copyXML the new flag value */
public void setCopyXML(boolean copyXML) { this.copyXML = copyXML; }
Returns:the Java class name of the Wrapper implementation used for servlets registered in this Context.
/** * @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.
Params:
  • wrapperClassName – The new wrapper class name
Throws:
/** * 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()); } } @Override public WebResourceRoot getResources() { Lock readLock = resourcesLock.readLock(); readLock.lock(); try { return resources; } finally { readLock.unlock(); } } @Override public void setResources(WebResourceRoot resources) { Lock writeLock = resourcesLock.writeLock(); writeLock.lock(); WebResourceRoot oldResources = null; try { if (getState().isAvailable()) { throw new IllegalStateException (sm.getString("standardContext.resourcesStart")); } oldResources = this.resources; if (oldResources == resources) return; this.resources = resources; if (oldResources != null) { oldResources.setContext(null); } if (resources != null) { resources.setContext(this); } support.firePropertyChange("resources", oldResources, resources); } finally { writeLock.unlock(); } } @Override public JspConfigDescriptor getJspConfigDescriptor() { return jspConfigDescriptor; } @Override public void setJspConfigDescriptor(JspConfigDescriptor descriptor) { this.jspConfigDescriptor = descriptor; } @Override public ThreadBindingListener getThreadBindingListener() { return threadBindingListener; } @Override public void setThreadBindingListener(ThreadBindingListener threadBindingListener) { this.threadBindingListener = threadBindingListener; } // ------------------------------------------------------ Public Properties
Returns:whether or not an attempt to modify the JNDI context will trigger an exception or if the request will be ignored.
/** * @return whether or not an attempt to modify the JNDI context will trigger * an exception or if the request will be ignored. */
public boolean getJndiExceptionOnFailedWrite() { return jndiExceptionOnFailedWrite; }
Controls whether or not an attempt to modify the JNDI context will trigger an exception or if the request will be ignored.
Params:
  • jndiExceptionOnFailedWrite – false to avoid an exception
/** * Controls whether or not an attempt to modify the JNDI context will * trigger an exception or if the request will be ignored. * * @param jndiExceptionOnFailedWrite <code>false</code> to avoid an exception */
public void setJndiExceptionOnFailedWrite( boolean jndiExceptionOnFailedWrite) { this.jndiExceptionOnFailedWrite = jndiExceptionOnFailedWrite; }
Returns:the Locale to character set mapper class for this Context.
/** * @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.
Params:
  • mapper – The new mapper class
/** * 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.
Returns:The work path
/** 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()) { try { workDir = new File(getCatalinaBase().getCanonicalFile(), getWorkDir()); } catch (IOException e) { log.warn(sm.getString("standardContext.workPath", getName()), e); } } return workDir.getAbsolutePath(); }
Returns:the work directory for this Context.
/** * @return the work directory for this Context. */
public String getWorkDir() { return this.workDir; }
Set the work directory for this Context.
Params:
  • workDir – The new work directory
/** * 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(); } } public boolean getClearReferencesRmiTargets() { return this.clearReferencesRmiTargets; } public void setClearReferencesRmiTargets(boolean clearReferencesRmiTargets) { boolean oldClearReferencesRmiTargets = this.clearReferencesRmiTargets; this.clearReferencesRmiTargets = clearReferencesRmiTargets; support.firePropertyChange("clearReferencesRmiTargets", oldClearReferencesRmiTargets, this.clearReferencesRmiTargets); }
Returns:the clearReferencesStopThreads flag for this Context.
/** * @return the clearReferencesStopThreads flag for this Context. */
public boolean getClearReferencesStopThreads() { return this.clearReferencesStopThreads; }
Set the clearReferencesStopThreads feature for this Context.
Params:
  • clearReferencesStopThreads – The new flag value
/** * 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); }
Returns:the clearReferencesStopTimerThreads flag for this Context.
/** * @return the clearReferencesStopTimerThreads flag for this Context. */
public boolean getClearReferencesStopTimerThreads() { return this.clearReferencesStopTimerThreads; }
Set the clearReferencesStopTimerThreads feature for this Context.
Params:
  • clearReferencesStopTimerThreads – The new flag value
/** * 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); }
Returns:the clearReferencesHttpClientKeepAliveThread flag for this Context.
/** * @return the clearReferencesHttpClientKeepAliveThread flag for this * Context. */
public boolean getClearReferencesHttpClientKeepAliveThread() { return this.clearReferencesHttpClientKeepAliveThread; }
Set the clearReferencesHttpClientKeepAliveThread feature for this Context.
Params:
  • clearReferencesHttpClientKeepAliveThread – The new flag value
/** * 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); } public boolean getClearReferencesObjectStreamClassCaches() { return clearReferencesObjectStreamClassCaches; } public void setClearReferencesObjectStreamClassCaches( boolean clearReferencesObjectStreamClassCaches) { boolean oldClearReferencesObjectStreamClassCaches = this.clearReferencesObjectStreamClassCaches; this.clearReferencesObjectStreamClassCaches = clearReferencesObjectStreamClassCaches; support.firePropertyChange("clearReferencesObjectStreamClassCaches", oldClearReferencesObjectStreamClassCaches, this.clearReferencesObjectStreamClassCaches); } public boolean getClearReferencesThreadLocals() { return clearReferencesThreadLocals; } public void setClearReferencesThreadLocals(boolean clearReferencesThreadLocals) { boolean oldClearReferencesThreadLocals = this.clearReferencesThreadLocals; this.clearReferencesThreadLocals = clearReferencesThreadLocals; support.firePropertyChange("clearReferencesThreadLocals", oldClearReferencesThreadLocals, this.clearReferencesThreadLocals); } public boolean getSkipMemoryLeakChecksOnJvmShutdown() { return skipMemoryLeakChecksOnJvmShutdown; } public void setSkipMemoryLeakChecksOnJvmShutdown(boolean skipMemoryLeakChecksOnJvmShutdown) { this.skipMemoryLeakChecksOnJvmShutdown = skipMemoryLeakChecksOnJvmShutdown; } public Boolean getFailCtxIfServletStartFails() { return failCtxIfServletStartFails; } public void setFailCtxIfServletStartFails( Boolean failCtxIfServletStartFails) { Boolean oldFailCtxIfServletStartFails = this.failCtxIfServletStartFails; this.failCtxIfServletStartFails = failCtxIfServletStartFails; support.firePropertyChange("failCtxIfServletStartFails", oldFailCtxIfServletStartFails, failCtxIfServletStartFails); } protected boolean getComputedFailCtxIfServletStartFails() { if(failCtxIfServletStartFails != null) { return failCtxIfServletStartFails.booleanValue(); } //else look at Host config if(getParent() instanceof StandardHost) { return ((StandardHost)getParent()).isFailCtxIfServletStartFails(); } //else return false; } // -------------------------------------------------------- Context Methods
Add a new Listener class name to the set of Listeners configured for this application.
Params:
  • listener – Java class name of a listener class
/** * 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); }
Add a new application parameter for this application.
Params:
  • parameter – The new application parameter
/** * 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.
Params:
  • child – Child container to be added
Throws:
/** * 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<jspMappings.length; i++) { addServletMappingDecoded(jspMappings[i], child.getName()); } } }
Add a security constraint to the set for this web application.
Params:
  • constraint – the new security constraint
/** * Add a security constraint to the set for this web application. * * @param constraint the new security constraint */
@Override public void addConstraint(SecurityConstraint constraint) { // Validate the proposed constraint SecurityCollection collections[] = constraint.findCollections(); for (SecurityCollection collection : collections) { String patterns[] = collection.findPatterns(); for (int j = 0; j < patterns.length; j++) { patterns[j] = adjustURLPattern(patterns[j]); if (!validateURLPattern(patterns[j])) throw new IllegalArgumentException (sm.getString ("standardContext.securityConstraint.pattern", patterns[j])); } if (collection.findMethods().length > 0 && collection.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 = Arrays.copyOf(constraints, constraints.length + 1); results[constraints.length] = constraint; constraints = results; } }
Add an error page for the specified error or Java exception.
Params:
  • errorPage – The error page definition to be added
/** * 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)); } } errorPageSupport.add(errorPage); fireContainerEvent("addErrorPage", errorPage); }
Add a filter definition to this Context.
Params:
  • filterDef – The filter definition to be added
/** * 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.
Params:
  • filterMap – The filter mapping to be added
Throws:
  • IllegalArgumentException – if the specified filter name does not match an existing filter definition, or the filter mapping is malformed
/** * 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.
Params:
  • filterMap – The filter mapping to be added
Throws:
  • IllegalArgumentException – if the specified filter name does not match an existing filter definition, or the filter mapping is malformed
/** * 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.
Params:
  • filterMap – the filter mapping
/** * Validate the supplied FilterMap. * * @param filterMap the filter mapping */
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")); for (String urlPattern : urlPatterns) { if (!validateURLPattern(urlPattern)) { throw new IllegalArgumentException (sm.getString("standardContext.filterMap.pattern", urlPattern)); } } }
Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
Params:
  • locale – locale to map an encoding for
  • encoding – encoding to be used for a give locale
/** * 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.
Params:
  • md – New message destination
/** * 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 new MIME mapping, replacing any existing mapping for the specified extension.
Params:
  • extension – Filename extension being mapped
  • mimeType – Corresponding MIME type
/** * 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.toLowerCase(Locale.ENGLISH), mimeType); } fireContainerEvent("addMimeMapping", extension); }
Add a new context initialization parameter.
Params:
  • name – Name of the new parameter
  • value – Value of the new parameter
Throws:
  • IllegalArgumentException – if the name or value is missing, or if this context initialization parameter has already been registered
/** * 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")); } // Add this parameter to our defined set if not already present String oldValue = parameters.putIfAbsent(name, value); if (oldValue != null) { throw new IllegalArgumentException( sm.getString("standardContext.parameter.duplicate", name)); } fireContainerEvent("addParameter", name); }
Add a security role reference for this web application.
Params:
  • role – Security role used in the application
  • link – Actual security role to check for
/** * 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.
Params:
  • role – New security 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 = Arrays.copyOf(securityRoles, securityRoles.length + 1); results[securityRoles.length] = role; securityRoles = results; } fireContainerEvent("addSecurityRole", role); }
Add a new servlet mapping, replacing any existing mapping for the specified pattern.
Params:
  • pattern – URL pattern to be mapped
  • name – Name of the corresponding servlet to execute
  • jspWildCard – true if name identifies the JspServlet and pattern contains a wildcard; false otherwise
Throws:
/** * 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 addServletMappingDecoded(String pattern, String name, boolean jspWildCard) { // Validate the proposed mapping if (findChild(name) == null) throw new IllegalArgumentException (sm.getString("standardContext.servletMap.name", name)); String adjustedPattern = adjustURLPattern(pattern); if (!validateURLPattern(adjustedPattern)) throw new IllegalArgumentException (sm.getString("standardContext.servletMap.pattern", adjustedPattern)); // Add this mapping to our registered set synchronized (servletMappingsLock) { String name2 = servletMappings.get(adjustedPattern); if (name2 != null) { // Don't allow more than one servlet on the same pattern Wrapper wrapper = (Wrapper) findChild(name2); wrapper.removeMapping(adjustedPattern); } servletMappings.put(adjustedPattern, name); } Wrapper wrapper = (Wrapper) findChild(name); wrapper.addMapping(adjustedPattern); fireContainerEvent("addServletMapping", adjustedPattern); }
Add a new watched resource to the set recognized by this Context.
Params:
  • name – New watched resource file name
/** * 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 = Arrays.copyOf(watchedResources, watchedResources.length + 1); results[watchedResources.length] = name; watchedResources = results; } fireContainerEvent("addWatchedResource", name); }
Add a new welcome file to the set recognized by this Context.
Params:
  • name – New welcome file 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 = Arrays.copyOf(welcomeFiles, welcomeFiles.length + 1); 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.
Params:
  • listener – Java class name of a LifecycleListener class
/** * 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 = Arrays.copyOf(wrapperLifecycles, wrapperLifecycles.length + 1); 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.
Params:
  • listener – Java class name of a ContainerListener class
/** * 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 = Arrays.copyOf(wrapperListeners, wrapperListeners.length + 1); 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.
/** * 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.getConstructor().newInstance(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("standardContext.createWrapper.error"), t); return null; } } else { wrapper = new StandardWrapper(); } synchronized (wrapperLifecyclesLock) { for (String wrapperLifecycle : wrapperLifecycles) { try { Class<?> clazz = Class.forName(wrapperLifecycle); LifecycleListener listener = (LifecycleListener) clazz.getConstructor().newInstance(); wrapper.addLifecycleListener(listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("standardContext.createWrapper.listenerError"), t); return null; } } } synchronized (wrapperListenersLock) { for (String wrapperListener : wrapperListeners) { try { Class<?> clazz = Class.forName(wrapperListener); ContainerListener listener = (ContainerListener) clazz.getConstructor().newInstance(); wrapper.addContainerListener(listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("standardContext.createWrapper.containerListenerError"), t); return null; } } } return wrapper; }
Return the set of application listener class names configured for this application.
/** * 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.
/** * 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.
/** * 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.
Params:
  • errorCode – Error code to look up
/** * Return the error page entry for the specified HTTP error code, * if any; otherwise return <code>null</code>. * * @param errorCode Error code to look up */
@Override public ErrorPage findErrorPage(int errorCode) { return errorPageSupport.find(errorCode); } @Override public ErrorPage findErrorPage(Throwable exceptionType) { return errorPageSupport.find(exceptionType); }
Return the set of defined error pages for all specified error codes and exception types.
/** * Return the set of defined error pages for all specified error codes * and exception types. */
@Override public ErrorPage[] findErrorPages() { return errorPageSupport.findAll(); }
Return the filter definition for the specified filter name, if any; otherwise return null.
Params:
  • filterName – Filter name to look up
/** * Return the filter definition for the specified filter name, if any; * otherwise return <code>null</code>. * * @param filterName Filter name to look up */
@Override public FilterDef findFilterDef(String filterName) { synchronized (filterDefs) { return filterDefs.get(filterName); } }
Returns:the set of defined filters for this Context.
/** * @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); } }
Returns:the set of filter mappings for this Context.
/** * @return the set of filter mappings for this Context. */
@Override public FilterMap[] findFilterMaps() { return filterMaps.asArray(); }
Params:
  • name – Name of the desired message destination
Returns:the message destination with the specified name, if any; otherwise, return null.
/** * @return the message destination with the specified name, if any; * otherwise, return <code>null</code>. * * @param name Name of the desired message destination */
public MessageDestination findMessageDestination(String name) { synchronized (messageDestinations) { return messageDestinations.get(name); } }
Returns:the set of defined message destinations for this web application. If none have been defined, a zero-length array is returned.
/** * @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); } }
Params:
  • extension – Extension to map to a MIME type
Returns:the MIME type to which the specified extension is mapped, if any; otherwise return null.
/** * @return the MIME type to which the specified extension is mapped, * if any; otherwise return <code>null</code>. * * @param extension Extension to map to a MIME type */
@Override public String findMimeMapping(String extension) { return mimeMappings.get(extension.toLowerCase(Locale.ENGLISH)); }
Returns:the extensions for which MIME mappings are defined. If there are none, a zero-length array is returned.
/** * @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); } }
Params:
  • name – Name of the parameter to return
Returns:the value for the specified context initialization parameter name, if any; otherwise return null.
/** * @return the value for the specified context initialization * parameter name, if any; otherwise return <code>null</code>. * * @param name Name of the parameter to return */
@Override public String findParameter(String name) { return parameters.get(name); }
Returns:the names of all defined context initialization parameters for this Context. If no parameters are defined, a zero-length array is returned.
/** * @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() { return parameters.keySet().toArray(new String[0]); }
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.
Params:
  • role – Security role to map
Returns:the role name
/** * 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 * @return the role name */
@Override public String findRoleMapping(String role) { String realRole = null; synchronized (roleMappings) { realRole = roleMappings.get(role); } if (realRole != null) return realRole; else return role; }
Params:
  • role – Security role to verify
Returns:true if the specified security role is defined for this application; otherwise return false.
/** * @return <code>true</code> if the specified security role is defined * for this application; otherwise return <code>false</code>. * * @param role Security role to verify */
@Override public boolean findSecurityRole(String role) { synchronized (securityRolesLock) { for (String securityRole : securityRoles) { if (role.equals(securityRole)) return true; } } return false; }
Returns:the security roles defined for this application. If none have been defined, a zero-length array is returned.
/** * @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; } }
Params:
  • pattern – Pattern for which a mapping is requested
Returns:the servlet name mapped by the specified pattern (if any); otherwise return null.
/** * @return the servlet name mapped by the specified pattern (if any); * otherwise return <code>null</code>. * * @param pattern Pattern for which a mapping is requested */
@Override public String findServletMapping(String pattern) { synchronized (servletMappingsLock) { return servletMappings.get(pattern); } }
Returns:the patterns of all defined servlet mappings for this Context. If no mappings are defined, a zero-length array is returned.
/** * @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); } }
Params:
  • name – Welcome file to verify
Returns:true if the specified welcome file is defined for this Context; otherwise return false.
/** * @return <code>true</code> if the specified welcome file is defined * for this Context; otherwise return <code>false</code>. * * @param name Welcome file to verify */
@Override public boolean findWelcomeFile(String name) { synchronized (welcomeFilesLock) { for (String welcomeFile : welcomeFiles) { if (name.equals(welcomeFile)) return true; } } return false; }
Returns:the set of watched resources for this Context. If none are defined, a zero length array will be returned.
/** * @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; } }
Returns:the set of welcome files defined for this Context. If none are defined, a zero-length array is returned.
/** * @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; } }
Returns:the set of LifecycleListener classes that will be added to newly created Wrappers automatically.
/** * @return the set of LifecycleListener classes that will be added to * newly created Wrappers automatically. */
@Override public String[] findWrapperLifecycles() { synchronized (wrapperLifecyclesLock) { return wrapperLifecycles; } }
Returns:the set of ContainerListener classes that will be added to newly created Wrappers automatically.
/** * @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 and changes to the web.xml file. It does not handle changes to any context.xml file. If the context.xml has changed, you should stop this Context and create (and start) a new Context instance instead. Note that there is additional code in CoyoteAdapter#postParseRequest() to handle mapping requests to paused Contexts.

Throws:
  • IllegalStateException – if the reloadable property is set to false.
/** * Reload this web application, if reloading is supported. * <p> * <b>IMPLEMENTATION NOTE</b>: This method is designed to deal with * reloads required by changes to classes in the underlying repositories * of our class loader and changes to the web.xml file. It does not handle * changes to any context.xml file. If the context.xml has changed, you * should stop this Context and create (and start) a new Context instance * instead. Note that there is additional code in * <code>CoyoteAdapter#postParseRequest()</code> to handle mapping requests * to paused Contexts. * * @exception IllegalStateException if the <code>reloadable</code> * property is set to <code>false</code>. */
@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.
Params:
  • listener – Java class name of the listener to be removed
/** * 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 listener 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 listener 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); }
Remove the application parameter with the specified name from the set for this application.
Params:
  • name – Name of the application parameter to remove
/** * 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.
Params:
  • child – Child container to be added
Throws:
/** * 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.
Params:
  • constraint – Constraint to be removed
/** * 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.
Params:
  • errorPage – The error page definition to be removed
/** * 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) { errorPageSupport.remove(errorPage); fireContainerEvent("removeErrorPage", errorPage); }
Remove the specified filter definition from this Context, if it exists; otherwise, no action is taken.
Params:
  • filterDef – Filter definition to be removed
/** * 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.
Params:
  • filterMap – The filter mapping to be removed
/** * 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 any message destination with the specified name.
Params:
  • name – Name of the message destination to remove
/** * 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 the MIME mapping for the specified extension, if it exists; otherwise, no action is taken.
Params:
  • extension – Extension to remove the mapping for
/** * 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.
Params:
  • name – Name of the parameter to remove
/** * 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) { parameters.remove(name); fireContainerEvent("removeParameter", name); }
Remove any security role reference for the specified name
Params:
  • role – Security role (as used in the application) to remove
/** * 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.
Params:
  • role – Security role to remove
/** * 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.
Params:
  • pattern – URL pattern of the mapping to remove
/** * 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); } fireContainerEvent("removeServletMapping", pattern); }
Remove the specified watched resource name from the list associated with this Context.
Params:
  • name – Name of the watched resource to be removed
/** * 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.
Params:
  • name – Name of the welcome file to be removed
/** * 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 welcome file 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.
Params:
  • listener – Class name of a LifecycleListener class to be removed
/** * 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 lifecycle listener 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 lifecycle listener 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.
Params:
  • listener – Class name of a ContainerListener class to be removed
/** * 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 listener 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 listener 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.
Returns:Cumulative processing times of all servlets in this StandardContext
/** * 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 (Container child : children) { result += ((StandardWrapper) child).getProcessingTime(); } } return result; }
Gets the maximum processing time of all servlets in this StandardContext.
Returns:Maximum processing time of all servlets in this StandardContext
/** * Gets the maximum processing time of all servlets in this * StandardContext. * * @return Maximum processing time of all servlets in this * StandardContext */
public long getMaxTime() { long result = 0; long time; Container[] children = findChildren(); if (children != null) { for (Container child : children) { time = ((StandardWrapper) child).getMaxTime(); if (time > result) result = time; } } return result; }
Gets the minimum processing time of all servlets in this StandardContext.
Returns:Minimum processing time of all servlets in this StandardContext
/** * Gets the minimum processing time of all servlets in this * StandardContext. * * @return Minimum processing time of all servlets in this * StandardContext */
public long getMinTime() { long result = -1; long time; Container[] children = findChildren(); if (children != null) { for (Container child : children) { time = ((StandardWrapper) child).getMinTime(); if (result < 0 || time < result) result = time; } } return result; }
Gets the cumulative request count of all servlets in this StandardContext.
Returns:Cumulative request count of all servlets in this StandardContext
/** * Gets the cumulative request count of all servlets in this * StandardContext. * * @return Cumulative request count of all servlets in this * StandardContext */
public int getRequestCount() { int result = 0; Container[] children = findChildren(); if (children != null) { for (Container child : children) { result += ((StandardWrapper) child).getRequestCount(); } } return result; }
Gets the cumulative error count of all servlets in this StandardContext.
Returns:Cumulative error count of all servlets in this StandardContext
/** * Gets the cumulative error count of all servlets in this * StandardContext. * * @return Cumulative error count of all servlets in this * StandardContext */
public int getErrorCount() { int result = 0; Container[] children = findChildren(); if (children != null) { for (Container child : children) { result += ((StandardWrapper) child).getErrorCount(); } } return result; }
Return the real path for a given virtual path, if possible; otherwise return null.
Params:
  • path – The path to the desired resource
/** * Return the real path for a given virtual path, if possible; otherwise * return <code>null</code>. * * @param path The path to the desired resource */
@Override public String getRealPath(String path) { // The WebResources API expects all paths to start with /. This is a // special case for consistency with earlier Tomcat versions. if ("".equals(path)) { path = "/"; } if (resources != null) { try { WebResource resource = resources.getResource(path); String canonicalPath = resource.getCanonicalPath(); if (canonicalPath == null) { return null; } else if ((resource.isDirectory() && !canonicalPath.endsWith(File.separator) || !resource.exists()) && path.endsWith("/")) { return canonicalPath + File.separatorChar; } else { return canonicalPath; } } catch (IllegalArgumentException iae) { // ServletContext.getRealPath() does not allow this to be thrown } } return null; }
Hook to track which Servlets were created via ServletContext.createServlet(Class<Servlet>).
Params:
  • servlet – the created Servlet
/** * Hook to track which Servlets were created via * {@link ServletContext#createServlet(Class)}. * * @param servlet the created Servlet */
public void dynamicServletCreated(Servlet servlet) { createdServlets.add(servlet); } public boolean wasCreatedDynamicServlet(Servlet servlet) { return createdServlets.contains(servlet); }
A helper class to manage the filter mappings in a Context.
/** * 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 ServletContext possibly both before and after those defined in the deployment descriptor.
/** * 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 ServletContext may have to be inserted before the mappings in the deployment descriptor but must be inserted in the order the 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.
/** * 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;
Returns:The set of filter mappings
/** * @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.
Params:
  • filterMap – The filter mapping to be added
/** * 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.
Params:
  • filterMap – The filter mapping to be added
/** * 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.
Params:
  • filterMap – The filter mapping to be removed
/** * 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.
Returns:true if all filter initialization completed successfully, or false otherwise.
/** * Configure and initialize the set of filters for this Context. * @return <code>true</code> if all filter initialization completed * successfully, or <code>false</code> otherwise. */
public boolean filterStart() { if (getLogger().isDebugEnabled()) { getLogger().debug("Starting filters"); } // Instantiate and record a FilterConfig for each defined filter boolean ok = true; synchronized (filterConfigs) { filterConfigs.clear(); for (Entry<String,FilterDef> entry : filterDefs.entrySet()) { String name = entry.getKey(); if (getLogger().isDebugEnabled()) { getLogger().debug(" Starting filter '" + name + "'"); } try { ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, entry.getValue()); filterConfigs.put(name, filterConfig); } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(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.
Returns:true if all filter finalization completed successfully, or false otherwise.
/** * Finalize and release the set of filters for this Context. * @return <code>true</code> if all filter finalization completed * successfully, or <code>false</code> otherwise. */
public boolean filterStop() { if (getLogger().isDebugEnabled()) getLogger().debug("Stopping filters"); // Release all Filter and FilterConfig instances synchronized (filterConfigs) { for (Entry<String, ApplicationFilterConfig> entry : filterConfigs.entrySet()) { if (getLogger().isDebugEnabled()) getLogger().debug(" Stopping filter '" + entry.getKey() + "'"); ApplicationFilterConfig filterConfig = entry.getValue(); filterConfig.release(); } filterConfigs.clear(); } return true; }
Find and return the initialized FilterConfig for the specified filter name, if any; otherwise return null.
Params:
  • name – Name of the desired filter
Returns:the filter config object
/** * Find and return the initialized <code>FilterConfig</code> for the * specified filter name, if any; otherwise return <code>null</code>. * * @param name Name of the desired filter * @return the filter config object */
public FilterConfig findFilterConfig(String name) { return filterConfigs.get(name); }
Configure the set of instantiated application event listeners for this Context.
Returns:true if all listeners wre initialized successfully, or false otherwise.
/** * Configure the set of instantiated application event listeners * for this Context. * @return <code>true</code> if all listeners wre * initialized successfully, or <code>false</code> otherwise. */
public boolean listenerStart() { if (log.isDebugEnabled()) log.debug("Configuring application event listeners"); // Instantiate the required listeners 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 { String listener = listeners[i]; results[i] = getInstanceManager().newInstance(listener); } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(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 List<Object> eventListeners = new ArrayList<>(); List<Object> lifecycleListeners = new ArrayList<>(); for (Object result : results) { if ((result instanceof ServletContextAttributeListener) || (result instanceof ServletRequestAttributeListener) || (result instanceof ServletRequestListener) || (result instanceof HttpSessionIdListener) || (result instanceof HttpSessionAttributeListener)) { eventListeners.add(result); } if ((result instanceof ServletContextListener) || (result instanceof HttpSessionListener)) { lifecycleListeners.add(result); } } // Listener instances may have been added directly to this Context by // ServletContextInitializers and other code via the pluggability APIs. // Put them these listeners after the ones defined in web.xml and/or // annotations then overwrite the list of instances with the new, full // list. eventListeners.addAll(Arrays.asList(getApplicationEventListeners())); setApplicationEventListeners(eventListeners.toArray()); for (Object lifecycleListener: getApplicationLifecycleListeners()) { lifecycleListeners.add(lifecycleListener); if (lifecycleListener instanceof ServletContextListener) { noPluggabilityListeners.add(lifecycleListener); } } setApplicationLifecycleListeners(lifecycleListeners.toArray()); // Send application start events if (getLogger().isDebugEnabled()) getLogger().debug("Sending application start events"); // Ensure context is not null getServletContext(); context.setNewServletContextListenerAllowed(false); Object instances[] = getApplicationLifecycleListeners(); if (instances == null || instances.length == 0) { return ok; } ServletContextEvent event = new ServletContextEvent(getServletContext()); ServletContextEvent tldEvent = null; if (noPluggabilityListeners.size() > 0) { noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext()); tldEvent = new ServletContextEvent(noPluggabilityServletContext); } for (Object instance : instances) { if (!(instance instanceof ServletContextListener)) { continue; } ServletContextListener listener = (ServletContextListener) instance; try { fireContainerEvent("beforeContextInitialized", listener); if (noPluggabilityListeners.contains(listener)) { listener.contextInitialized(tldEvent); } else { listener.contextInitialized(event); } fireContainerEvent("afterContextInitialized", listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); fireContainerEvent("afterContextInitialized", listener); getLogger().error(sm.getString("standardContext.listenerStart", instance.getClass().getName()), t); ok = false; } } return ok; }
Send an application stop event to all interested listeners.
Returns:true if all events were sent successfully, or false otherwise.
/** * Send an application stop event to all interested listeners. * @return <code>true</code> if all events were sent successfully, * or <code>false</code> otherwise. */
public boolean listenerStop() { if (log.isDebugEnabled()) log.debug("Sending application stop events"); boolean ok = true; Object listeners[] = getApplicationLifecycleListeners(); if (listeners != null && listeners.length > 0) { ServletContextEvent event = new ServletContextEvent(getServletContext()); ServletContextEvent tldEvent = null; if (noPluggabilityServletContext != null) { tldEvent = new ServletContextEvent(noPluggabilityServletContext); } for (int i = 0; i < listeners.length; i++) { int j = (listeners.length - 1) - i; if (listeners[j] == null) continue; if (listeners[j] instanceof ServletContextListener) { ServletContextListener listener = (ServletContextListener) listeners[j]; try { fireContainerEvent("beforeContextDestroyed", listener); if (noPluggabilityListeners.contains(listener)) { listener.contextDestroyed(tldEvent); } else { listener.contextDestroyed(event); } fireContainerEvent("afterContextDestroyed", listener); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); fireContainerEvent("afterContextDestroyed", listener); getLogger().error (sm.getString("standardContext.listenerStop", listeners[j].getClass().getName()), t); ok = false; } } try { if (getInstanceManager() != null) { getInstanceManager().destroyInstance(listeners[j]); } } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(t); getLogger().error (sm.getString("standardContext.listenerStop", listeners[j].getClass().getName()), t); ok = false; } } } // Annotation processing listeners = getApplicationEventListeners(); if (listeners != null) { for (int i = 0; i < listeners.length; i++) { int j = (listeners.length - 1) - i; if (listeners[j] == null) continue; try { if (getInstanceManager() != null) { getInstanceManager().destroyInstance(listeners[j]); } } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(t); getLogger().error (sm.getString("standardContext.listenerStop", listeners[j].getClass().getName()), t); ok = false; } } } setApplicationEventListeners(null); setApplicationLifecycleListeners(null); noPluggabilityServletContext = null; noPluggabilityListeners.clear(); return ok; }
Allocate resources, including proxy.
Throws:
  • LifecycleException – if a start error occurs
/** * Allocate resources, including proxy. * @throws LifecycleException if a start error occurs */
public void resourcesStart() throws LifecycleException { // Check current status in case resources were added that had already // been started if (!resources.getState().isAvailable()) { resources.start(); } if (effectiveMajorVersion >=3 && addWebinfClassesResources) { WebResource webinfClassesResource = resources.getResource( "/WEB-INF/classes/META-INF/resources"); if (webinfClassesResource.isDirectory()) { getResources().createWebResourceSet( WebResourceRoot.ResourceSetType.RESOURCE_JAR, "/", webinfClassesResource.getURL(), "/"); } } }
Deallocate resources and destroy proxy.
Returns:true if no error occurred
/** * Deallocate resources and destroy proxy. * @return <code>true</code> if no error occurred */
public boolean resourcesStop() { boolean ok = true; Lock writeLock = resourcesLock.writeLock(); writeLock.lock(); try { if (resources != null) { resources.stop(); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("standardContext.resourcesStop"), t); ok = false; } finally { writeLock.unlock(); } return ok; }
Load and initialize all servlets marked "load on startup" in the web application deployment descriptor.
Params:
  • children – Array of wrappers for all currently defined servlets (including those not declared load on startup)
Returns:true if load on startup was considered successful
/** * Load and initialize all servlets marked "load on startup" in the * web application deployment descriptor. * * @param children Array of wrappers for all currently defined * servlets (including those not declared load on startup) * @return <code>true</code> if load on startup was considered successful */
public boolean loadOnStartup(Container children[]) { // Collect "load on startup" servlets that need to be initialized TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>(); for (Container child : children) { Wrapper wrapper = (Wrapper) child; int loadOnStartup = wrapper.getLoadOnStartup(); if (loadOnStartup < 0) { continue; } Integer key = Integer.valueOf(loadOnStartup); ArrayList<Wrapper> list = map.get(key); if (list == null) { list = new ArrayList<>(); map.put(key, list); } list.add(wrapper); } // Load the collected "load on startup" servlets for (ArrayList<Wrapper> list : map.values()) { for (Wrapper wrapper : list) { try { wrapper.load(); } catch (ServletException e) { getLogger().error(sm.getString("standardContext.loadOnStartup.loadException", getName(), wrapper.getName()), StandardWrapper.getRootCause(e)); // NOTE: load errors (including a servlet that throws // UnavailableException from the init() method) are NOT // fatal to application startup // unless failCtxIfServletStartFails="true" is specified if(getComputedFailCtxIfServletStartFails()) { return false; } } } } return true; }
Start this component and implement the requirements of LifecycleBase.startInternal().
Throws:
  • LifecycleException – if this component detects a fatal error that prevents this component from being used
/** * 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 { if(log.isDebugEnabled()) log.debug("Starting " + getBaseName()); // Send j2ee.state.starting notification if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.state.starting", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } setConfigured(false); boolean ok = true; // Currently this is effectively a NO-OP but needs to be called to // ensure the NamingResources follows the correct lifecycle if (namingResources != null) { namingResources.start(); } // Post work directory postWorkDirectory(); // Add missing components as necessary if (getResources() == null) { // (1) Required by Loader if (log.isDebugEnabled()) log.debug("Configuring default Resources"); try { setResources(new StandardRoot(this)); } catch (IllegalArgumentException e) { log.error(sm.getString("standardContext.resourcesInit"), e); ok = false; } } if (ok) { resourcesStart(); } if (getLoader() == null) { WebappLoader webappLoader = new WebappLoader(); webappLoader.setDelegate(getDelegate()); setLoader(webappLoader); } // An explicit cookie processor hasn't been specified; use the default if (cookieProcessor == null) { cookieProcessor = new Rfc6265CookieProcessor(); } // Initialize character set mapper getCharsetMapper(); // Validate required extensions boolean dependencyCheck = true; try { dependencyCheck = ExtensionValidator.validateApplication (getResources(), this); } catch (IOException ioe) { log.error(sm.getString("standardContext.extensionValidationError"), ioe); dependencyCheck = false; } if (!dependencyCheck) { // do not make application available if dependency check fails ok = false; } // Reading the "catalina.useNaming" environment variable String useNamingProperty = System.getProperty("catalina.useNaming"); if ((useNamingProperty != null) && (useNamingProperty.equals("false"))) { useNaming = false; } if (ok && isUseNaming()) { if (getNamingContextListener() == null) { NamingContextListener ncl = new NamingContextListener(); ncl.setName(getNamingContextName()); ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite()); addLifecycleListener(ncl); setNamingContextListener(ncl); } } // Standard container startup if (log.isDebugEnabled()) log.debug("Processing standard container startup"); // Binding thread ClassLoader oldCCL = bindThread(); try { if (ok) { // Start our subordinate components, if any Loader loader = getLoader(); if (loader instanceof Lifecycle) { ((Lifecycle) loader).start(); } // since the loader just started, the webapp classloader is now // created. setClassLoaderProperty("clearReferencesRmiTargets", getClearReferencesRmiTargets()); setClassLoaderProperty("clearReferencesStopThreads", getClearReferencesStopThreads()); setClassLoaderProperty("clearReferencesStopTimerThreads", getClearReferencesStopTimerThreads()); setClassLoaderProperty("clearReferencesHttpClientKeepAliveThread", getClearReferencesHttpClientKeepAliveThread()); setClassLoaderProperty("clearReferencesObjectStreamClassCaches", getClearReferencesObjectStreamClassCaches()); setClassLoaderProperty("clearReferencesObjectStreamClassCaches", getClearReferencesObjectStreamClassCaches()); setClassLoaderProperty("clearReferencesThreadLocals", getClearReferencesThreadLocals()); // By calling unbindThread and bindThread in a row, we setup the // current Thread CCL to be the webapp classloader unbindThread(oldCCL); oldCCL = bindThread(); // Initialize logger again. Other components might have used it // too early, so it should be reset. logger = null; getLogger(); Realm realm = getRealmInternal(); if(null != realm) { if (realm instanceof Lifecycle) { ((Lifecycle) realm).start(); } // Place the CredentialHandler into the ServletContext so // applications can have access to it. Wrap it in a "safe" // handler so application's can't modify it. CredentialHandler safeHandler = new CredentialHandler() { @Override public boolean matches(String inputCredentials, String storedCredentials) { return getRealmInternal().getCredentialHandler().matches(inputCredentials, storedCredentials); } @Override public String mutate(String inputCredentials) { return getRealmInternal().getCredentialHandler().mutate(inputCredentials); } }; context.setAttribute(Globals.CREDENTIAL_HANDLER, safeHandler); } // Notify our interested LifecycleListeners fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null); // Start our child containers, if not already started for (Container child : findChildren()) { if (!child.getState().isAvailable()) { child.start(); } } // Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).start(); } // Acquire clustered manager Manager contextManager = null; Manager manager = getManager(); if (manager == null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.cluster.noManager", Boolean.valueOf((getCluster() != null)), Boolean.valueOf(distributable))); } if ((getCluster() != null) && distributable) { try { contextManager = getCluster().createManager(getName()); } catch (Exception ex) { log.error(sm.getString("standardContext.cluster.managerError"), ex); ok = false; } } else { contextManager = new StandardManager(); } } // Configure default manager if none was specified if (contextManager != null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.manager", contextManager.getClass().getName())); } setManager(contextManager); } if (manager!=null && (getCluster() != null) && distributable) { //let the cluster know that there is a context that is distributable //and that it has its own manager getCluster().registerManager(manager); } } if (!getConfigured()) { log.error(sm.getString("standardContext.configurationFail")); ok = false; } // We put the resources into the servlet context if (ok) { getServletContext().setAttribute (Globals.RESOURCES_ATTR, getResources()); if (getInstanceManager() == null) { setInstanceManager(createInstanceManager()); } getServletContext().setAttribute( InstanceManager.class.getName(), getInstanceManager()); InstanceManagerBindings.bind(getLoader().getClassLoader(), getInstanceManager()); // Create context attributes that will be required getServletContext().setAttribute( JarScanner.class.getName(), getJarScanner()); // Make the version info available getServletContext().setAttribute(Globals.WEBAPP_VERSION, getWebappVersion()); } // Set up the context init params mergeParameters(); // Call ServletContainerInitializers for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry : initializers.entrySet()) { try { entry.getKey().onStartup(entry.getValue(), getServletContext()); } catch (ServletException e) { log.error(sm.getString("standardContext.sciFail"), e); ok = false; break; } } // Configure and call application event listeners if (ok) { if (!listenerStart()) { log.error(sm.getString("standardContext.listenerFail")); ok = false; } } // Check constraints for uncovered HTTP methods // Needs to be after SCIs and listeners as they may programmatically // change constraints if (ok) { checkConstraintsForUncoveredMethods(findConstraints()); } try { // Start manager Manager manager = getManager(); if (manager instanceof Lifecycle) { ((Lifecycle) manager).start(); } } catch(Exception e) { log.error(sm.getString("standardContext.managerFail"), e); ok = false; } // Configure and call application filters if (ok) { if (!filterStart()) { log.error(sm.getString("standardContext.filterFail")); ok = false; } } // Load and initialize all "load on startup" servlets if (ok) { if (!loadOnStartup(findChildren())){ log.error(sm.getString("standardContext.servletFail")); ok = false; } } // Start ContainerBackgroundProcessor thread super.threadStart(); } finally { // Unbinding thread unbindThread(oldCCL); } // Set available status depending upon startup success if (ok) { if (log.isDebugEnabled()) log.debug("Starting completed"); } else { log.error(sm.getString("standardContext.startFailed", getName())); } startTime=System.currentTimeMillis(); // Send j2ee.state.running notification if (ok && (this.getObjectName() != null)) { Notification notification = new Notification("j2ee.state.running", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } // The WebResources implementation caches references to JAR files. On // some platforms these references may lock the JAR files. Since web // application start is likely to have read from lots of JARs, trigger // a clean-up now. getResources().gc(); // Reinitializing if something went wrong if (!ok) { setState(LifecycleState.FAILED); // Send j2ee.object.failed notification if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.object.failed", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } } else { setState(LifecycleState.STARTING); } } private void checkConstraintsForUncoveredMethods( SecurityConstraint[] constraints) { SecurityConstraint[] newConstraints = SecurityConstraint.findUncoveredHttpMethods(constraints, getDenyUncoveredHttpMethods(), getLogger()); for (SecurityConstraint constraint : newConstraints) { addConstraint(constraint); } } private void setClassLoaderProperty(String name, boolean value) { ClassLoader cl = getLoader().getClassLoader(); if (!IntrospectionUtils.setProperty(cl, name, Boolean.toString(value))) { // Failed to set log.info(sm.getString( "standardContext.webappClassLoader.missingProperty", name, Boolean.toString(value))); } } @Override public InstanceManager createInstanceManager() { javax.naming.Context context = null; if (isUseNaming() && getNamingContextListener() != null) { context = getNamingContextListener().getEnvContext(); } Map<String, Map<String, String>> injectionMap = buildInjectionMap( getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources()); return new DefaultInstanceManager(context, injectionMap, this, this.getClass().getClassLoader()); } private Map<String, Map<String, String>> buildInjectionMap(NamingResourcesImpl namingResources) { Map<String, Map<String, String>> injectionMap = new HashMap<>(); for (Injectable resource: namingResources.findLocalEjbs()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findEjbs()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findEnvironments()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findMessageDestinationRefs()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findResourceEnvRefs()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findResources()) { addInjectionTarget(resource, injectionMap); } for (Injectable resource: namingResources.findServices()) { addInjectionTarget(resource, injectionMap); } return injectionMap; } private void addInjectionTarget(Injectable resource, Map<String, Map<String, String>> injectionMap) { List<InjectionTarget> injectionTargets = resource.getInjectionTargets(); if (injectionTargets != null && injectionTargets.size() > 0) { String jndiName = resource.getName(); for (InjectionTarget injectionTarget: injectionTargets) { String clazz = injectionTarget.getTargetClass(); Map<String, String> injections = injectionMap.get(clazz); if (injections == null) { injections = new HashMap<>(); injectionMap.put(clazz, injections); } injections.put(injectionTarget.getTargetName(), jndiName); } } }
Merge the context initialization parameters specified in the application deployment descriptor with the application parameters described in the server configuration, respecting the override property of the application parameters appropriately.
/** * Merge the context initialization parameters specified in the application * deployment descriptor with the application parameters described in the * server configuration, respecting the <code>override</code> property of * the application parameters appropriately. */
private void mergeParameters() { Map<String,String> mergedParams = new HashMap<>(); String names[] = findParameters(); for (String s : names) { mergedParams.put(s, findParameter(s)); } ApplicationParameter params[] = findApplicationParameters(); for (ApplicationParameter param : params) { if (param.getOverride()) { if (mergedParams.get(param.getName()) == null) { mergedParams.put(param.getName(), param.getValue()); } } else { mergedParams.put(param.getName(), param.getValue()); } } ServletContext sc = getServletContext(); for (Map.Entry<String,String> entry : mergedParams.entrySet()) { sc.setInitParameter(entry.getKey(), entry.getValue()); } }
Stop this component and implement the requirements of LifecycleBase.stopInternal().
Throws:
  • LifecycleException – if this component detects a fatal error that prevents this component from being used
/** * 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 { // Send j2ee.state.stopping notification if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.state.stopping", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } // Context has been removed from Mapper at this point (so no new // requests will be mapped) but is still available. // Give the in progress async requests a chance to complete long limit = System.currentTimeMillis() + unloadDelay; while (inProgressAsyncCount.get() > 0 && System.currentTimeMillis() < limit) { try { Thread.sleep(50); } catch (InterruptedException e) { log.info(sm.getString("standardContext.stop.asyncWaitInterrupted"), e); break; } } // Once the state is set to STOPPING, the Context will report itself as // not available and any in progress async requests will timeout setState(LifecycleState.STOPPING); // Binding thread ClassLoader oldCCL = bindThread(); try { // Stop our child containers, if any final Container[] children = findChildren(); // Stop ContainerBackgroundProcessor thread threadStop(); for (Container child : children) { child.stop(); } // Stop our filters filterStop(); Manager manager = getManager(); if (manager instanceof Lifecycle && ((Lifecycle) manager).getState().isAvailable()) { ((Lifecycle) manager).stop(); } // Stop our application listeners listenerStop(); // Finalize our character set mapper setCharsetMapper(null); // Normal container shutdown processing if (log.isDebugEnabled()) log.debug("Processing standard container shutdown"); // JNDI resources are unbound in CONFIGURE_STOP_EVENT so stop // naming resources before they are unbound since NamingResources // does a JNDI lookup to retrieve the resource. This needs to be // after the application has finished with the resource if (namingResources != null) { namingResources.stop(); } fireLifecycleEvent(Lifecycle.CONFIGURE_STOP_EVENT, null); // Stop the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle && ((Lifecycle) pipeline).getState().isAvailable()) { ((Lifecycle) pipeline).stop(); } // Clear all application-originated servlet context attributes if (context != null) context.clearAttributes(); Realm realm = getRealmInternal(); if (realm instanceof Lifecycle) { ((Lifecycle) realm).stop(); } Loader loader = getLoader(); if (loader instanceof Lifecycle) { ClassLoader classLoader = loader.getClassLoader(); ((Lifecycle) loader).stop(); if (classLoader != null) { InstanceManagerBindings.unbind(classLoader); } } // Stop resources resourcesStop(); } finally { // Unbinding thread unbindThread(oldCCL); } // Send j2ee.state.stopped notification if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.state.stopped", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } // Reset application context context = null; // This object will no longer be visible or used. try { resetContext(); } catch( Exception ex ) { log.error( "Error resetting context " + this + " " + ex, ex ); } //reset the instance manager setInstanceManager(null); if (log.isDebugEnabled()) log.debug("Stopping complete"); }
Destroy needs to clean up the context completely. The problem is that undoing all the config in start() and restoring a 'fresh' state is impossible. After stop()/destroy()/init()/start() we should have the same state as if a fresh start was done - i.e read modified web.xml, etc. This can only be done by completely removing the context object and remapping a new one, or by cleaning up everything.
/** * Destroy needs to clean up the context completely. * * The problem is that undoing all the config in start() and restoring * a 'fresh' state is impossible. After stop()/destroy()/init()/start() * we should have the same state as if a fresh start was done - i.e * read modified web.xml, etc. This can only be done by completely * removing the context object and remapping a new one, or by cleaning * up everything. */
@Override protected void destroyInternal() throws LifecycleException { // If in state NEW when destroy is called, the object name will never // have been set so the notification can't be created if (getObjectName() != null) { // Send j2ee.object.deleted notification Notification notification = new Notification("j2ee.object.deleted", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } if (namingResources != null) { namingResources.destroy(); } Loader loader = getLoader(); if (loader instanceof Lifecycle) { ((Lifecycle) loader).destroy(); } Manager manager = getManager(); if (manager instanceof Lifecycle) { ((Lifecycle) manager).destroy(); } if (resources != null) { resources.destroy(); } super.destroyInternal(); } @Override public void backgroundProcess() { if (!getState().isAvailable()) return; Loader loader = getLoader(); if (loader != null) { try { loader.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString( "standardContext.backgroundProcess.loader", loader), e); } } Manager manager = getManager(); if (manager != null) { try { manager.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString( "standardContext.backgroundProcess.manager", manager), e); } } WebResourceRoot resources = getResources(); if (resources != null) { try { resources.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString( "standardContext.backgroundProcess.resources", resources), e); } } InstanceManager instanceManager = getInstanceManager(); if (instanceManager != null) { try { instanceManager.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString( "standardContext.backgroundProcess.instanceManager", resources), e); } } super.backgroundProcess(); } private void resetContext() throws Exception { // Restore the original state ( pre reading web.xml in start ) // If you extend this - override this method and make sure to clean up // Don't reset anything that is read from a <Context.../> element since // <Context .../> elements are read at initialisation will not be read // again for this object for (Container child : findChildren()) { removeChild(child); } startupTime = 0; startTime = 0; tldScanTime = 0; // Bugzilla 32867 distributable = false; applicationListeners = new String[0]; applicationEventListenersList.clear(); applicationLifecycleListenersObjects = new Object[0]; jspConfigDescriptor = null; initializers.clear(); createdServlets.clear(); postConstructMethods.clear(); preDestroyMethods.clear(); if(log.isDebugEnabled()) log.debug("resetContext " + getObjectName()); } // ------------------------------------------------------ Protected Methods
Adjust the URL pattern to begin with a leading slash, if appropriate (i.e. we are running a servlet 2.2 application). Otherwise, return the specified URL pattern unchanged.
Params:
  • urlPattern – The URL pattern to be adjusted (if needed) and returned
Returns:the URL pattern with a leading slash if needed
/** * Adjust the URL pattern to begin with a leading slash, if appropriate * (i.e. we are running a servlet 2.2 application). Otherwise, return * the specified URL pattern unchanged. * * @param urlPattern The URL pattern to be adjusted (if needed) * and returned * @return the URL pattern with a leading slash if needed */
protected String adjustURLPattern(String urlPattern) { if (urlPattern == null) return urlPattern; if (urlPattern.startsWith("/") || urlPattern.startsWith("*.")) return urlPattern; if (!isServlet22()) return urlPattern; if(log.isDebugEnabled()) log.debug(sm.getString("standardContext.urlPattern.patternWarning", urlPattern)); return "/" + urlPattern; }
Are we processing a version 2.2 deployment descriptor?
Returns:true if running a legacy Servlet 2.2 application
/** * Are we processing a version 2.2 deployment descriptor? * * @return <code>true</code> if running a legacy Servlet 2.2 application */
@Override public boolean isServlet22() { return XmlIdentifiers.WEB_22_PUBLIC.equals(publicId); } @Override public Set<String> addServletSecurity( ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) { Set<String> conflicts = new HashSet<>(); Collection<String> urlPatterns = registration.getMappings(); for (String urlPattern : urlPatterns) { boolean foundConflict = false; SecurityConstraint[] securityConstraints = findConstraints(); for (SecurityConstraint securityConstraint : securityConstraints) { SecurityCollection[] collections = securityConstraint.findCollections(); for (SecurityCollection collection : collections) { if (collection.findPattern(urlPattern)) { // First pattern found will indicate if there is a // conflict since for any given pattern all matching // constraints will be from either the descriptor or // not. It is not permitted to have a mixture if (collection.isFromDescriptor()) { // Skip this pattern foundConflict = true; conflicts.add(urlPattern); break; } else { // Need to overwrite constraint for this pattern collection.removePattern(urlPattern); // If the collection is now empty, remove it if (collection.findPatterns().length == 0) { securityConstraint.removeCollection(collection); } } } } // If the constraint now has no collections - remove it if (securityConstraint.findCollections().length == 0) { removeConstraint(securityConstraint); } // No need to check other constraints for the current pattern // once a conflict has been found if (foundConflict) { break; } } // Note: For programmatically added Servlets this may not be the // complete set of security constraints since additional // URL patterns can be added after the application has called // setSecurity. For all programmatically added servlets, the // #dynamicServletAdded() method sets a flag that ensures that // the constraints are re-evaluated before the servlet is // first used // If the pattern did not conflict, add the new constraint(s). if (!foundConflict) { SecurityConstraint[] newSecurityConstraints = SecurityConstraint.createConstraints( servletSecurityElement, urlPattern); for (SecurityConstraint securityConstraint : newSecurityConstraints) { addConstraint(securityConstraint); } } } return conflicts; }
Bind current thread, both for CL purposes and for JNDI ENC support during : startup, shutdown and reloading of the context.
Returns:the previous context class loader
/** * Bind current thread, both for CL purposes and for JNDI ENC support * during : startup, shutdown and reloading of the context. * * @return the previous context class loader */
protected ClassLoader bindThread() { ClassLoader oldContextClassLoader = bind(false, null); if (isUseNaming()) { try { ContextBindings.bindThread(this, getNamingToken()); } catch (NamingException e) { // Silent catch, as this is a normal case during the early // startup stages } } return oldContextClassLoader; }
Unbind thread and restore the specified context classloader.
Params:
  • oldContextClassLoader – the previous classloader
/** * Unbind thread and restore the specified context classloader. * * @param oldContextClassLoader the previous classloader */
protected void unbindThread(ClassLoader oldContextClassLoader) { if (isUseNaming()) { ContextBindings.unbindThread(this, getNamingToken()); } unbind(false, oldContextClassLoader); } @Override public ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader) { Loader loader = getLoader(); ClassLoader webApplicationClassLoader = null; if (loader != null) { webApplicationClassLoader = loader.getClassLoader(); } if (originalClassLoader == null) { if (usePrivilegedAction) { PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl(); originalClassLoader = AccessController.doPrivileged(pa); } else { originalClassLoader = Thread.currentThread().getContextClassLoader(); } } if (webApplicationClassLoader == null || webApplicationClassLoader == originalClassLoader) { // Not possible or not necessary to switch class loaders. Return // null to indicate this. return null; } ThreadBindingListener threadBindingListener = getThreadBindingListener(); if (usePrivilegedAction) { PrivilegedAction<Void> pa = new PrivilegedSetTccl(webApplicationClassLoader); AccessController.doPrivileged(pa); } else { Thread.currentThread().setContextClassLoader(webApplicationClassLoader); } if (threadBindingListener != null) { try { threadBindingListener.bind(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString( "standardContext.threadBindingListenerError", getName()), t); } } return originalClassLoader; } @Override public void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader) { if (originalClassLoader == null) { return; } if (threadBindingListener != null) { try { threadBindingListener.unbind(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString( "standardContext.threadBindingListenerError", getName()), t); } } if (usePrivilegedAction) { PrivilegedAction<Void> pa = new PrivilegedSetTccl(originalClassLoader); AccessController.doPrivileged(pa); } else { Thread.currentThread().setContextClassLoader(originalClassLoader); } }
Get naming context full name.
Returns:the context name
/** * Get naming context full name. * * @return the context name */
private String getNamingContextName() { if (namingContextName == null) { Container parent = getParent(); if (parent == null) { namingContextName = getName(); } else { Stack<String> stk = new Stack<>(); StringBuilder buff = new StringBuilder(); while (parent != null) { stk.push(parent.getName()); parent = parent.getParent(); } while (!stk.empty()) { buff.append("/" + stk.pop()); } buff.append(getName()); namingContextName = buff.toString(); } } return namingContextName; }
Naming context listener accessor.
Returns:the naming context listener associated with the webapp
/** * Naming context listener accessor. * * @return the naming context listener associated with the webapp */
public NamingContextListener getNamingContextListener() { return namingContextListener; }
Naming context listener setter.
Params:
  • namingContextListener – the new naming context listener
/** * Naming context listener setter. * * @param namingContextListener the new naming context listener */
public void setNamingContextListener(NamingContextListener namingContextListener) { this.namingContextListener = namingContextListener; }
Returns:the request processing paused flag for this Context.
/** * @return the request processing paused flag for this Context. */
@Override public boolean getPaused() { return this.paused; } @Override public boolean fireRequestInitEvent(ServletRequest request) { Object instances[] = getApplicationEventListeners(); if ((instances != null) && (instances.length > 0)) { ServletRequestEvent event = new ServletRequestEvent(getServletContext(), request); for (Object instance : instances) { if (instance == null) { continue; } if (!(instance instanceof ServletRequestListener)) { continue; } ServletRequestListener listener = (ServletRequestListener) instance; try { listener.requestInitialized(event); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); getLogger().error(sm.getString( "standardContext.requestListener.requestInit", instance.getClass().getName()), t); request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); return false; } } } return true; } @Override public boolean fireRequestDestroyEvent(ServletRequest request) { Object instances[] = getApplicationEventListeners(); if ((instances != null) && (instances.length > 0)) { ServletRequestEvent event = new ServletRequestEvent(getServletContext(), request); for (int i = 0; i < instances.length; i++) { int j = (instances.length -1) -i; if (instances[j] == null) continue; if (!(instances[j] instanceof ServletRequestListener)) continue; ServletRequestListener listener = (ServletRequestListener) instances[j]; try { listener.requestDestroyed(event); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); getLogger().error(sm.getString( "standardContext.requestListener.requestInit", instances[j].getClass().getName()), t); request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); return false; } } } return true; } @Override public void addPostConstructMethod(String clazz, String method) { if (clazz == null || method == null) throw new IllegalArgumentException( sm.getString("standardContext.postconstruct.required")); if (postConstructMethods.get(clazz) != null) throw new IllegalArgumentException(sm.getString( "standardContext.postconstruct.duplicate", clazz)); postConstructMethods.put(clazz, method); fireContainerEvent("addPostConstructMethod", clazz); } @Override public void removePostConstructMethod(String clazz) { postConstructMethods.remove(clazz); fireContainerEvent("removePostConstructMethod", clazz); } @Override public void addPreDestroyMethod(String clazz, String method) { if (clazz == null || method == null) throw new IllegalArgumentException( sm.getString("standardContext.predestroy.required")); if (preDestroyMethods.get(clazz) != null) throw new IllegalArgumentException(sm.getString( "standardContext.predestroy.duplicate", clazz)); preDestroyMethods.put(clazz, method); fireContainerEvent("addPreDestroyMethod", clazz); } @Override public void removePreDestroyMethod(String clazz) { preDestroyMethods.remove(clazz); fireContainerEvent("removePreDestroyMethod", clazz); } @Override public String findPostConstructMethod(String clazz) { return postConstructMethods.get(clazz); } @Override public String findPreDestroyMethod(String clazz) { return preDestroyMethods.get(clazz); } @Override public Map<String, String> findPostConstructMethods() { return postConstructMethods; } @Override public Map<String, String> findPreDestroyMethods() { return preDestroyMethods; }
Set the appropriate context attribute for our work directory.
/** * Set the appropriate context attribute for our work directory. */
private void postWorkDirectory() { // Acquire (or calculate) the work directory path String workDir = getWorkDir(); if (workDir == null || workDir.length() == 0) { // Retrieve our parent (normally a host) name String hostName = null; String engineName = null; String hostWorkDir = null; Container parentHost = getParent(); if (parentHost != null) { hostName = parentHost.getName(); if (parentHost instanceof StandardHost) { hostWorkDir = ((StandardHost)parentHost).getWorkDir(); } Container parentEngine = parentHost.getParent(); if (parentEngine != null) { engineName = parentEngine.getName(); } } if ((hostName == null) || (hostName.length() < 1)) hostName = "_"; if ((engineName == null) || (engineName.length() < 1)) engineName = "_"; String temp = getBaseName(); if (temp.startsWith("/")) temp = temp.substring(1); temp = temp.replace('/', '_'); temp = temp.replace('\\', '_'); if (temp.length() < 1) temp = ContextName.ROOT_NAME; if (hostWorkDir != null ) { workDir = hostWorkDir + File.separator + temp; } else { workDir = "work" + File.separator + engineName + File.separator + hostName + File.separator + temp; } setWorkDir(workDir); } // Create this directory if necessary File dir = new File(workDir); if (!dir.isAbsolute()) { String catalinaHomePath = null; try { catalinaHomePath = getCatalinaBase().getCanonicalPath(); dir = new File(catalinaHomePath, workDir); } catch (IOException e) { log.warn(sm.getString("standardContext.workCreateException", workDir, catalinaHomePath, getName()), e); } } if (!dir.mkdirs() && !dir.isDirectory()) { log.warn(sm.getString("standardContext.workCreateFail", dir, getName())); } // Set the appropriate servlet context attribute if (context == null) { getServletContext(); } context.setAttribute(ServletContext.TEMPDIR, dir); context.setAttributeReadOnly(ServletContext.TEMPDIR); }
Set the request processing paused flag for this Context.
Params:
  • paused – The new request processing paused flag
/** * Set the request processing paused flag for this Context. * * @param paused The new request processing paused flag */
private void setPaused(boolean paused) { this.paused = paused; }
Validate the syntax of a proposed <url-pattern> for conformance with specification requirements.
Params:
  • urlPattern – URL pattern to be validated
Returns:true if the URL pattern is conformant
/** * Validate the syntax of a proposed <code>&lt;url-pattern&gt;</code> * for conformance with specification requirements. * * @param urlPattern URL pattern to be validated * @return <code>true</code> if the URL pattern is conformant */
private boolean validateURLPattern(String urlPattern) { if (urlPattern == null) return false; if (urlPattern.indexOf('\n') >= 0 || urlPattern.indexOf('\r') >= 0) { return false; } if (urlPattern.equals("")) { return true; } if (urlPattern.startsWith("*.")) { if (urlPattern.indexOf('/') < 0) { checkUnusualURLPattern(urlPattern); return true; } else return false; } if (urlPattern.startsWith("/") && !urlPattern.contains("*.")) { checkUnusualURLPattern(urlPattern); return true; } else return false; }
Check for unusual but valid <url-pattern>s. See Bugzilla 34805, 43079 & 43080
/** * Check for unusual but valid <code>&lt;url-pattern&gt;</code>s. * See Bugzilla 34805, 43079 & 43080 */
private void checkUnusualURLPattern(String urlPattern) { if (log.isInfoEnabled()) { // First group checks for '*' or '/foo*' style patterns // Second group checks for *.foo.bar style patterns if((urlPattern.endsWith("*") && (urlPattern.length() < 2 || urlPattern.charAt(urlPattern.length()-2) != '/')) || urlPattern.startsWith("*.") && urlPattern.length() > 2 && urlPattern.lastIndexOf('.') > 1) { log.info(sm.getString("standardContext.suspiciousUrl", urlPattern, getName())); } } } // ------------------------------------------------------------- Operations @Override protected String getObjectNameKeyProperties() { StringBuilder keyProperties = new StringBuilder("j2eeType=WebModule,"); keyProperties.append(getObjectKeyPropertiesNameOnly()); keyProperties.append(",J2EEApplication="); keyProperties.append(getJ2EEApplication()); keyProperties.append(",J2EEServer="); keyProperties.append(getJ2EEServer()); return keyProperties.toString(); } private String getObjectKeyPropertiesNameOnly() { StringBuilder result = new StringBuilder("name=//"); String hostname = getParent().getName(); if (hostname == null) { result.append("DEFAULT"); } else { result.append(hostname); } String contextName = getName(); if (!contextName.startsWith("/")) { result.append('/'); } result.append(contextName); return result.toString(); } @Override protected void initInternal() throws LifecycleException { super.initInternal(); // Register the naming resources if (namingResources != null) { namingResources.init(); } // Send j2ee.object.created notification if (this.getObjectName() != null) { Notification notification = new Notification("j2ee.object.created", this.getObjectName(), sequenceNumber.getAndIncrement()); broadcaster.sendNotification(notification); } }
Remove a JMX notificationListener
See Also:
  • removeNotificationListener.removeNotificationListener(NotificationListener, NotificationFilter, Object)
/** * Remove a JMX notificationListener * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object) */
@Override public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object object) throws ListenerNotFoundException { broadcaster.removeNotificationListener(listener,filter,object); } private MBeanNotificationInfo[] notificationInfo;
Get JMX Broadcaster Info
See Also:
  • getNotificationInfo.getNotificationInfo()
/** * Get JMX Broadcaster Info * @see javax.management.NotificationBroadcaster#getNotificationInfo() */
@Override public MBeanNotificationInfo[] getNotificationInfo() { // FIXME: we not send j2ee.attribute.changed if (notificationInfo == null) { notificationInfo = new MBeanNotificationInfo[] { new MBeanNotificationInfo( new String[] { "j2ee.object.created" }, Notification.class.getName(), "web application is created"), new MBeanNotificationInfo( new String[] { "j2ee.state.starting" }, Notification.class.getName(), "change web application is starting"), new MBeanNotificationInfo( new String[] { "j2ee.state.running" }, Notification.class.getName(), "web application is running"), new MBeanNotificationInfo( new String[] { "j2ee.state.stopping" }, Notification.class.getName(), "web application start to stopped"), new MBeanNotificationInfo( new String[] { "j2ee.object.stopped" }, Notification.class.getName(), "web application is stopped"), new MBeanNotificationInfo( new String[] { "j2ee.object.deleted" }, Notification.class.getName(), "web application is deleted"), new MBeanNotificationInfo( new String[] { "j2ee.object.failed" }, Notification.class.getName(), "web application failed") }; } return notificationInfo; }
Add a JMX NotificationListener
See Also:
  • addNotificationListener.addNotificationListener(NotificationListener, NotificationFilter, Object)
/** * Add a JMX NotificationListener * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object) */
@Override public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object object) throws IllegalArgumentException { broadcaster.addNotificationListener(listener,filter,object); }
Remove a JMX-NotificationListener
See Also:
  • removeNotificationListener.removeNotificationListener(NotificationListener)
/** * Remove a JMX-NotificationListener * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener) */
@Override public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { broadcaster.removeNotificationListener(listener); } // ------------------------------------------------------------- Attributes
Returns:the naming resources associated with this web application.
/** * @return the naming resources associated with this web application. */
public String[] getWelcomeFiles() { return findWelcomeFiles(); } @Override public boolean getXmlNamespaceAware() { return webXmlNamespaceAware; } @Override public void setXmlNamespaceAware(boolean webXmlNamespaceAware) { this.webXmlNamespaceAware = webXmlNamespaceAware; } @Override public void setXmlValidation(boolean webXmlValidation) { this.webXmlValidation = webXmlValidation; } @Override public boolean getXmlValidation() { return webXmlValidation; } @Override public void setXmlBlockExternal(boolean xmlBlockExternal) { this.xmlBlockExternal = xmlBlockExternal; } @Override public boolean getXmlBlockExternal() { return xmlBlockExternal; } @Override public void setTldValidation(boolean tldValidation) { this.tldValidation = tldValidation; } @Override public boolean getTldValidation() { return tldValidation; }
The J2EE Server ObjectName this module is deployed on.
/** * The J2EE Server ObjectName this module is deployed on. */
private String server = null;
The Java virtual machines on which this module is running.
/** * The Java virtual machines on which this module is running. */
private String[] javaVMs = null; public String getServer() { return server; } public String setServer(String server) { return this.server=server; } public String[] getJavaVMs() { return javaVMs; } public String[] setJavaVMs(String[] javaVMs) { return this.javaVMs = javaVMs; }
Gets the time this context was started.
Returns:Time (in milliseconds since January 1, 1970, 00:00:00) when this context was started
/** * Gets the time this context was started. * * @return Time (in milliseconds since January 1, 1970, 00:00:00) when this * context was started */
public long getStartTime() { return startTime; } private static class NoPluggabilityServletContext implements ServletContext { private final ServletContext sc; public NoPluggabilityServletContext(ServletContext sc) { this.sc = sc; } @Override public String getContextPath() { return sc.getContextPath(); } @Override public ServletContext getContext(String uripath) { return sc.getContext(uripath); } @Override public int getMajorVersion() { return sc.getMajorVersion(); } @Override public int getMinorVersion() { return sc.getMinorVersion(); } @Override public int getEffectiveMajorVersion() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public int getEffectiveMinorVersion() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public String getMimeType(String file) { return sc.getMimeType(file); } @Override public Set<String> getResourcePaths(String path) { return sc.getResourcePaths(path); } @Override public URL getResource(String path) throws MalformedURLException { return sc.getResource(path); } @Override public InputStream getResourceAsStream(String path) { return sc.getResourceAsStream(path); } @Override public RequestDispatcher getRequestDispatcher(String path) { return sc.getRequestDispatcher(path); } @Override public RequestDispatcher getNamedDispatcher(String name) { return sc.getNamedDispatcher(name); } @Override @Deprecated public Servlet getServlet(String name) throws ServletException { return sc.getServlet(name); } @Override @Deprecated public Enumeration<Servlet> getServlets() { return sc.getServlets(); } @Override @Deprecated public Enumeration<String> getServletNames() { return sc.getServletNames(); } @Override public void log(String msg) { sc.log(msg); } @Override @Deprecated public void log(Exception exception, String msg) { sc.log(exception, msg); } @Override public void log(String message, Throwable throwable) { sc.log(message, throwable); } @Override public String getRealPath(String path) { return sc.getRealPath(path); } @Override public String getServerInfo() { return sc.getServerInfo(); } @Override public String getInitParameter(String name) { return sc.getInitParameter(name); } @Override public Enumeration<String> getInitParameterNames() { return sc.getInitParameterNames(); } @Override public boolean setInitParameter(String name, String value) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Object getAttribute(String name) { return sc.getAttribute(name); } @Override public Enumeration<String> getAttributeNames() { return sc.getAttributeNames(); } @Override public void setAttribute(String name, Object object) { sc.setAttribute(name, object); } @Override public void removeAttribute(String name) { sc.removeAttribute(name); } @Override public String getServletContextName() { return sc.getServletContextName(); } @Override public Dynamic addServlet(String servletName, String className) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Dynamic addServlet(String servletName, Servlet servlet) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Dynamic addJspFile(String jspName, String jspFile) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public <T extends Servlet> T createServlet(Class<T> c) throws ServletException { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public ServletRegistration getServletRegistration(String servletName) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Map<String,? extends ServletRegistration> getServletRegistrations() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public jakarta.servlet.FilterRegistration.Dynamic addFilter( String filterName, String className) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public jakarta.servlet.FilterRegistration.Dynamic addFilter( String filterName, Filter filter) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public jakarta.servlet.FilterRegistration.Dynamic addFilter( String filterName, Class<? extends Filter> filterClass) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public <T extends Filter> T createFilter(Class<T> c) throws ServletException { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public FilterRegistration getFilterRegistration(String filterName) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Map<String,? extends FilterRegistration> getFilterRegistrations() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public SessionCookieConfig getSessionCookieConfig() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void setSessionTrackingModes( Set<SessionTrackingMode> sessionTrackingModes) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Set<SessionTrackingMode> getDefaultSessionTrackingModes() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void addListener(String className) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public <T extends EventListener> void addListener(T t) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void addListener(Class<? extends EventListener> listenerClass) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public <T extends EventListener> T createListener(Class<T> c) throws ServletException { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public JspConfigDescriptor getJspConfigDescriptor() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public ClassLoader getClassLoader() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void declareRoles(String... roleNames) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public String getVirtualServerName() { return sc.getVirtualServerName(); } @Override public int getSessionTimeout() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void setSessionTimeout(int sessionTimeout) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public String getRequestCharacterEncoding() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void setRequestCharacterEncoding(String encoding) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public String getResponseCharacterEncoding() { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } @Override public void setResponseCharacterEncoding(String encoding) { throw new UnsupportedOperationException( sm.getString("noPluggabilityServletContext.notAllowed")); } } }