All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.web.VirtualServer Maven / Gradle / Ivy

There is a newer version: 4.1.2.181
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2017 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.
 */

// Portions Copyright [2016] [Payara Foundation]

package com.sun.enterprise.web;

import com.sun.enterprise.config.serverbeans.ApplicationRef;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.AuthRealm;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.HttpService;
import com.sun.enterprise.config.serverbeans.SecurityService;
import com.sun.enterprise.config.serverbeans.ServerTags;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.security.web.GlassFishSingleSignOn;
import com.sun.enterprise.server.logging.GFFileHandler;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.v3.common.PlainTextActionReporter;
import com.sun.enterprise.v3.services.impl.GrizzlyProxy;
import com.sun.enterprise.v3.services.impl.GrizzlyService;
import com.sun.enterprise.web.logger.CatalinaLogger;
import com.sun.enterprise.web.logger.FileLoggerHandler;
import com.sun.enterprise.web.logger.FileLoggerHandlerFactory;
import com.sun.enterprise.web.pluggable.WebContainerFeatureFactory;
import com.sun.enterprise.web.session.SessionCookieConfig;
import com.sun.web.security.RealmAdapter;
import java.io.File;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.catalina.*;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.authenticator.SingleSignOn;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.deploy.ErrorPage;
import org.apache.catalina.valves.RemoteAddrValve;
import org.apache.catalina.valves.RemoteHostValve;
import org.glassfish.api.ActionReport;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.DeployCommandParameters;
import org.glassfish.api.deployment.OpsParams;
import org.glassfish.api.deployment.UndeployCommandParameters;
import org.glassfish.api.deployment.archive.ArchiveHandler;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.deployment.common.ApplicationConfigInfo;
import org.glassfish.deployment.common.DeploymentContextImpl;
import org.glassfish.deployment.common.DeploymentUtils;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.web.ConfigException;
import org.glassfish.embeddable.web.Context;
import org.glassfish.embeddable.web.WebListener;
import org.glassfish.embeddable.web.config.VirtualServerConfig;
import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.ConnectionProbe;
import org.glassfish.grizzly.config.GenericGrizzlyListener;
import org.glassfish.grizzly.config.dom.NetworkListener;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.http.HttpCodecFilter;
import org.glassfish.grizzly.http.HttpPacket;
import org.glassfish.grizzly.http.HttpProbe;
import org.glassfish.grizzly.http.HttpRequestPacket;
import org.glassfish.grizzly.http.HttpResponsePacket;
import org.glassfish.grizzly.http.util.HttpStatus;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.ServerContext;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.glassfish.web.LogFacade;
import org.glassfish.web.admin.monitor.RequestProbeProvider;
import org.glassfish.web.deployment.archivist.WebArchivist;
import org.glassfish.web.deployment.descriptor.WebBundleDescriptorImpl;
import org.glassfish.web.loader.WebappClassLoader;
import org.glassfish.web.valve.GlassFishValve;
import org.jvnet.hk2.config.Transaction;
import org.jvnet.hk2.config.TransactionFailure;
import org.jvnet.hk2.config.types.Property;
import org.w3c.dom.*;


/**
 * Standard implementation of a virtual server (aka virtual host) in
 * the iPlanet Application Server.
 */

