Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/Java/Tomcat/java/org/apache/catalina/core/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 10.10.2023 mit Größe 204 kB image not shown  

Quelle  StandardContext.java   Sprache: JAVA

 
/*
 * 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.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
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.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.WebappClassLoaderBase;
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.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.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;
import org.apache.tomcat.util.threads.ScheduledThreadPoolExecutor;

/**
 * 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.
     */

    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.
     */

    protected boolean allowCasualMultipartParsing = false;

    /**
     * Control whether remaining request data will be read (swallowed) even if the request violates a data size
     * constraint.
     */

    private boolean swallowAbortedUploads = true;

    /**
     * The alternate deployment descriptor name.
     */

    private String altDDName = null;


    /**
     * Lifecycle provider.
     */

    private InstanceManager instanceManager = null;


    /**
     * The antiResourceLocking flag for this Context.
     */

    private boolean antiResourceLocking = false;


    /**
     * The list of unique application listener class names configured for this application, in the order they were
     * encountered in the resulting merged web.xml file.
     */

    private CopyOnWriteArrayList<String> applicationListeners = new CopyOnWriteArrayList<>();

    /**
     * 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.
     */

    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.
     */

    private Object applicationLifecycleListenersObjects[] = new Object[0];


    /**
     * 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.
     */

    private ApplicationParameter applicationParameters[] = new ApplicationParameter[0];

    private final Object applicationParametersLock = new Object();


    /**
     * The broadcaster that sends j2ee notifications.
     */

    private NotificationBroadcasterSupport broadcaster = null;

    /**
     * The Locale to character set mapper for this application.
     */

    private CharsetMapper charsetMapper = null;


    /**
     * The Java class name of the CharsetMapper class to be created.
     */

    private String charsetMapperClass = "org.apache.catalina.util.CharsetMapper";


    /**
     * The URL of the XML descriptor for this context.
     */

    private URL configFile = null;


    /**
     * The "correctly configured" flag for this Context.
     */

    private boolean configured = false;


    /**
     * The security constraints for this web application.
     */

    private volatile SecurityConstraint constraints[] = new SecurityConstraint[0];

    private final Object constraintsLock = new Object();


    /**
     * The ServletContext implementation associated with this Context.
     */

    protected ApplicationContext context = null;

    /**
     * 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?
     */

    private boolean cookies = true;


    /**
     * Should we allow the <code>ServletContext.getContext()</code> method to access the context of other web
     * applications in this server?
     */

    private boolean crossContext = false;


    /**
     * Encoded path.
     */

    private String encodedPath = null;


    /**
     * 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.
     */

    private boolean delegate = JreCompat.isGraalAvailable();


    private boolean denyUncoveredHttpMethods;


    /**
     * The display name of this web application.
     */

    private String displayName = null;


    /**
     * Override the default context xml location.
     */

    private String defaultContextXml;


    /**
     * Override the default web xml location.
     */

    private String defaultWebXml;


    /**
     * The distributable flag for this web application.
     */

    private boolean distributable = false;


    /**
     * The document root for this web application.
     */

    private String docBase = null;


    private final ErrorPageSupport errorPageSupport = new ErrorPageSupport();

    /**
     * The set of filter configurations (and associated filter instances) we have initialized, keyed by filter name.
     */

    private Map<String,ApplicationFilterConfig> filterConfigs = new HashMap<>(); // Guarded by filterDefs


    /**
     * 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 {@link ServletContext} possibly both before and after those defined in the
     * deployment descriptor.
     */

    private final ContextFilterMaps filterMaps = new ContextFilterMaps();

    /**
     * Ignore annotations.
     */

    private boolean ignoreAnnotations = false;


    /**
     * The 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.
     */

    private LoginConfig loginConfig = null;


    /**
     * 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.
     */

    private NamingContextListener namingContextListener = null;


    /**
     * The naming resources for this web application.
     */

    private NamingResourcesImpl namingResources = null;

    /**
     * The message destinations for this web application.
     */

    private HashMap<String,MessageDestination> messageDestinations = new HashMap<>();


    /**
     * 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.
     */

    private final Map<String,String> parameters = new ConcurrentHashMap<>();


    /**
     * 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.
     */

    private String publicId = null;


    /**
     * The reloadable flag for this web application.
     */

    private boolean reloadable = false;


    /**
     * Unpack WAR property.
     */

    private boolean unpackWAR = true;


    /**
     * Context level override for default {@link StandardHost#isCopyXML()}.
     */

    private boolean copyXML = false;


    /**
     * The default context override flag for this web application.
     */

    private boolean override = false;


    /**
     * The original document root for this web application.
     */

    private String originalDocBase = null;


    /**
     * The privileged flag for this web application.
     */

    private boolean privileged = false;


    /**
     * Should the next call to <code>addWelcomeFile()</code> cause replacement of any existing welcome files? This will
     * be set before processing the web application's deployment descriptor, so that application specified choices
     * <strong>replace</strong>, rather than append to, those defined in the global descriptor.
     */

    private boolean replaceWelcomeFiles = false;


    /**
     * The security role mappings for this application, keyed by role name (as used within the application).
     */

    private Map<String,String> roleMappings = new HashMap<>();


    /**
     * The security roles for this application, keyed by role name.
     */

    private String securityRoles[] = new String[0];

    private final Object securityRolesLock = new Object();


    /**
     * The servlet mappings for this web application, keyed by matching pattern.
     */

    private Map<String,String> servletMappings = new HashMap<>();

    private final Object servletMappingsLock = new Object();


    /**
     * The session timeout (in minutes) for this web application.
     */

    private int sessionTimeout = 30;

    /**
     * The notification sequence number.
     */

    private AtomicLong sequenceNumber = new AtomicLong(0);


    /**
     * Set flag to true to cause the system.out and system.err to be redirected to the logger when executing a servlet.
     */

    private boolean swallowOutput = false;


    /**
     * Amount of ms that the container will wait for servlets to unload.
     */

    private long unloadDelay = 2000;


    /**
     * The watched resources for this application.
     */

    private String watchedResources[] = new String[0];

    private final Object watchedResourcesLock = new Object();


    /**
     * The welcome files for this application.
     */

    private String welcomeFiles[] = new String[0];

    private final Object welcomeFilesLock = new Object();


    /**
     * The set of classnames of LifecycleListeners that will be added to each newly created Wrapper by
     * <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
     * <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).
     */

    private String workDir = null;


    /**
     * Java class name of the Wrapper class implementation we use.
     */

    private String wrapperClassName = StandardWrapper.class.getName();
    private Class<?> wrapperClass = null;


    /**
     * JNDI use flag.
     */

    private boolean useNaming = true;


    /**
     * 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.
     */

    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.
     */

    private boolean webXmlValidation = Globals.STRICT_SERVLET_COMPLIANCE;


    /**
     * Attribute value used to turn on/off XML namespace validation
     */

    private boolean webXmlNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;


    /**
     * Attribute used to turn on/off the use of external entities.
     */

    private boolean xmlBlockExternal = true;


    /**
     * Attribute value used to turn on/off XML validation
     */

    private boolean tldValidation = Globals.STRICT_SERVLET_COMPLIANCE;


    /**
     * 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
     */

    private boolean useHttpOnly = true;


    /**
     * 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. <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.
     */

    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.
     */

    private JarScanner jarScanner = null;

    /**
     * Enables the RMI Target memory leak detection to be controlled. This is necessary since the detection can only
     * work 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) <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 {@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 {@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.
     */

    private boolean renewThreadsWhenStoppingContext = true;

    /**
     * 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?
     */

    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?
     */

    private boolean skipMemoryLeakChecksOnJvmShutdown = false;

    /**
     * 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 {@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}
     * <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}
     * <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}
     * <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}
     * <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}
     * <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 <code>true</code> to allow requests mapped to servlets that do not explicitly declare @MultipartConfig or
     * have <multipart-config> specified in web.xml to parse multipart/form-data requests.
     *
     * @param allowCasualMultipartParsing <code>true</code> to allow such casual parsing, <code>false</code> otherwise.
     */

    @Override
    public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing) {
        this.allowCasualMultipartParsing = allowCasualMultipartParsing;
    }

    /**
     * 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 <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 <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.
     *
     * @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.
     *
     * @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.
     *
     * @param delegate The new flag
     */

    public void setDelegate(boolean delegate) {

        boolean oldDelegate = this.delegate;
        this.delegate = delegate;
        support.firePropertyChange("delegate", oldDelegate, this.delegate);

    }


    /**
     * @return true if the internal naming support is used.
     */

    public boolean isUseNaming() {
        return useNaming;
    }


    /**
     * 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.
     */

    @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.
     *
     * @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.
     *
     * @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.
     *
     * @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;
    }


    /**
     * @return the antiResourceLocking flag for this Context.
     */

    public boolean getAntiResourceLocking() {
        return this.antiResourceLocking;
    }


    /**
     * 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
    @Deprecated
    public boolean getUseBloomFilterForArchives() {
        return this.useBloomFilterForArchives;
    }


    @Override
    @Deprecated
    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 getParallelAnnotationScanning() {
        return this.parallelAnnotationScanning;
    }


    /**
     * @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.
     *
     * @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.
     *
     * @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.
     *
     * @param cookies The new flag
     */

    @Override
    public void setCookies(boolean cookies) {

        boolean oldCookies = this.cookies;
        this.cookies = cookies;
        support.firePropertyChange("cookies", oldCookies, this.cookies);

    }


    /**
     * Gets the name to use for session cookies. Overrides any setting that may be specified by the application.
     *
     * @return The value of the default session cookie name or null if not specified
     */

    @Override
    public String getSessionCookieName() {
        return sessionCookieName;
    }


    /**
     * Sets the name to use for session cookies. Overrides any setting that may be specified by the application.
     *
     * @param sessionCookieName The name to use
     */

    @Override
    public void setSessionCookieName(String sessionCookieName) {
        String oldSessionCookieName = this.sessionCookieName;
        this.sessionCookieName = sessionCookieName;
        support.firePropertyChange("sessionCookieName", oldSessionCookieName, sessionCookieName);
    }


    /**
     * Gets the value of the use HttpOnly cookies for session cookies flag.
     *
     * @return <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.
     *
     * @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.
     *
     * @return The value of the default session cookie domain or null if not specified
     */

    @Override
    public String getSessionCookieDomain() {
        return sessionCookieDomain;
    }


    /**
     * Sets the domain to use for session cookies. Overrides any setting that may be specified by the application.
     *
     * @param sessionCookieDomain The domain to use
     */

    @Override
    public void setSessionCookieDomain(String sessionCookieDomain) {
        String oldSessionCookieDomain = this.sessionCookieDomain;
        this.sessionCookieDomain = sessionCookieDomain;
        support.firePropertyChange("sessionCookieDomain", oldSessionCookieDomain, sessionCookieDomain);
    }


    /**
     * Gets the path to use for session cookies. Overrides any setting that may be specified by the application.
     *
     * @return The value of the default session cookie path or null if not specified
     */

    @Override
    public String getSessionCookiePath() {
        return sessionCookiePath;
    }


    /**
     * Sets the path to use for session cookies. Overrides any setting that may be specified by the application.
     *
     * @param sessionCookiePath The path to use
     */

    @Override
    public void setSessionCookiePath(String sessionCookiePath) {
        String oldSessionCookiePath = this.sessionCookiePath;
        this.sessionCookiePath = sessionCookiePath;
        support.firePropertyChange("sessionCookiePath", oldSessionCookiePath, sessionCookiePath);
    }


    @Override
    public boolean getSessionCookiePathUsesTrailingSlash() {
        return sessionCookiePathUsesTrailingSlash;
    }


    @Override
    public void setSessionCookiePathUsesTrailingSlash(boolean sessionCookiePathUsesTrailingSlash) {
        this.sessionCookiePathUsesTrailingSlash = sessionCookiePathUsesTrailingSlash;
    }


    @Override
    public boolean getCrossContext() {
        return this.crossContext;
    }


    /**
     * Set the "allow crossing servlet contexts" flag.
     *
     * @param crossContext The new cross contexts flag
     */

    @Override
    public void setCrossContext(boolean crossContext) {

        boolean oldCrossContext = this.crossContext;
        this.crossContext = crossContext;
        support.firePropertyChange("crossContext", oldCrossContext, this.crossContext);

    }

    public String getDefaultContextXml() {
        return defaultContextXml;
    }

    /**
     * Set the location of the default context xml that will be used. If not absolute, it'll be made relative to the
     * engine's base dir ( which defaults to catalina.base system property ).
     *
     * @param defaultContextXml The default web xml
     */

    public void setDefaultContextXml(String defaultContextXml) {
        this.defaultContextXml = defaultContextXml;
    }

    public String getDefaultWebXml() {
        return defaultWebXml;
    }

    /**
     * Set the location of the default web xml that will be used. If not absolute, it'll be made relative to the
     * engine's base dir ( which defaults to catalina.base system property ).
     *
     * @param defaultWebXml The default web xml
     */

    public void setDefaultWebXml(String defaultWebXml) {
        this.defaultWebXml = defaultWebXml;
    }

    /**
     * Gets the time (in milliseconds) it took to start this context.
     *
     * @return Time (in milliseconds) it took to start this context.
     */

    public long getStartupTime() {
        return startupTime;
    }

    public void setStartupTime(long startupTime) {
        this.startupTime = startupTime;
    }

    public long getTldScanTime() {
        return tldScanTime;
    }

    public void setTldScanTime(long tldScanTime) {
        this.tldScanTime = tldScanTime;
    }


    @Override
    public boolean getDenyUncoveredHttpMethods() {
        return denyUncoveredHttpMethods;
    }


    @Override
    public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) {
        this.denyUncoveredHttpMethods = denyUncoveredHttpMethods;
    }


    /**
     * @return the display name of this web application.
     */

    @Override
    public String getDisplayName() {
        return this.displayName;
    }


    /**
     * @return the alternate Deployment Descriptor name.
     */

    @Override
    public String getAltDDName() {
        return altDDName;
    }


    /**
     * Set an alternate Deployment Descriptor name.
     *
     * @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.
     *
     * @param displayName The new display name
     */

    @Override
    public void setDisplayName(String displayName) {

        String oldDisplayName = this.displayName;
        this.displayName = displayName;
        support.firePropertyChange("displayName", oldDisplayName, this.displayName);
    }


    /**
     * @return the distributable flag for this web application.
     */

    @Override
    public boolean getDistributable() {
        return this.distributable;
    }

    /**
     * Set the distributable flag for this web application.
     *
     * @param distributable The new distributable flag
     */

    @Override
    public void setDistributable(boolean distributable) {
        boolean oldDistributable = this.distributable;
        this.distributable = distributable;
        support.firePropertyChange("distributable", oldDistributable, this.distributable);
    }


    @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);
    }


    /**
     * @return the boolean on the annotations parsing.
     */

    @Override
    public boolean getIgnoreAnnotations() {
        return this.ignoreAnnotations;
    }


    /**
     * Set the boolean on the annotations parsing for this web application.
     *
     * @param ignoreAnnotations The boolean on the annotations parsing
     */

    @Override
    public void setIgnoreAnnotations(boolean ignoreAnnotations) {
        boolean oldIgnoreAnnotations = this.ignoreAnnotations;
        this.ignoreAnnotations = ignoreAnnotations;
        support.firePropertyChange("ignoreAnnotations", oldIgnoreAnnotations, this.ignoreAnnotations);
    }


    /**
     * @return the login configuration descriptor for this web application.
     */

    @Override
    public LoginConfig getLoginConfig() {
        return this.loginConfig;
    }


    /**
     * Set the login configuration descriptor for this web application.
     *
     * @param config The new login configuration
     */

    @Override
    public void setLoginConfig(LoginConfig config) {

        // Validate the incoming property value
        if (config == null) {
            throw new IllegalArgumentException(sm.getString("standardContext.loginConfig.required"));
        }
        String loginPage = config.getLoginPage();
        if ((loginPage != null) && !loginPage.startsWith("/")) {
            if (isServlet22()) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("standardContext.loginConfig.loginWarning", loginPage));
                }
                config.setLoginPage("/" + loginPage);
            } else {
                throw new IllegalArgumentException(sm.getString("standardContext.loginConfig.loginPage", loginPage));
            }
        }
        String errorPage = config.getErrorPage();
        if ((errorPage != null) && !errorPage.startsWith("/")) {
            if (isServlet22()) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("standardContext.loginConfig.errorWarning", errorPage));
                }
                config.setErrorPage("/" + errorPage);
            } else {
                throw new IllegalArgumentException(sm.getString("standardContext.loginConfig.errorPage", errorPage));
            }
        }

        // Process the property setting change
        LoginConfig oldLoginConfig = this.loginConfig;
        this.loginConfig = config;
        support.firePropertyChange("loginConfig", oldLoginConfig, this.loginConfig);

    }


    /**
     * @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.
     *
     * @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);
            }
        }
    }


    /**
     * @return the context path for this Context.
     */

    @Override
    public String getPath() {
        return path;
    }


    /**
     * Set the context path for this Context.
     *
     * @param path The new context path
     */

    @Override
    public void setPath(String path) {
        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);
        }
    }


    /**
     * @return the public identifier of the deployment descriptor DTD that is currently being parsed.
     */

    @Override
    public String getPublicId() {
        return this.publicId;
    }


    /**
     * Set the public identifier of the deployment descriptor DTD that is currently being parsed.
     *
     * @param publicId The public identifier
     */

    @Override
    public void setPublicId(String publicId) {

        if (log.isDebugEnabled()) {
            log.debug("Setting deployment descriptor public ID to '" + publicId + "'");
        }

        String oldPublicId = this.publicId;
        this.publicId = publicId;
        support.firePropertyChange("publicId", oldPublicId, publicId);

    }


    /**
     * @return the reloadable flag for this web application.
     */

    @Override
    public boolean getReloadable() {
        return this.reloadable;
    }


    /**
     * @return the default context override flag for this web application.
     */

    @Override
    public boolean getOverride() {
        return this.override;
    }


    /**
     * @return the original document root for this Context. This can be an absolute pathname, a relative pathname, or a
     *             URL. Is only set as deployment has change docRoot!
     */

    public String getOriginalDocBase() {
        return this.originalDocBase;
    }

    /**
     * Set the original document root for this Context. This can be an absolute pathname, a relative pathname, or a URL.
     *
     * @param docBase The original document root
     */

    public void setOriginalDocBase(String docBase) {

        this.originalDocBase = docBase;
    }


    /**
     * @return the parent class loader (if any) for this web application. This call is meaningful only
     *             <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();
    }


    /**
     * @return the privileged flag for this web application.
     */

    @Override
    public boolean getPrivileged() {
        return this.privileged;
    }


    /**
     * Set the privileged flag for this web application.
     *
     * @param privileged The new privileged flag
     */

    @Override
    public void setPrivileged(boolean privileged) {

        boolean oldPrivileged = this.privileged;
        this.privileged = privileged;
        support.firePropertyChange("privileged", oldPrivileged, this.privileged);

    }


    /**
     * Set the reloadable flag for this web application.
     *
     * @param reloadable The new reloadable flag
     */

    @Override
    public void setReloadable(boolean reloadable) {

        boolean oldReloadable = this.reloadable;
        this.reloadable = reloadable;
        support.firePropertyChange("reloadable", oldReloadable, this.reloadable);

    }


    /**
     * Set the default context override flag for this web application.
     *
     * @param override The new override flag
     */

    @Override
    public void setOverride(boolean override) {

        boolean oldOverride = this.override;
        this.override = override;
        support.firePropertyChange("override", oldOverride, this.override);

    }


    /**
     * 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);

    }


--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=93 H=97 G=94

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.