alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (StandardContext.java)

This example Glassfish source code file (StandardContext.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

arraylist, container, exception, file, http, illegalargumentexception, illegalargumentexception, lifecycle, lifecycle, lifecycleexception, list, list, net, network, override, request, response, servlet, string, string

The Glassfish StandardContext.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.catalina.core;

import com.sun.grizzly.util.buf.CharChunk;
import com.sun.grizzly.util.buf.MessageBytes;
import com.sun.grizzly.util.http.mapper.AlternateDocBase;
import com.sun.grizzly.util.http.mapper.Mapper;
import com.sun.grizzly.util.http.mapper.MappingData;
import org.apache.catalina.*;
import org.apache.catalina.deploy.*;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.mbeans.MBeanUtils;
import org.apache.catalina.session.ManagerBase;
import org.apache.catalina.session.PersistentManagerBase;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.util.*;
import org.apache.naming.ContextBindings;
import org.apache.naming.resources.BaseDirContext;
import org.apache.naming.resources.DirContextURLStreamHandler;
import org.apache.naming.resources.FileDirContext;
import org.apache.naming.resources.ProxyDirContext;
import org.apache.naming.resources.Resource;
import org.apache.naming.resources.WARDirContext;
import org.apache.tomcat.util.modeler.ManagedBean;
import org.apache.tomcat.util.modeler.Registry;
import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.web.loader.WebappClassLoader;
import org.glassfish.web.loader.ServletContainerInitializerUtil;
import org.glassfish.web.valve.GlassFishValve;

import javax.management.*;
import javax.naming.Binding;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.servlet.*;
import javax.servlet.descriptor.JspConfigDescriptor;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionListener;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URLDecoder;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Standard implementation of the <b>Context interface.  Each
 * child container must be a Wrapper implementation to process the
 * requests directed to a particular servlet.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @version $Revision: 1.48 $ $Date: 2007/07/25 00:52:04 $
 */

public class StandardContext
    extends ContainerBase
    implements Context, Serializable, ServletContext
{
    private static final transient Logger log = Logger.getLogger(
        StandardContext.class.getName());

    private static final ClassLoader standardContextClassLoader =
        StandardContext.class.getClassLoader();

    private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES =
        EnumSet.of(SessionTrackingMode.COOKIE);

    /**
     * Array containing the safe characters set.
     */
    protected static final URLEncoder urlEncoder;

    /**
     * The descriptive information string for this implementation.
     */
    private static final String info =
        "org.apache.catalina.core.StandardContext/1.0";

    private static final RuntimePermission GET_CLASSLOADER_PERMISSION =
        new RuntimePermission("getClassLoader");

    /**
     * GMT timezone - all HTTP dates are on GMT
     */
    static {
        urlEncoder = new URLEncoder();
        urlEncoder.addSafeCharacter('~');
        urlEncoder.addSafeCharacter('-');
        urlEncoder.addSafeCharacter('_');
        urlEncoder.addSafeCharacter('.');
        urlEncoder.addSafeCharacter('*');
        urlEncoder.addSafeCharacter('/');
    }


    // ----------------------------------------------------------- Constructors

    /**
     * Create a new StandardContext component with the default basic Valve.
     */
    public StandardContext() {
        pipeline.setBasic(new StandardContextValve());
        namingResources.setContainer(this);
        broadcaster = new NotificationBroadcasterSupport();
        if (Globals.IS_SECURITY_ENABLED) {
            mySecurityManager = (MySecurityManager)AccessController.doPrivileged(
                    new PrivilegedCreateSecurityManager());
        }
        
        //START PWC 6403328
        this.logPrefix = sm.getString("standardContext.logPrefix", logName());
        //END PWC 6403328
    }

    // ----------------------------------------------------- Instance Variables

    /**
     * The alternate deployment descriptor name.
     */
    private String altDDName = null;

    /**
     * Associated host name.
     */
    private String hostName;
    
    /**
     * The list of instantiated application event listeners
     */
    private transient List<EventListener> eventListeners =
        new ArrayList<EventListener>();

    /**
     * The list of ServletContextListeners
     */
    protected transient ArrayList<ServletContextListener> contextListeners =
        new ArrayList<ServletContextListener>();

    /**
     * The list of HttpSessionListeners
     */
    private transient List<HttpSessionListener> sessionListeners =
        new ArrayList<HttpSessionListener>();

    /**
     * The set of application parameters defined for this application.
     */
    private List<ApplicationParameter> applicationParameters =
        new ArrayList<ApplicationParameter>();

    /**
     * The application available flag for this Context.
     */
    private boolean available = false;

    /**
     * The broadcaster that sends j2ee notifications.
     */
    private transient NotificationBroadcasterSupport broadcaster = null;

    /**
     * The Locale to character set mapper for this application.
     */
    private transient CharsetMapper charsetMapper = null;

    /**
     * The Java class name of the CharsetMapper class to be created.
     */
    private String charsetMapperClass = CharsetMapper.class.getName();

    /**
     * The path to a file to save this Context information.
     */
    private String configFile = null;

    /**
     * The "correctly configured" flag for this Context.
     */
    private boolean configured = false;

    /**
     * The security constraints for this web application.
     */
    private List<SecurityConstraint> constraints =
        new ArrayList<SecurityConstraint>();

    /**
     * The ServletContext implementation associated with this Context.
     */
    // START RIMOD 4894300
    /*
    private transient ApplicationContext context = null;
    */
    protected transient ApplicationContext context = null;
    // END RIMOD 4894300

    /**
     *  Is the context initialized. 
     */
    private boolean isContextInitializedCalled = false;

    /**
     * Compiler classpath to use.
     */
    private String compilerClasspath = null;

    /**
     * Should we attempt to use cookies for session id communication?
     */
    private boolean cookies = true;

    /**
     * true if the rewriting of URLs with the jsessionids of HTTP
     * sessions belonging to this context is enabled, false otherwise
     */
    private boolean enableURLRewriting = true;

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

    /**
     * The "follow standard delegation model" flag that will be used to
     * configure our ClassLoader.
     */
    private boolean delegate = false;

    /**
     * The display name of this web application.
     */
    private String displayName = null;

    /**
     * Override the default web xml location. ContextConfig is not configurable
     * so the setter is not used.
     */
    private String defaultWebXml;

    /**
     * The distributable flag for this web application.
     */
    private boolean distributable = false;
    
    /**
     * Thread local data used during request dispatch.
     */
    private transient ThreadLocal<DispatchData> dispatchData =
        new ThreadLocal<DispatchData>();
        
    /**
     * The document root for this web application.
     */
    private String docBase = null;

    /**
     * The exception pages for this web application, keyed by fully qualified
     * class name of the Java exception.
     */
    private Map<String, ErrorPage> exceptionPages =
        new HashMap<String, ErrorPage>();

    /**
     * The default error page (error page that was declared
     * without any exception-type and error-code).
     */
    private ErrorPage defaultErrorPage;

    /**
     * The set of filter configurations (and associated filter instances) we
     * have initialized, keyed by filter name.
     */
    private Map<String, FilterConfig> filterConfigs =
        new HashMap<String, FilterConfig>();

    /**
     * The set of filter definitions for this application, keyed by
     * filter name.
     */
    private Map<String, FilterDef> filterDefs = new HashMap();

    /**
     * The list of filter mappings for this application, in the order
     * they were defined in the deployment descriptor.
     */
    private List<FilterMap> filterMaps = new ArrayList();

    /**
     * The list of classnames of InstanceListeners that will be added
     * to each newly created Wrapper by <code>createWrapper().
     */
    private ArrayList<String> instanceListeners = new ArrayList();

    /**
     * The set of already instantiated InstanceListeners that will be added
     * to each newly created Wrapper by <code>createWrapper().
     */
    private List<InstanceListener> instanceListenerInstances = new ArrayList();

    /**
     * The login configuration descriptor for this web application.
     */
    private LoginConfig loginConfig = null;
    
    // START PWC 6403328
    /**
     * Log prefix string
     */
    private String logPrefix = null;
    // END PWC 6403328
    
    /**
     * The mapper associated with this context.
     */
    private transient Mapper mapper = new Mapper();

    /**
     * The naming context listener for this web application.
     */
    private transient NamingContextListener namingContextListener = null;

    /**
     * The naming resources for this web application.
     */
    private NamingResources namingResources = new NamingResources();

    /**
     * The message destinations for this web application.
     */
    private Map<String, MessageDestination> messageDestinations = new HashMap();

    /**
     * The MIME mappings for this web application, keyed by extension.
     */
    private HashMap<String,String> mimeMappings = new HashMap();

    /**
     * The context initialization parameters for this web application,
     * keyed by name.
     */
    private HashMap<String, String> parameters = new HashMap();

    /**
     * The request processing pause flag (while reloading occurs)
     */
    private boolean paused = false;

    /**
     * The public identifier of the DTD for the web application deployment
     * descriptor version we are currently parsing.  This is used to support
     * relaxed validation rules when processing version 2.2 web.xml files.
     */
    private String publicId = null;

    /**
     * The reloadable flag for this web application.
     */
    private boolean reloadable = false;

    /**
     * Unpack WAR property.
     */
    private boolean unpackWAR = true;

    /**
     * The DefaultContext override flag for this web application.
     */
    private boolean override = false;
       
    /**
     * The 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() 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, rather than append to, those defined
     * in the global descriptor.
     */
    private boolean replaceWelcomeFiles = false;

    /**
     * With proxy caching disabled, setting this flag to true adds
     * Pragma and Cache-Control headers with "No-cache" as value.
     * Setting this flag to false does not add any Pragma header,
     * but sets the Cache-Control header to "private".
     */
    private boolean securePagesWithPragma = true;

    /**
     * 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
     */
    private List<String> securityRoles = new ArrayList();

    /**
     * The servlet mappings for this web application, keyed by
     * matching pattern.
     */
    private final Map<String, String> servletMappings = new HashMap();

    /**
     * The session timeout (in minutes) for this web application.
     */
    private int sessionTimeout = 30;

    /**
     * Has the session timeout (in minutes) for this web application
     * been over-ridden by web-xml
     * HERCULES:add
     */
    private boolean sessionTimeoutOveridden = false;

    /**
     * The notification sequence number.
     */
    private long sequenceNumber = 0;

    /**
     * The status code error pages for this web application, keyed by
     * HTTP status code (as an Integer).
     */
    private final Map<Integer, ErrorPage> statusPages =
        new HashMap<Integer, ErrorPage>();

    /**
     * The watched resources for this application.
     */
    private List<String> watchedResources =
            Collections.synchronizedList(new ArrayList<String>());

    /**
     * The welcome files for this application.
     */
    private String[] welcomeFiles = new String[0];

    /**
     * The list of classnames of LifecycleListeners that will be added
     * to each newly created Wrapper by <code>createWrapper().
     */
    private ArrayList<String> wrapperLifecycles = new ArrayList();

    /**
     * The list of classnames of ContainerListeners that will be added
     * to each newly created Wrapper by <code>createWrapper().
     */
    private List<String> wrapperListeners = new ArrayList();

    /**
     * The pathname to the work directory for this context (relative to
     * the server's home if not absolute).
     */
    private String workDir = null;

    /**
     * JNDI use flag.
     */
    private boolean useNaming = true;

    /**
     * Filesystem based flag.
     */
    private boolean filesystemBased = false;

    /**
     * Name of the associated naming context.
     */
    private String namingContextName = null;

    /**
     * Frequency of the session expiration, and related manager operations.
     * Manager operations will be done once for the specified amount of
     * backgrondProcess calls (ie, the lower the amount, the most often the
     * checks will occur).
     */
    private int managerChecksFrequency = 6;

    /**
     * Iteration count for background processing.
     */
    private int count = 0;

    /**
     * Caching allowed flag.
     */
    private boolean cachingAllowed = true;

    /**
     * Case sensitivity.
     */
    protected boolean caseSensitive = true;

    /**
     * Allow linking.
     */
    protected boolean allowLinking = false;

    /**
     * Cache max size in KB.
     */
    protected int cacheMaxSize = 10240; // 10 MB

    /**
     * Cache TTL in ms.
     */
    protected int cacheTTL = 5000;

    /**
     * Non proxied resources.
     */
    private transient DirContext webappResources = null;

    /*
     * Time (in milliseconds) it took to start this context
     */
    private long startupTime;

    /*
     * Time (in milliseconds since January 1, 1970, 00:00:00) when this
     * context was started
     */
    private long startTimeMillis;

    private long tldScanTime;

    // START SJSWS 6324431
    // Should the filter and security mapping be done
    // in a case sensitive manner
    protected boolean caseSensitiveMapping = true;
    // END SJSWS 6324431

    // START S1AS8PE 4817642
    /**
     * The flag that specifies whether to reuse the session id (if any) from
     * the request for newly created sessions
     */
    private boolean reuseSessionID = false;
    // END S1AS8PE 4817642

    // START RIMOD 4642650
    /**
     * The flag that specifies whether this context allows sendRedirect() to
     * redirect to a relative URL.
     */
    private boolean allowRelativeRedirect = false;

    // END RIMOD 4642650

    /** Name of the engine. If null, the domain is used.
     */
    private String engineName = null;
    /* SJSAS 6340499
    private String j2EEApplication="none";
     */
    // START SJSAS 6340499
    private String j2EEApplication="null";
    // END SJSAS 6340499
    private String j2EEServer="none";

    // START IASRI 4823322
    /**
     * List of configured Auditors for this context.
     */
    private transient Auditor[] auditors = null;
    // END IASRI 4823322

    // START RIMOD 4868393
    /**
     * used to create unique id for each app instance.
     */
    private static int instanceIDCounter = 1;
    // END RIMOD 4868393

    /**
     * Attribute value used to turn on/off XML validation
     */
    private boolean webXmlValidation = false;

    private String jvmRoute;

    /**
     * Attribute value used to turn on/off XML namespace validation
     */
    private boolean webXmlNamespaceAware = false;

    /**
     * Attribute value used to turn on/off XML validation
     */
    private boolean tldValidation = false;

    /**
     * Attribute value used to turn on/off TLD XML namespace validation
     */
    private boolean tldNamespaceAware = false;

    /**
     * Is the context contains the JSF servlet.
     */
    protected boolean isJsfApplication = false;

    // START S1AS8PE 4965017
    private boolean isReload = false;
    // END S1AS8PE 4965017

    /**
     * Alternate doc base resources
     */
    private ArrayList<AlternateDocBase> alternateDocBases = null;

    private boolean useMyFaces;

    private Set<SessionTrackingMode> sessionTrackingModes;

    /**
     * Encoded path.
     */
    private String encodedPath = null;

    /**
     * Session cookie config
     */
    private SessionCookieConfig sessionCookieConfig;

    /**
     * The name of the session tracking cookies created by this context
     * Cache the name here as the getSessionCookieConfig() is synchronized.
     */
    private String sessionCookieName = Globals.SESSION_COOKIE_NAME;

    private boolean sessionCookieNameInitialized = false;

    protected ConcurrentHashMap<String, ServletRegistrationImpl> servletRegisMap =
        new ConcurrentHashMap<String, ServletRegistrationImpl>();

    private ConcurrentHashMap<String, FilterRegistrationImpl> filterRegisMap =
        new ConcurrentHashMap<String, FilterRegistrationImpl>();

    private Map<String, String> jarName2WebFragNameMap;

    private List absoluteOrderingList;

    /**
     * The list of ordered libs, which is used as the value of the
     * ServletContext attribute with name javax.servlet.context.orderedLibs
     */
    private List<String> orderedLibs;

    // <jsp-config> related info aggregated from web.xml and web-fragment.xml
    private JspConfigDescriptor jspConfigDesc;

    // ServletContextListeners may be registered (via
    // ServletContext#addListener) only within the scope of
    // ServletContainerInitializer#onStartup
    private boolean isProgrammaticServletContextListenerRegistrationAllowed = false;

    /*
     * Security manager responsible for enforcing permission check on
     * ServletContext#getClassLoader
     */
    private transient MySecurityManager mySecurityManager;

    // Iterable over all ServletContainerInitializers that were discovered
    private Iterable<ServletContainerInitializer> servletContainerInitializers = null;

    // The major Servlet spec version of the web.xml
    private int effectiveMajorVersion = 0;

    // The minor Servlet spec version of the web.xml
    private int effectiveMinorVersion = 0;

    // ----------------------------------------------------- Context Properties

    public String getEncodedPath() {
        return encodedPath;
    }

    @Override
    public void setName( String name ) {
        super.setName( name );
        encodedPath = urlEncoder.encode(name);
    }

    /**
     * Is caching allowed ?
     */
    public boolean isCachingAllowed() {
        return cachingAllowed;
    }

    /**
     * Set caching allowed flag.
     */
    public void setCachingAllowed(boolean cachingAllowed) {
        this.cachingAllowed = cachingAllowed;
    }

    /**
     * Set case sensitivity.
     */
    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    /**
     * Is case sensitive ?
     */
    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    // START SJSWS 6324431
    /**
     * Set case sensitivity for filter and security constraint mappings.
     */
    public void setCaseSensitiveMapping(boolean caseSensitiveMap) {
        caseSensitiveMapping = caseSensitiveMap;
    }

    /**
     * Are filters and security constraints mapped in a case sensitive manner?
     */
    public boolean isCaseSensitiveMapping() {
        return caseSensitiveMapping;
    }
    // END SJSWS 6324431

    /**
     * Set allow linking.
     */
    public void setAllowLinking(boolean allowLinking) {
        this.allowLinking = allowLinking;
    }

    /**
     * Is linking allowed.
     */
    public boolean isAllowLinking() {
        return allowLinking;
    }

    /**
     * Set cache TTL.
     */
    public void setCacheTTL(int cacheTTL) {
        this.cacheTTL = cacheTTL;
    }

    /**
     * Get cache TTL.
     */
    public int getCacheTTL() {
        return cacheTTL;
    }

    /**
     * Return the maximum size of the cache in KB.
     */
    public int getCacheMaxSize() {
        return cacheMaxSize;
    }

    /**
     * Set the maximum size of the cache in KB.
     */
    public void setCacheMaxSize(int cacheMaxSize) {
        this.cacheMaxSize = cacheMaxSize;
    }

    /**
     * Return the "follow standard delegation model" flag used to configure
     * our ClassLoader.
     */
    public boolean getDelegate() {
        return 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", Boolean.valueOf(oldDelegate),
                                   Boolean.valueOf(this.delegate));
    }

    /**
     * Returns true if the internal naming support is used.
     */
    public boolean isUseNaming() {
        return useNaming;
    }

    /**
     * Enables or disables naming.
     */
    public void setUseNaming(boolean useNaming) {
        this.useNaming = useNaming;
    }

    /**
     * @return true if the resources associated with this context are
     * filesystem based, false otherwise
     */
    public boolean isFilesystemBased() {
        return filesystemBased;
    }

    /**
     * @return the list of initialized application event listeners
     * of this application, in the order in which they have been specified
     * in the deployment descriptor
     */
    public List<EventListener> getApplicationEventListeners() {
        return eventListeners;
    }
    
    public List<HttpSessionListener> getSessionListeners() {
        return sessionListeners;
    }
    
    /**
     * Return the application available flag for this Context.
     */
    public boolean getAvailable() {
        return available;
    }

    /**
     * Set the application available flag for this Context.
     *
     * @param available The new application available flag
     */
    public void setAvailable(boolean available) {
        boolean oldAvailable = this.available;
        this.available = available;
        support.firePropertyChange("available", Boolean.valueOf(oldAvailable),
            Boolean.valueOf(this.available));
    }

    /**
     * Return the Locale to character set mapper for this Context.
     */
    public CharsetMapper getCharsetMapper() {

        // Create a mapper the first time it is requested
        if (this.charsetMapper == null) {
            try {
                Class clazz = Class.forName(charsetMapperClass);
                this.charsetMapper =
                  (CharsetMapper) clazz.newInstance();
            } catch (Throwable t) {
                this.charsetMapper = new CharsetMapper();
            }
        }

        return (this.charsetMapper);
    }

    /**
     * Set the Locale to character set mapper for this Context.
     *
     * @param mapper The new mapper
     */
    public void setCharsetMapper(CharsetMapper mapper) {
        CharsetMapper oldCharsetMapper = this.charsetMapper;
        this.charsetMapper = mapper;
        if( mapper != null )
            this.charsetMapperClass= mapper.getClass().getName();
        support.firePropertyChange("charsetMapper", oldCharsetMapper,
                                   this.charsetMapper);
    }

    /**
     * @return the path to a file to save this Context information
     */
    public String getConfigFile() {
        return configFile;
    }

    /**
     * Set the path to a file to save this Context information.
     *
     * @param configFile The path to a file to save this Context information
     */
    public void setConfigFile(String configFile) {
        this.configFile = configFile;
    }

    /**
     * @return the "correctly configured" flag for this Context
     */
    public boolean getConfigured() {
        return configured;
    }

    /**
     * Sets the "correctly configured" flag for this Context.  This can be
     * set to false by startup listeners that detect a fatal configuration
     * error to avoid the application from being made available.
     *
     * @param configured The new correctly configured flag
     */
    public void setConfigured(boolean configured) {
        boolean oldConfigured = this.configured;
        this.configured = configured;
        support.firePropertyChange("configured",
            Boolean.valueOf(oldConfigured), Boolean.valueOf(this.configured));
    }

    /**
     * @return the "use cookies for session ids" flag
     */
    public boolean getCookies() {
        return cookies;
    }

    /**
     * Set the "use cookies for session ids" flag.
     *
     * @param cookies The new flag
     */
    public void setCookies(boolean cookies) {
        boolean oldCookies = this.cookies;
        this.cookies = cookies;
        support.firePropertyChange("cookies",
                                   Boolean.valueOf(oldCookies),
                                   Boolean.valueOf(this.cookies));
    }

    /**
     * Checks whether the rewriting of URLs with the jsessionids of
     * HTTP sessions belonging to this context is enabled or not.
     *
     * @return true if the rewriting of URLs with the jsessionids of HTTP
     * sessions belonging to this context is enabled, false otherwise
     */
    public boolean isEnableURLRewriting() {
        return enableURLRewriting;
    }

    /**
     * Enables or disables the rewriting of URLs with the jsessionids of
     * HTTP sessions belonging to this context.
     *
     * @param enableURLRewriting true if the rewriting of URLs with the
     * jsessionids of HTTP sessions belonging to this context should be
     * enabled, false otherwise
     */
    public void setEnableURLRewriting(boolean enableURLRewriting) {
        boolean oldEnableURLRewriting = this.enableURLRewriting;
        this.enableURLRewriting = enableURLRewriting;
        support.firePropertyChange("enableURLRewriting",
                                   Boolean.valueOf(oldEnableURLRewriting),
                                   Boolean.valueOf(this.enableURLRewriting));
    }


    /**
     * @return the "allow crossing servlet contexts" flag
     */
    public boolean getCrossContext() {
        return (this.crossContext);
    }

    /**
     * Sets the "allow crossing servlet contexts" flag.
     *
     * @param crossContext The new cross contexts flag
     */
    public void setCrossContext(boolean crossContext) {

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

    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 ).
     *
     * XXX  If a file is not found - we can attempt a getResource()
     *
     * @param defaultWebXml
     */
    public void setDefaultWebXml(String defaultWebXml) {
        this.defaultWebXml = defaultWebXml;
    }

    /**
     * Gets the time (in milliseconds) it took to start this context.
     *
     * @return Time (in milliseconds) it took to start this context.
     */
    public long getStartupTime() {
        return startupTime;
    }

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

    public long getTldScanTime() {
        return tldScanTime;
    }

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

    /**
     * Return the display name of this web application.
     */
    public String getDisplayName() {

        return (this.displayName);

    }

    /**
     * Return the alternate Deployment Descriptor name.
     */
    public String getAltDDName(){
        return altDDName;
    }

    /**
     * Set an alternate Deployment Descriptor name.
     */
    public void setAltDDName(String altDDName) {
        this.altDDName = altDDName;
        if (context != null) {
            context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
            context.setAttributeReadOnly(Globals.ALT_DD_ATTR);
        }
    }

    /**
     * Return the compiler classpath.
     */
    public String getCompilerClasspath(){
        return compilerClasspath;
    }

    /**
     * Set the compiler classpath.
     */
    public void setCompilerClasspath(String compilerClasspath) {
        this.compilerClasspath = compilerClasspath;
    }

    /**
     * Set the display name of this web application.
     *
     * @param displayName The new display name
     */
    public void setDisplayName(String displayName) {
        String oldDisplayName = this.displayName;
        this.displayName = displayName;
        support.firePropertyChange("displayName", oldDisplayName,
                                   this.displayName);
    }

    /**
     * Return the distributable flag for this web application.
     */
    public boolean getDistributable() {
        return distributable;
    }

    /**
     * Set the distributable flag for this web application.
     *
     * @param distributable The new distributable flag
     */
    public void setDistributable(boolean distributable) {
        boolean oldDistributable = this.distributable;
        this.distributable = distributable;
        support.firePropertyChange("distributable",
                                   Boolean.valueOf(oldDistributable),
                                   Boolean.valueOf(this.distributable));

        // Bugzilla 32866
        if(getManager() != null) {
            if(log.isLoggable(Level.FINE)) {
                log.fine("Propagating distributable=" + distributable
                         + " to manager");
            }
            getManager().setDistributable(distributable);
        }
    }

    /**
     * Return the document root for this Context.  This can be an absolute
     * pathname, a relative pathname, or a URL.
     */
    public String getDocBase() {
        return docBase;
    }

    /**
     * Set the document root for this Context.  This can be an absolute
     * pathname, a relative pathname, or a URL.
     *
     * @param docBase The new document root
     */
    public void setDocBase(String docBase) {
        this.docBase = docBase;
    }

    /**
     * Configures this context's alternate doc base mappings.
     *
     * @param urlPattern
     * @param docBase
     */
    public void addAlternateDocBase(String urlPattern, String docBase) {

        if (urlPattern == null || docBase == null) {
            throw new IllegalArgumentException(
                sm.getString(
                    "standardContext.alternateDocBase.missingPathOrUrlPattern"));
        }

        AlternateDocBase alternateDocBase = new AlternateDocBase();
        alternateDocBase.setUrlPattern(urlPattern);
        alternateDocBase.setDocBase(docBase);
        alternateDocBase.setBasePath(getBasePath(docBase));

        if (alternateDocBases == null) {
            alternateDocBases = new ArrayList<AlternateDocBase>();
        }
        alternateDocBases.add(alternateDocBase);
    }

    /**
     * Gets this context's configured alternate doc bases.
     *
     * @return This context's configured alternate doc bases
     */
    public ArrayList<AlternateDocBase> getAlternateDocBases() {
        return alternateDocBases;
    }

    /**
     * Return the frequency of manager checks.
     */
    public int getManagerChecksFrequency() {
        return managerChecksFrequency;
    }

    /**
     * Set the manager checks frequency.
     *
     * @param managerChecksFrequency the new manager checks frequency
     */
    public void setManagerChecksFrequency(int managerChecksFrequency) {

        if (managerChecksFrequency <= 0) {
            return;
        }

        int oldManagerChecksFrequency = this.managerChecksFrequency;
        this.managerChecksFrequency = managerChecksFrequency;
        support.firePropertyChange("managerChecksFrequency",
            Integer.valueOf(oldManagerChecksFrequency),
            Integer.valueOf(this.managerChecksFrequency));
    }

    /**
     * Return descriptive information about this Container implementation and
     * the corresponding version number, in the format
     * <code><description>/<version>.
     */
    @Override
    public String getInfo() {
        return (info);
    }

    public void setJvmRoute(String jvmRoute) {
        this.jvmRoute = jvmRoute;
    }

    public String getJvmRoute() {
        return jvmRoute;
    }

    public String getEngineName() {
        if( engineName != null ) return engineName;
        return domain;
    }

    public void setEngineName(String engineName) {
        this.engineName = engineName;
    }

    public String getJ2EEApplication() {
        return j2EEApplication;
    }

    public void setJ2EEApplication(String j2EEApplication) {
        this.j2EEApplication = j2EEApplication;
    }

    public String getJ2EEServer() {
        return j2EEServer;
    }

    public void setJ2EEServer(String j2EEServer) {
        this.j2EEServer = j2EEServer;
    }

    /**
     * Return the login configuration descriptor for this web application.
     */
    public LoginConfig getLoginConfig() {
        return (this.loginConfig);
    }

    /**
     * Set the login configuration descriptor for this web application.
     *
     * @param config The new login configuration
     */
    public void setLoginConfig(LoginConfig config) {

        // Validate the incoming property value
        if (config == null)
            throw new IllegalArgumentException
                (sm.getString("standardContext.loginConfig.required"));
        String loginPage = config.getLoginPage();
        if ((loginPage != null) && !loginPage.startsWith("/")) {
            if (isServlet22()) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine(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.isLoggable(Level.FINE)) {
                    log.fine(sm.getString(
                        "standardContext.loginConfig.errorWarning",
                        errorPage));
                }
                config.setErrorPage("/" + errorPage);
            } else {
                throw new IllegalArgumentException
                    (sm.getString("standardContext.loginConfig.errorPage",
                                  errorPage));
            }
        }

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

    /**
     * Get the mapper associated with the context.
     */
    public Mapper getMapper() {
        return mapper;
    }

    /**
     * Sets a new pipeline
     */
    public void restrictedSetPipeline(Pipeline pl) {
        pl.setBasic(new StandardContextValve());
        pipeline = pl;
        hasCustomPipeline = true;
    }

    /**
     * Return the naming resources associated with this web application.
     */
    public NamingResources getNamingResources() {
        return namingResources;
    }

    /**
     * Set the naming resources for this web application.
     *
     * @param namingResources The new naming resources
     */
    public void setNamingResources(NamingResources namingResources) {

        // Process the property setting change
        NamingResources oldNamingResources = this.namingResources;
        this.namingResources = namingResources;
        support.firePropertyChange("namingResources",
                                   oldNamingResources, this.namingResources);
    }

    /**
     * Return the context path for this Context.
     */
    public String getPath() {
        return (getName());
    }

    /**
     * Set the context path for this Context.
     * <p>
     * <b>IMPLEMENTATION NOTE:  The context path is used as the "name" of
     * a Context, because it must be unique.
     *
     * @param path The new context path
     */
    public void setPath(String path) {
        // XXX  Use host in name
        /* GlassFish Issue 2339
        setName(RequestUtil.URLDecode(path));
         */
        // START GlassFish Issue 2339
        setName(RequestUtil.urlDecode(path, "UTF-8"));
        // END GlassFish Issue 2339
    }

    /**
     * Return the public identifier of the deployment descriptor DTD that is
     * currently being parsed.
     */
    public String getPublicId() {
        return publicId;
    }

    /**
     * Set the public identifier of the deployment descriptor DTD that is
     * currently being parsed.
     *
     * @param publicId The public identifier
     */
    public void setPublicId(String publicId) {
        if (log.isLoggable(Level.FINEST))
            log.finest("Setting deployment descriptor public ID to '" +
                       publicId + "'");

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

    /**
     * Return the reloadable flag for this web application.
     */
    public boolean getReloadable() {
        return reloadable;
    }

    /**
     * Return the DefaultContext override flag for this web application.
     */
    public boolean getOverride() {
        return override;
    }

    /**
     * Gets the original document root for this Context, which 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, which 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 privileged flag for this web application.
     */
    public boolean getPrivileged() {
        return (this.privileged);
    }

    /**
     * Set the privileged flag for this web application.
     *
     * @param privileged The new privileged flag
     */
    public void setPrivileged(boolean privileged) {
        boolean oldPrivileged = this.privileged;
        this.privileged = privileged;
        support.firePropertyChange("privileged",
                                   Boolean.valueOf(oldPrivileged),
                                   Boolean.valueOf(this.privileged));
    }

    /**
     * Set the reloadable flag for this web application.
     *
     * @param reloadable The new reloadable flag
     */
    public void setReloadable(boolean reloadable) {
        boolean oldReloadable = this.reloadable;
        this.reloadable = reloadable;
        support.firePropertyChange("reloadable",
                                   Boolean.valueOf(oldReloadable),
                                   Boolean.valueOf(this.reloadable));
    }

    /**
     * Set the DefaultContext override flag for this web application.
     *
     * @param override The new override flag
     */
    public void setOverride(boolean override) {
        boolean oldOverride = this.override;
        this.override = override;
        support.firePropertyChange("override",
                                   Boolean.valueOf(oldOverride),
                                   Boolean.valueOf(this.override));
    }

    // START SJSAS 8.1 5049111
    /**
     * Scan the parent when searching for TLD listeners.
     */
    public boolean isJsfApplication(){
        return isJsfApplication;
    }
    // END SJSAS 8.1 5049111


    // START SJSAS 6253524
    /**
     * Indicates whether this web module contains any ad-hoc paths.
     *
     * An ad-hoc path is a servlet path that is mapped to a servlet
     * not declared in the web module's deployment descriptor.
     *
     * A web module all of whose mappings are for ad-hoc paths is called an
     * ad-hoc web module.
     *
     * @return true if this web module contains any ad-hoc paths, false
     * otherwise
     */
    public boolean hasAdHocPaths() {
        return false;
    }

    /**
     * Returns the name of the ad-hoc servlet responsible for servicing the
     * given path.
     *
     * @param path The path to service
     *
     * @return The name of the ad-hoc servlet responsible for servicing the
     * given path, or null if the given path is not an ad-hoc path
     */
    public String getAdHocServletName(String path) {
        return null;
    }
    // END SJSAS 6253524

    /**
     * Return the "replace welcome files" property.
     */
    public boolean isReplaceWelcomeFiles() {
        return replaceWelcomeFiles;
    }

    /**
     * Set the "replace welcome files" property.
     *
     * @param replaceWelcomeFiles The new property value
     */
    public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {

        boolean oldReplaceWelcomeFiles = this.replaceWelcomeFiles;
        this.replaceWelcomeFiles = replaceWelcomeFiles;
        support.firePropertyChange("replaceWelcomeFiles",
                                   Boolean.valueOf(oldReplaceWelcomeFiles),
                                   Boolean.valueOf(this.replaceWelcomeFiles));
    }

    /**
     * Returns the value of the securePagesWithPragma property.
     */
    public boolean isSecurePagesWithPragma() {
        return securePagesWithPragma;
    }

    /**
     * Sets the securePagesWithPragma property of this Context.
     *
     * Setting this property to true will result in Pragma and Cache-Control
     * headers with a value of "No-cache" if proxy caching has been disabled.
     *
     * Setting this property to false will not add any Pragma header,
     * but will set the Cache-Control header to "private".
     *
     * @param securePagesWithPragma true if Pragma and Cache-Control headers
     * are to be set to "No-cache" if proxy caching has been disabled, false
     * otherwise
     */
    public void setSecurePagesWithPragma(boolean securePagesWithPragma) {

        boolean oldSecurePagesWithPragma = this.securePagesWithPragma;
        this.securePagesWithPragma = securePagesWithPragma;
        support.firePropertyChange("securePagesWithPragma",
                                   Boolean.valueOf(oldSecurePagesWithPragma),
                                   Boolean.valueOf(this.securePagesWithPragma));
    }

    public void setUseMyFaces(boolean useMyFaces) {
        this.useMyFaces = useMyFaces;
    }

    public boolean isUseMyFaces() {
        return useMyFaces;
    }

    /**
     * Return the servlet context for which this Context is a facade.
     */
    public ServletContext getServletContext() {
        if (context == null) {
            context = new ApplicationContext(getBasePath(getDocBase()),
                                             this);
            if (altDDName != null
                    && context.getAttribute(Globals.ALT_DD_ATTR) == null){
                context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
                context.setAttributeReadOnly(Globals.ALT_DD_ATTR);
            }
        }

        return context.getFacade();
    }

    /**
     * Return the default session timeout (in minutes) for this
     * web application.
     */
    public int getSessionTimeout() {
        return sessionTimeout;
    }

    /**
     * Is the session timeout (in minutes) for this
     * web application over-ridden from the default
     * HERCULES:add
     */
    public boolean isSessionTimeoutOveridden() {
        return sessionTimeoutOveridden;
    }

    /**
     * Set the default session timeout (in minutes) for this
     * web application.
     *
     * @param timeout The new default session timeout
     */
    public void setSessionTimeout(int timeout) {

        int oldSessionTimeout = this.sessionTimeout;

        /*
         * SRV.13.4 ("Deployment Descriptor"):
         * If the timeout is 0 or less, the container ensures the default
         * behaviour of sessions is never to time out.
         */
        this.sessionTimeout = (timeout == 0) ? -1 : timeout;
        support.firePropertyChange("sessionTimeout",
                                   Integer.valueOf(oldSessionTimeout),
                                   Integer.valueOf(this.sessionTimeout));
        //HERCULES:add
        sessionTimeoutOveridden = true;
        //end HERCULES:add
    }

    /**
     * Unpack WAR flag accessor.
     */
    public boolean getUnpackWAR() {
        return unpackWAR;
    }

    /**
     * Unpack WAR flag mutator.
     */
    public void setUnpackWAR(boolean unpackWAR) {
        this.unpackWAR = unpackWAR;
    }

    /**
     * Set the resources DirContext object with which this Container is
     * associated.
     *
     * @param resources The newly associated DirContext
     */
    @Override
    public synchronized void setResources(DirContext resources) {

        if (started) {
            throw new IllegalStateException
                (sm.getString("standardContext.resources.started"));
        }

        DirContext oldResources = this.webappResources;
        if (oldResources == resources)
            return;

        if (resources instanceof BaseDirContext) {
            BaseDirContext baseDirContext = (BaseDirContext)resources;
            baseDirContext.setCached(isCachingAllowed());
            baseDirContext.setCacheTTL(getCacheTTL());
            baseDirContext.setCacheMaxSize(getCacheMaxSize());
        }
        if (resources instanceof FileDirContext) {
            filesystemBased = true;
            FileDirContext fileDirContext = (FileDirContext)resources;
            fileDirContext.setCaseSensitive(isCaseSensitive());
            fileDirContext.setAllowLinking(isAllowLinking());
        }
        this.webappResources = resources;

        // The proxied resources will be refreshed on start
        this.resources = null;

        support.firePropertyChange("resources", oldResources,
                                   this.webappResources);

    }

    private synchronized void setAlternateResources(
                            AlternateDocBase alternateDocBase,
                            DirContext resources) {

        if (started) {
            throw new IllegalStateException
                (sm.getString("standardContext.resources.started"));
        }

        DirContext oldResources = alternateDocBase.getWebappResources();
        if (oldResources == resources)
            return;

        if (resources instanceof BaseDirContext) {
            ((BaseDirContext) resources).setCached(isCachingAllowed());
            ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
            ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
        }
        if (resources instanceof FileDirContext) {
            filesystemBased = true;
            ((FileDirContext) resources).setCaseSensitive(isCaseSensitive());
            ((FileDirContext) resources).setAllowLinking(isAllowLinking());
        }
        alternateDocBase.setWebappResources(resources);
        // The proxied resources will be refreshed on start
        alternateDocBase.setResources(null);
    }

    // START S1AS8PE 4817642
    /**
     * Return the "reuse session IDs when creating sessions" flag
     */
    public boolean getReuseSessionID() {
        return reuseSessionID;
    }

    /**
     * Set the "reuse session IDs when creating sessions" flag
     *
     * @param reuse The new value for the flag
     */
    public void setReuseSessionID(boolean reuse) {
        reuseSessionID = reuse;
    }
    // END S1AS8PE 4817642



    // START RIMOD 4642650
    /**
     * Return whether this context allows sendRedirect() to redirect
     * to a relative URL.
     *
     * The default value for this property is 'false'.
     */
    public boolean getAllowRelativeRedirect() {

        return allowRelativeRedirect;

    }


    /**
     * Set whether this context allows sendRedirect() to redirect
     * to a relative URL.
     *
     * @param allowRelativeURLs The new value for this property.
     *                          The default value for this property is
     *                          'false'.
     */
    public void setAllowRelativeRedirect(boolean allowRelativeURLs) {

        allowRelativeRedirect = allowRelativeURLs;

    }


    // END RIMOD 4642650

    // START IASRI 4823322
    /**
     * Get Auditors associated with this context, if any.
     *
     * @return array of Auditor objects, or null
     *
     */
    public Auditor[] getAuditors() {
        return auditors;
    }


    /**
     * Set the Auditors associated with this context.
     *
     * @param auditor array of Auditor objects
     *
     */
    public void setAuditors(Auditor[] auditor) {
        this.auditors=auditor;
    }
    // END IASRI 4823322


    // START S1AS8PE 4965017
    public void setReload(boolean isReload) {
        this.isReload = isReload;
    }

    public boolean isReload() {
        return isReload;
    }
    // END S1AS8PE 4965017


    // ------------------------------------------------------ Public Properties


    /**
     * Return the Locale to character set mapper class for this Context.
     */
    public String getCharsetMapperClass() {

        return (this.charsetMapperClass);

    }


    /**
     * Set the Locale to character set mapper class for this Context.
     *
     * @param mapper The new mapper class
     */
    public void setCharsetMapperClass(String mapper) {

        String oldCharsetMapperClass = this.charsetMapperClass;
        this.charsetMapperClass = mapper;
        support.firePropertyChange("charsetMapperClass",
                                   oldCharsetMapperClass,
                                   this.charsetMapperClass);

    }


    /**
     * Get the absolute path to the work dir.
     *
     * @return the absolute path to the work dir
     */
    public String getWorkPath() {
        if (getWorkDir() == null) {
            return null;
        }
        File workDir = new File(getWorkDir());
        if (!workDir.isAbsolute()) {
            File catalinaHome = engineBase();
            String catalinaHomePath = null;
            try {
                catalinaHomePath = catalinaHome.getCanonicalPath();
                workDir = new File(catalinaHomePath,
                        getWorkDir());
            } catch (IOException e) {
            }
        }
              return workDir.getAbsolutePath();
    }

    /**
     * Return the work directory for this Context.
     */
    public String getWorkDir() {

        return (this.workDir);

    }


    /**
     * Set the work directory for this Context.
     *
     * @param workDir The new work directory
     */
    public void setWorkDir(String workDir) {
        this.workDir = workDir;
        if (started) {
            postWorkDirectory();
        }
    }


    // -------------------------------------------------------- Context Methods


    /**
     * Adds the Listener with the given class name that is declared in the
     * deployment descriptor to the set of Listeners configured for this
     * application.
     *
     * @param listener the fully qualified class name of the Listener
     */
    public void addApplicationListener(String listener) {
        addListener(listener, false);
    }

    /**
     * Add a new application parameter for this application.
     *
     * @param parameter The new application parameter
     */
    public void addApplicationParameter(ApplicationParameter parameter) {
        String newName = parameter.getName();
        Iterator<ApplicationParameter> i =
            applicationParameters.iterator(); 
        while (i.hasNext()) {
            ApplicationParameter applicationParameter = i.next();
            if (newName.equals(applicationParameter.getName())) {
                if (applicationParameter.getOverride()) {
                    applicationParameter.setValue(parameter.getValue());
                }
                return;
            }
        }

        applicationParameters.add(parameter);

        if (notifyContainerListeners) {
            fireContainerEvent("addApplicationParameter", parameter);
        }
    }

    /**
     * Adds the given child Container to this context.
     *
     * @param child the child Container to add
     *
     * @exception IllegalArgumentException if the given child Container is
     * not an instance of Wrapper
     */
    @Override
    public void addChild(Container child) {
        addChild(child, false, true);
    }

    /**
     * Adds the given child (Servlet) to this context.
     *
     * @param child the child (Servlet) to add
     * @param isProgrammatic true if the given child (Servlet) is being
     * added via one of the programmatic interfaces, and false if it is
     * declared in the deployment descriptor
     * @param createRegistration true if a ServletRegistration needs to be
     * created for the given child, and false if a (preliminary)
     * ServletRegistration had already been created (which would be the
     * case if the Servlet had been declared in the deployment descriptor
     * without any servlet-class, and the servlet-class was later provided
     * via ServletContext#addServlet)
     *
     * @exception IllegalArgumentException if the given child Container is
     * not an instance of Wrapper
     */
    protected void addChild(Container child, boolean isProgrammatic,
            boolean createRegistration) {

        if (!(child instanceof Wrapper)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.notWrapper"));
        }

        Wrapper wrapper = (Wrapper) child;
        String wrapperName = child.getName();

        if (createRegistration) {
            ServletRegistrationImpl regis = null;
            if (isProgrammatic ||
                    (null == wrapper.getServletClassName() &&
                        null == wrapper.getJspFile())) {
                regis = createDynamicServletRegistrationImpl(
                    (StandardWrapper) wrapper);
            } else {
                regis = createServletRegistrationImpl(
                    (StandardWrapper) wrapper);
            }
            servletRegisMap.put(wrapperName, regis);
            if (null == wrapper.getServletClassName() &&
                    null == wrapper.getJspFile()) {
                /*
                 * Preliminary registration for Servlet that was declared
                 * without any servlet-class. Once the registration is
                 * completed via ServletContext#addServlet, addChild will
                 * be called again, and 'wrapper' will have been configured
                 * with a proper class name at that time
                 */
                return;
            }
        }

        if ("javax.faces.webapp.FacesServlet".equals(
                wrapper.getServletClassName())) {
            isJsfApplication = true;
        }

        // Global JspServlet
        Wrapper oldJspServlet = null;

        // Allow webapp to override JspServlet inherited from global web.xml.
        boolean isJspServlet = "jsp".equals(wrapperName);
        if (isJspServlet) {
            oldJspServlet = (Wrapper) findChild("jsp");
            if (oldJspServlet != null) {
                removeChild(oldJspServlet);
            }
        }

        String jspFile = wrapper.getJspFile();
        if ((jspFile != null) && !jspFile.startsWith("/")) {
            if (isServlet22()) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine(sm.getString("standardContext.wrapper.warning",
                                          jspFile));
                }
                wrapper.setJspFile("/" + jspFile);
            } else {
                throw new IllegalArgumentException
                    (sm.getString("standardContext.wrapper.error", jspFile));
            }
        }

        super.addChild(child);

        // START SJSAS 6342808
        /* SJSWS 6362207
        if (started) {
        */
        // START SJSWS 6362207
        if (getAvailable()) {
        // END SJSWS 6362207
            /*
             * If this StandardContext has already been started, we need to
             * register the newly added child with JMX. Any children that were
             * added before this StandardContext was started have already been
             * registered with JMX (as part of StandardContext.start()).
             */
            if (wrapper instanceof StandardWrapper) {
                ((StandardWrapper) wrapper).registerJMX( this );
            }
        }
        // END SJSAS 6342808

        if (isJspServlet && oldJspServlet != null) {
            /*
             * The webapp-specific JspServlet inherits all the mappings
             * specified in the global web.xml, and may add additional ones.
             */
            String[] jspMappings = oldJspServlet.findMappings();
            for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
                addServletMapping(jspMappings[i], wrapperName);
            }
        }
    }

    protected ServletRegistrationImpl createServletRegistrationImpl(
            StandardWrapper wrapper) {
        return new ServletRegistrationImpl(wrapper, this);
    }

    protected ServletRegistrationImpl createDynamicServletRegistrationImpl(
            StandardWrapper wrapper) {
        return new DynamicServletRegistrationImpl(wrapper, this);
    }

    /**
     * Add a security constraint to the set for this web application.
     */
    public void addConstraint(SecurityConstraint constraint) {

        // Validate the proposed constraint
        SecurityCollection collections[] = constraint.findCollections();
        for(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]));
                }
            }
        }

        // Add this constraint to the set for our web application
        constraints.add(constraint);
    }

    /**
     * Add an EJB resource reference for this web application.
     *
     * @param ejb New EJB resource reference
     */
    public void addEjb(ContextEjb ejb) {
        namingResources.addEjb(ejb);
        if (notifyContainerListeners) {
           fireContainerEvent("addEjb", ejb.getName());
        }
    }

    /**
     * Add an environment entry for this web application.
     *
     * @param environment New environment entry
     */
    public void addEnvironment(ContextEnvironment environment) {

        ContextEnvironment env = findEnvironment(environment.getName());
        if ((env != null) && !env.getOverride())
            return;
        namingResources.addEnvironment(environment);

        if (notifyContainerListeners) {
            fireContainerEvent("addEnvironment", environment.getName());
        }
    }


    /**
     * Add resource parameters for this web application.
     *
     * @param resourceParameters New resource parameters
     */
    public void addResourceParams(ResourceParams resourceParameters) {
        namingResources.addResourceParams(resourceParameters);
        if (notifyContainerListeners) {
            fireContainerEvent("addResourceParams",
                               resourceParameters.getName());
        }
    }

    /**
     * Add an error page for the specified error or Java exception.
     *
     * @param errorPage The error page definition to be added
     */
    public void addErrorPage(ErrorPage errorPage) {
        // Validate the input parameters
        if (errorPage == null)
            throw new IllegalArgumentException
                (sm.getString("standardContext.errorPage.required"));
        String location = errorPage.getLocation();
        if ((location != null) && !location.startsWith("/")) {
            if (isServlet22()) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine(sm.getString("standardContext.errorPage.warning",
                                          location));
                }
                errorPage.setLocation("/" + location);
            } else {
                throw new IllegalArgumentException
                    (sm.getString("standardContext.errorPage.error",
                                  location));
            }
        }

        // Add the specified error page to our internal collections
        String exceptionType = errorPage.getExceptionType();
        if (exceptionType != null) {
            synchronized (exceptionPages) {
                exceptionPages.put(exceptionType, errorPage);
            }
        } else if (errorPage.getErrorCode() > 0) {
            synchronized (statusPages) {
                int errorCode = errorPage.getErrorCode();
                if ((errorCode >= 400) && (errorCode < 600)) {
                    statusPages.put(errorCode, errorPage);
                } else {
                    log.severe(sm.getString(
                        "standardContext.invalidErrorPageCode", errorCode));
                }
            }
        } else {
            defaultErrorPage = errorPage;
        }

        if (notifyContainerListeners) {
            fireContainerEvent("addErrorPage", errorPage);
        }
    }

    /**
     * Add a filter definition to this Context.
     *
     * @param filterDef The filter definition to be added
     */
    public void addFilterDef(FilterDef filterDef) {
        addFilterDef(filterDef, false, true);
    }

    public void addFilterDef(FilterDef filterDef, boolean isProgrammatic,
            boolean createRegistration) {
        if (createRegistration) {
            FilterRegistrationImpl regis = null;
            if (isProgrammatic || null == filterDef.getFilterClassName()) {
                regis = new DynamicFilterRegistrationImpl(filterDef, this);
            } else {
                regis = new FilterRegistrationImpl(filterDef, this);
            }
            filterRegisMap.put(filterDef.getFilterName(), regis);
            if (null == filterDef.getFilterClassName()) {
                /*
                 * Preliminary registration for Filter that was declared
                 * without any filter-class. Once the registration is
                 * completed via ServletContext#addFilter, addFilterDef will
                 * be called again, and 'filterDef' will have been configured
                 * with a proper class name at that time
                 */
                return;
            }
        }

        synchronized (filterDefs) {
            filterDefs.put(filterDef.getFilterName(), filterDef);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("addFilterDef", filterDef);
        }
    }

    /**
     * Add multiple filter mappings to this Context.
     *
     * @param filterMaps The filter mappings to be added
     *
     * @exception IllegalArgumentException if the specified filter name
     *  does not match an existing filter definition, or the filter mapping
     *  is malformed
     */
    public void addFilterMaps(FilterMaps filterMaps) {
        String[] servletNames = filterMaps.getServletNames();
        String[] urlPatterns = filterMaps.getURLPatterns();
        for (String servletName : servletNames) {
            FilterMap fmap = new FilterMap();
            fmap.setFilterName(filterMaps.getFilterName());
            fmap.setServletName(servletName);
            fmap.setDispatcherTypes(filterMaps.getDispatcherTypes());
            addFilterMap(fmap);
        }
        for (String urlPattern : urlPatterns) {
            FilterMap fmap = new FilterMap();
            fmap.setFilterName(filterMaps.getFilterName());
            fmap.setURLPattern(urlPattern);
            fmap.setDispatcherTypes(filterMaps.getDispatcherTypes());
            addFilterMap(fmap);
        }
    }

    /**
     * Add a filter mapping to this Context.
     *
     * @param filterMap The filter mapping to be added
     *
     * @exception IllegalArgumentException if the specified filter name
     *  does not match an existing filter definition, or the filter mapping
     *  is malformed
     */
    public void addFilterMap(FilterMap filterMap) {
        addFilterMap(filterMap, true);
    }


    /**
     * Add a filter mapping to this Context.
     *
     * @param filterMap The filter mapping to be added
     *
     * @param isMatchAfter true if the given filter mapping should be matched
     * against requests after any declared filter mappings of this servlet
     * context, and false if it is supposed to be matched before any declared
     * filter mappings of this servlet context
     *
     * @exception IllegalArgumentException if the specified filter name
     *  does not match an existing filter definition, or the filter mapping
     *  is malformed
     *
     */
    public void addFilterMap(FilterMap filterMap, boolean isMatchAfter) {

        // Validate the proposed filter mapping
        String filterName = filterMap.getFilterName();
        String servletName = filterMap.getServletName();
        String urlPattern = filterMap.getURLPattern();
        if (null == filterRegisMap.get(filterName)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.filterMap.name", filterName));
        }
        if ((servletName == null) && (urlPattern == null)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.filterMap.either"));
        }
        if ((servletName != null) && (urlPattern != null)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.filterMap.either"));
        }
        // Because filter-pattern is new in 2.3, no need to adjust
        // for 2.2 backwards compatibility
        if ((urlPattern != null) && !validateURLPattern(urlPattern)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.filterMap.pattern",
                              urlPattern));
        }

        // Add this filter mapping to our registered set
        if (isMatchAfter) {
            filterMaps.add(filterMap);
        } else {
            filterMaps.add(0, filterMap);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("addFilterMap", filterMap);
        }
    }

    /**
     * Gets the current servlet name mappings of the Filter with
     * the given name.
     */
    public Collection<String> getServletNameFilterMappings(String filterName) {
        HashSet<String> mappings = new HashSet();
        synchronized (filterMaps) {
            for (FilterMap fm : filterMaps) {
                if (filterName.equals(fm.getFilterName()) &&
                        fm.getServletName() != null) {
                    mappings.add(fm.getServletName());
                }
            }
        }
        return mappings;
    }

    /**
     * Gets the current URL pattern mappings of the Filter with the given
     * name.
     */
    public Collection<String> getUrlPatternFilterMappings(String filterName) {
        HashSet<String> mappings = new HashSet();
        synchronized (filterMaps) {
            for (FilterMap fm : filterMaps) {
                if (filterName.equals(fm.getFilterName()) &&
                        fm.getURLPattern() != null) {
                    mappings.add(fm.getURLPattern());
                }
            }
        }
        return mappings;
    }

    /**
     * Adds the filter with the given name and class name to this servlet
     * context.
     */
    public FilterRegistration.Dynamic addFilter(
            String filterName, String className) {
        synchronized (filterDefs) {
            // Make sure filter name is unique for this context
            if (findFilterDef(filterName) != null) {
                return null;
            }

            DynamicFilterRegistrationImpl regis =
                (DynamicFilterRegistrationImpl) filterRegisMap.get(
                    filterName);
            FilterDef filterDef = null;
            if (null == regis) {
                filterDef = new FilterDef();
            } else {
                // Complete preliminary filter registration
                filterDef = regis.getFilterDefinition();
            }

            filterDef.setFilterName(filterName);
            filterDef.setFilterClassName(className);

            addFilterDef(filterDef, true, (regis == null));
            if (null == regis) {
                regis = (DynamicFilterRegistrationImpl)
                    filterRegisMap.get(filterName);
            }

            return regis;
        }
    }

    /*
     * Registers the given filter instance with this ServletContext
     * under the given <tt>filterName.
     */
    public FilterRegistration.Dynamic addFilter(
            String filterName, Filter filter) {
        if (filterName == null || filter == null) {
            throw new NullPointerException("Null filter instance or name");
        }

        /*
         * Make sure the given Filter instance is unique across all deployed
         * contexts
         */
        Container host = getParent();
        if (host != null) {
            for (Container child : host.findChildren()) {
                if (child == this) {
                    // Our own context will be checked further down
                    continue;
                }
                if (((StandardContext) child).hasFilter(filter)) {
                    return null;
                }
            }
        }

        /*
         * Make sure the given Filter name and instance are unique within 
         * this context
         */
        synchronized (filterDefs) {
            for (Map.Entry<String, FilterDef> e : filterDefs.entrySet()) {
                if (filterName.equals(e.getKey()) ||
                        filter == e.getValue().getFilter()) {
                    return null;
                }
            }

            DynamicFilterRegistrationImpl regis =
                (DynamicFilterRegistrationImpl) filterRegisMap.get(
                    filterName);
            FilterDef filterDef = null;
            if (null == regis) {
                filterDef = new FilterDef();
            } else {
                // Complete preliminary filter registration
                filterDef = regis.getFilterDefinition();
            }

            filterDef.setFilterName(filterName);
            filterDef.setFilter(filter);

            addFilterDef(filterDef, true, (regis == null));
            if (null == regis) {
                regis = (DynamicFilterRegistrationImpl)
                    filterRegisMap.get(filterName);
            }

            return regis;
        }
    }

    /**
     * Checks whether this context contains the given Filter instance
     */
    public boolean hasFilter(Filter filter) {
        for (Map.Entry<String, FilterDef> e : filterDefs.entrySet()) {
            if (filter == e.getValue().getFilter()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Adds the filter with the given name and class type to this servlet
     * context.
     */
    public FilterRegistration.Dynamic addFilter(String filterName,
            Class <? extends Filter> filterClass) {
        synchronized (filterDefs) {
            if (findFilterDef(filterName) != null) {
                return null;
            }

            DynamicFilterRegistrationImpl regis =
                (DynamicFilterRegistrationImpl) filterRegisMap.get(
                    filterName);
            FilterDef filterDef = null;
            if (null == regis) {
                filterDef = new FilterDef();
            } else {
                // Complete preliminary filter registration
                filterDef = regis.getFilterDefinition();
            }

            filterDef.setFilterName(filterName);
            filterDef.setFilterClass(filterClass);

            addFilterDef(filterDef, true, (regis == null));
            if (null == regis) {
                regis = (DynamicFilterRegistrationImpl)
                    filterRegisMap.get(filterName);
            }

            return regis;
        }
    }

    /**
     * Instantiates the given Filter class and performs any required
     * resource injection into the new Filter instance before returning
     * it.
     */
    public <T extends Filter> T createFilter(Class clazz)
            throws ServletException {
        try {
            return createFilterInstance(clazz);
        } catch (Throwable t) {
            throw new ServletException("Unable to create Filter from " +
                                       "class " + clazz.getName(), t);
        }
    }

    /**
     * Gets the FilterRegistration corresponding to the filter with the
     * given <tt>filterName.
     */
    public FilterRegistration getFilterRegistration(String filterName) {
        return filterRegisMap.get(filterName);
    }

    /**
     * Gets a Map of the FilterRegistration objects corresponding to all
     * currently registered filters.
     */
    public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
        return Collections.unmodifiableMap(filterRegisMap);
    }

    /**
     * Gets the session tracking cookie configuration of this
     * <tt>ServletContext.
     */
    public synchronized SessionCookieConfig getSessionCookieConfig() {
        if (sessionCookieConfig == null) {
            sessionCookieConfig = new SessionCookieConfigImpl(this);
        }
        return sessionCookieConfig;
    }

    /**
     * Sets the name that will be assigned to any session tracking
     * cookies created on behalf of this context
     */
    void setSessionCookieName(String sessionCookieName) {
        this.sessionCookieName = sessionCookieName;
        sessionCookieNameInitialized = true;
    }

    /**
     * Gets the name that will be assigned to any session tracking
     * cookies created on behalf of this context
     */
    public String getSessionCookieName() {
        return sessionCookieName;
    }

    /**
     * @return the name that will be assigned to any session tracking
     * parameter created on behalf of this context
     */
    public String getSessionParameterName() {
        if (sessionCookieNameInitialized) {
            if (sessionCookieName != null && (!sessionCookieName.isEmpty())) {
               return sessionCookieName; 
            }
        }
        
        return Globals.SESSION_PARAMETER_NAME;
    }

    /**
     * Sets the session tracking modes that are to become effective for this
     * <tt>ServletContext.
     */
    public void setSessionTrackingModes(
            Set<SessionTrackingMode> sessionTrackingModes) {

        if (sessionTrackingModes.contains(SessionTrackingMode.SSL)) {
            throw new IllegalArgumentException(
                sm.getString(
                    "applicationContext.sessionTrackingModes.iae.unsupported",
                    SessionTrackingMode.SSL, getName()));
        }

        if (isContextInitializedCalled) {
            throw new IllegalStateException(
                sm.getString("applicationContext.alreadyInitialized",
                             "setSessionTrackingModes", getName()));
        }

        this.sessionTrackingModes =
            Collections.unmodifiableSet(sessionTrackingModes);

        if (sessionTrackingModes.contains(SessionTrackingMode.COOKIE)) {
            setCookies(true);
        } else {
            setCookies(false);
        }

        if (sessionTrackingModes.contains(SessionTrackingMode.URL)) {
            setEnableURLRewriting(true);
        } else {
            setEnableURLRewriting(false);
        }
    }

    /**
     * Gets the session tracking modes that are supported by default for this
     * <tt>ServletContext.
     *
     * @return set of the session tracking modes supported by default for
     * this <tt>ServletContext
     */
    public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
        return DEFAULT_SESSION_TRACKING_MODES;
    }

    /**
     * Gets the session tracking modes that are in effect for this
     * <tt>ServletContext.
     *
     * @return set of the session tracking modes in effect for this
     * <tt>ServletContext
     */
    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
        return (sessionTrackingModes != null ? sessionTrackingModes :
            DEFAULT_SESSION_TRACKING_MODES);
    }

    /**
     * Adds the listener with the given class name to this ServletContext.
     *
     * @param className the fully qualified class name of the listener
     */
    public void addListener(String className) {
        addListener(className, true);
    }


    /**
     * Adds the listener with the given class name to this ServletContext.
     *
     * @param className the fully qualified class name of the listener
     * @param isProgrammatic true if the listener is being added
     * programmatically, and false if it has been declared in the deployment
     * descriptor
     */
    private void addListener(String className, boolean isProgrammatic) {
        try {
            addListener(loadListener(getClassLoader(), className),
                        isProgrammatic);
        } catch (Throwable t) {
            throw new IllegalArgumentException(t); 
        }
    }

    /**
     * Adds the given listener instance to this ServletContext.
     *
     * @param t the listener to be added
     */
    public <T extends EventListener> void addListener(T t) {
        addListener(t, true);
    }

    /**
     * Adds the given listener instance to this ServletContext.
     *
     * @param t the listener to be added
     * @param isProgrammatic true if the listener is being added
     * programmatically, and false if it has been declared in the deployment
     * descriptor
     */
    private <T extends EventListener> void addListener(T t,
            boolean isProgrammatic) {
        if (isContextInitializedCalled) {
            throw new IllegalStateException(
                sm.getString("applicationContext.alreadyInitialized",
                             "addListener", getName()));
        }

        if ((t instanceof ServletContextListener) && isProgrammatic &&
                !isProgrammaticServletContextListenerRegistrationAllowed) {
            throw new IllegalArgumentException("Not allowed to register " + 
                "ServletContextListener programmatically");
        }

        boolean added = false;

        if (t instanceof ServletContextAttributeListener ||
                t instanceof ServletRequestAttributeListener ||
                t instanceof ServletRequestListener ||
                t instanceof HttpSessionAttributeListener) {
            eventListeners.add(t);
            added = true;
        }

        if (t instanceof HttpSessionListener) {
            sessionListeners.add((HttpSessionListener) t);
            if (!added) {
                added = true;
            }
        }

        if (t instanceof ServletContextListener) {
            ServletContextListener proxy = (ServletContextListener) t;
            if (isProgrammatic) {
                proxy = new RestrictedServletContextListener(
                    (ServletContextListener) t);
            }
            // Always add the JSF listener as the first element,
            // see GlassFish Issue 2563 for details
            boolean isFirst =
                "com.sun.faces.config.ConfigureListener".equals(
                    t.getClass().getName());
            if (isFirst) {
                contextListeners.add(0, proxy);
            } else {
                contextListeners.add(proxy);
            }
            if (!added) {
                added = true;
            }
        }

        if (!added) {
            throw new IllegalArgumentException("Invalid listener type " +
                t.getClass().getName());
        }
    }

    /**
     * Adds a listener of the given class type to this ServletContext.
     */
    public void addListener(Class <? extends EventListener> listenerClass) {
        try {
            addListener(createListenerInstance(listenerClass));
        } catch (Throwable t) {
            throw new IllegalArgumentException(t); 
        }
    }

    /**
     * Instantiates the given EventListener class and performs any
     * required resource injection into the new EventListener instance
     * before returning it.
     */
    public <T extends EventListener> T createListener(Class clazz)
            throws ServletException {
        if (!ServletContextListener.class.isAssignableFrom(clazz) &&
                !ServletContextAttributeListener.class.isAssignableFrom(clazz) &&
                !ServletRequestListener.class.isAssignableFrom(clazz) &&
                !ServletRequestAttributeListener.class.isAssignableFrom(clazz) &&
                !HttpSessionListener.class.isAssignableFrom(clazz) &&
                !HttpSessionAttributeListener.class.isAssignableFrom(clazz)) {
            throw new IllegalArgumentException(sm.getString(
                    "standardContext.invalidListenerType", clazz.getName()));
        }

        try {
            return createListenerInstance(clazz);
        } catch (Throwable t) {
            throw new ServletException(t);
        }
    }

    public void setJspConfigDescriptor(JspConfigDescriptor jspConfigDesc) {
        this.jspConfigDesc = jspConfigDesc;
    }

    /**
     * Gets the <code><jsp-config> related configuration
     * that was aggregated over the <code>web.xml and
     * <code>web-fragment.xml resources of the web application
     * represented by this ServletContext.
     */
    public JspConfigDescriptor getJspConfigDescriptor() {
        return jspConfigDesc;
    }

    /**
     * Gets the class loader of the web application represented by this
     * ServletContext.
     */
    public ClassLoader getClassLoader() {
        ClassLoader webappLoader = (getLoader() != null) ?
            getLoader().getClassLoader() : null;
        if (webappLoader == null) {
            return null;
        }
        if (mySecurityManager != null) {
            mySecurityManager.checkGetClassLoaderPermission(webappLoader);
        }
        return webappLoader;
    }

    public void declareRoles(String... roleNames) {
        for (String roleName : roleNames) {
            addSecurityRole(roleName);
        }
    }

    public void setEffectiveMajorVersion(int effectiveMajorVersion) {
        this.effectiveMajorVersion = effectiveMajorVersion;
    }

    public int getEffectiveMajorVersion() {
        return effectiveMajorVersion;
    }

    public void setEffectiveMinorVersion(int effectiveMinorVersion) {
        this.effectiveMinorVersion = effectiveMinorVersion;
    }
    
    public int getEffectiveMinorVersion() {
        return effectiveMinorVersion;
    }

    /**
     * Add the classname of an InstanceListener to be added to each
     * Wrapper appended to this Context.
     *
     * @param listener Java class name of an InstanceListener class
     */
    public void addInstanceListener(String listener) {
        instanceListeners.add(listener);
        if (notifyContainerListeners) {
            fireContainerEvent("addInstanceListener", listener);
        }
    }

    public void addInstanceListener(InstanceListener listener) {
        instanceListenerInstances.add(listener);
        if (notifyContainerListeners) {
            fireContainerEvent("addInstanceListener", listener);
        }
    }

    /**
     * Add the given URL pattern as a jsp-property-group.  This maps
     * resources that match the given pattern so they will be passed
     * to the JSP container.  Though there are other elements in the
     * property group, we only care about the URL pattern here.  The
     * JSP container will parse the rest.
     *
     * @param pattern URL pattern to be mapped
     */
    public void addJspMapping(String pattern) {
        String servletName = findServletMapping("*.jsp");
        if (servletName == null) {
            servletName = "jsp";
        }

        if( findChild(servletName) != null) {
            addServletMapping(pattern, servletName, true);
        } else {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Skipping " + pattern + " , no servlet "
                         + servletName);
            }
        }
    }

    /**
     * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
     *
     * @param locale locale to map an encoding for
     * @param encoding encoding to be used for a give locale
     */
    public void addLocaleEncodingMappingParameter(String locale, String encoding){
        getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
    }

    /**
     * Add a local EJB resource reference for this web application.
     *
     * @param ejb New EJB resource reference
     */
    public void addLocalEjb(ContextLocalEjb ejb) {
        namingResources.addLocalEjb(ejb);
        if (notifyContainerListeners) {
            fireContainerEvent("addLocalEjb", ejb.getName());
        }
    }

    /**
     * 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);
        }
        if (notifyContainerListeners) {
            fireContainerEvent("addMessageDestination", md.getName());
        }
    }

    /**
     * Add a message destination reference for this web application.
     *
     * @param mdr New message destination reference
     */
    public void addMessageDestinationRef(MessageDestinationRef mdr) {
        namingResources.addMessageDestinationRef(mdr);
        if (notifyContainerListeners) {
            fireContainerEvent("addMessageDestinationRef", mdr.getName());
        }
    }

    /**
     * Add a new MIME mapping, replacing any existing mapping for
     * the specified extension.
     *
     * @param extension Filename extension being mapped
     * @param mimeType Corresponding MIME type
     */
    public void addMimeMapping(String extension, String mimeType) {
        synchronized (mimeMappings) {
            mimeMappings.put(extension, mimeType);
        }
        if (notifyContainerListeners) {
            fireContainerEvent("addMimeMapping", extension);
        }
    }

    /**
     * Add a new context initialization parameter.
     *
     * @param name Name of the new parameter
     * @param value Value of the new  parameter
     *
     * @exception IllegalArgumentException if the name or value is missing,
     *  or if this context initialization parameter has already been
     *  registered
     */
    public void addParameter(String name, String value) {
        // Validate the proposed context initialization parameter
        if ((name == null) || (value == null))
            throw new IllegalArgumentException
                (sm.getString("standardContext.parameter.required"));
        if (parameters.get(name) != null)
            throw new IllegalArgumentException
                (sm.getString("standardContext.parameter.duplicate", name));

        // Add this parameter to our defined set
        synchronized (parameters) {
            parameters.put(name, value);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("addParameter", name);
        }
    }


    /**
     * Add a resource reference for this web application.
     *
     * @param resource New resource reference
     */
    public void addResource(ContextResource resource) {
        namingResources.addResource(resource);
        if (notifyContainerListeners) {
            fireContainerEvent("addResource", resource.getName());
        }
    }


    /**
     * Add a resource environment reference for this web application.
     *
     * @param name The resource environment reference name
     * @param type The resource environment reference type
     */
    public void addResourceEnvRef(String name, String type) {
        namingResources.addResourceEnvRef(name, type);
        if (notifyContainerListeners) {
            fireContainerEvent("addResourceEnvRef", name);
        }
    }

    /**
     * Add a resource link for this web application.
     *
     * @param resourceLink New resource link
     */
    public void addResourceLink(ContextResourceLink resourceLink) {
        namingResources.addResourceLink(resourceLink);
        if (notifyContainerListeners) {
            fireContainerEvent("addResourceLink", resourceLink.getName());
        }
    }


    /**
     * Add a security role reference for this web application.
     *
     * @param role Security role used in the application
     * @param link Actual security role to check for
     */
    public void addRoleMapping(String role, String link) {
        synchronized (roleMappings) {
            roleMappings.put(role, link);
        }
        if (notifyContainerListeners) {
            fireContainerEvent("addRoleMapping", role);
        }
    }

    /**
     * Add a new security role for this web application.
     *
     * @param role New security role
     */
    public void addSecurityRole(String role) {
        securityRoles.add(role);
        if (notifyContainerListeners) {
            fireContainerEvent("addSecurityRole", role);
        }
    }

    /**
     * Adds the given servlet mappings to this Context.
     *
     * <p>If any of the specified URL patterns are already mapped to a 
     * different Servlet, no updates will be performed.
     *
     * @param servletMap the Servlet mappings containing the Servlet name
     * and URL patterns
     *
     * @return the (possibly empty) Set of URL patterns that are already
     * mapped to a different Servlet
     *
     * @exception IllegalArgumentException if the specified servlet name
     * is not known to this Context
     */
     public Set<String> addServletMapping(ServletMap servletMap) {
         return addServletMapping(servletMap.getServletName(),
                                  servletMap.getUrlPatterns());
     }

    /**
     * Adds the given servlet mappings to this Context.
     *
     * <p>If any of the specified URL patterns are already mapped to a 
     * different Servlet, no updates will be performed.
     *
     * @param name the Servlet name
     * @param urlPatterns the URL patterns
     *
     * @return the (possibly empty) Set of URL patterns that are already
     * mapped to a different Servlet
     *
     * @exception IllegalArgumentException if the specified servlet name
     * is not known to this Context
     */
    public Set<String> addServletMapping(String name,
                                         String[] urlPatterns) {
        Set<String> conflicts = null;

        synchronized (servletMappings) {
            for (String pattern : urlPatterns) {
                pattern = adjustURLPattern(RequestUtil.urlDecode(pattern));
                if (!validateURLPattern(pattern)) {
                    throw new IllegalArgumentException(sm.getString(
                        "standardContext.servletMap.pattern", pattern));
                }

                // Ignore any conflicts with the container provided
                // Default- and JspServlet 
                String existing = servletMappings.get(pattern);
                if (existing != null &&
                        !existing.equals(Constants.DEFAULT_SERVLET_NAME) &&
                        !existing.equals(Constants.JSP_SERVLET_NAME) &&
                        !name.equals(Constants.DEFAULT_SERVLET_NAME) &&
                        !name.equals(Constants.JSP_SERVLET_NAME)) {
                    if (conflicts == null) {
                        conflicts = new HashSet<String>();
                    }
                    conflicts.add(pattern);
                }
            }

            if (conflicts == null) {
                for (String urlPattern : urlPatterns) {
                    addServletMapping(urlPattern, name, false);
                }
                return Collections.EMPTY_SET;
            } else {
                return conflicts;   
            }
        }
    }

    /**
     * Adds the given servlet mapping to this Context, overriding any
     * existing mapping for the specified pattern.
     *
     * @param pattern URL pattern to be mapped
     * @param name Name of the corresponding servlet to execute
     *
     * @exception IllegalArgumentException if the specified servlet name
     *  is not known to this Context
     */
    public void addServletMapping(String pattern, String name) {
        addServletMapping(pattern, name, false);
    }

    /**
     * Adds the given servlet mapping to this Context, overriding any
     * existing mapping for the specified pattern.
     *
     * @param pattern URL pattern to be mapped
     * @param name Name of the corresponding servlet to execute
     * @param jspWildCard true if name identifies the JspServlet
     * and pattern contains a wildcard; false otherwise
     *
     * @exception IllegalArgumentException if the specified servlet name
     * is not known to this Context
     */
    public void addServletMapping(String pattern, String name,
                                  boolean jspWildCard) {
        // Validate the proposed mapping
        ServletRegistrationImpl regis = servletRegisMap.get(name);
        if (null == regis) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.servletMap.name", name));
        }

        pattern = adjustURLPattern(RequestUtil.urlDecode(pattern));
        if (!validateURLPattern(pattern)) {
            throw new IllegalArgumentException
                (sm.getString("standardContext.servletMap.pattern", pattern));
        }

        /*
         * Add this mapping to our registered set. Make sure that it is 
         * possible to override the mappings of the container provided
         * Default- and JspServlet, and that these servlets are prevented
         * from overriding any user-defined mappings (depending on the order
         * in which the contents of the default-web.xml are merged with those
         * of the app's deployment descriptor).
         * This is to prevent the DefaultServlet from hijacking '/', and the
         * JspServlet from hijacking *.jsp(x).
         */
        synchronized (servletMappings) {
            String existing = servletMappings.get(pattern);
            if (existing != null) {
                if (!existing.equals(Constants.DEFAULT_SERVLET_NAME) &&
                        !existing.equals(Constants.JSP_SERVLET_NAME) &&
                        !name.equals(Constants.DEFAULT_SERVLET_NAME) &&
                        !name.equals(Constants.JSP_SERVLET_NAME)) {
                    throw new IllegalArgumentException(sm.getString(
                        "standardContext.duplicateServletMapping",
                        name, pattern, existing));
                }
                if (existing.equals(Constants.DEFAULT_SERVLET_NAME) ||
                        existing.equals(Constants.JSP_SERVLET_NAME)) {
                    // Override the mapping of the container provided
                    // Default- or JspServlet
                    Wrapper wrapper = (Wrapper) findChild(existing);
                    removePatternFromServlet(wrapper, pattern);
                    mapper.removeWrapper(pattern);
                    servletMappings.put(pattern, name);
                }
            } else {
                servletMappings.put(pattern, name);
            }
        }

        Wrapper wrapper = regis.getWrapper();
        wrapper.addMapping(pattern);

        // Update context mapper
        mapper.addWrapper(pattern, wrapper, jspWildCard, true);

        if (notifyContainerListeners) {
            fireContainerEvent("addServletMapping", pattern);
        }
    }

    /*
     * Adds the servlet with the given name and class name to this servlet
     * context.
     */
    public ServletRegistration.Dynamic addServlet(
            String servletName, String className) {
        synchronized (children) {
            if (findChild(servletName) == null) {
                DynamicServletRegistrationImpl regis =
                    (DynamicServletRegistrationImpl)
                        servletRegisMap.get(servletName);
                Wrapper wrapper = null;
                if (regis == null) {
                    wrapper = createWrapper();
                    wrapper.setServletClassName(className);
                } else {
                    // Complete preliminary servlet registration
                    wrapper = regis.getWrapper();
                    regis.setServletClassName(className);
                }
                wrapper.setName(servletName);
                addChild(wrapper, true, (null == regis));
                if (null == regis) {
                    regis = (DynamicServletRegistrationImpl)
                        servletRegisMap.get(servletName);
                }
                return regis;
            } else {
                return null;
            }
        }
    }

    /*
     * Registers the given servlet instance with this ServletContext
     * under the given <tt>servletName.
     */
    public ServletRegistration.Dynamic addServlet(
            String servletName, Servlet servlet) {
        return addServlet(servletName, servlet, null, null);
    }

    /*
     * Adds the servlet with the given name and class type to this servlet
     * context.
     */
    public ServletRegistration.Dynamic addServlet(String servletName,
            Class <? extends Servlet> servletClass) {
        // Make sure servlet name is unique for this context
        synchronized (children) {
            if (findChild(servletName) == null) {
                DynamicServletRegistrationImpl regis =
                    (DynamicServletRegistrationImpl)
                        servletRegisMap.get(servletName);
                Wrapper wrapper = null;
                if (regis == null) {
                    wrapper = createWrapper();
                    wrapper.setServletClass(servletClass);
                } else {
                    // Complete preliminary servlet registration
                    wrapper = regis.getWrapper();
                    regis.setServletClass(servletClass);
                }
                wrapper.setName(servletName);
                addChild(wrapper, true, (null == regis));
                if (null == regis) {
                    regis = (DynamicServletRegistrationImpl)
                        servletRegisMap.get(servletName);
                }
                return regis;
            } else {
                return null;
            }
        }
    }

    /**
     * Adds the given servlet instance with the given name to this servlet
     * context and initializes it.
     *
     * <p>In order to add any URL patterns that will be mapped to the
     * given servlet, addServletMappings must be used. If this context
     * has already been started, the URL patterns must be passed to
     * addServlet instead.
     *
     * @param servletName the servlet name
     * @param instance the servlet instance
     * @param initParams Map containing the initialization parameters for 
     * the servlet
     *
     * @throws ServletException if the servlet fails to be initialized
     */
    public ServletRegistration.Dynamic addServlet(String servletName,
            Servlet instance, Map<String, String> initParams) {
        return addServlet(servletName, instance, initParams, null);
    }

    /**
     * Adds the given servlet instance with the given name and URL patterns
     * to this servlet context, and initializes it.
     *
     * @param servletName the servlet name
     * @param servlet the servlet instance
     * @param initParams Map containing the initialization parameters for 
     * the servlet
     * @param urlPatterns the URL patterns that will be mapped to the servlet
     *
     * @return the ServletRegistration through which the servlet may be
     * further configured
     */
    public ServletRegistration.Dynamic addServlet(String servletName,
            Servlet servlet, Map<String, String> initParams,
            String... urlPatterns) {
        if (servletName == null || servlet == null) {
            throw new NullPointerException("Null servlet instance or name");
        }

        if (servlet instanceof SingleThreadModel) {
            throw new IllegalArgumentException("Servlet implements " +
                SingleThreadModel.class.getName());
        }

        /*
         * Make sure the given Servlet instance is unique across all deployed
         * contexts
         */
        Container host = getParent();
        if (host != null) {
            for (Container child : host.findChildren()) {
                if (child == this) {
                    // Our own context will be checked further down
                    continue;
                }
                if (((StandardContext) child).hasServlet(servlet)) {
                    return null;
                }
            }
        }
      
        /*
         * Make sure the given Servlet name and instance are unique within 
         * this context
         */
        synchronized (children) {
            for (Map.Entry<String, Container> e : children.entrySet()) {
                if (servletName.equals(e.getKey()) ||
                        servlet == ((StandardWrapper)e.getValue()).getServlet()) {
                    return null;
                }
            }

            DynamicServletRegistrationImpl regis =
                (DynamicServletRegistrationImpl)
                    servletRegisMap.get(servletName);
            StandardWrapper wrapper = null;
            if (regis == null) {
                wrapper = (StandardWrapper) createWrapper();
            } else {
                // Complete preliminary servlet registration
                wrapper = regis.getWrapper();
            }
                         
            wrapper.setName(servletName);
            wrapper.setServlet(servlet);
            if (initParams != null) {
                for (Map.Entry<String, String> e : initParams.entrySet()) {
                    wrapper.addInitParameter(e.getKey(), e.getValue());
                }
            }

            addChild(wrapper, true, (null == regis));
            if (null == regis) {
                regis = (DynamicServletRegistrationImpl)
                    servletRegisMap.get(servletName);
            }

            if (urlPatterns != null) {
                for (String urlPattern : urlPatterns) {
                    addServletMapping(urlPattern, servletName, false);
                }
            }

            return regis;
        }
    }

    /**
     * This method is overridden in web-glue to also remove the given
     * mapping from the deployment backend's WebBundleDescriptor.
     */
    protected void removePatternFromServlet(Wrapper wrapper, String pattern) {
        wrapper.removeMapping(pattern);
    }

    /**
     * Checks whether this context contains the given Servlet instance
     */
    public boolean hasServlet(Servlet servlet) {
        for (Map.Entry<String, Container> e : children.entrySet()) {
            if (servlet == ((StandardWrapper)e.getValue()).getServlet()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Instantiates the given Servlet class and performs any required
     * resource injection into the new Servlet instance before returning
     * it.
     */
    public <T extends Servlet> T createServlet(Class clazz)
            throws ServletException {
        try {
            return createServletInstance(clazz);
        } catch (Throwable t) {
            throw new ServletException("Unable to create Servlet from " +
                                       "class " + clazz.getName(), t);
        }
    }

    /**
     * Gets the ServletRegistration corresponding to the servlet with the
     * given <tt>servletName.
     */
    public ServletRegistration getServletRegistration(String servletName) {
        return servletRegisMap.get(servletName);
    }

    /**
     * Gets a Map of the ServletRegistration objects corresponding to all
     * currently registered servlets.
     */
    public Map<String, ? extends ServletRegistration> getServletRegistrations() {
        return Collections.unmodifiableMap(servletRegisMap);
    }

    public void setJarNameToWebFragmentNameMap(
                    Map<String, String> jarName2WebFragNameMap) {
        this.jarName2WebFragNameMap = jarName2WebFragNameMap;
    }

    public void setAbsoluteOrdering(List absoluteOrderingList) {
        this.absoluteOrderingList = absoluteOrderingList;
    }

    /**
     * @return true if this Context declares an absolute ordering of its
     * web fragments (without the use of any <others/> element), and the
     * web fragment JAR file with the given name is excluded from it;
     * false otherwise
     */
    public boolean isFragmentMissingFromAbsoluteOrdering(String jarName) {
        return (jarName2WebFragNameMap != null &&
            absoluteOrderingList != null &&
            !absoluteOrderingList.contains(
                jarName2WebFragNameMap.get(jarName)));
    }

    /**
     * Add a new watched resource to the set recognized by this Context.
     *
     * @param name New watched resource file name
     */
    public void addWatchedResource(String name) {
        watchedResources.add(name);
        fireContainerEvent("addWatchedResource", name);
    }

    /**
     * Add a new welcome file to the set recognized by this Context.
     *
     * @param name New welcome file name
     */
    public void addWelcomeFile(String name) {

        // Welcome files from the application deployment descriptor
        // completely replace those from the default conf/web.xml file
        if (replaceWelcomeFiles) {
            welcomeFiles = new String[0];
            setReplaceWelcomeFiles(false);
        }
        String results[] = new String[welcomeFiles.length + 1];
        for (int i = 0; i < welcomeFiles.length; i++)
            results[i] = welcomeFiles[i];
        results[welcomeFiles.length] = name;
        welcomeFiles = results;

        if (notifyContainerListeners) {
            fireContainerEvent("addWelcomeFile", name);
        }
    }

    /**
     * Add the classname of a LifecycleListener to be added to each
     * Wrapper appended to this Context.
     *
     * @param listener Java class name of a LifecycleListener class
     */
    public void addWrapperLifecycle(String listener) {
        wrapperLifecycles.add(listener);
        if (notifyContainerListeners) {
            fireContainerEvent("addWrapperLifecycle", listener);
        }
    }

    /**
     * Add the classname of a ContainerListener to be added to each
     * Wrapper appended to this Context.
     *
     * @param listener Java class name of a ContainerListener class
     */
    public void addWrapperListener(String listener) {
        wrapperListeners.add(listener);
        if (notifyContainerListeners) {
            fireContainerEvent("addWrapperListener", listener);
        }
    }

    /**
     * Factory method to create and return a new Wrapper instance, of
     * the Java implementation class appropriate for this Context
     * implementation.  The constructor of the instantiated Wrapper
     * will have been called, but no properties will have been set.
     */
    public Wrapper createWrapper() {
        Wrapper wrapper = new StandardWrapper();

        synchronized (instanceListeners) {
            for (String instanceListener : instanceListeners) {
                try {
                    Class clazz = Class.forName(instanceListener);
                    wrapper.addInstanceListener((InstanceListener)clazz.newInstance());
                } catch(Throwable t) {
                    log.log(Level.SEVERE,
                        sm.getString("standardContext.instanceListener",
                            instanceListener),
                        t);
                    return (null);
                }
            }
        }

        synchronized (instanceListenerInstances) {
            for(InstanceListener instanceListenerInstance : instanceListenerInstances) {
                wrapper.addInstanceListener(instanceListenerInstance);
            }
        }

        Iterator<String> i = wrapperLifecycles.iterator();
        while (i.hasNext()) {
            String wrapperLifecycle = i.next();
            try {
                Class clazz = Class.forName(wrapperLifecycle);
                if(wrapper instanceof Lifecycle) {
                    ((Lifecycle)wrapper).addLifecycleListener(
                        (LifecycleListener)clazz.newInstance());
                }
            } catch(Throwable t) {
                log.log(Level.SEVERE,
                    sm.getString("standardContext.lifecycleListener",
                                 wrapperLifecycle),
                    t);
                return (null);
            }
        }

        i = wrapperListeners.iterator(); 
        while (i.hasNext()) {
            String wrapperListener = i.next();
            try {
                Class clazz = Class.forName(wrapperListener);
                wrapper.addContainerListener((ContainerListener)
                    clazz.newInstance());
            } catch(Throwable t) {
                log.log(Level.SEVERE,
                    sm.getString("standardContext.containerListener",
                                 wrapperListener),
                    t);
                return (null);
            }
        }

        return (wrapper);
    }

    /**
     * Return the set of application parameters for this application.
     */
    public List<ApplicationParameter> findApplicationParameters() {
        return applicationParameters;
    }

    /**
     * Gets the security constraints defined for this web application.
     */
    public List<SecurityConstraint> getConstraints() {
        return constraints;
    }

    /**
     * Checks whether this web application has any security constraints
     * defined.
     */
    public boolean hasConstraints() {
        return !constraints.isEmpty();
    }

    /**
     * Return the EJB resource reference with the specified name, if any;
     * otherwise, return <code>null.
     *
     * @param name Name of the desired EJB resource reference
     */
    public ContextEjb findEjb(String name) {
        return namingResources.findEjb(name);
    }

    /**
     * Return the defined EJB resource references for this application.
     * If there are none, a zero-length array is returned.
     */
    public ContextEjb[] findEjbs() {
        return namingResources.findEjbs();
    }

    /**
     * Return the environment entry with the specified name, if any;
     * otherwise, return <code>null.
     *
     * @param name Name of the desired environment entry
     */
    public ContextEnvironment findEnvironment(String name) {
        return namingResources.findEnvironment(name);
    }

    /**
     * Return the set of defined environment entries for this web
     * application.  If none have been defined, a zero-length array
     * is returned.
     */
    public ContextEnvironment[] findEnvironments() {
        return namingResources.findEnvironments();
    }

    /**
     * Return the error page entry for the specified HTTP error code,
     * if any; otherwise return <code>null.
     *
     * @param errorCode Error code to look up
     */
    public ErrorPage findErrorPage(int errorCode) {
        if ((errorCode >= 400) && (errorCode < 600)) {
            return statusPages.get(errorCode);
        }

        return null;
    }

    /**
     * Return the error page entry for the specified Java exception type,
     * if any; otherwise return <code>null.
     *
     * @param exceptionType Exception type to look up
     */
    public ErrorPage findErrorPage(String exceptionType) {
        synchronized (exceptionPages) {
            return exceptionPages.get(exceptionType);
        }
    }

    /**
     * Gets the default error page of this context.
     *
     * <p>A default error page is an error page that was declared without
     * any exception-type and error-code.
     *
     * @return the default error page of this context, or null if this
     * context does not have any default error page
     */
    public ErrorPage getDefaultErrorPage() {
        return defaultErrorPage;
    }

    /**
     * Return the filter definition for the specified filter name, if any;
     * otherwise return <code>null.
     *
     * @param filterName Filter name to look up
     */
    public FilterDef findFilterDef(String filterName) {
        synchronized (filterDefs) {
            return filterDefs.get(filterName);
        }
    }

    /**
     * Return the set of defined filters for this Context.
     */
    public FilterDef[] findFilterDefs() {
        synchronized (filterDefs) {
            FilterDef results[] = new FilterDef[filterDefs.size()];
            return filterDefs.values().toArray(results);
        }
    }

    /**
     * Return the list of filter mappings for this Context.
     */
    public List<FilterMap> findFilterMaps() {
        return filterMaps;
    }

    /**
     * Return the list of InstanceListener classes that will be added to
     * newly created Wrappers automatically.
     */
    public List<String> findInstanceListeners() {
        return instanceListeners;
    }

    /**
     * Return the local EJB resource reference with the specified name, if any;
     * otherwise, return <code>null.
     *
     * @param name Name of the desired EJB resource reference
     */
    public ContextLocalEjb findLocalEjb(String name) {
        return namingResources.findLocalEjb(name);
    }

    /**
     * Return the defined local EJB resource references for this application.
     * If there are none, a zero-length array is returned.
     */
    public ContextLocalEjb[] findLocalEjbs() {
        return namingResources.findLocalEjbs();
    }

    /**
     * FIXME: Fooling introspection ...
     */
    public Context findMappingObject() {
        return (Context) getMappingObject();
    }

    /**
     * Return the message destination with the specified name, if any;
     * otherwise, return <code>null.
     *
     * @param name Name of the desired message destination
     */
    public MessageDestination findMessageDestination(String name) {
        synchronized (messageDestinations) {
            return messageDestinations.get(name);
        }
    }

    /**
     * Return the set of defined message destinations for this web
     * application.  If none have been defined, a zero-length array
     * is returned.
     */
    public MessageDestination[] findMessageDestinations() {
        synchronized (messageDestinations) {
            return messageDestinations.values().toArray(
                new MessageDestination[messageDestinations.size()]);
        }
    }

    /**
     * Return the message destination ref with the specified name, if any;
     * otherwise, return <code>null.
     *
     * @param name Name of the desired message destination ref
     */
    public MessageDestinationRef findMessageDestinationRef(String name) {
        return namingResources.findMessageDestinationRef(name);
    }

    /**
     * Return the set of defined message destination refs for this web
     * application.  If none have been defined, a zero-length array
     * is returned.
     */
    public MessageDestinationRef[] findMessageDestinationRefs() {
        return namingResources.findMessageDestinationRefs();
    }

    /**
     * Return the MIME type to which the specified extension is mapped,
     * if any; otherwise return <code>null.
     *
     * @param extension Extension to map to a MIME type
     */
    public String findMimeMapping(String extension) {

        String mimeType = mimeMappings.get(extension);
        if (mimeType == null) {
            // No mapping found, try case-insensitive match
            synchronized (mimeMappings) {
                for(String ext : mimeMappings.keySet()) {
                    if(ext.equalsIgnoreCase(extension)) {
                        // Case-insensitive extension match found
                        mimeType = mimeMappings.get(ext);
                        // Add given extension to the map, in order to make
                        // subsequent lookups faster
                        mimeMappings.put(extension, mimeType);
                        break;
                    }
                }
            }
        }

        return mimeType;
    }

    /**
     * Return the extensions for which MIME mappings are defined.  If there
     * are none, a zero-length array is returned.
     */
    public String[] findMimeMappings() {
        synchronized (mimeMappings) {
            return mimeMappings.keySet().toArray(
                new String[mimeMappings.size()]);
        }
    }

    /**
     * Return the value for the specified context initialization
     * parameter name, if any; otherwise return <code>null.
     *
     * @param name Name of the parameter to return
     */
    public String findParameter(String name) {
        synchronized (parameters) {
            return parameters.get(name);
        }
    }

    /**
     * Return the names of all defined context initialization parameters
     * for this Context.  If no parameters are defined, a zero-length
     * array is returned.
     */
    public String[] findParameters() {
        synchronized (parameters) {
            return parameters.keySet().toArray(new String[parameters.size()]);
        }
    }

    /**
     * Return the resource reference with the specified name, if any;
     * otherwise return <code>null.
     *
     * @param name Name of the desired resource reference
     */
    public ContextResource findResource(String name) {
        return namingResources.findResource(name);
    }

    /**
     * Return the resource environment reference type for the specified
     * name, if any; otherwise return <code>null.
     *
     * @param name Name of the desired resource environment reference
     */
    public String findResourceEnvRef(String name) {
        return namingResources.findResourceEnvRef(name);
    }

    /**
     * Return the set of resource environment reference names for this
     * web application.  If none have been specified, a zero-length
     * array is returned.
     */
    public String[] findResourceEnvRefs() {
        return namingResources.findResourceEnvRefs();
    }

    /**
     * Return the resource link with the specified name, if any;
     * otherwise return <code>null.
     *
     * @param name Name of the desired resource link
     */
    public ContextResourceLink findResourceLink(String name) {
        return namingResources.findResourceLink(name);
    }

    /**
     * Return the defined resource links for this application.  If
     * none have been defined, a zero-length array is returned.
     */
    public ContextResourceLink[] findResourceLinks() {
        return namingResources.findResourceLinks();
    }

    /**
     * Return the defined resource references for this application.  If
     * none have been defined, a zero-length array is returned.
     */
    public ContextResource[] findResources() {
        return namingResources.findResources();
    }

    /**
     * For the given security role (as used by an application), return the
     * corresponding role name (as defined by the underlying Realm) if there
     * is one.  Otherwise, return the specified role unchanged.
     *
     * @param role Security role to map
     */
    public String findRoleMapping(String role) {

        String realRole = null;
        synchronized (roleMappings) {
            realRole = roleMappings.get(role);
        }
        if (realRole != null)
            return (realRole);
        else
            return (role);
    }

    /**
     * Checks if the given security role is defined for this application.
     *
     * @param role Security role to check for
     *
     * @return true if the specified security role is defined
     * for this application, false otherwise
     */
    public boolean hasSecurityRole(String role) {
        return securityRoles.contains(role);
    }

    /**
     * Removes any security roles defined for this application.
     */
    public void removeSecurityRoles() {
        // Inform interested listeners
        if (notifyContainerListeners) {
            Iterator<String> i = securityRoles.iterator(); 
            while (i.hasNext()) {
                fireContainerEvent("removeSecurityRole", i.next());
            }
        }
        securityRoles.clear();
    }

    /**
     * Return the servlet name mapped by the specified pattern (if any);
     * otherwise return <code>null.
     *
     * @param pattern Pattern for which a mapping is requested
     */
    public String findServletMapping(String pattern) {
        synchronized (servletMappings) {
            return servletMappings.get(pattern);
        }
    }

    /**
     * Return the patterns of all defined servlet mappings for this
     * Context.  If no mappings are defined, a zero-length array is returned.
     */
    public String[] findServletMappings() {
        synchronized (servletMappings) {
            String results[] = new String[servletMappings.size()];
            return
                servletMappings.keySet().toArray(results);
        }
    }

    /**
     * Return the context-relative URI of the error page for the specified
     * HTTP status code, if any; otherwise return <code>null.
     *
     * @param status HTTP status code to look up
     */
    public ErrorPage findStatusPage(int status) {
        return statusPages.get(status);
    }

    /**
     * Return the set of HTTP status codes for which error pages have
     * been specified.  If none are specified, a zero-length array
     * is returned.
     */
    public int[] findStatusPages() {
        synchronized (statusPages) {
            int results[] = new int[statusPages.size()];
            Iterator<Integer> elements = statusPages.keySet().iterator();
            int i = 0;
            while (elements.hasNext())
                results[i++] = elements.next();
            return results;
        }
    }

    /**
     * Return <code>true if the specified welcome file is defined
     * for this Context; otherwise return <code>false.
     *
     * @param name Welcome file to verify
     */
    public boolean findWelcomeFile(String name) {
        synchronized (welcomeFiles) {
            for(String welcomeFile : welcomeFiles) {
                if(name.equals(welcomeFile)) {
                    return true;
                }
            }
        }
        return (false);
    }

    /**
     * Gets the watched resources defined for this web application.
     */
    public List<String> getWatchedResources() {
        return watchedResources;
    }

    /**
     * Return the set of welcome files defined for this Context.  If none are
     * defined, a zero-length array is returned.
     */
    public String[] findWelcomeFiles() {
        return (welcomeFiles);
    }

    /**
     * Return the list of LifecycleListener classes that will be added to
     * newly created Wrappers automatically.
     */
    public List<String> findWrapperLifecycles() {
        return wrapperLifecycles;
    }

    /**
     * Return the list of ContainerListener classes that will be added to
     * newly created Wrappers automatically.
     */
    public List<String> findWrapperListeners() {
        return wrapperListeners;
    }

    /**
     * Gets the Authenticator of this Context.
     *
     * @return the Authenticator of this Context
     */
    public Authenticator getAuthenticator() {
        Pipeline p = getPipeline();
        if (p != null) {
            for (GlassFishValve valve : p.getValves()) {
                if (valve instanceof Authenticator) {
                    return (Authenticator) valve;
                }
            }
        }
        return null;
    }

    /**
     * Reload this web application, if reloading is supported.
     * <p>
     * <b>IMPLEMENTATION NOTE:  This method is designed to deal with
     * reloads required by changes to classes in the underlying repositories
     * of our class loader.  It does not handle changes to the web application
     * deployment descriptor.  If that has occurred, you should stop this
     * Context and create (and start) a new Context instance instead.
     *
     * @exception IllegalStateException if the <code>reloadable
     *  property is set to <code>false.
     */
    public synchronized void reload() {

        // Validate our current component state
        if (!started)
            throw new IllegalStateException
                (sm.getString("containerBase.notStarted", logName()));

        // Make sure reloading is enabled
        //      if (!reloadable)
        //          throw new IllegalStateException
        //              (sm.getString("standardContext.notReloadable"));
        log.info(sm.getString("standardContext.reloadingStarted"));

        // Stop accepting requests temporarily
        setPaused(true);

        try {
            stop();
        } catch (LifecycleException e) {
            log.log(Level.SEVERE,
                    sm.getString("standardContext.stoppingContext", this),
                    e);
        }

        try {
            start();
        } catch (LifecycleException e) {
            log.log(Level.SEVERE,
                    sm.getString("standardContext.startingContext", this),
                    e);
        }

        setPaused(false);

    }

    /**
     * Remove the application parameter with the specified name from
     * the set for this application.
     *
     * @param name Name of the application parameter to remove
     */
    public void removeApplicationParameter(String name) {
        ApplicationParameter match = null;
        Iterator<ApplicationParameter> i =
            applicationParameters.iterator(); 
        while (i.hasNext()) {
            ApplicationParameter applicationParameter = i.next();
            // Make sure this parameter is currently present
            if (name.equals(applicationParameter.getName())) {
                match = applicationParameter;
                break;
            }
        }
        if (match != null) {
            applicationParameters.remove(match);
            // Inform interested listeners
            if (notifyContainerListeners) {
                fireContainerEvent("removeApplicationParameter", name);
            }
        }
    }

    /**
     * Removes the given child container.
     *
     * @param child the child container to be removed
     *
     * @exception IllegalArgumentException if the given child 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);
    }

    /**
     * Removes any security constraints from this web application.
     */
    public void removeConstraints() {
        // Inform interested listeners
        if (notifyContainerListeners) {
            Iterator<SecurityConstraint> i = constraints.iterator(); 
            while (i.hasNext()) {
                fireContainerEvent("removeConstraint", i.next());
            }
        }
        constraints.clear();
    }

    /**
     * Remove any EJB resource reference with the specified name.
     *
     * @param name Name of the EJB resource reference to remove
     */
    public void removeEjb(String name) {

        namingResources.removeEjb(name);

        if (notifyContainerListeners) {
            fireContainerEvent("removeEjb", name);
        }
    }

    /**
     * Remove any environment entry with the specified name.
     *
     * @param name Name of the environment entry to remove
     */
    public void removeEnvironment(String name) {
        if (namingResources == null) {
            return;
        }
        ContextEnvironment env = namingResources.findEnvironment(name);
        if (env == null) {
            throw new IllegalArgumentException
                ("Invalid environment name '" + name + "'");
        }

        namingResources.removeEnvironment(name);

        if (notifyContainerListeners) {
            fireContainerEvent("removeEnvironment", name);
        }
    }

    /**
     * Removes any error page declarations.
     */
    public void removeErrorPages() {
        synchronized (exceptionPages) {
            if (notifyContainerListeners) {
                for (ErrorPage errorPage : exceptionPages.values()) {
                    fireContainerEvent("removeErrorPage", errorPage);
                }
            }
            exceptionPages.clear();
        }
        synchronized (statusPages) {
            if (notifyContainerListeners) {
                for (ErrorPage statusPage : statusPages.values()) {
                    fireContainerEvent("removeErrorPage", statusPage);
                }
            }
            statusPages.clear();
        }
    }

    /**
     * Remove the specified filter definition from this Context, if it exists;
     * otherwise, no action is taken.
     *
     * @param filterDef Filter definition to be removed
     */
    public void removeFilterDef(FilterDef filterDef) {

        synchronized (filterDefs) {
            filterDefs.remove(filterDef.getFilterName());
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeFilterDef", filterDef);
        }
    }

    /**
     * Removes any filter mappings from this Context.
     */
    public void removeFilterMaps() {
        // Inform interested listeners
        if (notifyContainerListeners) {
            Iterator<FilterMap> i = filterMaps.iterator(); 
            while (i.hasNext()) {
                fireContainerEvent("removeFilterMap", i.next());
            }
        }
        filterMaps.clear();
    }

    /**
     * Remove a class name from the list of InstanceListener classes that
     * will be added to newly created Wrappers.
     *
     * @param listener Class name of an InstanceListener class to be removed
     */
    public void removeInstanceListener(String listener) {
        instanceListeners.remove(listener);
        // Inform interested listeners
        if (notifyContainerListeners) {
            fireContainerEvent("removeInstanceListener", listener);
        }
    }

    /**
     * Remove any local EJB resource reference with the specified name.
     *
     * @param name Name of the EJB resource reference to remove
     */
    public void removeLocalEjb(String name) {

        namingResources.removeLocalEjb(name);

        if (notifyContainerListeners) {
            fireContainerEvent("removeLocalEjb", name);
        }
    }

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

        if (notifyContainerListeners) {
            fireContainerEvent("removeMessageDestination", name);
        }
    }

    /**
     * Remove any message destination ref with the specified name.
     *
     * @param name Name of the message destination ref to remove
     */
    public void removeMessageDestinationRef(String name) {

        namingResources.removeMessageDestinationRef(name);

        if (notifyContainerListeners) {
            fireContainerEvent("removeMessageDestinationRef", name);
        }
    }

    /**
     * Remove the MIME mapping for the specified extension, if it exists;
     * otherwise, no action is taken.
     *
     * @param extension Extension to remove the mapping for
     */
    public void removeMimeMapping(String extension) {

        synchronized (mimeMappings) {
            mimeMappings.remove(extension);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeMimeMapping", extension);
        }
    }

    /**
     * Remove the context initialization parameter with the specified
     * name, if it exists; otherwise, no action is taken.
     *
     * @param name Name of the parameter to remove
     */
    public void removeParameter(String name) {

        synchronized (parameters) {
            parameters.remove(name);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeParameter", name);
        }
    }

    /**
     * Remove any resource reference with the specified name.
     *
     * @param resourceName Name of the resource reference to remove
     */
    public void removeResource(String resourceName) {
        String decoded = URLDecoder.decode(resourceName);
        if (namingResources == null) {
            return;
        }
        ContextResource resource = namingResources.findResource(decoded);
        if (resource == null) {
            throw new IllegalArgumentException
                ("Invalid resource name '" + decoded + "'");
        }

        namingResources.removeResource(decoded);

        if (notifyContainerListeners) {
            fireContainerEvent("removeResource", decoded);
        }
    }

    /**
     * Remove any resource environment reference with the specified name.
     *
     * @param name Name of the resource environment reference to remove
     */
    public void removeResourceEnvRef(String name) {

        namingResources.removeResourceEnvRef(name);

        if (notifyContainerListeners) {
            fireContainerEvent("removeResourceEnvRef", name);
        }
    }

    /**
     * Remove any resource link with the specified name.
     *
     * @param link Name of the resource link to remove
     */
    public void removeResourceLink(String link) {
        String decoded = URLDecoder.decode(link);
        if (namingResources == null) {
            return;
        }
        ContextResourceLink resource = namingResources.findResourceLink(decoded);
        if (resource == null) {
            throw new IllegalArgumentException
                ("Invalid resource name '" + decoded + "'");
        }

        namingResources.removeResourceLink(decoded);

        if (notifyContainerListeners) {
            fireContainerEvent("removeResourceLink", decoded);
        }
    }

    /**
     * Remove any security role reference for the specified name
     *
     * @param role Security role (as used in the application) to remove
     */
    public void removeRoleMapping(String role) {
        synchronized (roleMappings) {
            roleMappings.remove(role);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeRoleMapping", role);
        }
    }

    /**
     * Remove any servlet mapping for the specified pattern, if it exists;
     * otherwise, no action is taken.
     *
     * @param pattern URL pattern of the mapping to remove
     */
    public void removeServletMapping(String pattern) {

        String name = null;
        synchronized (servletMappings) {
            name = servletMappings.remove(pattern);
        }
        Wrapper wrapper = (Wrapper) findChild(name);
        if( wrapper != null ) {
            wrapper.removeMapping(pattern);
        }
        mapper.removeWrapper(pattern);

        if (notifyContainerListeners) {
            fireContainerEvent("removeServletMapping", pattern);
        }
    }

    /**
     * Checks whether this web application has any watched resources
     * defined.
     */
    @Override
    public boolean hasWatchedResources() {
        return !watchedResources.isEmpty();
    }

    /**
     * Clears any watched resources defined for this web application.
     */
    @Override
    public void removeWatchedResources() {
        synchronized (watchedResources) {
            // Inform interested listeners
            if (notifyContainerListeners) {
                Iterator<String> i = watchedResources.iterator(); 
                while (i.hasNext()) {
                    fireContainerEvent("removeWatchedResource", i.next());
                }
            }
            watchedResources.clear();
        }
    }
         
    @Override
    public void removeWelcomeFiles() {
        if (notifyContainerListeners) {
            for (String welcomeFile : welcomeFiles) {
                fireContainerEvent("removeWelcomeFile", welcomeFile);
            }
        }
        welcomeFiles = new String[0];
    }

    @Override
    public void removeWrapperLifecycles() {
        // Inform interested listeners
        if (notifyContainerListeners) {
            Iterator<String> i = wrapperLifecycles.iterator(); 
            while (i.hasNext()) {
                fireContainerEvent("removeWrapperLifecycle", i.next());
            }
        }
        wrapperLifecycles.clear();
    }

    @Override
    public void removeWrapperListeners() {
        // Inform interested listeners
        if (notifyContainerListeners) {
            Iterator<String> i = wrapperListeners.iterator(); 
            while (i.hasNext()) {
                fireContainerEvent("removeWrapperListener", i.next());
            }
        }
        wrapperListeners.clear();
    }

    @Override
    public void fireRequestInitializedEvent(ServletRequest request) {
        List<EventListener> listeners = getApplicationEventListeners();
        ServletRequestEvent event = null;
        if (!listeners.isEmpty()) {
            event = new ServletRequestEvent(getServletContext(), request);
            // create pre-service event
            Iterator<EventListener> iter = listeners.iterator();
            while (iter.hasNext()) {
                EventListener eventListener = iter.next();
                if (!(eventListener instanceof ServletRequestListener)) {
                    continue;
                }
                ServletRequestListener listener =
                    (ServletRequestListener) eventListener;
                // START SJSAS 6329662
                fireContainerEvent(ContainerEvent.BEFORE_REQUEST_INITIALIZED,
                    listener);
                // END SJSAS 6329662
                try {
                    listener.requestInitialized(event);
                } catch (Throwable t) {
                    log(sm.getString(
                        "standardContextValve.requestListener.requestInit",
                        listener.getClass().getName()),
                        t);
                    request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
                // START SJSAS 6329662
                } finally {
                    fireContainerEvent(ContainerEvent.AFTER_REQUEST_INITIALIZED,
                        listener);
                // END SJSAS 6329662
                }
            }
        }
    }

    @Override
    public void fireRequestDestroyedEvent(ServletRequest request) {
        List<EventListener> listeners = getApplicationEventListeners();
        if (!listeners.isEmpty()) {
            // create post-service event
            ServletRequestEvent event = new ServletRequestEvent(getServletContext(),
                request);
            int len = listeners.size();
            for (int i = 0; i < len; i++) {
                EventListener eventListener = listeners.get((len - 1) - i);
                if (!(eventListener instanceof ServletRequestListener)) {
                    continue;
                }
                ServletRequestListener listener =
                    (ServletRequestListener) eventListener;
                // START SJSAS 6329662
                fireContainerEvent(ContainerEvent.BEFORE_REQUEST_DESTROYED,
                    listener);
                // END SJSAS 6329662
                try {
                    listener.requestDestroyed(event);
                } catch (Throwable t) {
                    log(sm.getString(
                        "standardContextValve.requestListener.requestDestroyed",
                        listener.getClass().getName()),
                        t);
                    request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
                // START SJSAS 6329662
                } finally {
                    fireContainerEvent(ContainerEvent.AFTER_REQUEST_DESTROYED,
                        listener);
                // END SJSAS 6329662
                }
            }
        }
    }

    // --------------------------------------------------------- Public Methods

    /**
     * Configure and initialize the set of filters for this Context.
     * Return <code>true if all filter initialization completed
     * successfully, or <code>false otherwise.
     */
    public boolean filterStart() {

        if (log.isLoggable(Level.FINE))
            log.fine("Starting filters");
        // Instantiate and record a FilterConfig for each defined filter
        boolean ok = true;
        synchronized (filterConfigs) {
            filterConfigs.clear();
            for (String name : filterDefs.keySet()) {
                if(log.isLoggable(Level.FINE)) {
                    log.fine(" Starting filter '" + name + "'");
                }
                try {
                    filterConfigs.put(name,
                        new ApplicationFilterConfig(this,
                                                    filterDefs.get(name)));
                } catch(Throwable t) {
                    getServletContext().log
                        (sm.getString("standardContext.filterStart", name), t);
                    ok = false;
                }
            }
        }

        return (ok);

    }

    /**
     * Finalize and release the set of filters for this Context.
     * Return <code>true if all filter finalization completed
     * successfully, or <code>false otherwise.
     */
    public boolean filterStop() {

        if (log.isLoggable(Level.FINE))
            log.fine("Stopping filters");

        // Release all Filter and FilterConfig instances
        synchronized (filterConfigs) {
            for (String filterName : filterConfigs.keySet()) {
                if(log.isLoggable(Level.FINE)) {
                    log.fine(" Stopping filter '" + filterName + "'");
                }
                ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)filterConfigs.get(filterName);
                filterConfig.release();
            }
            filterConfigs.clear();
        }
        return (true);
    }

    /**
     * Find and return the initialized <code>FilterConfig for the
     * specified filter name, if any; otherwise return <code>null.
     *
     * @param name Name of the desired filter
     */
    public FilterConfig findFilterConfig(String name) {
        return filterConfigs.get(name);
    }

    /**
     * Notifies all ServletContextListeners at their contextInitialized
     * method.
     */
    protected void contextListenerStart() {
        ServletContextEvent event = new ServletContextEvent(
            getServletContext());
        for (ServletContextListener listener : contextListeners) {
            if (listener instanceof RestrictedServletContextListener) {
                listener = ((RestrictedServletContextListener) listener).
                    getNestedListener();
                context.setRestricted(true);
            }
            try {
                fireContainerEvent(ContainerEvent.BEFORE_CONTEXT_INITIALIZED,
                                   listener);
                listener.contextInitialized(event);
            } finally {
                context.setRestricted(false);
                fireContainerEvent(ContainerEvent.AFTER_CONTEXT_INITIALIZED,
                                   listener);
            }
        }

        /*
         * Make sure there are no preliminary servlet or filter
         * registrations left after all listeners have been notified
         */
        Collection<ServletRegistrationImpl> servletRegistrations =
            servletRegisMap.values();
        for (ServletRegistrationImpl regis : servletRegistrations) {
            if (null == regis.getClassName() && null == regis.getJspFile()) {
                throw new IllegalStateException(
                    sm.getString(
                        "standardContext.servletWithoutAnyClassOrJspFile",
                        regis.getName()));
            }
        }
        Collection<FilterRegistrationImpl> filterRegistrations =
            filterRegisMap.values();
        for (FilterRegistrationImpl regis : filterRegistrations) {
            if (null == regis.getClassName()) {
                throw new IllegalStateException(
                    sm.getString(
                        "standardContext.filterWithoutAnyClass",
                        regis.getName()));
            }
        }
        
        isContextInitializedCalled = true;
    }


    /**
     * Loads and instantiates the listener with the specified classname.
     *
     * @param loader the classloader to use
     * @param listenerClassName the fully qualified classname to instantiate
     *
     * @return the instantiated listener
     *
     * @throws Exception if the specified classname fails to be loaded or
     * instantiated
     */
    protected EventListener loadListener(ClassLoader loader,
                                         String listenerClassName)
            throws Exception {
        if (log.isLoggable(Level.FINE)) {
            log.fine("Configuring event listener class '" +
                     listenerClassName + "'");
        }
        return createListener((Class<EventListener>)
            loader.loadClass(listenerClassName));
    }

    /**
     * Notifies all ServletContextListeners at their contextDestroyed
     * method.
     *
     * @return <code>true if the event was processed successfully,
     * <code>false otherwise.
     */
    private boolean contextListenerStop() {

        boolean ok = true;

        if (contextListeners.isEmpty()) {
            return ok;
        }

        ServletContextEvent event = new ServletContextEvent(
            getServletContext());
        int len = contextListeners.size();
        for (int i = 0; i < len; i++) {
            // Invoke in reverse order of declaration 
            ServletContextListener listener =
                contextListeners.get((len - 1) - i);
            if (listener instanceof RestrictedServletContextListener) {
                listener = ((RestrictedServletContextListener) listener).
                    getNestedListener();
                context.setRestricted(true);
            }
            try {
                fireContainerEvent(ContainerEvent.BEFORE_CONTEXT_DESTROYED,
                                   listener);
                listener.contextDestroyed(event);
                fireContainerEvent(ContainerEvent.AFTER_CONTEXT_DESTROYED,
                                   listener);
            } catch (Throwable t) {
                context.setRestricted(false);
                fireContainerEvent(ContainerEvent.AFTER_CONTEXT_DESTROYED,
                                   listener);
                getServletContext().log(sm.getString(
                        "standardContext.listenerStop",
                        listener.getClass().getName()), t);
                ok = false;
            }
        }

        contextListeners.clear();

        return ok;
    }

    private void sessionListenerStop() {
        for (HttpSessionListener listener : sessionListeners) {
            // ServletContextListeners already had their PreDestroy called
            if (!(listener instanceof ServletContextListener)) {
                fireContainerEvent(ContainerEvent.PRE_DESTROY, listener);
            }
        }
        sessionListeners.clear();
    }

    private boolean eventListenerStop() {
        if (eventListeners.isEmpty()) {
            return true;
        }

        Iterator<EventListener> iter = eventListeners.iterator(); 
        while (iter.hasNext()) {
            EventListener listener = iter.next();
            // ServletContextListeners and HttpSessionListeners
            // already had their PreDestroy called
            if (listener instanceof ServletContextListener ||
                    listener instanceof HttpSessionListener) {
                continue;
            }
            fireContainerEvent(ContainerEvent.PRE_DESTROY, listener);
        }
        
        eventListeners.clear();

        return true;
    }

    /**
     * Allocate resources, including proxy.
     * Return <code>true if initialization was successfull,
     * or <code>false otherwise.
     */
    public boolean resourcesStart() {

        boolean ok = true;

        Hashtable<String, String> env = new Hashtable();
        if(getParent() != null) {
            env.put(ProxyDirContext.HOST, getParent().getName());
        }
        env.put(ProxyDirContext.CONTEXT, getName());
        try {
            ProxyDirContext proxyDirContext = new ProxyDirContext(env, webappResources);
            if(webappResources instanceof BaseDirContext) {
                ((BaseDirContext)webappResources).setDocBase(getBasePath(getDocBase()));
                ((BaseDirContext)webappResources).allocate();
            }
            // Register the cache in JMX
            if(isCachingAllowed()) {
                ObjectName resourcesName = new ObjectName(
                    this.getDomain() + ":type=Cache,host="
                        + getHostname() + ",path="
                    + (("".equals(encodedPath)) ? "/" : encodedPath));
                Registry.getRegistry(null, null).registerComponent
                    (proxyDirContext.getCache(), resourcesName, null);
            }
            this.resources = proxyDirContext;
        } catch(Throwable t) {
            if(log.isLoggable(Level.FINE)) {
                log.log(Level.SEVERE,
                    sm.getString("standardContext.resourcesStart",
                        getName()),
                    t);
            } else {
                log.log(Level.SEVERE,
                    sm.getString("standardContext.resourcesStart",
                        getName()) +
                        ": " + t.getMessage());
            }
            ok = false;
        }

        return ok;
    }

    /**
     * Starts this context's alternate doc base resources.
     */
    public void alternateResourcesStart() throws LifecycleException {

        if (alternateDocBases == null || alternateDocBases.isEmpty()) {
            return;
        }

        Hashtable env = new Hashtable();
        if (getParent() != null) {
            env.put(ProxyDirContext.HOST, getParent().getName());
        }
        env.put(ProxyDirContext.CONTEXT, getName());
        for(AlternateDocBase alternateDocBase : alternateDocBases) {
            String basePath = alternateDocBase.getBasePath();
            DirContext alternateWebappResources = alternateDocBase.getWebappResources();
            try {
                ProxyDirContext proxyDirContext = new ProxyDirContext(env, alternateWebappResources);
                if(alternateWebappResources instanceof BaseDirContext) {
                    ((BaseDirContext)alternateWebappResources).setDocBase(basePath);
                    ((BaseDirContext)alternateWebappResources).allocate();
                }
                alternateDocBase.setResources(proxyDirContext);
            } catch(Throwable t) {
                if(log.isLoggable(Level.FINE)) {
                    throw new LifecycleException(
                        sm.getString("standardContext.resourcesStart",
                            getName()),
                        t);
                } else {
                    throw new LifecycleException(
                        sm.getString("standardContext.resourcesStart",
                            getName()) +
                            ": " + t.getMessage());
                }
            }
        }
    }

    /**
     * Deallocate resources and destroy proxy.
     */
    public boolean resourcesStop() {

        boolean ok = true;

        try {
            if (resources != null) {
                if (resources instanceof Lifecycle) {
                    ((Lifecycle) resources).stop();
                }
                if (webappResources instanceof BaseDirContext) {
                    ((BaseDirContext) webappResources).release();
                }
                // Unregister the cache in JMX
                if (isCachingAllowed()) {
                    ObjectName resourcesName =
                        new ObjectName(this.getDomain()
                                       + ":type=Cache,host="
                                       + getHostname() + ",path="
                                       + (("".equals(getPath()))?"/"
                                          :getPath()));
                    Registry.getRegistry(null, null).unregisterComponent(resourcesName);
                }
            }
        } catch (Throwable t) {
            log.log(Level.SEVERE,
                    sm.getString("standardContext.resourcesStop"), t);
            ok = false;
        }

        this.resources = null;

        return (ok);

    }

    /**
     * Stops this context's alternate doc base resources.
     */
    public boolean alternateResourcesStop() {

        boolean ok = true;

        if (alternateDocBases == null || alternateDocBases.isEmpty()) {
            return ok;
        }
        for(AlternateDocBase alternateDocBase : alternateDocBases) {
            DirContext alternateResources = alternateDocBase.getResources();
            if(alternateResources instanceof Lifecycle) {
                try {
                    ((Lifecycle)alternateResources).stop();
                } catch(Throwable t) {
                    log.log(Level.SEVERE,
                        sm.getString("standardContext.resourcesStop"),
                        t);
                    ok = false;
                }
            }
            DirContext alternateWebappResources =
                alternateDocBase.getWebappResources();
            if(alternateWebappResources instanceof BaseDirContext) {
                try {
                    ((BaseDirContext)alternateWebappResources).release();
                } catch(Throwable t) {
                    log.log(Level.SEVERE,
                        sm.getString("standardContext.resourcesStop"),
                        t);
                    ok = false;
                }
            }
        }

        this.alternateDocBases = null;

        return (ok);
    }

    /**
     * Load and initialize all servlets marked "load on startup" in the
     * web application deployment descriptor.
     *
     * @param children Array of wrappers for all currently defined
     *  servlets (including those not declared load on startup)
     */
    /* SJSAS 6377790
    public void loadOnStartup(Container children[]){
    */
    // START SJSAS 6377790
    public void loadOnStartup(Container children[]) throws LifecycleException {
    // END SJSAS 6377790
        // Collect "load on startup" servlets that need to be initialized
        Map<Integer, List map =
            new TreeMap<Integer, List();
        for (Container aChildren : children) {
            Wrapper wrapper = (Wrapper)aChildren;
            int loadOnStartup = wrapper.getLoadOnStartup();
            if(loadOnStartup < 0) {
                continue;
            }
            Integer key = loadOnStartup;
            List<Wrapper> list = map.get(key);
            if(list == null) {
                list = new ArrayList<Wrapper>();
                map.put(key, list);
            }
            list.add(wrapper);
        }

        // Load the collected "load on startup" servlets
        for (List<Wrapper> list : map.values()) {
            for(Wrapper wrapper : list) {
                try {
                    wrapper.load();
                } catch(ServletException e) {
                    getServletContext().log
                        (sm.getString("standardWrapper.loadException",
                            getName()),
                            StandardWrapper.getRootCause(e));
                    // NOTE: load errors (including a servlet that throws
                    // UnavailableException from the init() method) are NOT
                    // fatal to application startup
                    // START SJSAS 6377790
                    throw new LifecycleException(
                        StandardWrapper.getRootCause(e));
                    // END SJSAS 6377790
                }
            }
        }
    }

    /**
     * Starts the session manager of this Context.
     */
    protected void managerStart() throws LifecycleException {
        if ((manager != null) && (manager instanceof Lifecycle)) {
            ((Lifecycle) getManager()).start();
        }
    }


    /**
     * Stops the session manager of this Context.
     */
    protected void managerStop() throws LifecycleException {
        if ((manager != null) && (manager instanceof Lifecycle)) {
            ((Lifecycle) manager).stop();
        }
    }

    /**
     * Start this Context component.
     *
     * @exception LifecycleException if a startup error occurs
     */
    @Override
    public synchronized void start() throws LifecycleException {

        if (started) {
            if (log.isLoggable(Level.INFO)) {
                log.info(sm.getString("containerBase.alreadyStarted",
                                      logName()));
            }
            return;
        }

        long startupTimeStart = System.currentTimeMillis();

        if(!initialized) {
            try {
                init();
            } catch( Exception ex ) {
                throw new LifecycleException("Error initializaing ", ex);
            }
        }
        if (log.isLoggable(Level.FINE)) {
            log.fine("Starting " +
                ("".equals(getName()) ? "ROOT" : getName()));
        }

        // Set JMX object name for proper pipeline registration
        preRegisterJMX();

        if ((oname != null) &&
            (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {
            // As things depend on the JMX registration, the context
            // must be reregistered again once properly initialized
            Registry.getRegistry(null, null).unregisterComponent(oname);
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        setAvailable(false);
        setConfigured(false);

        // Install DefaultContext configuration
        if (!getOverride()) {
            Container host = getParent();
            if (host instanceof StandardHost) {
                ((StandardHost)host).installDefaultContext(this);
                Container engine = host.getParent();
                if( engine instanceof StandardEngine ) {
                    ((StandardEngine)engine).installDefaultContext(this);
                }
            }
        }

        // Add missing components as necessary
        if (webappResources == null) {   // (1) Required by Loader
            if (log.isLoggable(Level.FINE)) {
                log.fine("Configuring default Resources");
            }
            try {
                if ((docBase != null) && (docBase.endsWith(".war")) &&
                        (!(new File(docBase).isDirectory())))
                    setResources(new WARDirContext());
                else
                    setResources(new FileDirContext());
            } catch (IllegalArgumentException e) {
                throw new LifecycleException(
                    sm.getString("standardContext.resourcesInit"), e);
            }
        }

        resourcesStart();

        // Add alternate resources
        if (alternateDocBases != null && !alternateDocBases.isEmpty()) {
            for(AlternateDocBase alternateDocBase : alternateDocBases) {
                String docBase = alternateDocBase.getDocBase();
                if(log.isLoggable(Level.FINE)) {
                    log.fine("Configuring alternate resources");
                }
                try {
                    if(docBase != null && docBase.endsWith(".war") &&
                        (!(new File(docBase).isDirectory()))) {
                        setAlternateResources(alternateDocBase,
                            new WARDirContext());
                    } else {
                        setAlternateResources(alternateDocBase,
                            new FileDirContext());
                    }
                } catch(IllegalArgumentException e) {
                    throw new LifecycleException(
                        sm.getString("standardContext.resourcesInit"), e);
                }
            }

            alternateResourcesStart();
        }

        // Look for a realm - that may have been configured earlier.
        // If the realm is added after context - it'll set itself.
        if (realm == null) {
            ObjectName realmName=null;
            try {
                realmName=new ObjectName( getEngineName() + ":type=Realm,host="
                                        + getHostname() + ",path=" + getPath());
                if( mserver.isRegistered(realmName ) ) {
                    mserver.invoke(realmName, "init",
                            new Object[] {},
                            new String[] {}
                    );
                }
            } catch( Throwable t ) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine("No realm for this host " + realmName);
                }
            }
        }

        if (getLoader() == null) {
            createLoader();
        }

        // Initialize character set mapper
        getCharsetMapper();

        // Post work directory
        postWorkDirectory();

        // Validate required extensions
        try {
            ExtensionValidator.validateApplication(getResources(), this);
        } catch (IOException ioe) {
            throw new LifecycleException(
                sm.getString("standardContext.dependencyCheck", this),
                ioe);
        }

        // Reading the "catalina.useNaming" environment variable
        String useNamingProperty = System.getProperty("catalina.useNaming");
        if ((useNamingProperty != null) &&
                ("false".equals(useNamingProperty))) {
            useNaming = false;
        }

        if (isUseNaming()) {
            if (namingContextListener == null) {
                namingContextListener = new NamingContextListener();
                namingContextListener.setDebug(getDebug());
                namingContextListener.setName(getNamingContextName());
                addLifecycleListener(namingContextListener);
            }
        }

        // Binding thread
        // START OF SJSAS 8.1 6174179
        //ClassLoader oldCCL = bindThread();
        ClassLoader oldCCL = null;
        // END OF SJSAS 8.1 6174179

        try {
            started = true;

            // Start our subordinate components, if any
            if ((loader != null) && (loader instanceof Lifecycle))
                ((Lifecycle) loader).start();
            if ((logger != null) && (logger instanceof Lifecycle))
                ((Lifecycle) logger).start();

            // Unbinding thread
            // START OF SJSAS 8.1 6174179
            //unbindThread(oldCCL);
            // END OF SJSAS 8.1 6174179

            // Binding thread
            oldCCL = bindThread();

            if ((realm != null) && (realm instanceof Lifecycle))
                ((Lifecycle) realm).start();
            if ((resources != null) && (resources instanceof Lifecycle))
                ((Lifecycle) resources).start();

            // Start our child containers, if any
            for (Container child : findChildren()) {
                if(child instanceof Lifecycle) {
                    ((Lifecycle)child).start();
                }
            }

            // Start the Valves in our pipeline (including the basic),
            // if any
            if (pipeline instanceof Lifecycle)
                ((Lifecycle) pipeline).start();

            // START SJSAS 8.1 5049111
            // Notify our interested LifecycleListeners
            lifecycle.fireLifecycleEvent(START_EVENT, null);
            // END SJSAS 8.1 5049111
        } catch (Throwable t) {
            throw new LifecycleException(t);
        } finally {
            // Unbinding thread
            unbindThread(oldCCL);
        }

        if (!getConfigured()) {
            throw new LifecycleException(
                sm.getString("standardContext.startFailed", getName()));
        }

        // Store some required info as ServletContext attributes
        postResources();
        if (orderedLibs != null && !orderedLibs.isEmpty()) {
            getServletContext().setAttribute(ServletContext.ORDERED_LIBS,
                orderedLibs);
            context.setAttributeReadOnly(ServletContext.ORDERED_LIBS);
        }

        // Initialize associated mapper
        mapper.setContext(getPath(), welcomeFiles, resources);

        // Binding thread
        oldCCL = bindThread();

        try {
            // Notify our interested LifecycleListeners
            lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

            // Support for pluggability : this has to be done before
            // listener events are fired
            callServletContainerInitializers();

            // Configure and call application event listeners
            contextListenerStart();

            // Start manager
            if ((manager != null) && (manager instanceof Lifecycle)) {
                ((Lifecycle) getManager()).start();
            }

            // Start ContainerBackgroundProcessor thread
            super.threadStart();

            // Configure and call application filters
            filterStart();

            // Load and initialize all "load on startup" servlets
            loadOnStartup(findChildren());
        } catch (Throwable t) {
            log.severe(sm.getString("standardContext.startFailed", getName()));
            try {
                stop();
            } catch (Throwable tt) {
                log.log(Level.SEVERE,
                        sm.getString("standardContext.startCleanup"), tt);
            }
            throw new LifecycleException(t);
        } finally {
            // Unbinding thread
            unbindThread(oldCCL);
        }

        // Set available status depending upon startup success
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Startup successfully completed");
        }

        setAvailable(true);

        // JMX registration
        registerJMX();

        startTimeMillis = System.currentTimeMillis();
        startupTime = startTimeMillis - startupTimeStart;

        // Send j2ee.state.running notification
        if (getObjectName() != null) {
            Notification notification =
                new Notification("j2ee.state.running", this.getObjectName(),
                                 sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

        // Close all JARs right away to avoid always opening a peak number
        // of files on startup
        if (getLoader() instanceof WebappLoader) {
            ((WebappLoader) getLoader()).closeJARs(true);
        }
    }

    protected Types getTypes() {
        return null;
    }

    protected void callServletContainerInitializers()
            throws LifecycleException {

        // Get the list of ServletContainerInitializers and the classes
        // they are interested in
        Map<Class>> interestList =
            ServletContainerInitializerUtil.getInterestList(
                servletContainerInitializers);
        Map<Class>> initializerList =
            ServletContainerInitializerUtil.getInitializerList(
                servletContainerInitializers, interestList,
                getTypes(),
                getClassLoader());
        if (initializerList == null) {
            return;
        }

        // Allow programmatic registration of ServletContextListeners, but
        // only within the scope of ServletContainerInitializer#onStartup
        isProgrammaticServletContextListenerRegistrationAllowed = true;

        // We have the list of initializers and the classes that satisfy
        // the condition. Time to call the initializers
        ServletContext ctxt = this.getServletContext();
        try {
            for (Class<? extends ServletContainerInitializer> initializer :
                    initializerList.keySet()) {
                // See IT 11333
                if (isUseMyFaces() &&
                        Globals.FACES_INITIALIZER.equals(initializer.getName())) {
                    continue;
                }
                try {
                    if (log.isLoggable(Level.FINE)) {
                        log.fine("Calling ServletContainerInitializer [" + initializer + "] onStartup with classes " +
                                initializerList.get(initializer));
                    }
                    ServletContainerInitializer iniInstance =
                        initializer.newInstance();
                    iniInstance.onStartup(
                        initializerList.get(initializer), ctxt);
                } catch (Throwable t) {
                    log.log(Level.SEVERE,
                        sm.getString(
                            "standardContext.servletContainerInitializer.error",
                            initializer.getCanonicalName()),
                        t);
                    throw new LifecycleException(t);
                }
            }
        } finally {
            isProgrammaticServletContextListenerRegistrationAllowed = false;
        }
    }

    public void setServletContainerInitializerInterestList(
            Iterable<ServletContainerInitializer> initializers)
 {
        servletContainerInitializers = initializers;
    }

    /**
     * Creates a classloader for this context.
     */
    public void createLoader() {
        ClassLoader parent = null;
        if (getPrivileged()) {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Configuring privileged default Loader");
            }
            parent = this.getClass().getClassLoader();
        } else {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Configuring non-privileged default Loader");
            }
            parent = getParentClassLoader();
        }
        WebappLoader webappLoader = new WebappLoader(parent);
        webappLoader.setDelegate(getDelegate());
        webappLoader.setUseMyFaces(useMyFaces);
        setLoader(webappLoader);
    }

    /**
     * Stop this Context component.
     *
     * @exception LifecycleException if a shutdown error occurs
     */
    @Override
    public synchronized void stop() throws LifecycleException {
        stop(false);
    }

    /**
     * Stop this Context component.
     *
     * @param isShutdown true if this Context is being stopped as part
     * of a domain shutdown (as opposed to an undeployment), and false otherwise
     * @exception LifecycleException if a shutdown error occurs
     */
    public synchronized void stop(boolean isShutdown)
            throws LifecycleException {

        // Validate and update our current component state
        if (!started) {
            if(log.isLoggable(Level.INFO))
                log.info(sm.getString("containerBase.notStarted", logName()));
            return;
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

        // Send j2ee.state.stopping notification
        if (this.getObjectName() != null) {
            Notification notification =
                new Notification("j2ee.state.stopping", this.getObjectName(),
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

        // Mark this application as unavailable while we shut down
        setAvailable(false);

        // Binding thread
        ClassLoader oldCCL = bindThread();

        try {
            // Stop our child containers, if any
            for (Container child : findChildren()) {
                if(child instanceof Lifecycle) {
                    ((Lifecycle)child).stop();
                }
            }

            // Stop our filters
            filterStop();

            // Stop ContainerBackgroundProcessor thread
            super.threadStop();

            if ((manager != null) && (manager instanceof Lifecycle)) {
                if(manager instanceof StandardManager) {
                    ((StandardManager)manager).stop(isShutdown);
                } else {
                    ((Lifecycle)manager).stop();
                }
            }

            /*
             * Stop all ServletContextListeners. It is important that they
             * are passed a ServletContext to their contextDestroyed() method
             * that still has all its attributes set. In other words, it is
             * important that we invoke these listeners before calling
             * context.clearAttributes()
             */
            contextListenerStop();

            sessionListenerStop();

            // Clear all application-originated servlet context attributes
            if (context != null) {
                context.clearAttributes();
            }

            /*
             * Stop all event listeners, including those of type
             * ServletContextAttributeListener. For the latter, it is
             * important that we invoke them after calling
             * context.clearAttributes, so that they receive the corresponding
             * attribute removal events
             */
            eventListenerStop();

            // Notify our interested LifecycleListeners
            lifecycle.fireLifecycleEvent(STOP_EVENT, null);
            started = false;

            // Stop the Valves in our pipeline (including the basic), if any
            if (pipeline instanceof Lifecycle) {
                ((Lifecycle) pipeline).stop();
            }

            // Finalize our character set mapper
            setCharsetMapper(null);

            // Stop resources
            resourcesStop();
            alternateResourcesStop();

            if ((realm != null) && (realm instanceof Lifecycle)) {
                ((Lifecycle) realm).stop();
            }
            if ((logger != null) && (logger instanceof Lifecycle)) {
                ((Lifecycle) logger).stop();
            }
            /* SJSAS 6347606
            if ((loader != null) && (loader instanceof Lifecycle)) {
                ((Lifecycle) loader).stop();
            }
            */
        } catch(Throwable t) {
            // started was "true" when it first enters the try block.
            // Note that it is set to false after STOP_EVENT is fired.
            // One need to fire STOP_EVENT to clean up naming information 
            // if START_EVENT is processed successfully.
            if (started) {
                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
            }

            if (t instanceof RuntimeException) {
                throw (RuntimeException)t;
            } else if (t instanceof LifecycleException) {
                throw (LifecycleException)t;
            } else {
                throw new LifecycleException(t);
            }
        } finally {

            // Unbinding thread
            unbindThread(oldCCL);

            // START SJSAS 6347606
            /*
             * Delay the stopping of the webapp classloader until this point,
             * because unbindThread() calls the security-checked
             * Thread.setContextClassLoader(), which may ask the current thread
             * context classloader (i.e., the webapp classloader) to load
             * Principal classes specified in the security policy file
             */
            if ((loader != null) && (loader instanceof Lifecycle)) {
                ((Lifecycle) loader).stop();
            }
            // END SJSAS 6347606
        }

        // Send j2ee.state.stopped notification
        if (this.getObjectName() != null) {
            Notification notification =
                new Notification("j2ee.state.stopped", this.getObjectName(),
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

        // Reset application context
        context = null;

        // This object will no longer be visible or used.
        try {
            resetContext();
        } catch( Exception ex ) {
            log.log(Level.SEVERE, sm.getString("standardContext.reset", this),
                    ex);
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

        if (log.isLoggable(Level.FINE))
            log.fine("Stopping complete");

    }

    /**
     * Destroys this context by cleaning it up completely.
     *
     * The problem is that undoing all the config in start() and restoring
     * a 'fresh' state is impossible. After stop()/destroy()/init()/start()
     * we should have the same state as if a fresh start was done - i.e
     * read modified web.xml, etc. This can only be done by completely
     * removing the context object and remapping a new one, or by cleaning
     * up everything.
     *
     * XXX  Should this be done in stop() ?
     */
    @Override
    public void destroy() throws Exception {
        if(oname != null) {
            // Send j2ee.object.deleted notification
            Notification notification =
                new Notification("j2ee.object.deleted", this.getObjectName(),
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        super.destroy();

        // START SJASAS 6359401
        // super.destroy() will stop session manager and cause it to unload
        // all its active sessions into a file. Delete this file, because this
        // context is being destroyed and must not leave any traces.
        if (getManager() instanceof ManagerBase) {
            ((ManagerBase)getManager()).release();
        }
        // END SJSAS 6359401

        instanceListeners.clear();
        instanceListenerInstances.clear();
    }

    private void resetContext() throws Exception, MBeanRegistrationException {
        // Restore the original state ( pre reading web.xml in start )
        // If you extend this - override this method and make sure to clean up
        children=new HashMap<String, Container>();
        startupTime = 0;
        startTimeMillis = 0;
        tldScanTime = 0;

        // Bugzilla 32867
        distributable = false;

        eventListeners.clear();
        contextListeners.clear();
        sessionListeners.clear();

        if (log.isLoggable(Level.FINE)) {
            log.fine("resetContext " + oname + " " + mserver);
        }
    }

    /**
     * Return a String representation of this component.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (getParent() != null) {
            sb.append(getParent().toString());
            sb.append(".");
        }
        sb.append("StandardContext[");
        sb.append(getName());
        sb.append("]");
        return (sb.toString());

    }

    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
    @Override
    public void backgroundProcess() {

        if (!started)
            return;

        count = (count + 1) % managerChecksFrequency;

        if ((getManager() != null) && (count == 0)) {
            if (getManager() instanceof StandardManager) {
                ((StandardManager) getManager()).processExpires();
            } else if (getManager() instanceof PersistentManagerBase) {
                PersistentManagerBase pManager =
                    (PersistentManagerBase) getManager();
                pManager.backgroundProcess();
            }
        }

        // START S1AS8PE 4965017
        if (isReload()) {
            if (getLoader() != null) {
                if (reloadable && (getLoader().modified())) {
                    try {
                        Thread.currentThread().setContextClassLoader
                            (standardContextClassLoader);
                        reload();
                    } finally {
                        if (getLoader() != null) {
                            Thread.currentThread().setContextClassLoader
                                (getClassLoader());
                        }
                    }
                }
                if (getLoader() instanceof WebappLoader) {
                    ((WebappLoader) getLoader()).closeJARs(false);
                }
            }
        }
        // END S1AS8PE 4965017
    }


    // ------------------------------------------------------ Protected Methods

    /**
     * Adjust the URL pattern to begin with a leading slash, if appropriate
     * (i.e. we are running a servlet 2.2 application).  Otherwise, return
     * the specified URL pattern unchanged.
     *
     * @param urlPattern The URL pattern to be adjusted (if needed)
     *  and returned
     */
    protected String adjustURLPattern(String urlPattern) {

        if (urlPattern == null)
            return (urlPattern);
        if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
            return (urlPattern);
        if (!isServlet22())
            return (urlPattern);
        if (log.isLoggable(Level.FINE)) {
            log.fine(sm.getString("standardContext.urlPattern.patternWarning",
                                  urlPattern));
        }
        return ("/" + urlPattern);

    }

    /**
     * Are we processing a version 2.2 deployment descriptor?
     */
    protected boolean isServlet22() {
        return publicId != null && publicId.equals(
            org.apache.catalina.startup.Constants.WebDtdPublicId_22);
    }

    /**
     * Return a File object representing the base directory for the
     * entire servlet container (i.e. the Engine container if present).
     */
    protected File engineBase() {
        String base=System.getProperty("catalina.base");
        if( base == null ) {
            StandardEngine eng=(StandardEngine)this.getParent().getParent();
            base=eng.getBaseDir();
        }
        return (new File(base));
    }


    // -------------------------------------------------------- Private Methods


    /**
     * Bind current thread, both for CL purposes and for JNDI ENC support
     * during : startup, shutdown and realoading of the context.
     *
     * @return the previous context class loader
     */
    private ClassLoader bindThread() {
        ClassLoader oldContextClassLoader =
            Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClassLoader());
        if (isUseNaming()) {
            try {
                ContextBindings.bindThread(this, this);
            } catch (Throwable e) {
                log.log(Level.WARNING, "Error during bindThread", e);
            }
        }

        return oldContextClassLoader;

    }

    /**
     * Unbind thread.
     */
    private void unbindThread(ClassLoader oldContextClassLoader) {
        Thread.currentThread().setContextClassLoader(oldContextClassLoader);
        if (isUseNaming()) {
            ContextBindings.unbindThread(this, this);
        }
    }

    /**
     * Get base path.
     */
    private String getBasePath(String docBase) {
        String basePath = null;
        Container container = this;
        while (container != null) {
            if (container instanceof Host)
                break;
            container = container.getParent();
        }
        File file = new File(docBase);
        if (!file.isAbsolute()) {
            if (container == null) {
                basePath = (new File(engineBase(), docBase)).getPath();
            } else {
                // Use the "appBase" property of this container
                String appBase = ((Host) container).getAppBase();
                file = new File(appBase);
                if (!file.isAbsolute())
                    file = new File(engineBase(), appBase);
                basePath = (new File(file, docBase)).getPath();
            }
        } else {
            basePath = file.getPath();
        }
        return basePath;
    }

    /**
     * Get app base.
     */
    private String getAppBase() {
        String appBase = null;
        Container container = this;
        while (container != null) {
            if (container instanceof Host)
                break;
            container = container.getParent();
        }
        if (container != null) {
            appBase = ((Host) container).getAppBase();
        }
        return appBase;
    }

    /**
     * Get config base.
     */
    private File getConfigBase() {
        File configBase =
            new File(System.getProperty("catalina.base"), "conf");
        if (!configBase.exists()) {
            return null;
        }
        Container container = this;
        Container host = null;
        Container engine = null;
        while (container != null) {
            if (container instanceof Host)
                host = container;
            if (container instanceof Engine)
                engine = container;
            container = container.getParent();
        }
        if (engine != null) {
            configBase = new File(configBase, engine.getName());
        }
        if (host != null) {
            configBase = new File(configBase, host.getName());
        }
        configBase.mkdirs();
        return configBase;
    }

    /**
     * Given a context path, get the config file name.
     */
    protected String getDefaultConfigFile() {
        String basename = null;
        String path = getPath();
        if ("".equals(path)) {
            basename = "ROOT";
        } else {
            basename = path.substring(1).replace('/', '_');
        }
        return (basename + ".xml");
    }

    /**
     * Copy a file.
     */
    private boolean copy(File src, File dest) {
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(src);
            os = new FileOutputStream(dest);
            byte[] buf = new byte[4096];
            while (true) {
                int len = is.read(buf);
                if (len < 0)
                    break;
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
        } catch (IOException e) {
            return false;
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                // Ignore
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (Exception e) {
                // Ignore
            }
        }
        return true;
    }


    /**
     * Get naming context full name.
     */
    public 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("/").append(stk.pop());
                }
                buff.append(getName());
                namingContextName = buff.toString();
            }
            // START RIMOD 4868393
            // append an id to make the name unique to the instance.
            namingContextName += instanceIDCounter++;
            // END RIMOD 4868393
        }
        return namingContextName;
    }

    /**
     * @return the request processing paused flag for this Context
     */
    public boolean getPaused() {
        return paused;
    }

    /**
     * Stores the resources of this application as ServletContext
     * attributes.
     */
    private void postResources() {
        getServletContext().setAttribute(
            Globals.RESOURCES_ATTR, getResources());
        context.setAttributeReadOnly(Globals.RESOURCES_ATTR);
        getServletContext().setAttribute(
            Globals.ALTERNATE_RESOURCES_ATTR, getAlternateDocBases());
        context.setAttributeReadOnly(Globals.ALTERNATE_RESOURCES_ATTR);
    }

    public String getHostname() {
        Container parentHost = getParent();
        if (parentHost != null) {
            hostName = parentHost.getName();
        }
        if ((hostName == null) || (hostName.length() < 1))
            hostName = "_";
        return hostName;
    }

    /**
     * Set the appropriate context attribute for our work directory.
     */
    private void postWorkDirectory() {

        // Acquire (or calculate) the work directory path
        String workDir = getWorkDir();
        if (workDir == null || 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 = getPath();
            if (temp.startsWith("/"))
                temp = temp.substring(1);
            temp = temp.replace('/', '_');
            temp = temp.replace('\\', '_');
            if (temp.length() < 1)
                temp = "_";
            if (hostWorkDir != null ) {
                workDir = hostWorkDir + File.separator + temp;
            } else {
                workDir = "work" + File.separator + engineName +
                    File.separator + hostName + File.separator + temp;
            }
            setWorkDir(workDir);
        }

        // Create this directory if necessary
        File dir = new File(workDir);
        if (!dir.isAbsolute()) {
            File catalinaHome = engineBase();
            String catalinaHomePath = null;
            try {
                catalinaHomePath = catalinaHome.getCanonicalPath();
                dir = new File(catalinaHomePath, workDir);
            } catch (IOException e) {
            }
        }
        dir.mkdirs();

        // Set the appropriate servlet context attribute
        getServletContext().setAttribute(ServletContext.TEMPDIR, dir);
        context.setAttributeReadOnly(ServletContext.TEMPDIR);

    }

    /**
     * Set the request processing paused flag for this Context.
     *
     * @param paused The new request processing paused flag
     */
    private void setPaused(boolean paused) {
        this.paused = paused;
    }

    /**
     * Validate the syntax of a proposed <code><url-pattern>
     * for conformance with specification requirements.
     *
     * @param urlPattern URL pattern to be validated
     */
    private boolean validateURLPattern(String urlPattern) {
        if (urlPattern == null) {
            return false;
        }
        if (urlPattern.isEmpty()) {
            return true;
        }
        if (urlPattern.indexOf('\n') >= 0 || urlPattern.indexOf('\r') >= 0) {
            log.warning(sm.getString("standardContext.crlfinurl", urlPattern));
            return false;
        }
        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 <code><url-pattern>s.
     * See Bugzilla 34805, 43079 & 43080
     */
    private void checkUnusualURLPattern(String urlPattern) {
        if (log.isLoggable(Level.INFO)) {
            if(urlPattern.endsWith("*") && (urlPattern.length() < 2 ||
                    urlPattern.charAt(urlPattern.length()-2) != '/')) {
                log.info("Suspicious url pattern: \"" + urlPattern + "\"" +
                        " in context [" + getName() + "] - see" +
                        " section SRV.11.2 of the Servlet specification" );
            }
        }
    }


    // -------------------- JMX methods  --------------------

    /**
     * Return the MBean Names of the set of defined environment entries for
     * this web application
     */
    public String[] getEnvironments() {
        ContextEnvironment[] envs = getNamingResources().findEnvironments();
        List<String> results = new ArrayList();
        for(ContextEnvironment env : envs) {
            try {
                ObjectName oname =
                    MBeanUtils.createObjectName(this.getEngineName(), env);
                results.add(oname.toString());
            } catch(MalformedObjectNameException e) {
                IllegalArgumentException iae = new IllegalArgumentException
                    ("Cannot create object name for environment " + env);
                iae.initCause(e);
                throw iae;
            }
        }
        return results.toArray(new String[results.size()]);

    }


    /**
     * Return the MBean Names of all the defined resource references for this
     * application.
     */
    public String[] getResourceNames() {

        ContextResource[] resources = getNamingResources().findResources();
        List<String> results = new ArrayList();
        for(ContextResource resource : resources) {
            try {
                ObjectName oname =
                    MBeanUtils.createObjectName(this.getEngineName(), resource);
                results.add(oname.toString());
            } catch(MalformedObjectNameException e) {
                IllegalArgumentException iae = new IllegalArgumentException
                    ("Cannot create object name for resource " + resource);
                iae.initCause(e);
                throw iae;
            }
        }
        return results.toArray(new String[results.size()]);

    }

    /**
     * Return the MBean Names of all the defined resource links for this
     * application
     */
    public String[] getResourceLinks() {

        ContextResourceLink[] links = getNamingResources().findResourceLinks();
        List<String> results = new ArrayList();
        for(ContextResourceLink link : links) {
            try {
                ObjectName oname =
                    MBeanUtils.createObjectName(this.getEngineName(), link);
                results.add(oname.toString());
            } catch(MalformedObjectNameException e) {
                IllegalArgumentException iae = new IllegalArgumentException
                    ("Cannot create object name for resource " + link);
                iae.initCause(e);
                throw iae;
            }
        }
        return results.toArray(new String[results.size()]);

    }

    // ------------------------------------------------------------- Operations


    /**
     * Add an environment entry for this web application.
     *
     * @param envName New environment entry name
     */
    public String addEnvironment(String envName, String type)
        throws MalformedObjectNameException {

        NamingResources nresources = getNamingResources();
        if (nresources == null) {
            return null;
        }
        ContextEnvironment env = nresources.findEnvironment(envName);
        if (env != null) {
            throw new IllegalArgumentException
                ("Invalid environment name - already exists '" + envName + "'");
        }
        env = new ContextEnvironment();
        env.setName(envName);
        env.setType(type);
        nresources.addEnvironment(env);

        // Return the corresponding MBean name
        ManagedBean managed = Registry.getRegistry(null, null).findManagedBean("ContextEnvironment");
        ObjectName oname =
            MBeanUtils.createObjectName(managed.getDomain(), env);
        return (oname.toString());

    }


    /**
     * Add a resource reference for this web application.
     *
     * @param resourceName New resource reference name
     */
    public String addResource(String resourceName, String type)
        throws MalformedObjectNameException {

        NamingResources nresources = getNamingResources();
        if (nresources == null) {
            return null;
        }
        ContextResource resource = nresources.findResource(resourceName);
        if (resource != null) {
            throw new IllegalArgumentException
                ("Invalid resource name - already exists'" + resourceName + "'");
        }
        resource = new ContextResource();
        resource.setName(resourceName);
        resource.setType(type);
        nresources.addResource(resource);

        // Return the corresponding MBean name
        ManagedBean managed = Registry.getRegistry(null, null).findManagedBean("ContextResource");
        ObjectName oname =
            MBeanUtils.createObjectName(managed.getDomain(), resource);
        return (oname.toString());
    }

    /**
     * Add a resource link for this web application.
     *
     * @param resourceLinkName New resource link name
     */
    public String addResourceLink(String resourceLinkName, String global,
                String name, String type) throws MalformedObjectNameException {

        NamingResources nresources = getNamingResources();
        if (nresources == null) {
            return null;
        }
        ContextResourceLink resourceLink =
                                nresources.findResourceLink(resourceLinkName);
        if (resourceLink != null) {
            throw new IllegalArgumentException
                ("Invalid resource link name - already exists'" +
                                                        resourceLinkName + "'");
        }
        resourceLink = new ContextResourceLink();
        resourceLink.setGlobal(global);
        resourceLink.setName(resourceLinkName);
        resourceLink.setType(type);
        nresources.addResourceLink(resourceLink);

        // Return the corresponding MBean name
        ManagedBean managed = Registry.getRegistry(null, null).findManagedBean("ContextResourceLink");
        ObjectName oname =
            MBeanUtils.createObjectName(managed.getDomain(), resourceLink);
        return (oname.toString());
    }

    @Override
    public ObjectName createObjectName(String hostDomain, ObjectName parentName)
            throws MalformedObjectNameException
    {
        String onameStr;
        StandardHost hst=(StandardHost)getParent();

        String hostName=getParent().getName();
        String name= "//" + ((hostName==null)? "DEFAULT" : hostName) +
                (("".equals(encodedPath)) ? "/" : encodedPath);

        String suffix=",J2EEApplication=" +
                getJ2EEApplication() + ",J2EEServer=" +
                getJ2EEServer();

        onameStr="j2eeType=WebModule,name=" + name + suffix;
        if( log.isLoggable(Level.FINE))
            log.fine("Registering " + onameStr + " for " + oname);

        // default case - no domain explictely set.
        if( getDomain() == null ) domain=hst.getDomain();
        return new ObjectName(getDomain() + ":" + onameStr);
    }

    public void updateObjectName() { 
        try {
            StandardHost host = (StandardHost) getParent();
            oname = createObjectName(host.getDomain(), host.getJmxName());
            controller = oname;
            for (Container wrapper : findChildren()) {
                ((StandardWrapper)wrapper).registerJMX(this);
            }
        } catch(Exception ex) {
            log.log(Level.INFO,
                    "Error updating ctx with jmx " + this + " " +
                    oname + " " + ex.toString(),
                    ex );
        }
    }

    private void preRegisterJMX() {
        try {
            StandardHost host = (StandardHost) getParent();
            if ((oname == null)
                    || (oname.getKeyProperty("j2eeType") == null)) {
                oname = createObjectName(host.getDomain(), host.getJmxName());
                controller = oname;
            }
        } catch(Exception ex) {
            log.log(Level.INFO,
                    "Error registering ctx with jmx " + this + " " +
                    oname + " " + ex.toString(),
                    ex );
        }
    }

    private void registerJMX() {
        try {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Checking for " + oname );
            }
            if(! Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname)) {
                controller = oname;
                Registry.getRegistry(null, null).registerComponent(
                    this, oname, null);

                // Send j2ee.object.created notification
                if (this.getObjectName() != null) {
                    Notification notification = new Notification(
                        "j2ee.object.created", this.getObjectName(),
                        sequenceNumber++);
                    broadcaster.sendNotification(notification);
                }
            }
            for (Container child : findChildren()) {
                ((StandardWrapper)child).registerJMX( this );
            }
        } catch (Exception ex) {
            log.log(Level.INFO,
                    "Error registering wrapper with jmx " + this + " " +
                    oname + " " + ex.toString(),
                    ex );
        }
    }

    /**
     * There are 2 cases:
     *
     *   1. The context is created and registered by internal APIs
     *   2. The context is created by JMX, and it'll self-register.
     *
     * @param server
     * @param name
     *
     * @return the ObjectName that was used for registration
     *
     * @throws Exception
     */
    @Override
    public ObjectName preRegister(MBeanServer server,
                                  ObjectName name)
            throws Exception
    {
        if( oname != null ) {
            //log.info( "Already registered " + oname + " " + name);
            // Temporary - /admin uses the old names
            return name;
        }
        ObjectName result=super.preRegister(server,name);
        return name;
    }

    @Override
    public void preDeregister() throws Exception {
        if( started ) {
            try {
                stop();
            } catch( Exception ex ) {
                log.log(Level.SEVERE,
                        sm.getString("standardContext.stoppingContext", this),
                        ex);
            }
        }
    }

    @Override
    public void init() throws Exception {

        if( this.getParent() == null ) {
            ObjectName parentName=getParentName();

            if( ! mserver.isRegistered(parentName)) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine("No host, creating one " + parentName);
                }
                StandardHost host=new StandardHost();
                host.setName(hostName);
                Registry.getRegistry(null, null).registerComponent(
                    host, parentName, null);
                mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );
            }
            ContextConfig config = new ContextConfig();
            this.addLifecycleListener(config);

            if (log.isLoggable(Level.FINE)) {
                log.fine( "AddChild " + parentName + " " + this);
            }
            try {
                mserver.invoke(parentName, "addChild", new Object[] { this },
                               new String[] {"org.apache.catalina.Container"});
            } catch (Exception e) {
                destroy();
                throw e;
            }
        }

        // It's possible that addChild may have started us
        if( initialized ) {
            return;
        }

        super.init();

        // START GlassFish 2439
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(INIT_EVENT, null);
        // END GlassFish 2439

        // Send j2ee.state.starting notification
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting",
                this.getObjectName(), sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

    }

    @Override
    public ObjectName getParentName() throws MalformedObjectNameException {
        // "Life" update
        String path=oname.getKeyProperty("name");
        if( path == null ) {
            log.severe(sm.getString(
                "standardContext.missingNameAttributeInName", getName()));
            return null;
        }
        if( ! path.startsWith( "//")) {
            log.severe(sm.getString("standardContext.malformedName",
                                    getName()));
        }
        path=path.substring(2);
        int delim=path.indexOf( "/" );
        hostName="localhost"; // Should be default...
        if( delim > 0 ) {
            hostName=path.substring(0, delim);
            path = path.substring(delim);
            if ("/".equals(path)) {
                this.setName("");
            } else {
                this.setName(path);
            }
        } else {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Setting path " +  path );
            }
            this.setName( path );
        }
        // XXX  The service and domain should be the same.
        String parentDomain=getEngineName();
        if( parentDomain == null ) parentDomain=domain;
        return new ObjectName( parentDomain + ":" +
                "type=Host,host=" + hostName);
    }

    public void create() throws Exception{
        init();
    }
    
    // ------------------------------------------------- ServletContext Methods
            
    /**
     * Return the value of the specified context attribute, if any;
     * otherwise return <code>null.
     */
    public Object getAttribute(String name) {
        return context.getAttribute(name);
    }
    
    /**
     * Return an enumeration of the names of the context attributes
     * associated with this context.
     */
    public Enumeration<String> getAttributeNames() {
        return context.getAttributeNames();
    }      
        
    /**
     * Returns the context path of the web application.
     */
    public String getContextPath() {
        return getPath();
    }

    /**
     * Return a <code>ServletContext object that corresponds to a
     * specified URI on the server.  
     */
    public ServletContext getContext(String uri) {       
        
        // Validate the format of the specified argument
        if ((uri == null) || (!uri.startsWith("/"))) {
            return (null);
        }

        Context child = null;
        try {
            Host host = (Host) getParent();
            String mapuri = uri;
            while (true) {
                child = (Context) host.findChild(mapuri);
                if (child != null)
                    break;
                int slash = mapuri.lastIndexOf('/');
                if (slash < 0)
                    break;
                mapuri = mapuri.substring(0, slash);
            }
        } catch (Throwable t) {
            return (null);
        }

        if (child == null) {
            return (null);
        }

        if (getCrossContext()) {
            // If crossContext is enabled, can always return the context
            return child.getServletContext();
        } else if (child == this) {
            // Can still return the current context
            return getServletContext();
        } else {
            // Nothing to return
            return (null);
        }
    }
    
    /**
     * Return the value of the specified initialization parameter, or
     * <code>null if this parameter does not exist.
     */
    public String getInitParameter(final String name) {
        return context.getInitParameter(name);
    }

    /**
     * Return the names of the context's initialization parameters, or an
     * empty enumeration if the context has no initialization parameters.
     */
    public Enumeration<String> getInitParameterNames() {
        return context.getInitParameterNames();
    }
    
    /**
     * @return true if the context initialization parameter with the given
     * name and value was set successfully on this ServletContext, and false
     * if it was not set because this ServletContext already contains a
     * context initialization parameter with a matching name
     */
    public boolean setInitParameter(String name, String value) {
        return context.setInitParameter(name, value);
    }    
        
    /**
     * Return the major version of the Java Servlet API that we implement.
     */
    public int getMajorVersion() {
        return context.getMajorVersion();
    }

    /**
     * Return the minor version of the Java Servlet API that we implement.
     */
    public int getMinorVersion() {
        return context.getMinorVersion();
    }
        
    /**
     * Return the MIME type of the specified file, or <code>null if
     * the MIME type cannot be determined.
     */
    public String getMimeType(String file) {
        
        if (file == null)
            return (null);
        int period = file.lastIndexOf(".");
        if (period < 0)
            return (null);
        String extension = file.substring(period + 1);
        if (extension.length() < 1)
            return (null);
        return (findMimeMapping(extension));
        
    }
        
    /**
     * Return a <code>RequestDispatcher object that acts as a
     * wrapper for the named servlet.
     */
    public RequestDispatcher getNamedDispatcher(String name) {
        
        // Validate the name argument
        if (name == null)
            return (null);

        // Create and return a corresponding request dispatcher
        Wrapper wrapper = (Wrapper) findChild(name);
        if (wrapper == null)
            return (null);
        
        return new ApplicationDispatcher(wrapper, null, null, null, null, name);
        
    }
    
    /**
     * Return the display name of this web application.
     */
    public String getServletContextName() {
        return getDisplayName();
    }
        
    /**
     * Remove the context attribute with the specified name, if any.
     */
    public void removeAttribute(String name) {
        context.removeAttribute(name);
    }
            
    /**
     * Bind the specified value with the specified context attribute name,
     * replacing any existing value for that name.
     */
    public void setAttribute(String name, Object value) {
        context.setAttribute(name, value);
    }
        
    /**
     * Return the name and version of the servlet container.
     */
    public String getServerInfo() {
        return context.getServerInfo();
    }
        
    /**
     * Return the real path corresponding to the given virtual path, or
     * <code>null if the container was unable to perform the
     * translation
     */
    public String getRealPath(String path) {
        if (!isFilesystemBased())
            return null;

        if (path == null) {
            return null;
        }

        File file = null;
        if (alternateDocBases == null
                || alternateDocBases.size() == 0) {
            file = new File(getBasePath(getDocBase()), path);
        } else {
            AlternateDocBase match = AlternateDocBase.findMatch(
                                                path, alternateDocBases);
            if (match != null) {
                file = new File(match.getBasePath(), path);
            } else {
                // None of the url patterns for alternate doc bases matched
                file = new File(getBasePath(getDocBase()), path);
            }
        }

        if (!file.exists()) {
            try {
                // Try looking up resource in
                // WEB-INF/lib/[*.jar]/META-INF/resources
                URL u = getMetaInfResource(path);
                return (u != null ? u.getPath() : file.getAbsolutePath());
            } catch (Exception e) {
                return null;
            }
        } else {
            return file.getAbsolutePath();
        }
    }    
    
    /**
     * Writes the specified message to a servlet log file.
     */
    public void log(String message) {
        org.apache.catalina.Logger logger = getLogger();
        if (logger != null) {
            /* PWC 6403328
            logger.log(context.logName() + message, Logger.INFORMATION);
            */
            //START PWC 6403328
            logger.log(logPrefix + message, org.apache.catalina.Logger.INFORMATION);
            //END PWC 6403328
        }
    }
    
    /**
     * Writes the specified exception and message to a servlet log file.
     */
    public void log(Exception exception, String message) {     
        org.apache.catalina.Logger logger = getLogger();
        if (logger != null)
            logger.log(exception, logName() + message);
    }       
        
    /**
     * Writes the specified message and exception to a servlet log file.
     */
    public void log(String message, Throwable throwable) {
        org.apache.catalina.Logger logger = getLogger();
        if (logger != null)
            logger.log(logName() + message, throwable);
    }
        
    public Servlet getServlet(String name) {
        return context.getServlet(name);
    }
    
    public Enumeration<String> getServletNames() {
        return context.getServletNames();
    }            
        
    public Enumeration<Servlet> getServlets() {
        return context.getServlets();
    }
        
    /**
     * Return the requested resource as an <code>InputStream.  The
     * path must be specified according to the rules described under
     * <code>getResource.  If no such resource can be identified,
     * return <code>null.
     */
    public InputStream getResourceAsStream(String path) {

        if (path == null || !path.startsWith("/"))
            return (null);

        path = RequestUtil.normalize(path);
        if (path == null)
            return (null);

        DirContext resources = null;

        if (alternateDocBases == null
                || alternateDocBases.size() == 0) {
            resources = getResources();
        } else {
            AlternateDocBase match = AlternateDocBase.findMatch(
                                path, alternateDocBases);
            if (match != null) {
                resources = match.getResources();
            } else {
                // None of the url patterns for alternate doc bases matched
                resources = getResources();
            }
        }

        if (resources != null) {
            try {
                Object resource = resources.lookup(path);
                if (resource instanceof Resource)
                    return (((Resource) resource).streamContent());
            } catch (Exception e) {
                try {
                    // Try looking up resource in
                    // WEB-INF/lib/[*.jar]/META-INF/resources
                    URL u = getMetaInfResource(path);
                    return (u != null ? u.openStream() : null);
                } catch (Exception ee) {
                    // do nothing
                }
            }
        }
        return (null);
    }
        
    /**
     * Return the URL to the resource that is mapped to a specified path.
     * The path must begin with a "/" and is interpreted as relative to the
     * current context root.
     */
    public java.net.URL getResource(String path)
        throws MalformedURLException {

        if (path == null || !path.startsWith("/")) {
            throw new MalformedURLException(
                sm.getString("applicationContext.resourcePaths.iae",
                             path));
        }
        
        path = RequestUtil.normalize(path);
        if (path == null)
            return (null);

        String libPath = "/WEB-INF/lib/";
        if ((path.startsWith(libPath)) && (path.endsWith(".jar"))) {
            File jarFile = null;
            if (isFilesystemBased()) {
                jarFile = new File(getBasePath(docBase), path);
            } else {
                jarFile = new File(getWorkPath(), path);
            }
            if (jarFile.exists()) {
                return jarFile.toURL();
            } else {
                return null;
            }

        } else {

            DirContext resources = null;
            if (alternateDocBases == null
                    || alternateDocBases.size() == 0) {
                resources = context.getResources();
            } else {
                AlternateDocBase match = AlternateDocBase.findMatch(
                                                path, alternateDocBases);
                if (match != null) {
                    resources = match.getResources();
                } else {
                    // None of the url patterns for alternate doc bases matched
                    resources = getResources();
                }
            }

            if (resources != null) {
                String fullPath = getName() + path;
                String hostName = getParent().getName();
                try {
                    resources.lookup(path);
                    return new java.net.URL
                        /* SJSAS 6318494
                        ("jndi", null, 0, getJNDIUri(hostName, fullPath),
                         */
                        // START SJAS 6318494
                        ("jndi", "", 0, getJNDIUri(hostName, fullPath),
                        // END SJSAS 6318494
		         new DirContextURLStreamHandler(resources));
                } catch (Exception e) {
                    try {
                        // Try looking up resource in
                        // WEB-INF/lib/[*.jar]/META-INF/resources
                        return getMetaInfResource(path);
                    } catch (Exception ee) {
                        // do nothing
                    }
                }
            }
        }

        return (null);
    }
        
    /**
     * Return a Set containing the resource paths of resources member of the
     * specified collection. Each path will be a String starting with
     * a "/" character. The returned set is immutable.
     */
    public Set<String> getResourcePaths(String path) {
        // Validate the path argument
        if (path == null) {
            return null;
        }
        if (!path.startsWith("/")) {
            throw new IllegalArgumentException
                (sm.getString("applicationContext.resourcePaths.iae", path));
        }

        path = RequestUtil.normalize(path);
        if (path == null)
            return (null);

        DirContext resources = null;

        if (alternateDocBases == null
                || alternateDocBases.size() == 0) {
            resources = getResources();
        } else {
            AlternateDocBase match = AlternateDocBase.findMatch(
                                path, alternateDocBases);
            if (match != null) {
                resources = match.getResources();
            } else {
                // None of the url patterns for alternate doc bases matched
                resources = getResources();
            }
        }

        if (resources != null) {
            return (getResourcePathsInternal(resources, path));
        }

        return (null);
    }    
    
    /**
     * Internal implementation of getResourcesPath() logic.
     *
     * @param resources Directory context to search
     * @param path Collection path
     */
    private Set<String> getResourcePathsInternal(DirContext resources,
                                                 String path) {
        HashSet<String> set = new HashSet();
        try {
            listCollectionPaths(set, resources, path);
        } catch (NamingException e) {
            // Ignore, need to check for resource paths underneath
            // WEB-INF/lib/[*.jar]/META-INF/resources, see next
        }
        try {
            // Trigger expansion of bundled JAR files
            URL u = getMetaInfResource(path);
            String realPath = (u != null ? u.getPath() : null);
            if (realPath != null) {
                File[] children = new File(realPath).listFiles();
                StringBuilder sb = null;
                for (File child : children) {
                    sb = new StringBuilder(path);
                    sb.append("/");
                    sb.append(child.getName());
                    if (child.isDirectory()) {
                        sb.append("/");
                    }
                    set.add(sb.toString());
                }
            }
        } catch (Exception e) {
            // ignore
        }
        return Collections.unmodifiableSet(set);
    }
         
    /**
     * Return a <code>RequestDispatcher instance that acts as a
     * wrapper for the resource at the given path.  The path must begin
     * with a "/" and is interpreted as relative to the current context root.
     */
    public RequestDispatcher getRequestDispatcher(String path) {
        
        // Validate the path argument
        if (path == null) {
            return null;
        }

        if (!path.startsWith("/") && !path.isEmpty()) {
            throw new IllegalArgumentException(
                sm.getString("applicationContext.requestDispatcher.iae",
                             path));
        }

        // Get query string
        String queryString = null;
        int pos = path.indexOf('?');
        if (pos >= 0) {
            queryString = path.substring(pos + 1);
            path = path.substring(0, pos);
        }

        path = RequestUtil.normalize(path);
        if (path == null)
            return (null);

        pos = path.length();

        // Use the thread local URI and mapping data
        DispatchData dd = dispatchData.get();
        if (dd == null) {
            dd = new DispatchData();
            dispatchData.set(dd);
        }

        MessageBytes uriMB = dd.uriMB;
        uriMB.recycle();

        // Retrieve the thread local mapping data
        MappingData mappingData = dd.mappingData;

        // Map the URI
        CharChunk uriCC = uriMB.getCharChunk();
        try {
            uriCC.append(getPath(), 0, getPath().length());
            /*
             * Ignore any trailing path params (separated by ';') for mapping
             * purposes
             */
            int semicolon = path.indexOf(';');
            if (pos >= 0 && semicolon > pos) {
                semicolon = -1;
            }
            uriCC.append(path, 0, semicolon > 0 ? semicolon : pos);
            getMapper().map(uriMB, mappingData);
            if (mappingData.wrapper == null) {
                return (null);
            }
            /*
             * Append any trailing path params (separated by ';') that were
             * ignored for mapping purposes, so that they're reflected in the
             * RequestDispatcher's requestURI
             */
            if (semicolon > 0) {
                uriCC.append(path, semicolon, pos - semicolon);
            }
        } catch (Exception e) {
            // Should never happen
            log(sm.getString("applicationContext.mapping.error"), e);
            return (null);
        }

        Wrapper wrapper = (Wrapper) mappingData.wrapper;
        String wrapperPath = mappingData.wrapperPath.toString();
        String pathInfo = mappingData.pathInfo.toString();

        mappingData.recycle();
        
        // Construct a RequestDispatcher to process this request
        return new ApplicationDispatcher
            (wrapper, uriCC.toString(), wrapperPath, pathInfo, 
             queryString, null);
    }
    
        
    // ------------------------------------------------------------- Attributes


    /**
     * Return the naming resources associated with this web application.
     */
    public DirContext getStaticResources() {
        return getResources();
    }

    /**
     * Return the naming resources associated with this web application.
     * FIXME: Fooling introspection ...
     */
    public DirContext findStaticResources() {
        return getResources();
    }

    /**
     * Return the naming resources associated with this web application.
     */
    public String[] getWelcomeFiles() {
        return findWelcomeFiles();
    }

    /**
     * Set the validation feature of the XML parser used when
     * parsing xml instances.
     * @param webXmlValidation true to enable xml instance validation
     */
    public void setXmlValidation(boolean webXmlValidation){
        this.webXmlValidation = webXmlValidation;
    }

    /**
     * Get the server.xml <context> attribute's xmlValidation.
     * @return true if validation is enabled.
     *
     */
    public boolean getXmlValidation(){
        return webXmlValidation;
    }

    /**
     * Get the server.xml <context> attribute's xmlNamespaceAware.
     * @return true if namespace awarenes is enabled.
     */
    public boolean getXmlNamespaceAware(){
        return webXmlNamespaceAware;
    }

    /**
     * Set the namespace aware feature of the XML parser used when
     * parsing xml instances.
     * @param webXmlNamespaceAware true to enable namespace awareness
     */
    public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
        this.webXmlNamespaceAware= webXmlNamespaceAware;
    }

    /**
     * Set the validation feature of the XML parser used when
     * parsing tlds files.
     * @param tldValidation true to enable xml instance validation
     */
    public void setTldValidation(boolean tldValidation){
        this.tldValidation = tldValidation;
    }

    /**
     * Get the server.xml <context> attribute's webXmlValidation.
     * @return true if validation is enabled.
     *
     */
    public boolean getTldValidation(){
        return tldValidation;
    }

    /**
     * Get the server.xml <host> attribute's xmlNamespaceAware.
     * @return true if namespace awarenes is enabled.
     */
    public boolean getTldNamespaceAware(){
        return tldNamespaceAware;
    }

    /**
     * Set the namespace aware feature of the XML parser used when
     * parsing xml instances.
     * @param tldNamespaceAware true to enable namespace awareness
     */
    public void setTldNamespaceAware(boolean tldNamespaceAware){
        this.tldNamespaceAware= tldNamespaceAware;
    }    
    
    /**
     * Sets the list of ordered libs, which will be used as the value of the
     * ServletContext attribute with name javax.servlet.context.orderedLibs
     */
    public void setOrderedLibs(List<String> orderedLibs) {
        this.orderedLibs = orderedLibs;
    }

    public void startRecursive() throws LifecycleException {
        // nothing to start recursively, the servlets will be started by
        // load-on-startup
        start();
    }

    public int getState() {
        if( started ) {
            return 1; // RUNNING
        }
        if( initialized ) {
            return 0; // starting ? 
        }
        if( ! available ) { 
            return 4; //FAILED
        }
        // 2 - STOPPING
        return 3; // STOPPED
    }

    boolean isContextInitializedCalled() {
        return isContextInitializedCalled;
    }

    /**
     * Creates an ObjectInputStream that provides special deserialization
     * logic for classes that are normally not serializable (such as
     * javax.naming.Context).
     */
    public ObjectInputStream createObjectInputStream(InputStream is)
            throws IOException {

        ObjectInputStream ois = null;

        Loader loader = getLoader();
        if (loader != null) {
            ClassLoader classLoader = loader.getClassLoader();
            if (classLoader != null) {
                try {
                    ois = new CustomObjectInputStream(is, classLoader);
                } catch (IOException ioe) {
                    log.log(Level.SEVERE,
                            "Unable to create custom ObjectInputStream",
                            ioe);
                }
            }
        }

        if (ois == null) {
            ois = new ObjectInputStream(is);
        }

        return ois;
    }

    /**
     * Creates an ObjectOutputStream that provides special serialization
     * logic for classes that are normally not serializable (such as
     * javax.naming.Context).
     */
    public ObjectOutputStream createObjectOutputStream(OutputStream os)
            throws IOException {
        return new ObjectOutputStream(os); 
    }

    /**
     * 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 getStartTimeMillis() {
        return startTimeMillis;
    }
    
    public boolean isEventProvider() {
        return false;
    }
    
    public boolean isStatisticsProvider() {
        return false;
    }

    /*
     * HTTP session related monitoring events
     */
    public void sessionCreatedEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionDestroyedEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionRejectedEvent(int maxSessions) {
        // Deliberate noop
    }

    public void sessionExpiredEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionPersistedStartEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionPersistedEndEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionActivatedStartEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionActivatedEndEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionPassivatedStartEvent(HttpSession session) {
        // Deliberate noop
    }

    public void sessionPassivatedEndEvent(HttpSession session) {
        // Deliberate noop
    }
    
    public static class RestrictedServletContextListener
            implements ServletContextListener {

        /*
         * The ServletContextListener to which to delegate
         */
        private ServletContextListener delegate;

        /**
         * Constructor
         */
        public RestrictedServletContextListener(
                ServletContextListener delegate) {
            this.delegate = delegate;
        }
        
        public void contextInitialized(ServletContextEvent sce) {
            delegate.contextInitialized(sce);
        }

        public void contextDestroyed(ServletContextEvent sce) {
            delegate.contextDestroyed(sce);
        }

        public ServletContextListener getNestedListener() {
            return delegate;
        }
    }

    /**
     * Instantiates the given Servlet class.
     *
     * @return the new Servlet instance
     */
    protected <T extends Servlet> T createServletInstance(Class clazz)
            throws Exception{
        return clazz.newInstance();
    }

    /**
     * Instantiates the given Filter class.
     *
     * @return the new Filter instance
     */
    protected <T extends Filter> T createFilterInstance(Class clazz)
            throws Exception{
        return clazz.newInstance();
    }

    /**
     * Instantiates the given EventListener class.
     *
     * @return the new EventListener instance
     */
    public <T extends EventListener> T createListenerInstance(
                Class<T> clazz) throws Exception{
        return clazz.newInstance();
    }

    /**
     * Custom security manager responsible for enforcing permission
     * check on ServletContext#getClassLoader if necessary.
     */
    private static class MySecurityManager extends SecurityManager {

        /*
         * @return true if the specified class loader <code>cl
         * can be found in the class loader delegation chain of the
         * <code>start class loader, false otherwise
         */
        boolean isAncestor(ClassLoader start, ClassLoader cl) {
            ClassLoader acl = start;
            do {
	        acl = acl.getParent();
                if (cl == acl) {
                    return true;
                }
            } while (acl != null);
            return false;
        }

        /*
         * Checks whether access to the webapp class loader associated 
         * with this Context should be granted to the caller of 
         * ServletContext#getClassLoader.
         *
         * If no security manager exists, this method returns immediately.
         *
         * Otherwise, it calls the security manager's checkPermission
         * method with the getClassLoader permission if the class loader
         * of the caller of ServletContext#getClassLoader is not the same as,
         * or an ancestor of the webapp class loader associated with this
         * Context.
         */
        void checkGetClassLoaderPermission(ClassLoader webappLoader) {
            SecurityManager sm = System.getSecurityManager();
            if (sm == null) {
                return;
            }

            // Get the current execution stack as an array of classes
            Class[] classContext = getClassContext();

            /*
             * Determine the caller of ServletContext#getClassLoader:
             *
             * classContext[0]:
             *   org.apache.catalina.core.StandardContext$MySecurityManager
             * classContext[1]:
             *   org.apache.catalina.core.StandardContext
             * classContext[2]:
             *   org.apache.catalina.core.StandardContext
             * classContext[3]:
             *   org.apache.catalina.core.ApplicationContext
             * classContext[4]:
             *  org.apache.catalina.core.ApplicationContextFacade
             * classContext[5]:
             *  Caller whose classloader to check
             *
             * NOTE: INDEX MUST BE ADJUSTED WHENEVER EXECUTION STACK
             * CHANGES, E.G., DUE TO CODE BEING REORGANIZED
             */
            ClassLoader ccl = classContext[5].getClassLoader();
            if (ccl != null && ccl != webappLoader && 
                    !isAncestor(webappLoader, ccl)) {
                sm.checkPermission(GET_CLASSLOADER_PERMISSION);
            }
        }
    }

    private static class PrivilegedCreateSecurityManager implements PrivilegedAction {
        public Object run() {
            return new MySecurityManager();
        }
    }

    /**
     * List resource paths (recursively), and store all of them in the given
     * Set.
     */
    private static void listCollectionPaths
        (Set<String> set, DirContext resources, String path)
        throws NamingException {

        Enumeration<Binding> childPaths = resources.listBindings(path);
        while (childPaths.hasMoreElements()) {
            Binding binding = childPaths.nextElement();
            String name = binding.getName();
            StringBuilder childPath = new StringBuilder(path);
            if (!"/".equals(path) && !path.endsWith("/"))
                childPath.append("/");
            childPath.append(name);
            Object object = binding.getObject();
            if (object instanceof DirContext) {
                childPath.append("/");
            }
            set.add(childPath.toString());
        }
    }
    
    /**
     * Get full path, based on the host name and the context path.
     */
    private static String getJNDIUri(String hostName, String path) {
        if (!path.startsWith("/"))
            return "/" + hostName + "/" + path;
        else
            return "/" + hostName + path;
    }
    
    /**
     * Internal class used as thread-local storage when doing path
     * mapping during dispatch.
     */
    private static final class DispatchData {
        public MessageBytes uriMB;
        public MappingData mappingData;

        public DispatchData() {
            uriMB = MessageBytes.newInstance();
            CharChunk uriCC = uriMB.getCharChunk();
            uriCC.setLimit(-1);
            mappingData = new MappingData();
        }
    }

    /**
     * Get resource from META-INF/resources/ in jars.
     */
    URL getMetaInfResource(String path) {

        path = Globals.META_INF_RESOURCES + path;

        ClassLoader cl = getLoader().getClassLoader();
        if (cl instanceof WebappClassLoader) {
            return ((WebappClassLoader)cl).getResourceFromJars(path);
        }

        // This probably won't happen
        return cl.getResource(path);
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish StandardContext.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.