public class VirtualServer extends StandardHost 
        implements org.glassfish.embeddable.web.VirtualServer {

    private static final String STATE = "state";
    private static final String SSO_MAX_IDLE ="sso-max-inactive-seconds";
    private static final String SSO_REAP_INTERVAL ="sso-reap-interval-seconds";
    private static final String SSO_COOKIE_SECURE ="sso-cookie-secure";
    private static final String DISABLED = "disabled";
    private static final String OFF = "off";
    private static final String ON = "on";

    /**
     * The logger to use for logging this virtual server
     */
    private static final Logger DEFAULT_LOGGER = LogFacade.getLogger();

    /**
     * The resource bundle containing the message strings for _logger.
     */
    protected static final ResourceBundle rb = DEFAULT_LOGGER.getResourceBundle();


    // ------------------------------------------------------------ Constructor

    /**
     * Default constructor that simply gets a handle to the web container
     * subsystem's logger.
     */
    public VirtualServer() {
        origPipeline = pipeline;
        vsPipeline = new VirtualServerPipeline(this);
        accessLogValve = new PEAccessLogValve();
        accessLogValve.setContainer(this);
    }

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

    /*
     * The custom pipeline of this VirtualServer, which implements the
     * following virtual server features:
     *
     * - state (disabled/off)
     * - redirects
     */
    private VirtualServerPipeline vsPipeline;

    /*
     * The original (standard) pipeline of this VirtualServer.
     *
     * Only one (custom or original) pipeline may be active at any given time.
     * Any updates (such as adding or removing valves) to the currently
     * active pipeline are propagated to the other.
     */
    private Pipeline origPipeline;

    /**
     * The id of this virtual server as specified in the configuration.
     */
    private String _id = null;

    /**
     * The logger to use for logging this virtual server
     */
    protected Logger _logger = DEFAULT_LOGGER;

    /**
     * The descriptive information about this implementation.
     */
    private static final String _info =
        "com.sun.enterprise.web.VirtualServer/1.0";

    /**
     * The config bean associated with this VirtualServer
     */
    private com.sun.enterprise.config.serverbeans.VirtualServer vsBean;

    /**
     * The mime mapping associated with this VirtualServer
     */
    private MimeMap mimeMap;

    /*
     * Indicates whether symbolic links from this virtual server's docroot
     * are followed. This setting is inherited by all web modules deployed on
     * this virtual server, unless overridden by a web modules allowLinking
     * property in sun-web.xml.
     */
    private boolean allowLinking = false;

    private String[] cacheControls;

    private ClassLoaderHierarchy clh;

    private Domain domain;

    private ServiceLocator services;

    // Is this virtual server active?
    private boolean isActive;

    private String authRealmName;

    /*
     * The accesslog valve of this VirtualServer.
     *
     * This valve is activated, that is, added to this virtual server's
     * pipeline, only when access logging has been enabled. When acess logging
     * has been disabled, this valve is removed from this virtual server's
     * pipeline.
     */
    private PEAccessLogValve accessLogValve;

    // The value of the ssoCookieSecure property
    private String ssoCookieSecure = null;

    private boolean ssoCookieHttpOnly = false;

    private String defaultContextPath = null;

    private ServerContext serverContext;

    private Config serverConfig;

    private GrizzlyService grizzlyService;

    private WebContainer webContainer;

    private boolean ssoFailoverEnabled = false;

    private volatile FileLoggerHandler fileLoggerHandler = null;

    private volatile FileLoggerHandlerFactory fileLoggerHandlerFactory = null;

    private Deployment deployment = null;

    private ArchiveFactory factory = null;

    private ActionReport report = null;

    // ------------------------------------------------------------- Properties

    /**
     * Return the virtual server identifier.
     */
    public String getID() {
        return _id;
    }

    /**
     * Set the virtual server identifier string.
     *
     * @param id New identifier for this virtual server
     */
    public void setID(String id) {
        _id = id;
    }

    /**
     * Sets the state of this virtual server.
     *
     * @param isActive true if this virtual server is active, false otherwise
     */
    public void setIsActive(boolean isActive) {
        this.isActive = isActive;
        if (isActive) {
            vsPipeline.setIsDisabled(false);
            vsPipeline.setIsOff(false);
            if (pipeline == vsPipeline && !vsPipeline.hasRedirects()) {
                // Restore original pipeline
                setPipeline(origPipeline);
            }
        }
    }
    
    /**
     * Gets the value of the allowLinking property of this virtual server.
     *
     * @return true if symbolic links from this virtual server's docroot (as
     * well as symbolic links from archives of web modules deployed on this
     * virtual server) are followed, false otherwise
     */
    public boolean getAllowLinking() {
        return allowLinking;
    }

    /**
     * Sets the allowLinking property of this virtual server, which determines
     * whether symblic links from this virtual server's docroot are followed.
     *
     * This property is inherited by all web modules deployed on this virtual
     * server, unless overridden by the allowLinking property in a web module's
     * sun-web.xml.
     *
     * @param allowLinking Value of allowLinking property
     */
    public void setAllowLinking(boolean allowLinking) {
        this.allowLinking = allowLinking;
    }

    /**
     * Gets the config bean associated with this VirtualServer.
     */
    public com.sun.enterprise.config.serverbeans.VirtualServer getBean(){
        return vsBean;
    }

    /**
     * Sets the config bean for this VirtualServer
     */
    public void setBean(
            com.sun.enterprise.config.serverbeans.VirtualServer vsBean){
        this.vsBean = vsBean;
    }

    /**
     * Gets the mime map associated with this VirtualServer.
     */
    public MimeMap getMimeMap(){
        return mimeMap;
    }

    /**
     * Sets the mime map for this VirtualServer
     */
    public void setMimeMap(MimeMap mimeMap){
        this.mimeMap = mimeMap;
    }

    /**
     * Gets the Cache-Control configuration of this VirtualServer.
     *
     * @return Cache-Control configuration of this VirtualServer, or null if
     * no such configuration exists for this VirtualServer
     */
    public String[] getCacheControls() {
        return cacheControls;
    }

    /**
     * Sets the Cache-Control configuration for this VirtualServer
     *
     * @param cacheControls Cache-Control configuration settings for this
     * VirtualServer
     */
    public void setCacheControls(String[] cacheControls) {
        this.cacheControls = cacheControls;
    }

    public void setServices(ServiceLocator services) {
        this.services = services;
    }

    public String getInfo() {
        return _info;
    }

    public void setDefaultContextPath(String defaultContextPath) {
        this.defaultContextPath = defaultContextPath;
    }

    public void setFileLoggerHandlerFactory(FileLoggerHandlerFactory factory) {
        fileLoggerHandlerFactory = factory;
    }

    public void setClassLoaderHierarchy(ClassLoaderHierarchy clh) {
        this.clh = clh;
    }

    public void setDomain(Domain domain) {
        this.domain = domain;
    }

    @Override
    public Container findChild(String contextRoot) {
        if (defaultContextPath != null && "/".equals(contextRoot)) {
            return super.findChild(defaultContextPath);
        } else {
            return super.findChild(contextRoot);
        }
    }


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

    /**
     * Configures the Secure attribute of the given SSO cookie.
     *
     * @param ssoCookie the SSO cookie to be configured
     * @param hreq the HttpServletRequest that has initiated the SSO session
     */
    @Override
    public void configureSingleSignOnCookieSecure(Cookie ssoCookie,
                                                  HttpServletRequest hreq) {
        super.configureSingleSignOnCookieSecure(ssoCookie, hreq);
        if (ssoCookieSecure != null &&
                !ssoCookieSecure.equals(SessionCookieConfig.DYNAMIC_SECURE)) {
            ssoCookie.setSecure(Boolean.parseBoolean(ssoCookieSecure));
        }
    }

    @Override
    public void configureSingleSignOnCookieHttpOnly(Cookie ssoCookie) {
        ssoCookie.setHttpOnly(ssoCookieHttpOnly);
    }


    // ------------------------------------------------------ Lifecycle Methods

    /**
     * Adds the given valve to the currently active pipeline, keeping the
     * pipeline that is not currently active in sync.
     */
    public synchronized void addValve(GlassFishValve valve) {
        super.addValve(valve);
        if (pipeline == vsPipeline) {
            origPipeline.addValve(valve);
        } else {
            vsPipeline.addValve(valve);
        }
    }


    /**
     * Adds the given Tomcat-style valve to the currently active pipeline,
     * keeping the pipeline that is not currently active in sync.
     */
    public synchronized void addValve(Valve valve) {
        super.addValve(valve);
        if (pipeline == vsPipeline) {
            origPipeline.addValve(valve);
        } else {
            vsPipeline.addValve(valve);
        }
    }


    /**
     * Removes the given valve from the currently active pipeline, keeping the
     * valve that is not currently active in sync.
     */
    public synchronized void removeValve(GlassFishValve valve) {
        super.removeValve(valve);
        if (pipeline == vsPipeline) {
            origPipeline.removeValve(valve);
        } else {
            vsPipeline.removeValve(valve);
        }
    }
    
    private ConfigBeansUtilities getConfigBeansUtilities() {
    	if (services == null) return null;
    	return services.getService(ConfigBeansUtilities.class);
    }

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

    /**
     * Gets the context root of the web module that the user/configuration
     * has designated as the default-web-module for this virtual server.
     *
     * The default-web-module for a virtual server is specified via the
     * 'default-web-module' attribute of the 'virtual-server' element in
     * server.xml. This is an optional attribute and if the configuration
     * does not specify another web module (standalone or part of a
     * j2ee-application) that is configured at a context-root="", then
     * a default web module will be created and loaded. The value for this
     * attribute is either "${standalone-web-module-name}" or
     * "${j2ee-app-name}:${web-module-uri}".
     *
     * @return null if the default-web-module has not been specified or
     *              if the web module specified either could not be found or
     *              is disabled or does not specify this virtual server (if
     *              it specifies a value for the virtual-servers attribute) or
     *              if there was an error loading its deployment descriptors.
     */
    protected String getDefaultContextPath(Domain domain,
            ApplicationRegistry appRegistry) {

        String contextRoot = null;
        String wmID = getDefaultWebModuleID();

        if (wmID != null) {
            // Check if the default-web-module is part of a
            // j2ee-application
            Applications appsBean = domain.getApplications();
            WebModuleConfig wmInfo = findWebModuleInJ2eeApp(appsBean, wmID,
                                                            appRegistry);
            if (wmInfo == null) {
            	ConfigBeansUtilities cbu = getConfigBeansUtilities();
            	if (cbu == null) {
            		contextRoot = null;
            	}
            	else {
                    contextRoot = cbu.getContextRoot(wmID);
            	}
            } else {
                contextRoot = wmInfo.getContextPath();
            }

            if (contextRoot == null) {
                Object[] params = { wmID, getID() };
                _logger.log(Level.SEVERE, LogFacade.VS_DEFAULT_WEB_MODULE_NOT_FOUND, params);
            }
        }

        return contextRoot;
    }

    protected WebModuleConfig getDefaultWebModule(Domain domain,
            WebArchivist webArchivist, ApplicationRegistry appRegistry) {

        WebModuleConfig wmInfo = null;

        String wmID = getDefaultWebModuleID();
        if (wmID != null) {
            // Check if the default-web-module is part of a
            // j2ee-application
            Applications appsBean = domain.getApplications();
            wmInfo = findWebModuleInJ2eeApp(appsBean, wmID, appRegistry);
            if (wmInfo == null) {
            	ConfigBeansUtilities cbu = getConfigBeansUtilities();
            	String contextRoot = null;
            	String location = null;
            	if (cbu != null) {
            		contextRoot = cbu.getContextRoot(wmID);
            		location = cbu.getLocation(wmID);
            	}
            	
                if (contextRoot!=null && location != null) {
                    File docroot = new File(location);
                    final WebBundleDescriptorImpl wbd = webArchivist.getDefaultWebXmlBundleDescriptor();
                    wmInfo = new WebModuleConfig();
                    wbd.setName(Constants.DEFAULT_WEB_MODULE_NAME);
                    wbd.setContextRoot(contextRoot);
                    wmInfo.setLocation(docroot);
                    wmInfo.setDescriptor(wbd);
                    wmInfo.setParentLoader(EmbeddedWebContainer.class.getClassLoader());
                    WebappClassLoader cloader = AccessController.doPrivileged(new PrivilegedAction() {
                        @Override
                        public WebappClassLoader run() {
                            return new WebappClassLoader(EmbeddedWebContainer.class.getClassLoader(), wbd.getApplication());
                        }
                    });
                    wmInfo.setAppClassLoader(cloader);
                }
            }

            if (wmInfo == null) {
                _logger.log(Level.SEVERE, LogFacade.VS_DEFAULT_WEB_MODULE_NOT_FOUND, new Object[] {wmID, getID()});
            }
        }

        return wmInfo;
    }


    /**
     * If a default web module has not yet been configured and added to this
     * virtual server's list of web modules then return the configuration
     * information needed in order to create a default web module for this
     * virtual server.
     *
     * This method should be invoked only after all the standalone modules
     * and the modules within j2ee-application elements have been added to
     * this virtual server's list of modules (only then will one know whether
     * the user has already configured a default web module or not).
     */
    public WebModuleConfig createSystemDefaultWebModuleIfNecessary(
            WebArchivist webArchivist) {

        WebModuleConfig wmInfo = null;

        // Add a default context only if one hasn't already been loaded
        // and then too only if docroot is not null
        //
        String docroot = getAppBase();
        if (getDefaultWebModuleID() == null && findChild("") == null
                && docroot != null) {

            final WebBundleDescriptorImpl wbd =
                webArchivist.getDefaultWebXmlBundleDescriptor();
            wmInfo = new WebModuleConfig();
            wbd.setModuleID(Constants.DEFAULT_WEB_MODULE_NAME);
            wbd.setContextRoot("");
            wmInfo.setLocation(new File(docroot));
            wmInfo.setDescriptor(wbd);
            wmInfo.setParentLoader(
                serverContext.getCommonClassLoader());
            if ( wbd.getApplication() == null ) {
                Application application = Application.createApplication();
                application.setVirtual(true);
                application.setName(Constants.DEFAULT_WEB_MODULE_NAME);
                wbd.setApplication(application);
            }
            WebappClassLoader loader = AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public WebappClassLoader run() {
                    return new WebappClassLoader(serverContext.getCommonClassLoader(), wbd.getApplication());
                }
            });
            loader.start();            
            wmInfo.setAppClassLoader(loader);
        }

        return wmInfo;

    }

    /**
     * Returns the id of the default web module for this virtual server
     * as specified in the 'default-web-module' attribute of the
     * 'virtual-server' element.
     */
    protected String getDefaultWebModuleID() {
        String wmID = vsBean.getDefaultWebModule();
        if ("".equals(wmID)) {
            wmID = null;
        }
        if (wmID != null && _logger.isLoggable(Level.FINE)) {
            Object[] params = { wmID, _id };
            _logger.log(Level.FINE, LogFacade.VS_DEFAULT_WEB_MODULE, params);
        }

        return wmID;
    }

    /**
     * Finds and returns information about a web module embedded within a
     * J2EE application, which is identified by a string of the form
     * a:b or a#b, where a is the name
     * of the J2EE application and b is the name of the embedded
     * web module.
     *
     * @return null if id does not identify a web module embedded
     * within a J2EE application.
     */
    protected WebModuleConfig findWebModuleInJ2eeApp(Applications appsBean,
            String id, ApplicationRegistry appRegistry) {

        WebModuleConfig wmInfo = null;

        // Check for ':' separator
        int separatorIndex = id.indexOf(Constants.NAME_SEPARATOR);
        if (separatorIndex == -1) {
            // Check for '#' separator
            separatorIndex = id.indexOf('#');
        }
        if (separatorIndex != -1) {
            String appID = id.substring(0, separatorIndex);
            String moduleID = id.substring(separatorIndex + 1);

            com.sun.enterprise.config.serverbeans.Application appBean =
                appsBean.getModule(
                com.sun.enterprise.config.serverbeans.Application.class, appID);

            if ((appBean != null) && Boolean.valueOf(appBean.getEnabled())) {
                String location = appBean.getLocation();
                String moduleDir = DeploymentUtils.getRelativeEmbeddedModulePath(
                                                            location, moduleID);

                ApplicationInfo appInfo = appRegistry.get(appID);
                final Application app = appInfo != null? appInfo.getMetaData(Application.class) : null;
                if (appInfo == null) {
                    // XXX ApplicaionInfo is NULL after restart
                    Object[] params = { id, getID() };
                    _logger.log(Level.SEVERE, LogFacade.VS_DEFAULT_WEB_MODULE_DISABLED,
                            params);
                    return wmInfo;
                }

                final WebBundleDescriptorImpl wbd = app.getModuleByTypeAndUri(WebBundleDescriptorImpl.class, moduleID);
                String webUri = wbd.getModuleDescriptor().getArchiveUri();
                String contextRoot = wbd.getModuleDescriptor().getContextRoot();
                if (moduleID.equals(webUri)) {
                    StringBuilder dir = new StringBuilder(location);
                    dir.append(File.separator);
                    dir.append(moduleDir);
                    File docroot = new File(dir.toString());
                    wmInfo = new WebModuleConfig();
                    wbd.setName(moduleID);
                    wbd.setContextRoot(contextRoot);
                    wmInfo.setDescriptor(wbd);
                    wmInfo.setLocation(docroot);
                    wmInfo.setParentLoader(EmbeddedWebContainer.class.getClassLoader());
                    WebappClassLoader cloader = AccessController.doPrivileged(new PrivilegedAction() {
                        @Override
                        public WebappClassLoader run() {
                            return new WebappClassLoader(EmbeddedWebContainer.class.getClassLoader(), app);
                        }
                    });
                    wmInfo.setAppClassLoader(cloader);

                }
            } else {
                Object[] params = { id, getID() };
                _logger.log(Level.SEVERE, LogFacade.VS_DEFAULT_WEB_MODULE_DISABLED,
                            params);
            }
        }

        return wmInfo;
    }

    /**
     * Virtual servers are maintained in the reference contained
     * in Server element. First, we need to find the server
     * and then get the virtual server from the correct reference
     *
     * @param appName Name of the app to get vs
     *
     * @return virtual servers as a string (separated by space or comma)
     *
    private String getVirtualServers(String appName) {
        String ret = null;
        Server server = Globals.getDefaultHabitat().forContract(Server.class).get();
        for (ApplicationRef appRef : server.getApplicationRef()) {
            if (appRef.getRef().equals(appName)) {
                return appRef.getVirtualServers();
            }
        }

        return ret;
    } */


    /**
     * Delete all aliases.
     */
    public void clearAliases(){
        aliases = new String[0];
    }

    private void setIsDisabled(boolean isDisabled) {
        vsPipeline.setIsDisabled(isDisabled);
        vsPipeline.setIsOff(false);
        if (isDisabled && pipeline != vsPipeline) {
            // Enable custom pipeline
            setPipeline(vsPipeline);
        }
    }

    private void setIsOff(boolean isOff) {
        vsPipeline.setIsOff(isOff);
        vsPipeline.setIsDisabled(false);
        if (isOff && pipeline != vsPipeline) {
            // Enable custom pipeline
            setPipeline(vsPipeline);
        }
    }

    private void close(FileLoggerHandler handler) {
        if (handler != null && !handler.isAssociated()) {
            if (fileLoggerHandlerFactory != null) {
                // should always be here
                fileLoggerHandlerFactory.removeHandler(handler.getLogFile());
            }
            handler.flush();
            handler.close();
        }
    }

    private void setLogger(Logger newLogger, String logLevel) {
        _logger = newLogger;
        // wrap into a cataline logger
        CatalinaLogger catalinaLogger = new CatalinaLogger(newLogger);
        catalinaLogger.setLevel(logLevel);
        setLogger(catalinaLogger);
    }

    /**
     * @return The properties of this virtual server
     */
    List getProperties() {
        return vsBean.getProperty();
    }

    /**
     * Configures this virtual server.
     */
    public void configure(
                    String vsID,
                    com.sun.enterprise.config.serverbeans.VirtualServer vsBean,
                    String vsDocroot,
                    String vsLogFile,
                    MimeMap vsMimeMap,
                    String logServiceFile,
                    String logLevel) {
        setDebug(debug);
        setAppBase(vsDocroot);
        setName(vsID);
        setID(vsID);
        setBean(vsBean);
        setMimeMap(vsMimeMap);

        String defaultContextXmlLocation = Constants.DEFAULT_CONTEXT_XML;
        String defaultWebXmlLocation = Constants.DEFAULT_WEB_XML;

        //Begin EE: 4920692 Make the default-web.xml be relocatable
        Property prop = vsBean.getProperty("default-web-xml");
        if (prop != null) {
            defaultWebXmlLocation = prop.getValue();
        }
        //End EE: 4920692 Make the default-web.xml be relocatable

        // allowLinking
        boolean allowLinking = false;
        prop = vsBean.getProperty("allowLinking");
        if (prop != null) {
            allowLinking = Boolean.parseBoolean(prop.getValue());
        }
        setAllowLinking(allowLinking);

        prop = vsBean.getProperty("contextXmlDefault");
        if (prop != null) {
            defaultContextXmlLocation = prop.getValue();
        }
        setDefaultWebXmlLocation(defaultWebXmlLocation);
        setDefaultContextXmlLocation(defaultContextXmlLocation);

        // Set vs state
        String state = vsBean.getState();
        if (state == null) {
            state = ON;
        }
        if (DISABLED.equalsIgnoreCase(state)) {
            setIsActive(false);
        } else {
            setIsActive(Boolean.parseBoolean(state));
        }

        setLogFile(vsLogFile, logLevel, logServiceFile);
    }

    /**
     * Configures the valve_ and listener_ properties of this VirtualServer.
     */
    protected void configureCatalinaProperties(){

        List props = vsBean.getProperty();
        if (props == null) {
            return;
        }

        for (Property prop : props) {

            String propName = prop.getName();
            String propValue = prop.getValue();
            if (propName == null || propValue == null) {
                _logger.log(Level.WARNING,
                        LogFacade.NULL_VIRTUAL_SERVER_PROPERTY,
                        getName());
            }

            if (propName != null) {
                if (propName.startsWith("valve_")) {
                    addValve(propValue);
                } else if (propName.startsWith("listener_")) {
                    addListener(propValue);
                } else if (propName.equals("securePagesWithPragma")){
                    setSecurePagesWithPragma(Boolean.valueOf(propValue));
                }
            }
        }
    }


    /*
     * Configures this virtual server with the specified log file.
     *
     * @param logFile The value of the virtual server's log-file attribute in
     * the domain.xml
     */
    synchronized void setLogFile(String logFile, String logLevel, String logServiceFile) {

        /** catalina file logger code
        String logPrefix = logFile;
        String logDir = null;
        String logSuffix = null;

        if (logPrefix == null || logPrefix.equals("")) {
            return;
        }

        int index = logPrefix.lastIndexOf(File.separatorChar);
        if (index != -1) {
            logDir = logPrefix.substring(0, index);
            logPrefix = logPrefix.substring(index+1);
        }

        index = logPrefix.indexOf('.');
        if (index != -1) {
            logSuffix = logPrefix.substring(index);
            logPrefix = logPrefix.substring(0, index);
        }

        logPrefix += "_";

        FileLogger contextLogger = new FileLogger();
        if (logDir != null) {
            contextLogger.setDirectory(logDir);
        }
        contextLogger.setPrefix(logPrefix);
        if (logSuffix != null) {
            contextLogger.setSuffix(logSuffix);
        }
        contextLogger.setTimestamp(true);
        contextLogger.setLevel(logLevel); 
         */
        

        /*
         * Configure separate logger for this virtual server only if
         * 'log-file' attribute of this  and 'file'
         * attribute of  are different (See 6189219).
         */
        boolean noCustomLog = (logFile == null ||
            (logServiceFile != null && new File(logFile).equals(
                    new File(logServiceFile))));

        if ((fileLoggerHandler == null && noCustomLog) ||
                (fileLoggerHandler != null && logFile != null &&
                logFile.equals(fileLoggerHandler.getLogFile()))) {
            return;
        }

        Logger newLogger = null;
        FileLoggerHandler oldHandler = fileLoggerHandler;
        //remove old handler
        if (oldHandler != null) {
            _logger.removeHandler(oldHandler);
        }

        if (noCustomLog) {
            fileLoggerHandler = null;
            newLogger = _logger;
        } else {
            // append the _logger name with "._vs."
            String lname = _logger.getName() + "._vs." + getID();
            newLogger = LogManager.getLogManager().getLogger(lname);
            if (newLogger == null) {
                newLogger = new Logger(lname, null) {
                    // set thread id, see LogDomains.getLogger method
                    @Override
                    public void log(LogRecord record) {
                        if (record.getResourceBundle() == null) {
                            ResourceBundle bundle = getResourceBundle();
                            if (bundle != null) {
                                record.setResourceBundle(bundle);
                            }
                        }
                        record.setThreadID((int)Thread.currentThread().getId());
                        super.log(record);
                    }

                    // use the same resource bundle as default vs logger
                    @Override
                    public ResourceBundle getResourceBundle() {
                        return rb;
                    }

                    @Override
                    public synchronized void addHandler(Handler handler) {
                        super.addHandler(handler);
                        if (handler instanceof FileLoggerHandler) {
                            ((FileLoggerHandler)handler).associate();
                        }
                    }

                    @Override
                    public synchronized void removeHandler(Handler handler) {
                        if (!(handler instanceof FileLoggerHandler)) {
                            super.removeHandler(handler);
                        } else {
                            boolean hasHandler = false;
                            Handler[] hs = getHandlers();
                            if (hs != null) {
                                for (Handler h : hs) {
                                    if (h == handler) {
                                        hasHandler = true;
                                        break;
                                    }
                                }
                            }
                            if (hasHandler) {
                                super.removeHandler(handler);
                                ((FileLoggerHandler)handler).disassociate();
                            }
                        }
                    }
                };

                synchronized(Logger.class) {
                    LogManager.getLogManager().addLogger(newLogger);
                }
            }

            // remove old handlers if necessary
            Handler[] handlers = newLogger.getHandlers();
            if (handlers != null) {
                for (Handler h : handlers) {
                    newLogger.removeHandler(h);
                }
            }

            // add handlers from root that is not GFFileHandler
            Logger rootLogger = Logger.global.getParent();
            if (rootLogger != null) {
                Handler[] rootHandlers = rootLogger.getHandlers();
                if (rootHandlers != null) {
                    for (Handler h : rootHandlers) {
                        if (!(h instanceof GFFileHandler)) {
                            newLogger.addHandler(h);
                        }
                    }
                }
            }

            // create and add new handler
            fileLoggerHandler = fileLoggerHandlerFactory.getHandler(logServiceFile);
            newLogger.addHandler(fileLoggerHandler);            
            newLogger.setUseParentHandlers(false);
        }

        setLogger(newLogger, logLevel);
        close(oldHandler);
    }

    /**
     * Adds each host name from the 'hosts' attribute as an alias
     */
    void configureAliases() {
        List hosts = StringUtils.parseStringList(vsBean.getHosts(), ",");
        for (int i=0; i < hosts.size(); i++ ){
            String alias = hosts.get(i).toString();
            if ( !alias.equalsIgnoreCase("localhost") &&
                    !alias.equalsIgnoreCase("localhost.localdomain")){
                addAlias(alias);
            }
        }
    }
    
    void configureAliases(String... hosts) {
        for (String host : hosts) {
            if ( !host.equalsIgnoreCase("localhost") &&
                    !host.equalsIgnoreCase("localhost.localdomain")){
                addAlias(host);
            }
        }
    }

    /**
     * Configures this virtual server with its authentication realm.
     *
     * Checks if this virtual server specifies any authRealm property, and
     * if so, ensures that its value identifies a valid realm.
     *
     * @param securityService The security-service element from domain.xml
     */
    void configureAuthRealm(SecurityService securityService) {
        List properties = vsBean.getProperty();
        if (properties != null && properties.size() > 0) {
            for (Property p: properties) {
                if (p != null && "authRealm".equals(p.getName())) {
                    authRealmName = p.getValue();
                    if (authRealmName != null) {
                        AuthRealm realm = null;
                        List rs = securityService.getAuthRealm();
                        if (rs != null && rs.size() > 0) {
                            for (AuthRealm r : rs) {
                                if (r != null &&
                                        r.getName().equals(authRealmName)) {
                                    realm = r;
                                    break;
                                }
                            }
                        }

                        if (realm == null) {
                            _logger.log(Level.SEVERE, LogFacade.INVALID_AUTH_REALM,
                                new Object[] {getID(), authRealmName});
                        }
                    }
                    break;
                }
            }
        }
    }

    /**
     * Gets the value of the authRealm property of this virtual server.
     *
     * @return The value of the authRealm property of this virtual server,
     * or null of this virtual server does not have any such property
     */
    String getAuthRealmName() {
        return authRealmName;
    }

    /**
     * Adds the Valve with the given class name to this
     * VirtualServer.
     *
     * @param valveName The valve's fully qualified class nam
     */
    protected void addValve(String valveName) {
        Object valve = safeLoadInstance(valveName);
        if (valve instanceof Valve) {
            addValve((Valve) valve);
        } else if (valve instanceof GlassFishValve) {
            addValve((GlassFishValve) valve);
        } else {
            _logger.log(Level.WARNING, LogFacade.NOT_A_VALVE, valveName);
        }
    }

    /**
     * Adds the Catalina listener with the given class name to this
     * VirtualServer.
     *
     * @param listenerName The fully qualified class name of the listener
     */
    protected void addListener(String listenerName) {
        Object listener = safeLoadInstance(listenerName);

        if ( listener == null ) return;

        if (listener instanceof ContainerListener) {
            addContainerListener((ContainerListener)listener);
        } else if (listener instanceof LifecycleListener){
            addLifecycleListener((LifecycleListener)listener);
        } else {
            _logger.log(Level.SEVERE, LogFacade.INVALID_LISTENER_VIRTUAL_SERVER,
                new Object[] {listenerName, getID()});
        }
    }

    @Override
    protected Object loadInstance(String className) throws Exception {
        // See IT 11674 for why CommonClassLoader must be used
        Class clazz = serverContext.getCommonClassLoader().loadClass(className);
        return clazz.newInstance();
    }

    private Object safeLoadInstance(String className){
        try{
            return loadInstance(className);
        } catch (Throwable ex){
            _logger.log(Level.SEVERE, LogFacade.UNABLE_TO_LOAD_EXTENSION_SEVERE, ex);
        }
        return null;
    }

    /**
     * Configures this VirtualServer with its send-error properties.
     */
    void configureErrorPage() {

        ErrorPage errorPage = null;

        List props = vsBean.getProperty();
        if (props == null) {
            return;
        }

        for (Property prop : props) {
            String propName = prop.getName();
            String propValue = prop.getValue();
            if (propName == null || propValue == null) {
                _logger.log(Level.WARNING,
                        LogFacade.NULL_VIRTUAL_SERVER_PROPERTY,
                        getID());
                continue;
            }

            if (!propName.startsWith("send-error_")) {
                continue;
            }

            /*
             * Validate the prop value
             */
            String path = null;
            String reason = null;
            String status = null;

            String[] errorParams = propValue.split(" ");
            for (int j=0; j props = vsBean.getProperty();
        if (props == null) {
            return;
        }

        for (Property prop : props) {

            String propName = prop.getName();
            String propValue = prop.getValue();
            if (propName == null || propValue == null) {
                _logger.log(Level.WARNING,
                        LogFacade.NULL_VIRTUAL_SERVER_PROPERTY,
                        getID());
                continue;
            }

            if (!propName.startsWith("redirect_")) {
                continue;
            }

            /*
             * Validate the prop value
             */
            String from = null;
            String url = null;
            String urlPrefix = null;
            String escape = null;

            String[] redirectParams = propValue.split(" ");
            for (int j=0; j 0
                    && urlPrefix != null && urlPrefix.length() > 0) {
                _logger.log(Level.WARNING,
                        LogFacade.REDIRECT_BOTH_URL_AND_URL_PREFIX,
                        new Object[] { propValue, getID() });
            }

            boolean escapeURI = true;
            if (escape != null) {
                if ("yes".equalsIgnoreCase(escape)) {
                    escapeURI = true;
                } else if ("no".equalsIgnoreCase(escape)) {
                    escapeURI = false;
                } else {
                    _logger.log(Level.WARNING,
                        LogFacade.REDIRECT_INVALID_ESCAPE,
                        new Object[] { propValue, getID() });
                }
            }

            vsPipeline.addRedirect(from, url, urlPrefix, escapeURI);
        }

        if (vsPipeline.hasRedirects()) {
            if (pipeline != vsPipeline) {
                // Enable custom pipeline
                setPipeline(vsPipeline);
            }
        } else if (isActive && pipeline != origPipeline) {
            setPipeline(origPipeline);
        }
    }

    /**
     * Configures the SSO valve of this VirtualServer.
     */
    void configureSingleSignOn(boolean globalSSOEnabled,
            WebContainerFeatureFactory webContainerFeatureFactory,
            boolean ssoFailoverEnabled) {


        if (!isSSOEnabled(globalSSOEnabled)) {
            /*
             * Disable SSO
             */
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, LogFacade.DISABLE_SSO, getID());
            }

            boolean hasExistingSSO = false;
            // Remove existing SSO valve (if any)
            GlassFishValve[] valves = getValves();
            for (int i=0; valves!=null && i codecFilters = grizzlyListener.getFilters(HttpCodecFilter.class);
                    if (codecFilters == null || codecFilters.isEmpty()) {
                        // if it's AJP listener - it's ok if we didn't find HttpCodecFilter
                        if (grizzlyListener.isAjpEnabled()) {
                            continue;
                        }
                        _logger.log(Level.SEVERE, LogFacade.CODE_FILTERS_NULL, new Object[] {listener.getName(), codecFilters});
                    } else {
                        for (HttpCodecFilter codecFilter : codecFilters) {
                            if (codecFilter.getMonitoringConfig().getProbes().length == 0) {
                                HttpProbeImpl httpProbe = new HttpProbeImpl(listener, isAccessLoggingEnabled(globalAccessLoggingEnabled));
                                codecFilter.getMonitoringConfig().addProbes(httpProbe);
                            }
                        }
                    }
                    grizzlyListener.getTransport().getConnectionMonitoringConfig().addProbes(new ConnectionProbe.Adapter() {

                        RequestProbeProvider requestProbeProvider = webContainer.getRequestProbeProvider();

                        @Override
                        public void onReadEvent(Connection connection, Buffer data, int size) {
                            if (requestProbeProvider != null) {
                                requestProbeProvider.dataReceivedEvent(size, _id);
                            }
                        }

                        @Override
                        public void onWriteEvent(Connection connection, Buffer data, long size) {
                            if (requestProbeProvider != null) {
                                requestProbeProvider.dataSentEvent(size, _id);
                            }
                        }
                    });

                } else {
                    // check the listener is enabled before spitting out the SEVERE log
                    if (Boolean.parseBoolean(listener.getEnabled())) {
                        _logger.log(Level.SEVERE, LogFacade.PROXY_NULL, new Object[] {listener.getName()});
                    }
                }

            } catch (Exception ex) {
                _logger.log(Level.SEVERE, LogFacade.ADD_HTTP_PROBES_ERROR, ex);
            }
        }
    }


    /**
     * Reconfigures the access log of this VirtualServer with its
     * updated access log related properties.
     */
    void reconfigureAccessLog(String globalAccessLogBufferSize,
                              String globalAccessLogWriteInterval,
                              ServiceLocator services,
                              Domain domain,
                              boolean globalAccessLoggingEnabled) {
        try {
            if (accessLogValve.isStarted()) {
                accessLogValve.stop();
            }
            boolean start = accessLogValve.updateVirtualServerProperties(
                vsBean.getId(), vsBean, domain, services,
                globalAccessLogBufferSize, globalAccessLogWriteInterval);
            if (start && isAccessLoggingEnabled(globalAccessLoggingEnabled)) {
                enableAccessLogging();
            } else {
                disableAccessLogging();
            }
        } catch (LifecycleException le) {
            _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG, le);
        }
    }

    /**
     * Reconfigures the access log of this VirtualServer with the
     * updated attributes of the access-log element from domain.xml.
     */
    void reconfigureAccessLog(
            HttpService httpService,
            WebContainerFeatureFactory webcontainerFeatureFactory) {

        try {
            boolean restart = false;
            if (accessLogValve.isStarted()) {
                accessLogValve.stop();
                restart = true;
            }
            accessLogValve.updateAccessLogAttributes(
                httpService,
                webcontainerFeatureFactory);
            if (restart) {
                accessLogValve.start();
                for (HttpProbeImpl p : getHttpProbeImpl()) {
                    p.enableAccessLogging();
                }
            }
        } catch (LifecycleException le) {
            _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG, le);
        }
    }

    /**
     * @return the accesslog valve of this virtual server
     */
    PEAccessLogValve getAccessLogValve() {
        return accessLogValve;
    }

    /**
     * Enables access logging for this virtual server, by adding its
     * accesslog valve to its pipeline, or starting its accesslog valve
     * if it is already present in the pipeline.
     */
    void enableAccessLogging() {
        if (!isAccessLogValveActivated()) {
            addValve((GlassFishValve) accessLogValve);
        } else {
            try {
                if (accessLogValve.isStarted()) {
                    accessLogValve.stop();
                }
                accessLogValve.start();
                for (HttpProbeImpl p : getHttpProbeImpl()) {
                    p.enableAccessLogging();
                }
            } catch (LifecycleException le) {
                _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG, le);
            }
        }
    }

    /**
     * Disables access logging for this virtual server, by removing its
     * accesslog valve from its pipeline.
     */
    void disableAccessLogging() {
        removeValve(accessLogValve);
        for (HttpProbeImpl p : getHttpProbeImpl()) {
            p.disableAccessLogging();
        }
    }

    /**
     * @return true if the accesslog valve of this virtual server has been
     * activated, that is, added to this virtual server's pipeline; false
     * otherwise
     */
    private boolean isAccessLogValveActivated() {

        Pipeline p = getPipeline();
        if (p != null) {
            GlassFishValve[] valves = p.getValves();
            if (valves != null) {
                for (int i=0; i values = StringUtils.parseStringList(cacheControl, ",");
            if (values != null && !values.isEmpty()) {
                setCacheControls(values.toArray(new String[values.size()]));
            }
        }
    }

    /**
     * Checks if SSO is enabled for this VirtualServer.
     *
     * @return The value of the sso-enabled property for this VirtualServer
     */
    private boolean isSSOEnabled(boolean globalSSOEnabled) {
        String ssoEnabled = "inherit";
        if (vsBean != null) {
            ssoEnabled = vsBean.getSsoEnabled();
        }
        return "inherit".equals(ssoEnabled) && globalSSOEnabled
            || ConfigBeansUtilities.toBoolean(ssoEnabled); 
    }

    private void setSingleSignOnForChildren(SingleSignOn sso) {
        for (Container container : findChildren()) {
            if (container instanceof StandardContext) {
                StandardContext context = (StandardContext)container;
                for (GlassFishValve valve: context.getValves()) {
                    if (valve instanceof AuthenticatorBase) {
                        ((AuthenticatorBase)valve).setSingleSignOn(sso);
                        break;
                    }
                }
            }
        }
    }

    /**
     * Determines whether access logging is enabled for this virtual server.
     *
     * @param globalAccessLoggingEnabled The value of the
     * accessLoggingEnabled property of the http-service element
     *
     * @return true if access logging is enabled for this virtual server,
     * false otherwise.
     */
    boolean isAccessLoggingEnabled(boolean globalAccessLoggingEnabled) {
        String enabled = vsBean.getAccessLoggingEnabled();
        return "inherit".equals(enabled) && globalAccessLoggingEnabled ||
            ConfigBeansUtilities.toBoolean(enabled);
    }

    @Override
    public void setRealm(Realm realm) {
        if ((realm != null) && !(realm instanceof RealmAdapter)) {
            _logger.log(Level.SEVERE, LogFacade.IGNORE_INVALID_REALM,
                    new Object[] { realm.getClass().getName(),
                        RealmAdapter.class.getName()});
        } else {
            super.setRealm(realm);
        }
    }

    /**
     * Configures the security level of the SSO cookie for this virtual
     * server, based on the value of its sso-cookie-secure attribute
     */
    private void configureSingleSignOnCookieSecure() {
        String cookieSecure = vsBean.getSsoCookieSecure();
        if (!"true".equalsIgnoreCase(cookieSecure) &&
                !"false".equalsIgnoreCase(cookieSecure) &&
                !cookieSecure.equalsIgnoreCase(
                    SessionCookieConfig.DYNAMIC_SECURE)) {
            _logger.log(Level.WARNING, LogFacade.INVALID_SSO_COOKIE_SECURE,
                        new Object[] {cookieSecure, getID()});
        } else {
            ssoCookieSecure = cookieSecure;
        }
    }

    private void configureSingleSignOnCookieHttpOnly() {
        ssoCookieHttpOnly = Boolean.parseBoolean(vsBean.getSsoCookieHttpOnly());
    }

    /**
     * Configures the error report valve of this VirtualServer.
     *
     * 

The error report valve of a virtual server is specified through * a property with name errorReportValve, whose value is the * valve's fully qualified classname. A null or empty classname * disables the error report valve and therefore the container's * default error page mechanism for error responses. */ void configureErrorReportValve() { Property prop = vsBean.getProperty(Constants.ERROR_REPORT_VALVE); if (prop != null) { setErrorReportValveClass(prop.getValue()); } } void setServerContext(ServerContext serverContext) { this.serverContext = serverContext; } void setServerConfig(Config serverConfig) { this.serverConfig = serverConfig; } void setGrizzlyService(GrizzlyService grizzlyService) { this.grizzlyService = grizzlyService; } void setWebContainer(WebContainer webContainer) { this.webContainer = webContainer; } // ----------------------------------------------------- embedded methods private VirtualServerConfig config; private List listeners = new ArrayList(); /** * Sets the docroot of this VirtualServer. * * @param docRoot the docroot of this VirtualServer. */ public void setDocRoot(File docRoot) { this.setAppBase(docRoot.getPath()); } /** * Gets the docroot of this VirtualServer. */ public File getDocRoot() { return new File(getAppBase()); } /** * Sets the collection of WebListener instances from which * this VirtualServer receives requests. * * @param webListeners the collection of WebListener instances from which * this VirtualServer receives requests. */ public void setWebListeners(WebListener... webListeners) { if (webListeners != null) { listeners = Arrays.asList(webListeners); } } /** * Gets the collection of WebListener instances from which * this VirtualServer receives requests. * * @return the collection of WebListener instances from which * this VirtualServer receives requests. */ public Collection getWebListeners() { return listeners; } /** * Registers the given Context with this VirtualServer * at the given context root. * *

If this VirtualServer has already been started, the * given context will be started as well. */ public void addContext(Context context, String contextRoot) throws ConfigException, GlassFishException { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.VS_ADDED_CONTEXT); } if (!(context instanceof ContextFacade)) { // embedded context should always be created via ContextFacade return; } if (!contextRoot.startsWith("/")) { contextRoot = "/"+contextRoot; } ExtendedDeploymentContext deploymentContext = null; try { if (factory==null) factory = services.getService(ArchiveFactory.class); ContextFacade facade = (ContextFacade) context; File docRoot = facade.getDocRoot(); ClassLoader classLoader = facade.getClassLoader(); ReadableArchive archive = factory.openArchive(docRoot); if (report==null) report = new PlainTextActionReporter(); ServerEnvironment env = services.getService(ServerEnvironment.class); DeployCommandParameters params = new DeployCommandParameters(); params.contextroot = contextRoot; params.enabled = Boolean.FALSE; params.origin = OpsParams.Origin.deploy; params.virtualservers = getName(); params.target = "server"; ExtendedDeploymentContext initialContext = new DeploymentContextImpl(report, archive, params, env); if (deployment==null) deployment = services.getService(Deployment.class); ArchiveHandler archiveHandler = deployment.getArchiveHandler(archive); if (archiveHandler==null) { throw new RuntimeException("Cannot find archive handler for source archive"); } params.name = archiveHandler.getDefaultApplicationName(archive, initialContext); Applications apps = domain.getApplications(); ApplicationInfo appInfo = deployment.get(params.name); ApplicationRef appRef = domain.getApplicationRefInServer(params.target, params.name); if (appInfo!=null && appRef!=null) { if (appRef.getVirtualServers().contains(getName())) { throw new ConfigException( "Context with name "+params.name+" is already registered on virtual server "+getName()); } else { String virtualServers = appRef.getVirtualServers(); virtualServers = virtualServers + ","+getName(); params.virtualservers = virtualServers; params.force = Boolean.TRUE; if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "Virtual server "+getName()+" added to context "+params.name); } return; } } deploymentContext = deployment.getBuilder( _logger, params, report).source(archive).archiveHandler( archiveHandler).build(initialContext); Properties properties = new Properties(); deploymentContext.getAppProps().putAll(properties); if (classLoader != null) { ClassLoader parentCL = clh.createApplicationParentCL(classLoader, deploymentContext); ClassLoader cl = archiveHandler.getClassLoader(parentCL, deploymentContext); deploymentContext.setClassLoader(cl); } ApplicationConfigInfo savedAppConfig = new ApplicationConfigInfo(apps.getModule(com.sun.enterprise.config.serverbeans.Application.class, params.name)); Properties appProps = deploymentContext.getAppProps(); String appLocation = DeploymentUtils.relativizeWithinDomainIfPossible(deploymentContext.getSource().getURI()); appProps.setProperty(ServerTags.LOCATION, appLocation); appProps.setProperty(ServerTags.OBJECT_TYPE, "user"); appProps.setProperty(ServerTags.CONTEXT_ROOT, contextRoot); savedAppConfig.store(appProps); Transaction t = deployment.prepareAppConfigChanges(deploymentContext); appInfo = deployment.deploy(deploymentContext); if (appInfo!=null) { facade.setAppName(appInfo.getName()); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.VS_ADDED_CONTEXT, new Object[]{getName(), appInfo.getName()}); } deployment.registerAppInDomainXML(appInfo, deploymentContext, t); } else { if (report.getActionExitCode().equals(ActionReport.ExitCode.FAILURE)) { throw new ConfigException(report.getMessage()); } } // Update web.xml with programmatically added servlets, filters, and listeners File file = null; boolean delete = true; com.sun.enterprise.config.serverbeans.Application appBean = apps.getApplication(params.name); if (appBean != null) { file = new File(deploymentContext.getSource().getURI().getPath(), "/WEB-INF/web.xml"); if (file.exists()) { delete = false; } updateWebXml(facade, file); } else { _logger.log(Level.SEVERE, LogFacade.APP_NOT_FOUND); } ReadableArchive source = appInfo.getSource(); UndeployCommandParameters undeployParams = new UndeployCommandParameters(params.name); undeployParams.origin = UndeployCommandParameters.Origin.undeploy; undeployParams.target = "server"; ExtendedDeploymentContext undeploymentContext = deployment.getBuilder(_logger, undeployParams, report).source(source).build(); deployment.undeploy(params.name, undeploymentContext); params.origin = DeployCommandParameters.Origin.load; params.enabled = Boolean.TRUE; archive = factory.openArchive(docRoot); deploymentContext = deployment.getBuilder(_logger, params, report).source(archive).build(); if (classLoader != null) { ClassLoader parentCL = clh.createApplicationParentCL(classLoader, deploymentContext); archiveHandler = deployment.getArchiveHandler(archive); ClassLoader cl = archiveHandler.getClassLoader(parentCL, deploymentContext); deploymentContext.setClassLoader(cl); } deployment.deploy(deploymentContext); // Enable the app using the modified web.xml // We can't use Deployment.enable since it doesn't take DeploymentContext with custom class loader deployment.updateAppEnabledAttributeInDomainXML(params.name, params.target, true); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.VS_ENABLED_CONTEXT, new Object[]{getName(), params.name()}); } if (delete) { if (file != null) { if (file.exists() && !file.delete()) { String path = file.toString(); _logger.log(Level.WARNING, LogFacade.UNABLE_TO_DELETE, path); } } } if (contextRoot.equals("/")) { contextRoot = ""; } WebModule wm = (WebModule) findChild(contextRoot); if (wm != null) { facade.setUnwrappedContext(wm); wm.setEmbedded(true); if (config != null) { wm.setDefaultWebXml(config.getDefaultWebXml()); } } else { throw new ConfigException("Deployed app not found "+contextRoot); } if (deploymentContext != null) { deploymentContext.postDeployClean(true); } } catch (Exception ex) { if (deployment!=null && deploymentContext!=null) { deploymentContext.clean(); } throw new GlassFishException(ex); } } /** * Stops the given context and removes it from this * VirtualServer. */ public void removeContext(Context context) throws GlassFishException { ActionReport report = services.getService(ActionReport.class, "plain"); Deployment deployment = services.getService(Deployment.class); String name; if (context instanceof ContextFacade) { name = ((ContextFacade)context).getAppName(); } else { name = context.getPath(); } ApplicationInfo appInfo = deployment.get(name); if (appInfo == null) { report.setMessage("Cannot find deployed application of name " + name); report.setActionExitCode(ActionReport.ExitCode.FAILURE); throw new GlassFishException("Cannot find deployed application of name " + name); } ReadableArchive source = appInfo.getSource(); if (source == null) { report.setMessage("Cannot get source archive for undeployment"); report.setActionExitCode(ActionReport.ExitCode.FAILURE); throw new GlassFishException("Cannot get source archive for undeployment"); } UndeployCommandParameters params = new UndeployCommandParameters(name); params.origin = UndeployCommandParameters.Origin.undeploy; params.target = "server"; ExtendedDeploymentContext deploymentContext = null; try { deploymentContext = deployment.getBuilder(_logger, params, report).source(source).build(); deployment.undeploy(name, deploymentContext); deployment.unregisterAppFromDomainXML(name, "server"); } catch (IOException e) { _logger.log(Level.SEVERE, LogFacade.REMOVE_CONTEXT_ERROR, e); report.setActionExitCode(ActionReport.ExitCode.FAILURE); throw new GlassFishException("Cannot create context for undeployment ", e); } catch (TransactionFailure e) { throw new GlassFishException(e); } finally { if (deploymentContext!=null) { deploymentContext.clean(); } } if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.REMOVED_CONTEXT, name); } } /** * Finds the Context registered at the given context root. */ public Context getContext(String contextRoot) { if (!contextRoot.startsWith("/")) { contextRoot = "/"+contextRoot; } return (Context)findChild(contextRoot); } /** * Gets the collection of Context instances registered with * this VirtualServer. */ public Collection getContexts() { Collection ctxs = new ArrayList(); for (Container container : findChildren()) { if (container instanceof Context) { ctxs.add((Context)container); } } return ctxs; } /** * Reconfigures this VirtualServer with the given * configuration. * *

In order for the given configuration to take effect, this * VirtualServer may be stopped and restarted. */ public void setConfig(VirtualServerConfig config) throws ConfigException { this.config = config; configureSingleSignOn(config.isSsoEnabled(), Globals.getDefaultHabitat().getService( PEWebContainerFeatureFactoryImpl.class), false); if (config.isAccessLoggingEnabled()) { enableAccessLogging(); } else { disableAccessLogging(); } setDefaultWebXmlLocation(config.getDefaultWebXml()); setDefaultContextXmlLocation(config.getContextXmlDefault()); setAllowLinking(config.isAllowLinking()); configureRemoteAddressFilterValve(config.getAllowRemoteAddress(), config.getDenyRemoteAddress()); configureRemoteHostFilterValve(config.getAllowRemoteHost(), config.getAllowRemoteHost()); configureAliases(config.getHostNames()); } /** * Gets the current configuration of this VirtualServer. */ public VirtualServerConfig getConfig() { return config; } @Override public synchronized void stop() throws LifecycleException { if (fileLoggerHandler != null) { _logger.removeHandler(fileLoggerHandler); close(fileLoggerHandler); fileLoggerHandler = null; } setLogger(_logger, "INFO"); super.stop(); } public void updateWebXml(ContextFacade facade, File file) throws Exception { Map servlets = facade.getAddedServlets(); Map mappings = facade.getServletMappings(); List listeners = facade.getListeners(); Map filters = facade.getAddedFilters(); Map servletNameFilterMappings = facade.getServletNameFilterMappings(); Map urlPatternFilterMappings = facade.getUrlPatternFilterMappings(); if (!filters.isEmpty() || !listeners.isEmpty() || !servlets.isEmpty()) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.MODIFYING_WEB_XML, file.getAbsolutePath()); } DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = null; Element webapp = null; if ((file != null) && (file.exists())) { doc = dBuilder.parse(file); webapp = doc.getDocumentElement(); } else { doc = dBuilder.newDocument(); webapp = doc.createElement("web-app"); webapp.setAttribute("xmln", "http://java.sun.com/xml/ns/j2ee"); webapp.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); webapp.setAttribute("xsi:schemaLocation", "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"); webapp.setAttribute("version", "2.4"); doc.appendChild(webapp); } boolean entryFound = false; // Update for (Map.Entry entry : filters.entrySet()) { NodeList filterList = doc.getElementsByTagName("filter-name"); for (int i=0; i initParams = facade.getFilterRegistration(entry.getKey().toString()).getInitParameters(); if ((initParams != null) && (!initParams.isEmpty())) { Element initParam = doc.createElement("init-param"); for (Map.Entry param : initParams.entrySet()) { Element paramName = doc.createElement("param-name"); paramName.setTextContent(param.getKey().toString()); initParam.appendChild(paramName); Element paramValue = doc.createElement("param-value"); paramValue.setTextContent(param.getValue().toString()); initParam.appendChild(paramValue); } filter.appendChild(initParam); } webapp.appendChild(filter); } } // Update for (Map.Entry mapping : servletNameFilterMappings.entrySet()) { Element filterMapping = doc.createElement("filter-mapping"); Element filterName = doc.createElement("filter-name"); filterName.setTextContent(mapping.getKey().toString()); filterMapping.appendChild(filterName); Element servletName = doc.createElement("servlet-name"); servletName.setTextContent(mapping.getValue().toString()); filterMapping.appendChild(servletName); webapp.appendChild(filterMapping); } for (Map.Entry mapping : urlPatternFilterMappings.entrySet()) { Element filterMapping = doc.createElement("filter-mapping"); Element filterName = doc.createElement("filter-name"); filterName.setTextContent(mapping.getKey().toString()); filterMapping.appendChild(filterName); Element urlPattern = doc.createElement("url-pattern"); urlPattern.setTextContent(mapping.getValue().toString()); filterMapping.appendChild(urlPattern); webapp.appendChild(filterMapping); } entryFound = false; // Update for (Map.Entry entry : servlets.entrySet()) { NodeList servletList = doc.getElementsByTagName("servlet-name"); for (int i=0; i initParams = facade.getServletRegistration(entry.getKey().toString()).getInitParameters(); if ((initParams != null) && (!initParams.isEmpty())) { Element initParam = doc.createElement("init-param"); for (Map.Entry param : initParams.entrySet()) { Element paramName = doc.createElement("param-name"); paramName.setTextContent(param.getKey().toString()); initParam.appendChild(paramName); Element paramValue = doc.createElement("param-value"); paramValue.setTextContent(param.getValue().toString()); initParam.appendChild(paramValue); } servlet.appendChild(initParam); } webapp.appendChild(servlet); } } entryFound = false; // Update for (Map.Entry mapping : mappings.entrySet()) { NodeList servletList = doc.getElementsByTagName("servlet-name"); for (int i=0; i getGrizzlyNetworkListeners() { List listenerList = StringUtils.parseStringList( vsBean.getNetworkListeners(), ","); String[] listeners = (listenerList != null) ? listenerList.toArray(new String[listenerList.size()]) : new String[0]; List networkListeners = new ArrayList(); for (String listener : listeners) { for (NetworkListener networkListener : serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener()) { if (networkListener.getName().equals(listener)) { networkListeners.add(networkListener); } } } return networkListeners; } private List getHttpProbeImpl() { List httpProbes = new ArrayList<>(); for (final NetworkListener listener : getGrizzlyNetworkListeners()) { final GrizzlyProxy proxy = (GrizzlyProxy) grizzlyService.lookupNetworkProxy(listener); if (proxy != null) { GenericGrizzlyListener grizzlyListener = (GenericGrizzlyListener) proxy.getUnderlyingListener(); List codecFilters = grizzlyListener.getFilters(HttpCodecFilter.class); if (codecFilters != null && !codecFilters.isEmpty()) { for (HttpCodecFilter codecFilter : codecFilters) { HttpProbe[] probes = codecFilter.getMonitoringConfig().getProbes(); if (probes != null) { for (HttpProbe probe : probes) { if (probe instanceof HttpProbeImpl) { httpProbes.add((HttpProbeImpl)probe); } } } } } } } return httpProbes; } // ---------------------------------------------------------- Nested Classes private final class HttpProbeImpl extends HttpProbe.Adapter { boolean accessLoggingEnabled = false; NetworkListener listener = null; public HttpProbeImpl(NetworkListener listener, boolean accessLoggingEnabled) { this.listener = listener; this.accessLoggingEnabled = accessLoggingEnabled; } public void enableAccessLogging() { accessLoggingEnabled = true; } public void disableAccessLogging() { accessLoggingEnabled = false; } @Override public void onErrorEvent(Connection connection, HttpPacket packet, Throwable error) { if (accessLoggingEnabled) { if (packet instanceof HttpRequestPacket) { final HttpRequestPacket requestPacket = (HttpRequestPacket) packet; final HttpResponsePacket responsePacket = requestPacket.getResponse(); // 400 should be hardcoded since the response status isn't available for bad requests responsePacket.setStatus(HttpStatus.BAD_REQUEST_400); org.glassfish.grizzly.http.server.Request request = org.glassfish.grizzly.http.server.Request.create(); // org.glassfish.grizzly.http.server.Response response = org.glassfish.grizzly.http.server.Response.create(); org.glassfish.grizzly.http.server.Response response = request.getResponse(); // request.initialize(response, requestPacket, FilterChainContext.create(connection), null); request.initialize(/*response,*/ requestPacket, FilterChainContext.create(connection), null); response.initialize(request, responsePacket, FilterChainContext.create(connection), null, null); Response res = new Response(); res.setCoyoteResponse(response); WebConnector connector = webContainer.getConnectorMap().get(listener.getName()); if (connector != null) { Request req = new Request(); req.setCoyoteRequest(request); req.setConnector(connector); try { accessLogValve.postInvoke(req, res); } catch (IOException ex) { _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG, ex); } } else { _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG); } } else { _logger.log(Level.SEVERE, LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy