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

Glassfish example source code file (WebContainer.java)

This example Glassfish source code file (WebContainer.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

container, exception, inject, io, lifecycleexception, lifecycleexception, list, list, log, logging, net, network, object, servlet, string, string, virtualserver, virtualserver, webconnector, webmodule

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

package com.sun.enterprise.web;

import com.sun.appserv.server.util.Version;
import com.sun.common.util.logging.LoggingConfigImpl;
import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.SessionProperties;
import com.sun.enterprise.container.common.spi.util.ComponentEnvManager;
import com.sun.enterprise.container.common.spi.util.InjectionManager;
import com.sun.enterprise.container.common.spi.util.JavaEEIOUtils;
import com.sun.enterprise.deployment.WebBundleDescriptor;
import com.sun.enterprise.deployment.WebComponentDescriptor;
import com.sun.enterprise.deployment.archivist.WebArchivist;
import com.sun.enterprise.deployment.runtime.web.ManagerProperties;
import com.sun.enterprise.deployment.runtime.web.SessionManager;
import com.sun.enterprise.deployment.runtime.web.StoreProperties;
import com.sun.enterprise.deployment.runtime.web.*;
import com.sun.enterprise.deployment.util.WebValidatorWithoutCL;
import com.sun.enterprise.security.integration.RealmInitializer;
import com.sun.enterprise.util.Result;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.v3.services.impl.ContainerMapper;
import com.sun.enterprise.v3.services.impl.GrizzlyService;
import com.sun.enterprise.web.connector.coyote.PECoyoteConnector;
import com.sun.enterprise.web.logger.FileLoggerHandlerFactory;
import com.sun.enterprise.web.logger.IASLogger;
import com.sun.enterprise.web.pluggable.WebContainerFeatureFactory;
import com.sun.enterprise.web.reconfig.WebConfigListener;
import com.sun.grizzly.config.ContextRootInfo;
import com.sun.grizzly.config.dom.NetworkConfig;
import com.sun.grizzly.config.dom.NetworkListener;
import com.sun.grizzly.config.dom.NetworkListeners;
import com.sun.grizzly.util.buf.MessageBytes;
import com.sun.grizzly.util.http.mapper.Mapper;
import com.sun.grizzly.util.http.mapper.MappingData;
import com.sun.hk2.component.ConstructorWomb;
import com.sun.logging.LogDomains;
import org.apache.catalina.*;
import org.apache.catalina.Engine;
import org.apache.catalina.connector.Request;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.jasper.runtime.JspFactoryImpl;
import org.apache.jasper.xmlparser.ParserUtils;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.api.web.TldProvider;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.api.ServerContext;
import org.glassfish.internal.data.ApplicationRegistry;
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.grizzly.ContextMapper;
import org.glassfish.web.admin.monitor.*;
import org.glassfish.web.valve.GlassFishValve;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.Habitat;
import org.jvnet.hk2.component.PostConstruct;
import org.jvnet.hk2.component.PreDestroy;
import org.jvnet.hk2.component.Singleton;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.ObservableBean;
import org.jvnet.hk2.config.types.Property;
import org.xml.sax.EntityResolver;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.imageio.ImageIO;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.tagext.JspTag;
import java.io.File;
import java.io.IOException;
import java.lang.ClassLoader;
import java.net.BindException;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Web container service
 *
 * @author jluehe
 * @author amyroh
 * @author swchan2
 */
@SuppressWarnings({"StringContatenationInLoop"})
@Service(name = "com.sun.enterprise.web.WebContainer")
@Scoped(Singleton.class)
public class WebContainer implements org.glassfish.api.container.Container, PostConstruct, PreDestroy, EventListener {

    // -------------------------------------------------- Constants

    public static final String DISPATCHER_MAX_DEPTH = "dispatcher-max-depth";

    static final int DEFAULT_REAP_INTERVAL = 60;   // 1 minute

    public static final String JWS_APPCLIENT_EAR_NAME = "__JWSappclients";
    public static final String JWS_APPCLIENT_WAR_NAME = "sys";
    private static final String JWS_APPCLIENT_MODULE_NAME = JWS_APPCLIENT_EAR_NAME + ":" + JWS_APPCLIENT_WAR_NAME + ".war";

    private static final String DOL_DEPLOYMENT =
            "com.sun.enterprise.web.deployment.backend";

    private static final String MONITORING_NODE_SEPARATOR = "/";
    /**
     * The logger to use for logging ALL web container related messages.
     */
    protected static final Logger _logger = LogDomains.getLogger(
            WebContainer.class, LogDomains.WEB_LOGGER);

    protected static final ResourceBundle rb = _logger.getResourceBundle();

    /**
     * The current <code>WebContainer instance used (single).
     */
    protected static WebContainer webContainer;

    /**
     * Are we using Tomcat deployment backend or DOL?
     */
    protected static boolean useDOLforDeployment = true;

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

    @Inject
    private Domain domain;

    @Inject
    private Habitat habitat;

    @Inject
    ServerContext _serverContext;

    @Inject
    private ApplicationRegistry appRegistry;

    @Inject
    private ComponentEnvManager componentEnvManager;

    @Inject(name = ServerEnvironment.DEFAULT_INSTANCE_NAME)
    private Config serverConfig;

    @Inject(optional = true)
    private DasConfig dasConfig;

    @Inject
    private Events events;

    @Inject
    private ClassLoaderHierarchy clh;

    @Inject
    private GrizzlyService grizzlyService;

    @Inject
    private LoggingConfigImpl logConfig;

    //@Inject
    //MonitoringService monitoringService;

    @Inject
    private FileLoggerHandlerFactory fileLoggerHandlerFactory;

    @Inject
    private JavaEEIOUtils javaEEIOUtils;

    private HashMap<String, WebConnector> connectorMap = new HashMap();

    private EmbeddedWebContainer _embedded;
    private Engine engine;
    private String instanceName;

    private String logLevel = "INFO";


    private WebConnector jkConnector;

    /**
     * Allow disabling accessLog mechanism
     */
    protected boolean globalAccessLoggingEnabled = true;

    /**
     * AccessLog buffer size for storing logs.
     */
    protected String globalAccessLogBufferSize = null;

    /**
     * AccessLog interval before the valve flush its buffer to the disk.
     */
    protected String globalAccessLogWriteInterval = null;

    /**
     * The default-redirect port
     */
    protected int defaultRedirectPort = -1;

    /**
     * <tt>false when the Grizzly File Cache is enabled. When disabled
     * the Servlet Container temporary Naming cache is used when loading the
     * resources.
     */
    protected boolean catalinaCachingAllowed = true;

    @Inject
    protected ServerEnvironment instance = null;

    // TODO
    //protected WebModulesManager webModulesManager = null;
    //protected AppsManager appsManager = null;

    /**
     * The schema2beans object that represents the root node of server.xml.
     */
    private Server _serverBean = null;

    /**
     * Controls the verbosity of the web container subsystem's debug messages.
     * <p/>
     * This value is non-zero only when the iAS level is one of FINE, FINER
     * or FINEST.
     */
    protected int _debug = 0;

    /**
     * Top-level directory for files generated (compiled JSPs) by
     * standalone web modules.
     */
    private String _modulesWorkRoot = null;

    /**
     * Absolute path for location where all the deployed
     * standalone modules are stored for this Server Instance.
     */
    protected File _modulesRoot = null;

    /**
     * Top-level directory for files generated by application web modules.
     */
    private String _appsWorkRoot = null;

    // START S1AS 6178005
    /**
     * Top-level directory where ejb stubs for applications are stored.
     */
    private String appsStubRoot = null;
    // END S1AS 6178005

    /**
     * Indicates whether dynamic reloading is enabled (as specified by
     * the dynamic-reload-enabled attribute of <applications> in server.xml)
     */
    private boolean _reloadingEnabled = false;

    /**
     * The number of seconds between checks for modified classes (if
     * dynamic reloading is enabled).
     * <p/>
     * This value is specified by the reload-poll-interval attribute of
     * <applications> in server.xml.
     */
    private int _pollInterval = 2;

    /**
     * Has this component been started yet?
     */
    protected boolean _started = false;

    /**
     * The global (at the http-service level) ssoEnabled property.
     */
    protected boolean globalSSOEnabled = true;

    protected volatile WebContainerFeatureFactory webContainerFeatureFactory;

    /**
     * The value of the instance-level session property named "enableCookies"
     */
    boolean instanceEnableCookies = true;

    @Inject
    ServerConfigLookup serverConfigLookup;

    protected JspProbeProvider jspProbeProvider = null;
    protected RequestProbeProvider requestProbeProvider = null;
    protected ServletProbeProvider servletProbeProvider = null;
    protected SessionProbeProvider sessionProbeProvider = null;
    protected WebModuleProbeProvider webModuleProbeProvider = null;

    protected WebConfigListener configListener = null;

    // Indicates whether we are being shut down
    private boolean isShutdown = false;

    private final Object mapperUpdateSync = new Object();

    private SecurityService securityService = null;

    private WebStatsProviderBootstrap webStatsProviderBootstrap = null;

    private InjectionManager injectionMgr;

    private InvocationManager invocationMgr;

    private Collection<TldProvider> tldProviders;

    private String logServiceFile = null;

    /**
     * Static initialization
     */
    static {
        if (System.getProperty(DOL_DEPLOYMENT) != null) {
            useDOLforDeployment = Boolean.valueOf(System.getProperty(DOL_DEPLOYMENT));
        }
    }

    public void postConstruct() {

        createProbeProviders();

        injectionMgr = habitat.getByContract(InjectionManager.class);
        invocationMgr = habitat.getByContract(InvocationManager.class);
        tldProviders = habitat.getAllByContract(TldProvider.class);

        //createMonitoringConfig();
        createStatsProviders();

        setJspFactory();

        _appsWorkRoot =
                instance.getApplicationCompileJspPath().getAbsolutePath();
        _modulesRoot = instance.getApplicationRepositoryPath();

        // START S1AS 6178005
        appsStubRoot = instance.getApplicationStubPath().getAbsolutePath();
        // END S1AS 6178005

        // TODO: ParserUtils should become a @Service and it should initialize itself.
        // TODO: there should be only one EntityResolver for both DigesterFactory
        // and ParserUtils
        File root = _serverContext.getInstallRoot();
        File libRoot = new File(root, "lib");
        File schemas = new File(libRoot, "schemas");
        File dtds = new File(libRoot, "dtds");

        try {
            ParserUtils.setSchemaResourcePrefix(schemas.toURI().toURL().toString());
            ParserUtils.setDtdResourcePrefix(dtds.toURI().toURL().toString());
            ParserUtils.setEntityResolver(habitat.getComponent(EntityResolver.class, "web"));
        } catch (MalformedURLException e) {
            _logger.log(Level.SEVERE, "webContainer.exceptionSetSchemasDtdsLocation", e);
        }

        instanceName = _serverContext.getInstanceName();

        webContainerFeatureFactory = getWebContainerFeatureFactory();

        configureDynamicReloadingSettings();
        setDebugLevel();

        String maxDepth = null;
        if (serverConfig.getWebContainer() != null)
            maxDepth = serverConfig.getWebContainer().getPropertyValue(DISPATCHER_MAX_DEPTH);
        if (maxDepth != null) {
            int depth = -1;
            try {
                depth = Integer.parseInt(maxDepth);
            } catch (NumberFormatException e) {
            }

            if (depth > 0) {
                Request.setMaxDispatchDepth(depth);
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("Maximum depth for nested request "
                            + "dispatches set to "
                            + maxDepth);
                }
            }
        }

        logServiceFile = null;
        Map<String, String> logProps = null;
        try {
            logProps = logConfig.getLoggingProperties();
            if (logProps != null) {
                logServiceFile = logProps.get("com.sun.enterprise.server.logging.GFFileHandler.file");

                if (logServiceFile.contains("${com.sun.aas.instanceRoot}")) {
                    String instanceRoot = System.getProperty("com.sun.aas.instanceRoot");
                    String f = logServiceFile.replace("${com.sun.aas.instanceRoot}", instanceRoot);
                    logServiceFile = f;
                }

                logLevel = logProps.get("org.apache.catalina.level");
            }
        } catch (IOException ioe) {
            _logger.log(Level.SEVERE, "webContainer.unableDetermineServerLogLocation", ioe);
        }

        _embedded = habitat.getByType(EmbeddedWebContainer.class);
        _embedded.setWebContainer(this);
        _embedded.setLogServiceFile(logServiceFile);
        _embedded.setLogLevel(logLevel);
        _embedded.setFileLoggerHandlerFactory(fileLoggerHandlerFactory);
        _embedded.setWebContainerFeatureFactory(webContainerFeatureFactory);

        _embedded.setCatalinaHome(instance.getDomainRoot().getAbsolutePath());
        _embedded.setCatalinaBase(instance.getDomainRoot().getAbsolutePath());
        _embedded.setUseNaming(false);
        if (_debug > 1)
            _embedded.setDebug(_debug);
        _embedded.setLogger(new IASLogger(_logger));

        engine = _embedded.createEngine();
        engine.setParentClassLoader(EmbeddedWebContainer.class.getClassLoader());
        _embedded.addEngine(engine);
        ((StandardEngine) engine).setDomain(_serverContext.getDefaultDomainName());
        engine.setName(_serverContext.getDefaultDomainName());

        /*
        * Set the server info.
        * By default, the server info is taken from Version#getVersion.
        * However, customers may override it via the product.name system
        * property.
        * Some customers prefer not to disclose the server info
        * for security reasons, in which case they would set the value of the
        * product.name system property to the empty string. In this case,
        * the server name will not be publicly disclosed via the "Server"
        * HTTP response header (which will be suppressed) or any container
        * generated error pages. However, it will still appear in the
        * server logs (see IT 6900).
        */
        String serverInfo = System.getProperty("product.name");
        if (serverInfo == null) {
            ServerInfo.setServerInfo(Version.getVersion());
            ServerInfo.setPublicServerInfo(Version.getVersion());
        } else if (serverInfo.isEmpty()) {
            ServerInfo.setServerInfo(Version.getVersion());
            ServerInfo.setPublicServerInfo(serverInfo);
        } else {
            ServerInfo.setServerInfo(serverInfo);
            ServerInfo.setPublicServerInfo(serverInfo);
        }

        initInstanceSessionProperties();

        ConstructorWomb<WebConfigListener> womb =
                new ConstructorWomb<WebConfigListener>(
                        WebConfigListener.class,
                        habitat,
                        null);
        configListener = womb.get(null);

        ObservableBean bean = (ObservableBean) ConfigSupport.getImpl(
                serverConfig.getHttpService());
        bean.addListener(configListener);

        bean = (ObservableBean) ConfigSupport.getImpl(
                serverConfig.getNetworkConfig().getNetworkListeners());
        bean.addListener(configListener);

        if (serverConfig.getAvailabilityService() != null) {
            bean = (ObservableBean) ConfigSupport.getImpl(
                    serverConfig.getAvailabilityService());
            bean.addListener(configListener);
        }

        // embedded mode does not have manager-propertie in domain.xml
        if (configListener.managerProperties != null) {
            ObservableBean managerBean = (ObservableBean) ConfigSupport.getImpl(
                    configListener.managerProperties);
            managerBean.addListener(configListener);
        }

        configListener.setContainer(this);
        configListener.setLogger(_logger);

        events.register(this);

        grizzlyService.addMapperUpdateListener(configListener);

        HttpService httpService = serverConfig.getHttpService();
        NetworkConfig networkConfig = serverConfig.getNetworkConfig();
        if (networkConfig != null) {
            //continue;
            securityService = serverConfig.getSecurityService();

            // Configure HTTP listeners
            NetworkListeners networkListeners = networkConfig.getNetworkListeners();
            if (networkListeners != null) {
                List<NetworkListener> listeners = networkListeners.getNetworkListener();
                for (NetworkListener listener : listeners) {
                    if (ConfigBeansUtilities.toBoolean(listener.getJkEnabled())) {
                        createJKConnector(listener, httpService);
                    } else {
                        createHttpListener(listener, httpService);
                    }
                }
            }
            createJKConnector(null, httpService);

            setDefaultRedirectPort(defaultRedirectPort);

            // Configure virtual servers
            createHosts(httpService, securityService);
        }

        loadSystemDefaultWebModules();

        //_lifecycle.fireLifecycleEvent(START_EVENT, null);
        _started = true;

        /*
         * Start the embedded container.
         * Make sure to set the thread's context classloader to the
         * classloader of this class (see IT 8866 for details)
         */
        ClassLoader current = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(
                getClass().getClassLoader());
        try {
            /*
             * Trigger a call to sun.awt.AppContext.getAppContext().
             * This will pin the classloader of this class in memory
             * and fix a memory leak affecting instances of WebappClassLoader
             * that was caused by a JRE implementation change in 1.6.0_15
             * onwards. See IT 11110
             */
            ImageIO.getCacheDirectory();
            _embedded.start();
        } catch (LifecycleException le) {
            _logger.log(Level.SEVERE,
                    "webcontainer.exceptionDuringEmbeddedStart", le);
            return;
        } finally {
            // Restore original context classloader
            Thread.currentThread().setContextClassLoader(current);
        }
    }

    public void event(Event event) {
        if (event.is(Deployment.ALL_APPLICATIONS_PROCESSED)) {
            // configure default web modules for virtual servers after all
            // applications are processed
            loadDefaultWebModulesAfterAllAppsProcessed();
        } else if (event.is(EventTypes.PREPARE_SHUTDOWN)) {
            isShutdown = true;
        }
    }

    /**
     * Notifies any interested listeners that all ServletContextListeners
     * of the web module represented by the given WebBundleDescriptor
     * have been invoked at their contextInitialized method
     */
    void afterServletContextInitializedEvent(WebBundleDescriptor wbd) {
        events.send(new Event<WebBundleDescriptor>(
                WebBundleDescriptor.AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT, wbd),
                false);
    }

    public void preDestroy() {
        try {
            _embedded.stop();
        } catch (LifecycleException le) {
            _logger.log(Level.SEVERE,
                    "webcontainer.exceptionDuringEmbeddedStop", le);
            return;
        }
    }

    JavaEEIOUtils getJavaEEIOUtils() {
        return javaEEIOUtils;
    }

    public boolean isShutdown() {
        return isShutdown;
    }

    Collection<TldProvider> getTldProviders() {
        return tldProviders;
    }

    /**
     * Gets the probe provider for servlet related events.
     */
    public ServletProbeProvider getServletProbeProvider() {
        return servletProbeProvider;
    }


    /**
     * Gets the probe provider for jsp related events.
     */
    public JspProbeProvider getJspProbeProvider() {
        return jspProbeProvider;
    }


    /**
     * Gets the probe provider for session related events.
     */
    public SessionProbeProvider getSessionProbeProvider() {
        return sessionProbeProvider;
    }


    /**
     * Gets the probe provider for request/response related events.
     */
    public RequestProbeProvider getRequestProbeProvider() {
        return requestProbeProvider;
    }

    /**
     * Gets the probe provider for web module related events.
     */
    public WebModuleProbeProvider getWebModuleProbeProvider() {
        return webModuleProbeProvider;
    }

    public String getName() {
        return "Web";
    }

    public Class<? extends WebDeployer> getDeployer() {
        return WebDeployer.class;
    }

    InvocationManager getInvocationManager() {
        return invocationMgr;
    }

    public WebConnector getJkConnector() {
        return jkConnector;
    }

    /**
     * Instantiates and injects the given Servlet class for the given
     * WebModule
     */
    <T extends Servlet> T createServletInstance(WebModule module,
                                                Class<T> clazz) throws Exception {
        validateJSR299Scope(clazz);
        WebComponentInvocation inv = new WebComponentInvocation(module);
        try {
            invocationMgr.preInvoke(inv);
            return (T) injectionMgr.createManagedObject(clazz);
        } finally {
            invocationMgr.postInvoke(inv);
        }
    }

    /**
     * Instantiates and injects the given Filter class for the given
     * WebModule
     */
    <T extends Filter> T createFilterInstance(WebModule module,
                                              Class<T> clazz) throws Exception {
        validateJSR299Scope(clazz);
        WebComponentInvocation inv = new WebComponentInvocation(module);
        try {
            invocationMgr.preInvoke(inv);
            return (T) injectionMgr.createManagedObject(clazz);
        } finally {
            invocationMgr.postInvoke(inv);
        }
    }

    /**
     * Instantiates and injects the given EventListener class for the
     * given WebModule
     */
    <T extends java.util.EventListener> T createListenerInstance(
            WebModule module, Class<T> clazz) throws Exception {
        validateJSR299Scope(clazz);
        WebComponentInvocation inv = new WebComponentInvocation(module);
        try {
            invocationMgr.preInvoke(inv);
            return (T) injectionMgr.createManagedObject(clazz);
        } finally {
            invocationMgr.postInvoke(inv);
        }
    }

    /**
     * Instantiates and injects the given tag handler class for the given
     * WebModule
     */
    public <T extends JspTag> T createTagHandlerInstance(WebModule module,
                                                         Class<T> clazz) throws Exception {
        WebComponentInvocation inv = new WebComponentInvocation(module);
        try {
            invocationMgr.preInvoke(inv);
            return (T) injectionMgr.createManagedObject(clazz);
        } finally {
            invocationMgr.postInvoke(inv);
        }
    }

    /**
     * Use an network-listener subelements and creates a corresponding
     * Tomcat Connector for each.
     *
     * @param httpService The http-service element
     * @param listener    the configuration element.
     */
    protected WebConnector createHttpListener(NetworkListener listener,
                                              HttpService httpService) {
        return createHttpListener(listener, httpService, null);
    }


    protected WebConnector createHttpListener(NetworkListener listener,
                                              HttpService httpService,
                                              Mapper mapper) {

        if (!Boolean.valueOf(listener.getEnabled())) {
            return null;
        }

        int port = 8080;
        WebConnector connector;

        checkHostnameUniqueness(listener.getName(), httpService);

        try {
            port = Integer.parseInt(listener.getPort());
        } catch (NumberFormatException nfe) {
            String msg = rb.getString("pewebcontainer.http_listener.invalid_port");
            msg = MessageFormat.format(msg, listener.getPort(),
                    listener.getName());
            throw new IllegalArgumentException(msg);
        }

        if (mapper == null) {
            for (Mapper m : habitat.getAllByContract(Mapper.class)) {
                if (m.getPort() == port && m instanceof ContextMapper) {
                    ContextMapper cm = (ContextMapper) m;
                    if (listener.getName().equals(cm.getId())) {
                        mapper = m;
                        break;
                    }
                }
            }
        }

        String defaultVS = listener.findHttpProtocol().getHttp().getDefaultVirtualServer();
        if (!defaultVS.equals(org.glassfish.api.web.Constants.ADMIN_VS)) {
            // Before we start a WebConnector, let's makes sure there is
            // not another Container already listening on that port
            MessageBytes host = MessageBytes.newInstance();
            char[] c = defaultVS.toCharArray();
            host.setChars(c, 0, c.length);

            MessageBytes mb = MessageBytes.newInstance();
            mb.setChars(new char[]{'/'}, 0, 1);

            MappingData md = new MappingData();
            try {
                mapper.map(host, mb, md);
            } catch (Exception e) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "", e);
                }
            }

            if (md.context != null && md.context instanceof ContextRootInfo) {
                ContextRootInfo r = (ContextRootInfo) md.context;
                if (!(r.getAdapter() instanceof ContainerMapper)) {
                    new BindException("Port " + port + " is already used by Container: "
                            + r.getAdapter() +
                            " and will not get started.").printStackTrace();
                    return null;
                }
            }
        }

        /*
         * Create Connector. Connector is SSL-enabled if
         * 'security-enabled' attribute in <http-listener>
         * element is set to TRUE.
         */
        boolean isSecure = Boolean.valueOf(listener.findHttpProtocol().getSecurityEnabled());
        if (isSecure && defaultRedirectPort == -1) {
            defaultRedirectPort = port;
        }
        String address = listener.getAddress();
        if ("any".equals(address) || "ANY".equals(address)
                || "INADDR_ANY".equals(address)) {
            address = null;
            /*
             * Setting 'address' to NULL will cause Tomcat to pass a
             * NULL InetAddress argument to the java.net.ServerSocket
             * constructor, meaning that the server socket will accept
             * connections on any/all local addresses.
             */
        }

        connector = (WebConnector) _embedded.createConnector(
                address, port, isSecure);

        connector.setMapper(mapper);

        if (_logger.isLoggable(Level.INFO)) {
            _logger.log(Level.INFO, "webContainer.HTTP.listenerAndPort", new Object[]{listener.getName(), listener.getAddress(), listener.getPort()});
        }

        connector.setName(listener.getName());
        connector.setInstanceName(instanceName);
        connector.configure(listener, isSecure, httpService);

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "create.listenerport",
                    new Object[]{port, connector});
        }

        _embedded.addConnector(connector);

        connectorMap.put(listener.getName(), connector);

        // If we already know the redirect port, then set it now
        // This situation will occurs when dynamic reconfiguration occurs
        String redirectPort = listener.findHttpProtocol().getHttp().getRedirectPort();
        if (redirectPort != null) {
            connector.setRedirectPort(Integer.parseInt(redirectPort));
        } else if (defaultRedirectPort != -1) {
            connector.setRedirectPort(defaultRedirectPort);
        }

        ObservableBean httpListenerBean = (ObservableBean) ConfigSupport.getImpl(
                listener);
        httpListenerBean.addListener(configListener);

        return connector;
    }

    /**
     * Starts the AJP connector that will listen to call from Apache using
     * mod_jk, mod_jk2 or mod_ajp.
     */
    protected WebConnector createJKConnector(NetworkListener listener,
                                             HttpService httpService) {

        int port = 8009;
        boolean isSecure = false;
        String address = null;

        if (listener == null) {
            String portString =
                    System.getProperty("com.sun.enterprise.web.connector.enableJK");
            if (portString == null) {
                // do not create JK Connector if property is not set
                return null;
            } else {
                try {
                    port = Integer.parseInt(portString);
                } catch (NumberFormatException ex) {
                    // use default port 8009
                    port = 8009;
                }
            }
        } else {
            port = Integer.parseInt(listener.getPort());
            isSecure = Boolean.valueOf(listener.findHttpProtocol().getSecurityEnabled());
            address = listener.getAddress();
        }

        if (isSecure && defaultRedirectPort == -1) {
            defaultRedirectPort = port;
        }

        if ("any".equals(address) || "ANY".equals(address)
                || "INADDR_ANY".equals(address)) {
            address = null;
            /*
             * Setting 'address' to NULL will cause Tomcat to pass a
             * NULL InetAddress argument to the java.net.ServerSocket
             * constructor, meaning that the server socket will accept
             * connections on any/all local addresses.
             */
        }

        jkConnector = (WebConnector) _embedded.createConnector(address,
                port, "ajp");
        jkConnector.configureJKProperties(listener);

        String defaultHost = "server";
        String jkConnectorName = "jk-connector";
        if (listener != null) {
            defaultHost = listener.findHttpProtocol().getHttp().getDefaultVirtualServer();
            jkConnectorName = listener.getName();
        }
        jkConnector.setDefaultHost(defaultHost);
        jkConnector.setName(jkConnectorName);
        jkConnector.setDomain(_serverContext.getDefaultDomainName());
        jkConnector.setInstanceName(instanceName);
        if (listener != null) {
            jkConnector.configure(listener, isSecure, httpService);
            connectorMap.put(listener.getName(), jkConnector);
        }

        if (_logger.isLoggable(Level.INFO)) {
            _logger.log(Level.INFO, "webContainer.virtualServer.hostAndPort", new Object[]{defaultHost, port});
        }


        for (Mapper m : habitat.getAllByContract(Mapper.class)) {
            if (m.getPort() == port && m instanceof ContextMapper) {
                ContextMapper cm = (ContextMapper) m;
                if (listener.getName().equals(cm.getId())) {
                    jkConnector.setMapper(m);
                    break;
                }
            }
        }

        _embedded.addConnector(jkConnector);


        return jkConnector;

    }

    /**
     * Assigns the given redirect port to each Connector whose corresponding
     * http-listener element in domain.xml does not specify its own
     * redirect-port attribute.
     * <p/>
     * The given defaultRedirectPort corresponds to the port number of the
     * first security-enabled http-listener in domain.xml.
     * <p/>
     * This method does nothing if none of the http-listener elements is
     * security-enabled, in which case Tomcat's default redirect port (443)
     * will be used.
     *
     * @param defaultRedirectPort The redirect port to be assigned to any
     *                            Connector object that doesn't specify its own
     */
    private void setDefaultRedirectPort(int defaultRedirectPort) {
        if (defaultRedirectPort != -1) {
            Connector[] connectors = _embedded.getConnectors();
            for (Connector connector : connectors) {
                if (connector.getRedirectPort() == -1) {
                    connector.setRedirectPort(defaultRedirectPort);
                }
            }
        }
    }

    /**
     * Configure http-service properties.
     *
     * @deprecated most of these properties are handled elsewhere.  validate and remove outdated properties checks
     */
    public void configureHttpServiceProperties(HttpService httpService,
                                               PECoyoteConnector connector) {
        // Configure Connector with <http-service> properties
        List<Property> httpServiceProps = httpService.getProperty();

        // Set default ProxyHandler impl, may be overriden by
        // proxyHandler property
        connector.setProxyHandler(new ProxyHandlerImpl());

        globalSSOEnabled = ConfigBeansUtilities.toBoolean(httpService.getSsoEnabled());
        globalAccessLoggingEnabled = ConfigBeansUtilities.toBoolean(httpService.getAccessLoggingEnabled());
        globalAccessLogWriteInterval = httpService.getAccessLog().getWriteIntervalSeconds();
        globalAccessLogBufferSize = httpService.getAccessLog().getBufferSizeBytes();
        if (httpServiceProps != null) {
            for (Property httpServiceProp : httpServiceProps) {
                String propName = httpServiceProp.getName();
                String propValue = httpServiceProp.getValue();

                if (connector.configureHttpListenerProperty(propName, propValue)) {
                    continue;
                }

                if ("connectionTimeout".equals(propName)) {
                    connector.setConnectionTimeout(Integer.parseInt(propValue));
                } else if ("tcpNoDelay".equals(propName)) {
                    connector.setTcpNoDelay(ConfigBeansUtilities.toBoolean(propValue));
                } else if ("traceEnabled".equals(propName)) {
                    connector.setAllowTrace(ConfigBeansUtilities.toBoolean(propValue));
                } else if ("authPassthroughEnabled".equals(propName)) {
                    connector.setAuthPassthroughEnabled(
                            ConfigBeansUtilities.toBoolean(propValue));
                } else if ("ssl-session-timeout".equals(propName)) {
                    connector.setSslSessionTimeout(propValue);
                } else if ("ssl3-session-timeout".equals(propName)) {
                    connector.setSsl3SessionTimeout(propValue);
                } else if ("ssl-cache-entries".equals(propName)) {
                    connector.setSslSessionCacheSize(propValue);
                } else if ("proxyHandler".equals(propName)) {
                    connector.setProxyHandler(propValue);
                } else {
                    String msg = rb.getString("pewebcontainer.invalid_http_service_property");
                    _logger.log(Level.WARNING,
                            MessageFormat.format(msg, httpServiceProp.getName()));
                }
            }
        }
    }

    /*
     * Ensures that the host names of all virtual servers associated with the
     * HTTP listener with the given listener id are unique.
     *
     * @param listenerId The id of the HTTP listener whose associated virtual
     * servers are checked for uniqueness of host names
     * @param httpService The http-service element whose virtual servers are
     * checked
     */

    private void checkHostnameUniqueness(String listenerId,
                                         HttpService httpService) {

        List<com.sun.enterprise.config.serverbeans.VirtualServer> listenerVses = null;

        // Determine all the virtual servers associated with the given listener
        for (com.sun.enterprise.config.serverbeans.VirtualServer vse : httpService.getVirtualServer()) {
            List<String> vsListeners = StringUtils.parseStringList(vse.getNetworkListeners(), ",");
            for (int j = 0; vsListeners != null && j < vsListeners.size(); j++) {
                if (listenerId.equals(vsListeners.get(j))) {
                    if (listenerVses == null) {
                        listenerVses = new ArrayList<com.sun.enterprise.config.serverbeans.VirtualServer>();
                    }
                    listenerVses.add(vse);
                    break;
                }
            }
        }
        if (listenerVses == null) {
            return;
        }

        for (int i = 0; i < listenerVses.size(); i++) {
            com.sun.enterprise.config.serverbeans.VirtualServer vs
                    = listenerVses.get(i);
            List hosts = StringUtils.parseStringList(vs.getHosts(), ",");
            for (int j = 0; hosts != null && j < hosts.size(); j++) {
                String host = (String) hosts.get(j);
                for (int k = 0; k < listenerVses.size(); k++) {
                    if (k <= i) {
                        continue;
                    }
                    com.sun.enterprise.config.serverbeans.VirtualServer otherVs
                            = listenerVses.get(k);
                    List otherHosts = StringUtils.parseStringList(otherVs.getHosts(), ",");
                    for (int l = 0; otherHosts != null && l < otherHosts.size(); l++) {
                        if (host.equals(otherHosts.get(l))) {
                            _logger.log(Level.SEVERE,
                                    "pewebcontainer.duplicate_host_name",
                                    new Object[]{host, vs.getId(),
                                            otherVs.getId(),
                                            listenerId});
                        }
                    }
                }
            }
        }
    }


    /**
     * Enumerates the virtual-server subelements of the given http-service
     * element, and creates a corresponding Host for each.
     *
     * @param httpService     The http-service element
     * @param securityService The security-service element
     */
    protected void createHosts(HttpService httpService, SecurityService securityService) {

        List<com.sun.enterprise.config.serverbeans.VirtualServer> virtualServers = httpService.getVirtualServer();
        for (com.sun.enterprise.config.serverbeans.VirtualServer vs : virtualServers) {
            createHost(vs, httpService, securityService);
            if (_logger.isLoggable(Level.INFO)) {
                _logger.log(Level.INFO, "webContainer.virtualServer.created", vs.getId());
            }

        }
    }


    /**
     * Creates a Host from a virtual-server config bean.
     *
     * @param vsBean          The virtual-server configuration bean
     * @param httpService     The http-service element.
     * @param securityService The security-service element
     */
    public VirtualServer createHost(
            com.sun.enterprise.config.serverbeans.VirtualServer vsBean,
            HttpService httpService,
            SecurityService securityService) {

        MimeMap mm = null;
        String vs_id = vsBean.getId();

        String docroot = vsBean.getPropertyValue("docroot");
        if (docroot == null) {
            docroot = vsBean.getDocroot();
        }

        validateDocroot(docroot,
                vs_id,
                vsBean.getDefaultWebModule());

        VirtualServer vs = createHost(vs_id, vsBean, docroot, mm
        );

        // cache control
        Property cacheProp = vsBean.getProperty("setCacheControl");
        if (cacheProp != null) {
            vs.configureCacheControl(cacheProp.getValue());
        }

        PEAccessLogValve accessLogValve = vs.getAccessLogValve();
        boolean startAccessLog = accessLogValve.configure(
                vs_id, vsBean, httpService, domain,
                habitat, webContainerFeatureFactory,
                globalAccessLogBufferSize, globalAccessLogWriteInterval);
        if (startAccessLog
                && vs.isAccessLoggingEnabled(globalAccessLoggingEnabled)) {
            vs.addValve((GlassFishValve) accessLogValve);
        }

        if (_logger.isLoggable(Level.FINEST)) {
            _logger.log(Level.FINEST, "Created virtual server " + vs_id);
        }

        /*
         * We must configure the Host with its associated port numbers and
         * alias names before adding it as an engine child and thereby
         * starting it, because a MapperListener, which is associated with
         * an HTTP listener and receives notifications about Host
         * registrations, relies on these Host properties in order to determine
         * whether a new Host needs to be added to the HTTP listener's Mapper.
         */
        configureHost(vs, securityService);

        // Add Host to Engine
        engine.addChild(vs);

        ObservableBean virtualServerBean = (ObservableBean) ConfigSupport.getImpl(vsBean);
        virtualServerBean.addListener(configListener);

        return vs;
    }


    /**
     * Validate the docroot properties of a virtual-server.
     */
    protected void validateDocroot(String docroot, String vs_id,
                                   String defaultWebModule) {
        if (docroot == null) {
            return;
        }

        boolean isValid = new File(docroot).exists();
        if (!isValid) {
            String msg = rb.getString(
                    "pewebcontainer.virtual_server.invalid_docroot");
            msg = MessageFormat.format(msg, vs_id, docroot);
            throw new IllegalArgumentException(msg);
        }
    }


    /**
     * Configures the given virtual server.
     *
     * @param vs              The virtual server to be configured
     * @param securityService The security-service element
     */
    protected void configureHost(VirtualServer vs, SecurityService securityService) {

        com.sun.enterprise.config.serverbeans.VirtualServer vsBean = vs.getBean();

        vs.configureAliases();

        // Set the ports with which this virtual server is associated
        List<String> listeners = StringUtils.parseStringList(
                vsBean.getNetworkListeners(), ",");
        if (listeners == null) {
            return;
        }

        HashSet<NetworkListener> httpListeners = new HashSet();
        for (String listener : listeners) {
            boolean found = false;
            for (NetworkListener httpListener :
                    serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener()) {
                if (httpListener.getName().equals(listener)) {
                    httpListeners.add(httpListener);
                    found = true;
                    break;
                }
            }
            if (!found) {
                String msg = rb.getString(
                        "webcontainer.listenerReferencedByHostNotExist");
                msg = MessageFormat.format(msg, listener, vs.getName());
                _logger.log(Level.SEVERE, msg);
            }
        }

        configureHostPortNumbers(vs, httpListeners);
        vs.configureCatalinaProperties();
        vs.configureAuthRealm(securityService);
    }


    /**
     * Configures the given virtual server with the port numbers of its
     * associated http listeners.
     *
     * @param vs        The virtual server to configure
     * @param listeners The http listeners with which the given virtual
     *                  server is associated
     */
    protected void configureHostPortNumbers(VirtualServer vs,
                                            HashSet<NetworkListener> listeners) {

        boolean addJkListenerName = jkConnector != null &&
                !vs.getName().equalsIgnoreCase(
                        org.glassfish.api.web.Constants.ADMIN_VS);

        List<String> listenerNames = new ArrayList();
        for (NetworkListener listener : listeners) {
            if (Boolean.valueOf(listener.getEnabled())) {
                listenerNames.add(listener.getName());
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("Virtual Server " + vs.getID() +
                            " set listener name " + listener.getName());
                }
            } else {
                if (vs.getName().equalsIgnoreCase(
                        org.glassfish.api.web.Constants.ADMIN_VS)) {
                    String msg = rb.getString(
                            "pewebcontainer.httpListener.mustNotDisable");
                    msg = MessageFormat.format(msg, listener.getName(),
                            vs.getName());
                    throw new IllegalArgumentException(msg);
                }
            }
        }

        if (addJkListenerName && (!listenerNames.contains(jkConnector.getName()))) {
            listenerNames.add(jkConnector.getName());
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("Virtual Server " + vs.getID() +
                        " set jk listener name " + jkConnector.getName());
            }
        }

        vs.setNetworkListenerNames(
                listenerNames.toArray(new String[listenerNames.size()]));
    }


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

    /**
     * Create a virtual server/host.
     */
    public VirtualServer createHost(String vsID,
                                    com.sun.enterprise.config.serverbeans.VirtualServer vsBean,
                                    String docroot, MimeMap mimeMap) {

        // Initialize the docroot
        VirtualServer vs = (VirtualServer) _embedded.createHost(vsID,
                vsBean, docroot, vsBean.getLogFile(), mimeMap);
        vs.configureState();
        vs.configureRemoteAddressFilterValve();
        vs.configureRemoteHostFilterValve();
        vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled());
        vs.configureRedirect();
        vs.configureErrorPage();
        vs.configureErrorReportValve();
        vs.setServerContext(getServerContext());

        return vs;
    }


    /**
     * Gracefully terminate the active use of the public methods of this
     * component.  This method should be the last one called on a given
     * instance of this component.
     *
     * @throws IllegalStateException if this component has not been started
     * @throws LifecycleException    if this component detects a fatal error
     *                               that needs to be reported
     */
    public void stop() throws LifecycleException {
        // Validate and update our current component state
        if (!_started) {
            String msg = rb.getString("webcontainer.notStarted");
            throw new LifecycleException(msg);
        }

        _started = false;

        // stop the embedded container
        try {
            _embedded.stop();
        } catch (LifecycleException ex) {
            if (!ex.getMessage().contains("has not been started")) {
                throw ex;
            }
        }
    }


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


    /**
     * Configures a default web module for each virtual server based on the
     * virtual server's docroot if a virtual server does not specify
     * any default-web-module, and none of its web modules are loaded at "/"
     * <p/>
     * Needed in postConstruct before Deployment.ALL_APPLICATIONS_PROCESSED
     * for "jsp from docroot before web container start" scenario
     */

    public void loadSystemDefaultWebModules() {

        WebModuleConfig wmInfo = null;
        String defaultPath = null;

        Container[] vsArray = getEngine().findChildren();
        for (Container aVsArray : vsArray) {
            if (aVsArray instanceof VirtualServer) {
                VirtualServer vs = (VirtualServer) aVsArray;
                /*
                * Let AdminConsoleAdapter handle any requests for
                * the root context of the '__asadmin' virtual-server, see
                * https://glassfish.dev.java.net/issues/show_bug.cgi?id=5664
                */
                if (org.glassfish.api.web.Constants.ADMIN_VS.equals(
                        vs.getName())) {
                    continue;
                }

                // Create default web module off of virtual
                // server's docroot if necessary                   
                wmInfo = vs.createSystemDefaultWebModuleIfNecessary(
                        habitat.getComponent(
                                WebArchivist.class));
                if (wmInfo != null) {
                    defaultPath = wmInfo.getContextPath();
                    loadStandaloneWebModule(vs, wmInfo);
                }
                if (_logger.isLoggable(Level.INFO)) {
                    _logger.log(Level.INFO,
                            "webContainer.virtualServer.loadedDefaultWebModule",
                            new Object[]{vs.getName(), defaultPath});
                }

            }
        }

    }


    /**
     * Configures a default web module for each virtual server
     * if default-web-module is defined.
     */
    public void loadDefaultWebModulesAfterAllAppsProcessed() {

        String defaultPath = null;

        Container[] vsArray = getEngine().findChildren();
        for (Container aVsArray : vsArray) {
            if (aVsArray instanceof VirtualServer) {
                VirtualServer vs = (VirtualServer) aVsArray;
                /*
                * Let AdminConsoleAdapter handle any requests for
                * the root context of the '__asadmin' virtual-server, see
                * https://glassfish.dev.java.net/issues/show_bug.cgi?id=5664
                */
                if (org.glassfish.api.web.Constants.ADMIN_VS.equals(
                        vs.getName())) {
                    continue;
                }
                WebModuleConfig wmInfo = vs.getDefaultWebModule(domain,
                        habitat.getComponent(
                                WebArchivist.class),
                        appRegistry);
                if (wmInfo != null) {
                    defaultPath = wmInfo.getContextPath();
                    // Virtual server declares default-web-module
                    try {
                        updateDefaultWebModule(vs, vs.getNetworkListenerNames(), wmInfo);
                    } catch (LifecycleException le) {
                        String msg = rb.getString(
                                "webcontainer.defaultWebModuleError");
                        msg = MessageFormat.format(msg, defaultPath,
                                vs.getName());
                        _logger.log(Level.SEVERE, msg, le);
                    }
                    if (_logger.isLoggable(Level.INFO)) {
                        _logger.log(Level.INFO, "webContainer.virtual-server.loadedDefaultWebModule",
                                new Object[]{vs.getName(), defaultPath});
                    }

                } else {
                    // No need to create default web module off of virtual
                    // server's docroot since system web modules are already
                    // created in WebContainer.postConstruct
                }
            }
        }
    }


    /**
     * Load a default-web-module on the specified virtual server.
     */
    public void loadDefaultWebModule(
            com.sun.enterprise.config.serverbeans.VirtualServer vsBean) {

        VirtualServer virtualServer = (VirtualServer)
                getEngine().findChild(vsBean.getId());

        if (virtualServer != null) {
            loadDefaultWebModule(virtualServer);
        }
    }


    /**
     * Load a default-web-module on the specified virtual server.
     */
    public void loadDefaultWebModule(VirtualServer vs) {

        String defaultPath = null;
        WebModuleConfig wmInfo = vs.getDefaultWebModule(domain,
                habitat.getComponent(
                        WebArchivist.class),
                appRegistry);
        if (wmInfo != null) {
            defaultPath = wmInfo.getContextPath();
            // Virtual server declares default-web-module
            try {
                updateDefaultWebModule(vs, vs.getNetworkListenerNames(), wmInfo);
            } catch (LifecycleException le) {
                String msg = rb.getString("webcontainer.defaultWebModuleError");
                msg = MessageFormat.format(msg, defaultPath, vs.getName());
                _logger.log(Level.SEVERE, msg, le);
            }

        } else {
            // Create default web module off of virtual
            // server's docroot if necessary                   
            wmInfo = vs.createSystemDefaultWebModuleIfNecessary(
                    habitat.getComponent(
                            WebArchivist.class));
            if (wmInfo != null) {
                defaultPath = wmInfo.getContextPath();
                loadStandaloneWebModule(vs, wmInfo);
            }
        }

        if (_logger.isLoggable(Level.INFO)) {
            _logger.log(Level.INFO, "webContainer.virtual-server.loadedDefaultWebModule",
                    new Object[]{vs.getName(), defaultPath});
        }
    }


    /**
     * Load the specified web module as a standalone module on the specified
     * virtual server.
     */
    protected void loadStandaloneWebModule(VirtualServer vs,
                                           WebModuleConfig wmInfo) {
        try {
            loadWebModule(vs, wmInfo, "null", null);
        } catch (Throwable t) {
            String msg = rb.getString("webContainer.loadWebModuleError");
            msg = MessageFormat.format(msg, wmInfo.getName());
            _logger.log(Level.SEVERE, msg, t);
        }
    }


    /**
     * Whether or not a component (either an application or a module) should be
     * enabled is defined by the "enable" attribute on both the
     * application/module element and the application-ref element.
     *
     * @param moduleName The name of the component (application or module)
     * @return boolean
     */
    protected boolean isEnabled(String moduleName) {
        // TODO dochez : optimize
        /*
        Domain domain = habitat.getComponent(Domain.class);
        applications = domain.getApplications().getLifecycleModuleOrJ2EeApplicationOrEjbModuleOrWebModuleOrConnectorModuleOrAppclientModuleOrMbeanOrExtensionModule();
        com.sun.enterprise.config.serverbeans.WebModule webModule = null;
        for (Object module : applications) {
            if (module instanceof WebModule) {
                if (moduleName.equals(((com.sun.enterprise.config.serverbeans.WebModule) module).getName())) {
                    webModule = (com.sun.enterprise.config.serverbeans.WebModule) module;
                }
            }
        }    em
        ServerContext env = habitat.getComponent(ServerContext.class);
        List<Server> servers = domain.getServers().getServer();
        Server thisServer = null;
        for (Server server : servers) {
            if (env.getInstanceName().equals(server.getName())) {
                thisServer = server;
            }
        }
        List<ApplicationRef> appRefs = thisServer.getApplicationRef();
        ApplicationRef appRef = null;
        for (ApplicationRef ar : appRefs) {
            if (ar.getRef().equals(moduleName)) {
                appRef = ar;
            }
        }

        return ((webModule != null && Boolean.valueOf(webModule.getEnabled())) &&
                (appRef != null && Boolean.valueOf(appRef.getEnabled())));
         */
        return true;
    }

    /**
     * Creates and configures a web module for each virtual server
     * that the web module is hosted under.
     * <p/>
     * If no virtual servers have been specified, then the web module will
     * not be loaded.
     */
    public List<Result loadWebModule(
            WebModuleConfig wmInfo, String j2eeApplication,
            Properties deploymentProperties) {
        List<Result results = new ArrayList>();
        String vsIDs = wmInfo.getVirtualServers();
        List<String> vsList = StringUtils.parseStringList(vsIDs, " ,");
        if (vsList == null || vsList.isEmpty()) {
            _logger.log(Level.INFO,
                    "webcontainer.webModuleNotLoadedNoVirtualServers",
                    wmInfo.getName());
            return results;
        }

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "About to load web module " +
                    wmInfo.getName() + " to virtual servers " + vsIDs);
        }

        List<String> nonProcessedVSList = new ArrayList(vsList);
        Container[] vsArray = getEngine().findChildren();
        for (Container aVsArray : vsArray) {
            if (aVsArray instanceof VirtualServer) {
                VirtualServer vs = (VirtualServer) aVsArray;
                boolean eqVS = vsList.contains(vs.getID());
                if (eqVS) {
                    nonProcessedVSList.remove(vs.getID());
                }
                Set<String> matchedAliases = matchAlias(vsList, vs);
                boolean hasMatchedAlias = (matchedAliases.size() > 0);
                if (hasMatchedAlias) {
                    nonProcessedVSList.removeAll(matchedAliases);
                }
                if (eqVS || hasMatchedAlias) {
                    WebModule ctx = null;
                    try {
                        ctx = loadWebModule(vs, wmInfo, j2eeApplication,
                                deploymentProperties);
                        results.add(new Result(ctx));
                    } catch (Throwable t) {
                        if (ctx != null) {
                            ctx.setAvailable(false);
                        }
                        results.add(new Result(t));
                    }
                }
            }
        }

        if (nonProcessedVSList.size() > 0) {
            StringBuilder sb = new StringBuilder();
            boolean follow = false;
            for (String alias : nonProcessedVSList) {
                 if (follow) {
                     sb.append(",");
                 }
                 sb.append(alias);
                 follow = true;
            }
            Object[] params = {wmInfo.getName(), sb.toString()};
            _logger.log(Level.SEVERE, "webcontainer.moduleNotLoadedToVS",
                            params);
        }
        return results;
    }


    /**
     * Deploy on aliases as well as host.
     */
    private boolean verifyAlias(List<String> vsList, VirtualServer vs) {
        for (int i = 0; i < vs.getAliases().length; i++) {
            if (vsList.contains(vs.getAliases()[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Find all matched aliases.
     * This is more expensive than verifyAlias.
     */
    private Set<String> matchAlias(List vsList, VirtualServer vs) {
        Set<String> matched = new HashSet();
        for (String alias : vs.getAliases()) {
            if (vsList.contains(alias)) {
                matched.add(alias);
            }
        }

        return matched;
    }


    /**
     * Creates and configures a web module and adds it to the specified
     * virtual server.
     */
    private WebModule loadWebModule(
            VirtualServer vs,
            WebModuleConfig wmInfo,
            String j2eeApplication,
            Properties deploymentProperties)
            throws Exception {

        String wmName = wmInfo.getName();
        String wmContextPath = wmInfo.getContextPath();

        if (wmContextPath.indexOf('%') != -1) {
            try {
                RequestUtil.urlDecode(wmContextPath, "UTF-8");
            } catch (Exception e) {
                String msg = rb.getString(
                        "webcontainer.invalidEncodedContextRoot");
                msg = MessageFormat.format(msg, wmName, wmContextPath);
                throw new Exception(msg);
            }
        }

        if (wmContextPath.length() == 0 &&
                vs.getDefaultWebModuleID() != null) {
            String msg = rb.getString("webcontainer.defaultWebModuleConflict");
            msg = MessageFormat.format(msg,
                    new Object[]{wmName, vs.getID()});
            throw new Exception(msg);
        }

        wmInfo.setWorkDirBase(_appsWorkRoot);
        // START S1AS 6178005
        wmInfo.setStubBaseDir(appsStubRoot);
        // END S1AS 6178005

        String displayContextPath = null;
        if (wmContextPath.length() == 0)
            displayContextPath = "/";
        else
            displayContextPath = wmContextPath;

        Map<String, AdHocServletInfo> adHocPaths = null;
        Map<String, AdHocServletInfo> adHocSubtrees = null;
        WebModule ctx = (WebModule) vs.findChild(wmContextPath);
        if (ctx != null) {
            if (ctx instanceof AdHocWebModule) {
                /*
                 * Found ad-hoc web module which has been created by web
                 * container in order to store mappings for ad-hoc paths
                 * and subtrees.
                 * All these mappings must be propagated to the context
                 * that is being deployed.
                 */
                if (ctx.hasAdHocPaths()) {
                    adHocPaths = ctx.getAdHocPaths();
                }
                if (ctx.hasAdHocSubtrees()) {
                    adHocSubtrees = ctx.getAdHocSubtrees();
                }
                vs.removeChild(ctx);
            } else if (Constants.DEFAULT_WEB_MODULE_NAME
                    .equals(ctx.getModuleName())) {
                /*
                 * Dummy context that was created just off of a docroot,
                 * (see
                 * VirtualServer.createSystemDefaultWebModuleIfNecessary()).
                 * Unload it so it can be replaced with the web module to be
                 * loaded
                 */
                unloadWebModule(wmContextPath,
                        ctx.getJ2EEApplication(),
                        vs.getName(),
                        true,
                        null);
            } else if (!ctx.getAvailable()) {
                /*
                 * Context has been marked unavailable by a previous
                 * call to disableWebModule. Mark the context as available and
                 * return
                 */
                ctx.setAvailable(true);
                return ctx;
            } else {
                String msg = rb.getString("webcontainer.duplicateContextRoot");
                throw new Exception(MessageFormat.format(msg, vs.getID(),
                        ctx.getModuleName(), displayContextPath, wmName));
            }
        }

        if (_logger.isLoggable(Level.FINEST)) {
            Object[] params = {wmName, vs.getID(), displayContextPath};
            _logger.log(Level.FINEST, "webcontainer.loadModule", params);
        }

        File docBase = null;
        if (JWS_APPCLIENT_MODULE_NAME.equals(wmName)) {
            docBase = new File(System.getProperty("com.sun.aas.installRoot"));
        } else {
            docBase = wmInfo.getLocation();
        }

        ctx = (WebModule) _embedded.createContext(
                wmName,
                wmContextPath,
                docBase,
                vs.getDefaultContextXmlLocation(),
                vs.getDefaultWebXmlLocation(),
                useDOLforDeployment,
                wmInfo);

        // for now disable JNDI
        ctx.setUseNaming(false);

        // Set JSR 77 object name and attributes
        Engine engine = (Engine) vs.getParent();
        if (engine != null) {
            ctx.setEngineName(engine.getName());
            ctx.setJvmRoute(engine.getJvmRoute());
        }
        String j2eeServer = _serverContext.getInstanceName();
        String domain = _serverContext.getDefaultDomainName();
        String server = domain + ":j2eeType=J2EEServer,name=" + j2eeServer;
        // String[] javaVMs = J2EEModuleUtil.getjavaVMs();
        ctx.setDomain(domain);

        ctx.setJ2EEServer(j2eeServer);
        ctx.setJ2EEApplication(j2eeApplication);
        ctx.setCachingAllowed(false);
        ctx.setCacheControls(vs.getCacheControls());
        ctx.setBean(wmInfo.getBean());

        if (adHocPaths != null) {
            ctx.addAdHocPaths(adHocPaths);
        }
        if (adHocSubtrees != null) {
            ctx.addAdHocSubtrees(adHocSubtrees);
        }

        // Object containing web.xml information
        WebBundleDescriptor wbd = wmInfo.getDescriptor();

        // Set the context root 
        if (wbd != null) {
            ctx.setContextRoot(wbd.getContextRoot());
        } else {
            // Should never happen.
            _logger.log(Level.WARNING, "webContainer.unableSetContextRoot", wmInfo);
        }

        //
        // Ensure that the generated directory for JSPs in the document root
        // (i.e. those that are serviced by a system default-web-module)
        // is different for each virtual server.
        String wmInfoWorkDir = wmInfo.getWorkDir();
        if (wmInfoWorkDir != null) {
            StringBuilder workDir = new StringBuilder(wmInfo.getWorkDir());
            if (wmName.equals(Constants.DEFAULT_WEB_MODULE_NAME)) {
                workDir.append("-");
                workDir.append(FileUtils.makeFriendlyFilename(vs.getID()));
            }
            ctx.setWorkDir(workDir.toString());
        }

        ClassLoader parentLoader = wmInfo.getParentLoader();
        if (parentLoader == null) {
            // Use the shared classloader as the parent for all
            // standalone web-modules
            parentLoader = _serverContext.getSharedClassLoader();
        }
        ctx.setParentClassLoader(parentLoader);


        if (wbd != null) {
            // Determine if an alternate DD is set for this web-module in
            // the application
            ctx.configureAlternateDD(wbd);
            ctx.configureWebServices(wbd);
        }

        // Object containing sun-web.xml information
        SunWebApp iasBean = null;

        // The default context is the only case when wbd == null
        if (wbd != null) {
            iasBean = wbd.getSunDescriptor();
        }

        // set the sun-web config bean
        ctx.setIasWebAppConfigBean(iasBean);

        // Configure SingleThreadedServletPools, work/tmp directory etc
        ctx.configureMiscSettings(iasBean, vs, displayContextPath);

        // Configure alternate docroots if dummy web module
        if (ctx.getID().startsWith(Constants.DEFAULT_WEB_MODULE_NAME)) {
            ctx.setAlternateDocBases(vs.getProperties());
        }

        // Configure the class loader delegation model, classpath etc
        Loader loader = ctx.configureLoader(iasBean);

        // Set the class loader on the DOL object
        if (wbd != null && wbd.hasWebServices()) {
            wbd.addExtraAttribute("WEBLOADER", loader);
        }

        // Configure the session manager and other related settings
        ctx.configureSessionSettings(wbd, wmInfo);

        // set i18n info from locale-charset-info tag in sun-web.xml
        ctx.setI18nInfo();

        if (wbd != null) {
            String resourceType = wmInfo.getObjectType();
            boolean isSystem = resourceType != null &&
                    resourceType.startsWith("system-");
            // security will generate policy for system default web module
            if (!wmName.startsWith(Constants.DEFAULT_WEB_MODULE_NAME)) {
                // TODO : v3 : dochez Need to remove dependency on security
                Realm realm = habitat.getByContract(Realm.class);
                if ("null".equals(j2eeApplication)) {
                    /*
                     * Standalone webapps inherit the realm referenced by
                     * the virtual server on which they are being deployed,
                     * unless they specify their own
                     */
                    if (realm != null && realm instanceof RealmInitializer) {
                        ((RealmInitializer) realm).initializeRealm(
                                wbd, isSystem, vs.getAuthRealmName());
                        ctx.setRealm(realm);
                    }
                } else {
                    if (realm != null && realm instanceof RealmInitializer) {
                        ((RealmInitializer) realm).initializeRealm(
                                wbd, isSystem, null);
                        ctx.setRealm(realm);
                    }
                }
            }

            // post processing DOL object for standalone web module
            if (wbd.getApplication() != null &&
                    wbd.getApplication().isVirtual()) {
                wbd.visit(new WebValidatorWithoutCL());
            }
        }

        // Add virtual server mime mappings, if present
        addMimeMappings(ctx, vs.getMimeMap());

        String moduleName = Constants.DEFAULT_WEB_MODULE_NAME;
        String monitoringNodeName = moduleName;
        if (wbd != null && wbd.getApplication() != null) {
            // Not a dummy web module
            com.sun.enterprise.deployment.Application app =
                    wbd.getApplication();
            ctx.setStandalone(app.isVirtual());
            // S1AS BEGIN WORKAROUND FOR 6174360
            if (app.isVirtual()) {
                // Standalone web module
                moduleName = app.getRegistrationName();
                monitoringNodeName = wbd.getModuleID();
            } else {
                // Nested (inside EAR) web module
                moduleName = wbd.getModuleDescriptor().getArchiveUri();
                StringBuilder sb = new StringBuilder();
                sb.append(app.getRegistrationName()).
                        append(MONITORING_NODE_SEPARATOR).append(moduleName);
                monitoringNodeName = sb.toString().replaceAll("\\.", "\\\\.").
                        replaceAll("_war", "\\\\.war");
            }
            // S1AS END WORKAROUND FOR 6174360
        }
        ctx.setModuleName(moduleName);
        ctx.setMonitoringNodeName(monitoringNodeName);

        List<String> servletNames = new ArrayList();
        if (wbd != null) {
            for (WebComponentDescriptor webCompDesc : wbd.getWebComponentDescriptors()) {
                if (webCompDesc.isServlet()) {
                    servletNames.add(webCompDesc.getCanonicalName());
                }
            }
        }

        webStatsProviderBootstrap.registerApplicationStatsProviders(monitoringNodeName,
                vs.getName(), servletNames);

        vs.addChild(ctx);

        ctx.loadSessions(deploymentProperties);

        return ctx;
    }


    /*
     * Updates the given virtual server with the given default path.
     *
     * The given default path corresponds to the context path of one of the
     * web contexts deployed on the virtual server that has been designated
     * as the virtual server's new default-web-module.
     *
     * @param virtualServer The virtual server to update
     * @param ports The port numbers of the HTTP listeners with which the
     * given virtual server is associated
     * @param defaultContextPath The context path of the web module that has
     * been designated as the virtual server's new default web module, or null
     * if the virtual server no longer has any default-web-module
     */

    protected void updateDefaultWebModule(VirtualServer virtualServer,
                                          String[] listenerNames,
                                          WebModuleConfig wmInfo)
            throws LifecycleException {

        String defaultContextPath = null;
        if (wmInfo != null) {
            defaultContextPath = wmInfo.getContextPath();
        }
        if (defaultContextPath != null
                && !defaultContextPath.startsWith("/")) {
            defaultContextPath = "/" + defaultContextPath;
            wmInfo.getDescriptor().setContextRoot(defaultContextPath);
        }

        Connector[] connectors = _embedded.findConnectors();
        for (Connector connector : connectors) {
            PECoyoteConnector conn = (PECoyoteConnector) connector;
            String name = conn.getName();
            for (String listenerName : listenerNames) {
                if (name.equals(listenerName)) {
                    Mapper mapper = conn.getMapper();
                    try {
                        mapper.setDefaultContextPath(virtualServer.getName(),
                                defaultContextPath);
                        for (String alias : virtualServer.findAliases()) {
                            mapper.setDefaultContextPath(alias,
                                    defaultContextPath);
                        }
                        virtualServer.setDefaultContextPath(defaultContextPath);
                    } catch (Exception e) {
                        throw new LifecycleException(e);
                    }
                }
            }
        }
    }


    /**
     * Utility Method to access the ServerContext
     */
    public ServerContext getServerContext() {
        return _serverContext;
    }


    ServerConfigLookup getServerConfigLookup() {
        return serverConfigLookup;
    }


    File getLibPath() {
        return instance.getLibPath();
    }


    /**
     * The application id for this web module
     * HERCULES:add
     */
    public String getApplicationId(WebModule wm) {
        return wm.getID();
    }


    /**
     * Return the Absolute path for location where all the deployed
     * standalone modules are stored for this Server Instance.
     */
    public File getModulesRoot() {
        return _modulesRoot;
    }


    /**
     * Get the persistence frequency for this web module
     * (this is the value from sun-web.xml if defined
     *
     * @param smBean the session manager config bean
     *               HERCULES:add
     */
    private String getPersistenceFrequency(SessionManager smBean) {
        String persistenceFrequency = null;
        ManagerProperties mgrBean = smBean.getManagerProperties();
        if (mgrBean != null && mgrBean.sizeWebProperty() > 0) {
            WebProperty[] props = mgrBean.getWebProperty();
            for (WebProperty prop : props) {
                String name = prop.getAttributeValue(WebProperty.NAME);
                String value = prop.getAttributeValue(WebProperty.VALUE);
                if (name == null || value == null) {
                    throw new IllegalArgumentException(
                            rb.getString("webcontainer.nullWebProperty"));
                }
                if (name.equalsIgnoreCase("persistenceFrequency")) {
                    persistenceFrequency = value;
                    break;
                }
            }
        }
        return persistenceFrequency;
    }

    /**
     * Get the persistence scope for this web module
     * (this is the value from sun-web.xml if defined
     *
     * @param smBean the session manager config bean
     *               HERCULES:add
     */
    private String getPersistenceScope(SessionManager smBean) {
        String persistenceScope = null;
        StoreProperties storeBean = smBean.getStoreProperties();
        if (storeBean != null && storeBean.sizeWebProperty() > 0) {
            WebProperty[] props = storeBean.getWebProperty();
            for (WebProperty prop : props) {
                String name = prop.getAttributeValue(WebProperty.NAME);
                String value = prop.getAttributeValue(WebProperty.VALUE);
                if (name == null || value == null) {
                    throw new IllegalArgumentException(
                            rb.getString("webcontainer.nullWebProperty"));
                }
                if (name.equalsIgnoreCase("persistenceScope")) {
                    persistenceScope = value;
                    break;
                }
            }
        }
        return persistenceScope;
    }


    /**
     * Undeploy a web application.
     *
     * @param contextRoot    the context's name to undeploy
     * @param appName        the J2EE appname used at deployment time
     * @param virtualServers List of current virtual-server object.
     */
    public void unloadWebModule(String contextRoot,
                                String appName,
                                String virtualServers,
                                Properties props) {
        unloadWebModule(contextRoot, appName, virtualServers, false, props);
    }

    /**
     * Undeploy a web application.
     *
     * @param contextRoot    the context's name to undeploy
     * @param appName        the J2EE appname used at deployment time
     * @param virtualServers List of current virtual-server object.
     * @param dummy          true if the web module to be undeployed is a dummy web
     *                       module, that is, a web module created off of a virtual server's
     *                       docroot
     */
    public void unloadWebModule(String contextRoot,
                                String appName,
                                String virtualServers,
                                boolean dummy,
                                Properties props) {

        if (_logger.isLoggable(Level.FINEST)) {
            _logger.finest("WebContainer.unloadWebModule(): contextRoot: "
                    + contextRoot + " appName:" + appName);
        }

        // tomcat contextRoot starts with "/"
        if (contextRoot.length() != 0 && !contextRoot.startsWith("/")) {
            contextRoot = "/" + contextRoot;
        } else if ("/".equals(contextRoot)) {
            // Make corresponding change as in WebModuleConfig.getContextPath()
            contextRoot = "";
        }

        List<String> hostList = StringUtils.parseStringList(virtualServers, " ,");
        boolean unloadFromAll = hostList == null || hostList.isEmpty();
        boolean hasBeenUndeployed = false;
        VirtualServer host = null;
        WebModule context = null;
        Container[] hostArray = getEngine().findChildren();
        for (Container aHostArray : hostArray) {
            host = (VirtualServer) aHostArray;
            if (unloadFromAll || hostList.contains(host.getName())
                    || verifyAlias(hostList, host)) {
                context = (WebModule) host.findChild(contextRoot);
                if (context != null) {
                    context.saveSessions(props);
                    host.removeChild(context);

                    webStatsProviderBootstrap.unregisterApplicationStatsProviders(
                            context.getMonitoringNodeName(), host.getName());

                    try {
                        /*
                         * If the webapp is being undeployed as part of a
                         * domain shutdown, we don't want to destroy it,
                         * as that would remove any sessions persisted to
                         * file. Any active sessions need to survive the
                         * domain shutdown, so that they may be resumed
                         * after the domain has been restarted.
                         */
                        if (!isShutdown) {
                            context.destroy();
                        }
                    } catch (Exception ex) {
                        String msg = rb.getString(
                                "webcontainer.webmodule.exceptionDuringDestroy");
                        msg = MessageFormat.format(msg, contextRoot,
                                host.getName());
                        _logger.log(Level.WARNING, msg, ex);
                    }
                    if (_logger.isLoggable(Level.FINEST)) {
                        _logger.log(Level.FINEST,
                                "[WebContainer] Context " + contextRoot
                                        + " undeployed from " + host);
                    }
                    hasBeenUndeployed = true;
                    host.fireContainerEvent(Deployer.REMOVE_EVENT, context);
                    /*
                     * If the web module that has been unloaded
                     * contained any mappings for ad-hoc paths,
                     * those mappings must be preserved by registering an
                     * ad-hoc web module at the same context root
                     */
                    if (context.hasAdHocPaths()
                            || context.hasAdHocSubtrees()) {
                        WebModule wm = createAdHocWebModule(
                                context.getID(),
                                host,
                                contextRoot,
                                context.getJ2EEApplication());
                        wm.addAdHocPaths(context.getAdHocPaths());
                        wm.addAdHocSubtrees(context.getAdHocSubtrees());
                    }
                    // START GlassFish 141
                    if (!dummy) {
                        WebModuleConfig wmInfo =
                                host.createSystemDefaultWebModuleIfNecessary(
                                        habitat.getComponent(
                                                WebArchivist.class));
                        if (wmInfo != null) {
                            loadStandaloneWebModule(host, wmInfo);
                        }
                    }
                    // END GlassFish 141
                }
            }
        }

        if (!hasBeenUndeployed) {
            _logger.log(Level.SEVERE, "webContainer.undeployError", contextRoot);
        }
    }


    /**
     * Suspends the web application with the given appName that has been
     * deployed at the given contextRoot on the given virtual servers.
     *
     * @param contextRoot the context root
     * @param appName     the J2EE appname used at deployment time
     * @param hosts       the list of virtual servers
     */
    public boolean suspendWebModule(String contextRoot,
                                    String appName,
                                    String hosts) {
        boolean hasBeenSuspended = false;
        List<String> hostList = StringUtils.parseStringList(hosts, " ,");
        if (hostList == null || hostList.isEmpty()) {
            return hasBeenSuspended;
        }

        // tomcat contextRoot starts with "/"
        if (contextRoot.length() != 0 && !contextRoot.startsWith("/")) {
            contextRoot = "/" + contextRoot;
        }
        VirtualServer host = null;
        Context context = null;
        for (Container aHostArray : getEngine().findChildren()) {
            host = (VirtualServer) aHostArray;
            if (hostList.contains(host.getName()) ||
                    verifyAlias(hostList, host)) {
                context = (Context) host.findChild(contextRoot);
                if (context != null) {
                    context.setAvailable(false);
                    if (_logger.isLoggable(Level.FINEST)) {
                        _logger.log(Level.FINEST,
                                "[WebContainer] Context "
                                        + contextRoot + " disabled from "
                                        + host);
                    }
                    hasBeenSuspended = true;
                }
            }
        }

        if (!hasBeenSuspended) {
            _logger.log(Level.WARNING, "webContainer.disableWebModuleError", contextRoot);
        }

        return hasBeenSuspended;
    }


    /**
     * Save the server-wide dynamic reloading settings for use when
     * configuring each web module.
     */
    private void configureDynamicReloadingSettings() {
        if (dasConfig != null) {
            _reloadingEnabled = Boolean.parseBoolean(dasConfig.getDynamicReloadEnabled());
            String seconds = dasConfig.getDynamicReloadPollIntervalInSeconds();
            if (seconds != null) {
                try {
                    _pollInterval = Integer.parseInt(seconds);
                } catch (NumberFormatException e) {
                }
            }
        }
    }


    /**
     * Sets the debug level for Catalina's containers based on the logger's
     * log level.
     */
    private void setDebugLevel() {
        Level logLevel = _logger.getLevel() != null ?
                _logger.getLevel() : Level.INFO;
        if (logLevel.equals(Level.FINE))
            _debug = 1;
        else if (logLevel.equals(Level.FINER))
            _debug = 2;
        else if (logLevel.equals(Level.FINEST))
            _debug = 5;
        else
            _debug = 0;
    }


    /**
     * Get the lifecycle listeners associated with this lifecycle. If this
     * Lifecycle has no listeners registered, a zero-length array is returned.
     */
    public LifecycleListener[] findLifecycleListeners() {
        return new LifecycleListener[0];
    }


    /**
     * Gets all the virtual servers whose http-listeners attribute value
     * contains the given http-listener id.
     */
    List<VirtualServer> getVirtualServersForHttpListenerId(
            HttpService httpService, String httpListenerId) {

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

        List<VirtualServer> result = new ArrayList();

        for (com.sun.enterprise.config.serverbeans.VirtualServer vs : httpService.getVirtualServer()) {
            List<String> listeners = StringUtils.parseStringList(vs.getNetworkListeners(), ",");
            if (listeners != null) {
                ListIterator<String> iter = listeners.listIterator();
                while (iter.hasNext()) {
                    if (httpListenerId.equals(iter.next())) {
                        VirtualServer match = (VirtualServer)
                                getEngine().findChild(vs.getId());
                        if (match != null) {
                            result.add(match);
                        }
                        break;
                    }
                }
            }
        }

        return result;
    }


    /**
     * Adds the given mime mappings to those of the specified context, unless
     * they're already present in the context (that is, the mime mappings of
     * the specified context, which correspond to those in default-web.xml,
     * can't be overridden).
     *
     * @param ctx     The StandardContext to whose mime mappings to add
     * @param mimeMap The mime mappings to be added
     */
    private void addMimeMappings(StandardContext ctx, MimeMap mimeMap) {
        if (mimeMap == null) {
            return;
        }

        for (Iterator itr = mimeMap.getExtensions(); itr.hasNext();) {
            String extension = (String) itr.next();
            if (ctx.findMimeMapping(extension) == null) {
                ctx.addMimeMapping(extension, mimeMap.getType(extension));
            }
        }
    }

    /**
     * Return the parent/top-level container in _embedded for virtual
     * servers.
     */
    public Engine getEngine() {
        return _embedded.getEngines()[0];
    }


    /**
     * Registers the given ad-hoc path at the given context root.
     *
     * @param path        The ad-hoc path to register
     * @param ctxtRoot    The context root at which to register
     * @param appName     The name of the application with which the ad-hoc path is
     *                    associated
     * @param servletInfo Info about the ad-hoc servlet that will service
     *                    requests on the given path
     */
    public void registerAdHocPath(
            String path,
            String ctxtRoot,
            String appName,
            AdHocServletInfo servletInfo) {

        registerAdHocPathAndSubtree(path, null, ctxtRoot, appName,
                servletInfo);
    }


    /**
     * Registers the given ad-hoc path and subtree at the given context root.
     *
     * @param path        The ad-hoc path to register
     * @param subtree     The ad-hoc subtree path to register
     * @param ctxtRoot    The context root at which to register
     * @param appName     The name of the application with which the ad-hoc path
     *                    and subtree are associated
     * @param servletInfo Info about the ad-hoc servlet that will service
     *                    requests on the given ad-hoc path and subtree
     */
    public void registerAdHocPathAndSubtree(
            String path,
            String subtree,
            String ctxtRoot,
            String appName,
            AdHocServletInfo servletInfo) {

        WebModule wm = null;

        Container[] vsList = getEngine().findChildren();
        for (Container aVsList : vsList) {
            VirtualServer vs = (VirtualServer) aVsList;
            if (vs.getName().equalsIgnoreCase(
                    org.glassfish.api.web.Constants.ADMIN_VS)) {
                // Do not deploy on admin vs
                continue;
            }
            wm = (WebModule) vs.findChild(ctxtRoot);
            if (wm == null) {
                wm = createAdHocWebModule(vs, ctxtRoot, appName);
            }
            wm.addAdHocPathAndSubtree(path, subtree, servletInfo);
        }
    }


    /**
     * Unregisters the given ad-hoc path from the given context root.
     *
     * @param path     The ad-hoc path to unregister
     * @param ctxtRoot The context root from which to unregister
     */
    public void unregisterAdHocPath(String path, String ctxtRoot) {
        unregisterAdHocPathAndSubtree(path, null, ctxtRoot);
    }


    /**
     * Unregisters the given ad-hoc path and subtree from the given context
     * root.
     *
     * @param path     The ad-hoc path to unregister
     * @param subtree  The ad-hoc subtree to unregister
     * @param ctxtRoot The context root from which to unregister
     */
    public void unregisterAdHocPathAndSubtree(String path,
                                              String subtree,
                                              String ctxtRoot) {

        WebModule wm = null;

        Container[] vsList = getEngine().findChildren();
        for (Container aVsList : vsList) {
            VirtualServer vs = (VirtualServer) aVsList;
            if (vs.getName().equalsIgnoreCase(
                    org.glassfish.api.web.Constants.ADMIN_VS)) {
                // Do not undeploy from admin vs, because we never
                // deployed onto it
                continue;
            }
            wm = (WebModule) vs.findChild(ctxtRoot);
            if (wm == null) {
                continue;
            }
            /*
            * If the web module was created by the container for the
            * sole purpose of mapping ad-hoc paths and subtrees,
            * and does no longer contain any ad-hoc paths or subtrees,
            * remove the web module.
            */
            wm.removeAdHocPath(path);
            wm.removeAdHocSubtree(subtree);
            if (wm instanceof AdHocWebModule && !wm.hasAdHocPaths()
                    && !wm.hasAdHocSubtrees()) {
                vs.removeChild(wm);
                try {
                    wm.destroy();
                } catch (Exception ex) {
                    String msg = rb.getString(
                            "webcontainer.webmodule.exceptionDuringDestroy");
                    msg = MessageFormat.format(msg, wm.getPath(), vs.getName());
                    _logger.log(Level.WARNING, msg, ex);
                }
            }
        }
    }

    /*
     * Creates an ad-hoc web module and registers it on the given virtual
     * server at the given context root.
     *
     * @param vs The virtual server on which to add the ad-hoc web module
     * @param ctxtRoot The context root at which to register the ad-hoc
     * web module
     * @param appName The name of the application to which the ad-hoc module
     * being generated belongs
     *
     * @return The newly created ad-hoc web module
     */

    private WebModule createAdHocWebModule(
            VirtualServer vs,
            String ctxtRoot,
            String appName) {
        return createAdHocWebModule(appName, vs, ctxtRoot, appName);
    }

    /*
     * Creates an ad-hoc web module and registers it on the given virtual
     * server at the given context root.
     *
     * @param id the id of the ad-hoc web module
     * @param vs The virtual server on which to add the ad-hoc web module
     * @param ctxtRoot The context root at which to register the ad-hoc
     * web module
     * @param appName The name of the application to which the ad-hoc module
     * being generated belongs
     *
     * @return The newly created ad-hoc web module
     */

    private WebModule createAdHocWebModule(
            String id,
            VirtualServer vs,
            String ctxtRoot,
            String appName) {

        AdHocWebModule wm = new AdHocWebModule();
        wm.setID(id);
        wm.setWebContainer(this);

        wm.restrictedSetPipeline(new WebPipeline(wm));

        // The Parent ClassLoader of the AdhocWebModule was null
        // [System ClassLoader]. With the new hierarchy, the thread context
        // classloader needs to be set.
        //if (Boolean.getBoolean(com.sun.enterprise.server.PELaunch.USE_NEW_CLASSLOADER_PROPERTY)) {
        wm.setParentClassLoader(
                Thread.currentThread().getContextClassLoader());
        //}

        wm.setContextRoot(ctxtRoot);
        wm.setJ2EEApplication(appName);
        wm.setName(ctxtRoot);
        wm.setDocBase(vs.getAppBase());
        wm.setEngineName(vs.getParent().getName());

        String domain = _serverContext.getDefaultDomainName();
        wm.setDomain(domain);

        String j2eeServer = _serverContext.getInstanceName();
        wm.setJ2EEServer(j2eeServer);

        wm.setCrossContext(true);
        //wm.setJavaVMs(J2EEModuleUtil.getjavaVMs());

        vs.addChild(wm);

        return wm;
    }


    /**
     * Removes the dummy module (the module created off of a virtual server's
     * docroot) from the given virtual server if such a module exists.
     *
     * @param vs The virtual server whose dummy module is to be removed
     */
    void removeDummyModule(VirtualServer vs) {
        WebModule ctx = (WebModule) vs.findChild("");
        if (ctx != null
                && Constants.DEFAULT_WEB_MODULE_NAME.equals(
                ctx.getModuleName())) {
            unloadWebModule("", ctx.getJ2EEApplication(),
                    vs.getName(), true, null);
        }
    }


    /**
     * Initializes the instance-level session properties (read from
     * config.web-container.session-config.session-properties in domain.xml).
     */
    private void initInstanceSessionProperties() {

        SessionProperties spBean =
                serverConfigLookup.getInstanceSessionProperties();

        if (spBean == null || spBean.getProperty() == null) {
            return;
        }

        List<Property> props = spBean.getProperty();
        if (props == null) {
            return;
        }

        for (Property prop : props) {
            String propName = prop.getName();
            String propValue = prop.getValue();
            if (propName == null || propValue == null) {
                throw new IllegalArgumentException(
                        rb.getString("webcontainer.nullWebProperty"));
            }

            if (propName.equalsIgnoreCase("enableCookies")) {
                instanceEnableCookies = ConfigBeansUtilities.toBoolean(propValue);
            } else if (_logger.isLoggable(Level.INFO)) {
                Object[] params = {propName};
                _logger.log(Level.INFO, "webcontainer.notYet", params);
            }
        }
    }

    private static synchronized void setJspFactory() {
        if (JspFactory.getDefaultFactory() == null) {
            JspFactory.setDefaultFactory(new JspFactoryImpl());
        }
    }


    /**
     * Delete virtual-server.
     *
     * @param httpService element which contains the configuration info.
     */
    public void deleteHost(HttpService httpService) throws LifecycleException {

        VirtualServer virtualServer;

        // First we need to find which virtual-server was deleted. In
        // reconfig/VirtualServerReconfig, it is impossible to lookup
        // the vsBean because the element is removed from domain.xml
        // before handleDelete is invoked.
        Container[] virtualServers = getEngine().findChildren();
        for (int i = 0; i < virtualServers.length; i++) {
            for (com.sun.enterprise.config.serverbeans.VirtualServer vse : httpService.getVirtualServer()) {
                if (virtualServers[i].getName().equals(vse.getId())) {
                    virtualServers[i] = null;
                    break;
                }
            }
        }
        for (Container virtualServer1 : virtualServers) {
            virtualServer = (VirtualServer) virtualServer1;
            if (virtualServer != null) {
                if (virtualServer.getID().equals(
                        org.glassfish.api.web.Constants.ADMIN_VS)) {
                    throw new LifecycleException(
                            "Cannot delete admin virtual-server.");
                }
                Container[] webModules = virtualServer.findChildren();
                for (Container webModule : webModules) {
                    unloadWebModule(webModule.getName(),
                            webModule.getName(),
                            virtualServer.getID(),
                            null);
                }
                try {
                    virtualServer.destroy();
                } catch (Exception e) {
                    String msg = rb.getString("webContainer.destroyVsError");
                    msg = MessageFormat.format(msg, virtualServer.getID());
                    _logger.log(Level.WARNING, msg, e);
                }
            }
        }
    }


    /**
     * Updates a virtual-server element.
     *
     * @param vsBean the virtual-server config bean.
     */
    public void updateHost(com.sun.enterprise.config.serverbeans.VirtualServer vsBean) throws LifecycleException {

        if (org.glassfish.api.web.Constants.ADMIN_VS.equals(vsBean.getId())) {
            return;
        }
        final VirtualServer vs = (VirtualServer) getEngine().findChild(vsBean.getId());

        if (vs == null) {
            _logger.log(Level.WARNING, "webContainer.cannotUpdateNonExistenceVs", vsBean.getId());
            return;
        }

        boolean updateListeners = false;

        // Only update connectors if virtual-server.http-listeners is changed dynamically
        if (vs.getNetworkListeners() == null) {
            if (vsBean.getNetworkListeners() == null) {
                updateListeners = false;
            } else {
                updateListeners = true;
            }
        } else if (vs.getNetworkListeners().equals(vsBean.getNetworkListeners())) {
            updateListeners = false;
        } else {
            List<String> vsList = StringUtils.parseStringList(
                vs.getNetworkListeners(), ",");
            List<String> vsBeanList = StringUtils.parseStringList(
                vsBean.getNetworkListeners(), ",");
            for (String vsBeanName : vsBeanList) {
                if (!vsList.contains(vsBeanName)) {
                    updateListeners = true;
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.fine(vsBeanName
                                + "is not included network listeners "
                                + vs.getNetworkListeners());
                    }
                    break;
                }
            }
        }

        // Must retrieve the old default-web-module before updating the
        // virtual server with the new vsBean, because default-web-module is
        // read from vsBean
        String oldDefaultWebModule = vs.getDefaultWebModuleID();

        vs.setBean(vsBean);

        String vsLogFile = vsBean.getLogFile();
        vs.setLogFile(vsLogFile, logLevel, logServiceFile);

        vs.configureState();

        vs.clearAliases();
        vs.configureAliases();

        vs.reconfigureAccessLog(globalAccessLogBufferSize,
                globalAccessLogWriteInterval,
                habitat,
                domain,
                globalAccessLoggingEnabled);

        // support both docroot property and attribute
        String docroot = vsBean.getPropertyValue("docroot");
        if (docroot == null) {
            docroot = vsBean.getDocroot();
        }
        if (docroot != null) {
            updateDocroot(docroot, vs, vsBean);
        }

        List<Property> props = vs.getProperties();
        for (Property prop : props) {
            updateHostProperties(vsBean, prop.getName(), prop.getValue(), securityService, vs);
        }
        vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled());
        vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain,
                globalAccessLoggingEnabled);

        // old listener names
        List<String> oldListenerList = StringUtils.parseStringList(
                vsBean.getNetworkListeners(), ",");
        String[] oldListeners = (oldListenerList != null) ?
                oldListenerList.toArray(new String[oldListenerList.size()]) :
                new String[0];
        // new listener config
        HashSet<NetworkListener> networkListeners = new HashSet();
        if (oldListenerList != null) {
            for (String listener : oldListeners) {
                boolean found = false;
                for (NetworkListener httpListener :
                        serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener()) {
                    if (httpListener.getName().equals(listener)) {
                        networkListeners.add(httpListener);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    String msg = rb.getString(
                            "webcontainer.listenerReferencedByHostNotExist");
                    msg = MessageFormat.format(msg, listener, vs.getName());
                    _logger.log(Level.SEVERE, msg);
                }
            }
            // Update the port numbers with which the virtual server is
            // associated
            configureHostPortNumbers(vs, networkListeners);
        } else {
            // The virtual server is not associated with any http listeners
            vs.setNetworkListenerNames(new String[0]);
        }

        // Disassociate the virtual server from all http listeners that
        // have been removed from its http-listeners attribute
        for (String oldListener : oldListeners) {
            boolean found = false;
            for (NetworkListener httpListener : networkListeners) {
                if (httpListener.getName().equals(oldListener)) {
                    found = true;
                }
            }
            if (!found) {
                // http listener was removed
                Connector[] connectors = _embedded.findConnectors();
                for (Connector connector : connectors) {
                    WebConnector conn = (WebConnector) connector;
                    if (oldListener.equals(conn.getName())) {
                        try {
                            conn.getMapperListener().unregisterHost(
                                    vs.getJmxName());
                        } catch (Exception e) {
                            throw new LifecycleException(e);
                        }
                    }
                }

            }
        }

        // Associate the virtual server with all http listeners that
        // have been added to its http-listeners attribute
        for (NetworkListener httpListener : networkListeners) {
            boolean found = false;
            for (String oldListener : oldListeners) {
                if (httpListener.getName().equals(oldListener)) {
                    found = true;
                }
            }
            if (!found) {
                // http listener was added
                Connector[] connectors = _embedded.findConnectors();
                for (Connector connector : connectors) {
                    WebConnector conn = (WebConnector)
                            connector;
                    if (httpListener.getName().equals(conn.getName())) {
                        if (!conn.isAvailable()) {
                            conn.start();
                        }
                        try {
                            conn.getMapperListener().registerHost(
                                    vs.getJmxName());
                        } catch (Exception e) {
                            throw new LifecycleException(e);
                        }
                    }
                }
            }
        }

        // Remove the old default web module if one was configured, by
        // passing in "null" as the default context path
        if (oldDefaultWebModule != null) {
            updateDefaultWebModule(vs, oldListeners, null);
        }

        /*
         * Add default web module if one has been configured for the
         * virtual server. If the module declared as the default web module
         * has already been deployed at the root context, we don't have
         * to do anything.
         */
        WebModuleConfig wmInfo = vs.getDefaultWebModule(domain,
                habitat.getComponent(WebArchivist.class),
                appRegistry);
        if ((wmInfo != null) && (wmInfo.getContextPath() != null) &&
                !"".equals(wmInfo.getContextPath()) &&
                !"/".equals(wmInfo.getContextPath())) {
            // Remove dummy context that was created off of docroot, if such
            // a context exists
            removeDummyModule(vs);
            updateDefaultWebModule(vs,
                    vs.getNetworkListenerNames(),
                    wmInfo);
        } else {
            WebModuleConfig wmc =
                    vs.createSystemDefaultWebModuleIfNecessary(
                            habitat.getComponent(WebArchivist.class));
            if (wmc != null) {
                loadStandaloneWebModule(vs, wmc);
            }
        }

        if (updateListeners) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("Virtual server " + vs.getName()
                        + " network listeners are updated from "
                        + vs.getNetworkListeners() +" to " + vsBean.getNetworkListeners());
            }
            /*
             * Need to update connector and mapper restart is required
             * when virtual-server.http-listeners is changed dynamically
             */
            List<NetworkListener> httpListeners =
                    serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener();
            if (httpListeners != null) {
                for (NetworkListener httpListener : httpListeners) {
                    updateConnector(httpListener, habitat.getByType(HttpService.class));
                }
            }
        }

    }


    /**
     * Update virtual-server properties.
     */
    public void updateHostProperties(
            com.sun.enterprise.config.serverbeans.VirtualServer vsBean,
            String name, String value, SecurityService securityService, final VirtualServer vs) {
        if (vs == null) {
            return;
        }
        vs.setBean(vsBean);

        if (name == null) {
            return;
        }

        if (name.startsWith("alternatedocroot_")) {
            updateAlternateDocroot(vs);
        } else if ("setCacheControl".equals(name)) {
            vs.configureCacheControl(value);
        } else if (Constants.ACCESS_LOGGING_ENABLED.equals(name)) {
            vs.reconfigureAccessLog(globalAccessLogBufferSize,
                    globalAccessLogWriteInterval, habitat, domain,
                    globalAccessLoggingEnabled);
        } else if (Constants.ACCESS_LOG_PROPERTY.equals(name)) {
            vs.reconfigureAccessLog(globalAccessLogBufferSize,
                    globalAccessLogWriteInterval, habitat, domain,
                    globalAccessLoggingEnabled);
        } else if (Constants.ACCESS_LOG_WRITE_INTERVAL_PROPERTY.equals(name)) {
            vs.reconfigureAccessLog(globalAccessLogBufferSize,
                    globalAccessLogWriteInterval,
                    habitat,
                    domain,
                    globalAccessLoggingEnabled);
        } else if (Constants.ACCESS_LOG_BUFFER_SIZE_PROPERTY.equals(name)) {
            vs.reconfigureAccessLog(globalAccessLogBufferSize,
                    globalAccessLogWriteInterval,
                    habitat,
                    domain,
                    globalAccessLoggingEnabled);
        } else if ("allowRemoteHost".equals(name)
                || "denyRemoteHost".equals(name)) {
            vs.configureRemoteHostFilterValve();
        } else if ("allowRemoteAddress".equals(name)
                || "denyRemoteAddress".equals(name)) {
            vs.configureRemoteAddressFilterValve();
        } else if (Constants.SSO_ENABLED.equals(name)) {
            vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled());
        } else if ("authRealm".equals(name)) {
            vs.configureAuthRealm(securityService);
        } else if (name.startsWith("send-error")) {
            vs.configureErrorPage();
        } else if (Constants.ERROR_REPORT_VALVE.equals(name)) {
            vs.setErrorReportValveClass(value);
        } else if (name.startsWith("redirect")) {
            vs.configureRedirect();
        } else if (name.startsWith("contextXmlDefault")) {
            vs.setDefaultContextXmlLocation(value);
        }
    }

    private boolean isSsoFailoverEnabled() {
        boolean webContainerAvailabilityEnabled =
            serverConfigLookup.getWebContainerAvailabilityEnabledFromConfig();
        boolean isSsoFailoverEnabled =
            serverConfigLookup.isSsoFailoverEnabledFromConfig();
        return isSsoFailoverEnabled && webContainerAvailabilityEnabled;
    }

    /**
     * Processes an update to the http-service element
     */
    public void updateHttpService(HttpService httpService) throws LifecycleException {

        if (httpService == null) {
            return;
        }

        /*
         * Update each virtual server with the sso-enabled and
         * access logging related properties of the updated http-service
         */
        globalSSOEnabled = ConfigBeansUtilities.toBoolean(httpService.getSsoEnabled());
        globalAccessLogWriteInterval = httpService.getAccessLog().getWriteIntervalSeconds();
        globalAccessLogBufferSize = httpService.getAccessLog().getBufferSizeBytes();
        globalAccessLoggingEnabled = ConfigBeansUtilities.toBoolean(httpService.getAccessLoggingEnabled());

        // for availability-service.web-container-availability
        webContainerFeatureFactory = getWebContainerFeatureFactory();

        List<com.sun.enterprise.config.serverbeans.VirtualServer> virtualServers =
                httpService.getVirtualServer();
        for (com.sun.enterprise.config.serverbeans.VirtualServer virtualServer : virtualServers) {
            final VirtualServer vs = (VirtualServer) getEngine().findChild(virtualServer.getId());
            if (vs != null) {
                vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled());
                vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain,
                        globalAccessLoggingEnabled);
                updateHost(virtualServer);
            }
        }

    }


    /**
     * Update an http-listener property
     *
     * @param listener  the configuration bean.
     * @param propName  the property name
     * @param propValue the property value
     */
    public void updateConnectorProperty(NetworkListener listener,
                                        String propName,
                                        String propValue)
            throws LifecycleException {

        WebConnector connector = connectorMap.get(listener.getName());
        if (connector != null) {
            connector.configHttpProperties(listener.findHttpProtocol().getHttp(),
                    listener.findTransport(), listener.findHttpProtocol().getSsl());
            connector.configureHttpListenerProperty(propName, propValue);
        }
    }


    /**
     * Update an network-listener
     *
     * @param httpService the configuration bean.
     */
    public void updateConnector(NetworkListener networkListener,
                                HttpService httpService)
            throws LifecycleException {

        synchronized (mapperUpdateSync) {
            // Disable dynamic reconfiguration of the http listener at which
            // the admin related webapps (including the admingui) are accessible.
            // Notice that in GlassFish v3, we support a domain.xml configuration
            // that does not declare any admin-listener, in which case the
            // admin-related webapps are accessible on http-listener-1.
            if (networkListener.findHttpProtocol().getHttp().getDefaultVirtualServer().equals(
                    org.glassfish.api.web.Constants.ADMIN_VS) ||
                    "http-listener-1".equals(networkListener.getName()) &&
                            connectorMap.get("admin-listener") == null) {
                return;
            }

            WebConnector connector = connectorMap.get(networkListener.getName());
            if (connector != null) {
                deleteConnector(connector);
            }

            if (!Boolean.valueOf(networkListener.getEnabled())) {
                return;
            }

            connector = addConnector(networkListener, httpService, false);

            // Update the list of listener names of all associated virtual servers with
            // the listener's new listener name , so that the associated virtual
            // servers will be registered with the listener's request mapper when
            // the listener is started
            List<VirtualServer> virtualServers =
                    getVirtualServersForHttpListenerId(httpService, networkListener.getName());
            if (virtualServers != null) {
                Mapper mapper = connector.getMapper();
                for (VirtualServer vs : virtualServers) {
                    boolean found = false;
                    String[] listenerNames = vs.getNetworkListenerNames();
                    String name = connector.getName();
                    for (String listenerName : listenerNames) {
                        if (listenerName.equals(name)) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        String[] newListenerNames = new String[listenerNames.length + 1];
                        System.arraycopy(listenerNames, 0, newListenerNames, 0, listenerNames.length);
                        newListenerNames[listenerNames.length] = connector.getName();
                        vs.setNetworkListenerNames(newListenerNames);
                    }

                    // Check if virtual server has default-web-module configured,
                    // and if so, configure the http listener's mapper with this
                    // information
                    String defaultWebModulePath = vs.getDefaultContextPath(
                            domain, appRegistry);
                    if (defaultWebModulePath != null) {
                        try {
                            mapper.setDefaultContextPath(vs.getName(),
                                    defaultWebModulePath);
                            vs.setDefaultContextPath(defaultWebModulePath);
                        } catch (Exception e) {
                            throw new LifecycleException(e);
                        }
                    }
                }
            }

            connector.start();
        }
    }

    /**
     * Method gets called, when GrizzlyService changes HTTP Mapper, associated
     * with specific port.
     *
     * @param httpService  {@link HttpService}
     * @param httpListener {@link NetworkListener}, which {@link Mapper} was changed
     * @param mapper       new {@link Mapper} value
     */
    public void updateMapper(HttpService httpService, NetworkListener httpListener,
                             Mapper mapper) {
        synchronized (mapperUpdateSync) {
            WebConnector connector = connectorMap.get(httpListener.getName());
            if (connector != null && connector.getMapper() != mapper) {
                try {
                    updateConnector(httpListener, httpService);
                } catch (LifecycleException le) {
                    _logger.log(Level.SEVERE, "webcontainer.exceptionConfigHttpService", le);
                }
            }
        }
    }


    public WebConnector addConnector(NetworkListener httpListener,
                                     HttpService httpService,
                                     boolean start)
            throws LifecycleException {

        synchronized (mapperUpdateSync) {
            int port = Integer.parseInt(httpListener.getPort());

            // Add the listener name of the new http-listener to its
            // default-virtual-server, so that when the new http-listener
            // and its MapperListener are started, they will recognize the
            // default-virtual-server as one of their own, and add it to the
            // Mapper
            String virtualServerName = httpListener.findHttpProtocol().getHttp().getDefaultVirtualServer();
            VirtualServer vs =
                    (VirtualServer) getEngine().findChild(virtualServerName);
            List<String> list = Arrays.asList(vs.getNetworkListenerNames());
            // Avoid adding duplicate network-listener name
            if (!list.contains(httpListener.getName())) {
                String[] oldListenerNames = vs.getNetworkListenerNames();
                String[] newListenerNames = new String[oldListenerNames.length + 1];
                System.arraycopy(oldListenerNames, 0, newListenerNames, 0, oldListenerNames.length);
                newListenerNames[oldListenerNames.length] = httpListener.getName();
                vs.setNetworkListenerNames(newListenerNames);
            } 

            Mapper mapper = null;
            for (Mapper m : habitat.getAllByContract(Mapper.class)) {
                if (m.getPort() == port && m instanceof ContextMapper) {
                    ContextMapper cm = (ContextMapper) m;
                    if (httpListener.getName().equals(cm.getId())) {
                        mapper = m;
                        break;
                    }
                }
            }

            WebConnector connector =
                    createHttpListener(httpListener, httpService, mapper);

            if (connector.getRedirectPort() == -1) {
                connector.setRedirectPort(defaultRedirectPort);
            }

            if (start) {
                connector.start();
            }
            return connector;
        }
    }


    /**
     * Stops and deletes the specified http listener.
     */
    public void deleteConnector(WebConnector connector)
            throws LifecycleException {

        String name = connector.getName();

        Connector[] connectors = _embedded.findConnectors();
        for (Connector conn : connectors) {
            if (name.equals(conn.getName())) {
                _embedded.removeConnector(conn);
                connectorMap.remove(connector.getName());
            }
        }
    }


    /**
     * Stops and deletes the specified http listener.
     */
    public void deleteConnector(NetworkListener httpListener)
            throws LifecycleException {

        Connector[] connectors = _embedded.findConnectors();
        String name = httpListener.getName();
        for (Connector conn : connectors) {
            if (name.equals(conn.getName())) {
                _embedded.removeConnector(conn);
                connectorMap.remove(name);
            }
        }

    }


    /**
     * Reconfigures the access log valve of each virtual server with the
     * updated attributes of the <access-log> element from domain.xml.
     */
    public void updateAccessLog(HttpService httpService) {
        Container[] virtualServers = getEngine().findChildren();
        for (Container virtualServer : virtualServers) {
            ((VirtualServer) virtualServer).reconfigureAccessLog(
                    httpService, webContainerFeatureFactory);
        }
    }


    /**
     * Updates the docroot of the given virtual server
     */
    private void updateDocroot(
            String docroot,
            VirtualServer vs,
            com.sun.enterprise.config.serverbeans.VirtualServer vsBean) {

        validateDocroot(docroot, vsBean.getId(),
                vsBean.getDefaultWebModule());
        vs.setAppBase(docroot);
        removeDummyModule(vs);
        WebModuleConfig wmInfo =
                vs.createSystemDefaultWebModuleIfNecessary(
                        habitat.getComponent(WebArchivist.class));
        if (wmInfo != null) {
            loadStandaloneWebModule(vs, wmInfo);
        }
    }


    private void updateAlternateDocroot(VirtualServer vs) {
        removeDummyModule(vs);
        WebModuleConfig wmInfo = vs.createSystemDefaultWebModuleIfNecessary(
                habitat.getComponent(WebArchivist.class));
        if (wmInfo != null) {
            loadStandaloneWebModule(vs, wmInfo);
        }
    }


    /**
     * is Tomcat using default domain name as its domain
     */
    protected boolean isTomcatUsingDefaultDomain() {
        // need to be careful and make sure tomcat jmx mapping works
        // since setting this to true might result in undeployment problems
        return true;
    }


    /**
     * Creates probe providers for Servlet, JSP, Session, and
     * Request/Response related events.
     * <p/>
     * While the Servlet, JSP, and Session related probe providers are
     * shared by all web applications (where every web application
     * qualifies its probe events with its application name), the
     * Request/Response related probe provider is shared by all HTTP
     * listeners.
     */
    private void createProbeProviders() {
        webModuleProbeProvider = new WebModuleProbeProvider();
        servletProbeProvider = new ServletProbeProvider();
        jspProbeProvider = new JspProbeProvider();
        sessionProbeProvider = new SessionProbeProvider();
        requestProbeProvider = new RequestProbeProvider();
    }


    /**
     * Creates statistics providers for Servlet, JSP, Session, and
     * Request/Response related events.
     */
    private void createStatsProviders() {
        HttpServiceStatsProviderBootstrap httpStatsProviderBootstrap =
                habitat.getByType(HttpServiceStatsProviderBootstrap.class);
        webStatsProviderBootstrap =
                habitat.getByType(WebStatsProviderBootstrap.class);
    }


    /*
     * Loads the class with the given name using the common classloader,
     * which is responsible for loading any classes from the domain's
     * lib directory
     *
     * @param className the name of the class to load
     */

    public Class loadCommonClass(String className) throws Exception {
        return clh.getCommonClassLoader().loadClass(className);
    }

    /**
     * According to SRV 15.5.15, Servlets, Filters, Listeners can only be
     * without any scope annotation or are annotated with
     *
     * @Dependent scope. All other scopes are invalid and must be rejected.
     */
    private void validateJSR299Scope(Class clazz) {
        if (clazz.isAnnotationPresent(RequestScoped.class) ||
                clazz.isAnnotationPresent(ApplicationScoped.class) ||
                clazz.isAnnotationPresent(SessionScoped.class) ||
                clazz.isAnnotationPresent(ConversationScoped.class)) {

            String msg = rb.getString("webcontainer.invalidAnnotationScope");
            msg = MessageFormat.format(msg, clazz.getName());
            throw new IllegalArgumentException(msg);
        }
    }

    /**
     * Return the WebContainerFeatureFactory according to the configuration.
     * @return WebContainerFeatuerFactory
     */
    private WebContainerFeatureFactory getWebContainerFeatureFactory() {
        String featureFactoryName =
                    (serverConfigLookup.getWebContainerAvailabilityEnabledFromConfig() ? "ha" : "pe");
        return webContainerFeatureFactory = habitat.getComponent(
                    WebContainerFeatureFactory.class, featureFactoryName);
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish WebContainer.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.