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: 7.2024.1.Alpha1
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-2021] [Payara Foundation and/or its affiliates]

package com.sun.enterprise.web;

import static com.sun.enterprise.security.common.AppservAccessController.privileged;
import static com.sun.enterprise.web.Constants.DEFAULT_WEB_MODULE_NAME;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
import static java.util.logging.Level.WARNING;
import static org.glassfish.api.web.Constants.ADMIN_VS;
import static org.glassfish.web.LogFacade.IGNORE_INVALID_REALM;
import static org.glassfish.web.LogFacade.INVALID_AUTH_REALM;
import static org.glassfish.web.LogFacade.INVALID_LISTENER_VIRTUAL_SERVER;
import static org.glassfish.web.LogFacade.NOT_A_VALVE;
import static org.glassfish.web.LogFacade.UNABLE_RECONFIGURE_ACCESS_LOG;
import static org.glassfish.web.LogFacade.UNABLE_TO_LOAD_EXTENSION_SEVERE;
import static org.glassfish.web.LogFacade.VS_ADDED_CONTEXT;
import static org.glassfish.web.LogFacade.VS_DEFAULT_WEB_MODULE;
import static org.glassfish.web.LogFacade.VS_DEFAULT_WEB_MODULE_DISABLED;
import static org.glassfish.web.LogFacade.VS_DEFAULT_WEB_MODULE_NOT_FOUND;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
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 jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import javax.xml.XMLConstants;
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.Container;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
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.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.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

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.admin.report.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;

/**
 * Standard implementation of a virtual server (aka virtual host) in the Payara Server.
 */
public class VirtualServer extends StandardHost implements org.glassfish.embeddable.web.VirtualServer {

    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 DISABLED = "disabled";
    private static final String ON = "on";

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

    /**
     * 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.
     */// XXX: WebContainer.createHost is the only time many of the set methods in Virtual Server
       // are used, they might be movable to the constructor or injected
    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 final 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 final Pipeline origPipeline;

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

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

    /**
     * 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;
    private String[] cacheControls;
    private ClassLoaderHierarchy classLoaderHierarchy;
    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 final PEAccessLogValve accessLogValve;

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

    private boolean ssoCookieHttpOnly;
    private String defaultContextPath;
    private ServerContext serverContext;
    private Config serverConfig;
    private GrizzlyService grizzlyService;
    private WebContainer webContainer;
    private boolean ssoFailoverEnabled;

    private volatile FileLoggerHandler fileLoggerHandler;
    private volatile FileLoggerHandlerFactory fileLoggerHandlerFactory;

    private Deployment deployment;
    private ArchiveFactory factory;
    private ActionReport report;

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

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

    /**
     * Set the virtual server identifier string.
     *
     * @param id New identifier for this virtual server
     */
    @Override
    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.
     *
     * @return
     */
    public com.sun.enterprise.config.serverbeans.VirtualServer getBean() {
        return vsBean;
    }

    /**
     * Sets the config bean for this VirtualServer
     *
     * @param vsBean
     */
    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
     *
     * @param mimeMap
     */
    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;
    }

    @Override
    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.classLoaderHierarchy = clh;
    }

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

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

        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.
     */
    @Override
    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.
     *
     * @param valve
     */
    @Override
    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.
     */
    @Override
    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}".
     *
     * @param domain
     * @param appRegistry
     * @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 defaultWebModuleId = getDefaultWebModuleID();

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

            if (contextRoot == null) {
                _logger.log(SEVERE, VS_DEFAULT_WEB_MODULE_NOT_FOUND, new Object[] { defaultWebModuleId, getID() });
            }
        }

        return contextRoot;
    }

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

        WebModuleConfig webModuleConfig = null;

        String defaultWebModuleId = getDefaultWebModuleID();
        if (defaultWebModuleId != null) {

            // Check if the default-web-module is part of an ee-application
            webModuleConfig = findWebModuleInJ2eeApp(domain.getApplications(), defaultWebModuleId, appRegistry);
            if (webModuleConfig == null) {
                String contextRoot = null;
                String location = null;

                ConfigBeansUtilities configBeansUtilities = getConfigBeansUtilities();
                if (configBeansUtilities != null) {
                    contextRoot = configBeansUtilities.getContextRoot(defaultWebModuleId);
                    location = configBeansUtilities.getLocation(defaultWebModuleId);
                }

                if (contextRoot != null && location != null) {
                    WebBundleDescriptorImpl webBundleDescriptorImpl = webArchivist.getDefaultWebXmlBundleDescriptor();
                    webBundleDescriptorImpl.setName(DEFAULT_WEB_MODULE_NAME);
                    webBundleDescriptorImpl.setContextRoot(contextRoot);

                    webModuleConfig = new WebModuleConfig();
                    webModuleConfig.setLocation(new File(location));
                    webModuleConfig.setDescriptor(webBundleDescriptorImpl);
                    webModuleConfig.setParentLoader(EmbeddedWebContainer.class.getClassLoader());
                    webModuleConfig.setAppClassLoader(privileged(() ->
                        new WebappClassLoader(EmbeddedWebContainer.class.getClassLoader(), webBundleDescriptorImpl.getApplication())));
                }
            }

            if (webModuleConfig == null) {
                _logger.log(SEVERE, VS_DEFAULT_WEB_MODULE_NOT_FOUND, new Object[] { defaultWebModuleId, getID() });
            }
        }

        return webModuleConfig;
    }

    /**
     * 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). * * @param webArchivist * @return */ public WebModuleConfig createSystemDefaultWebModuleIfNecessary(WebArchivist webArchivist) { WebModuleConfig webModuleConfig = 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) { WebBundleDescriptorImpl webBundleDescriptor = webArchivist.getDefaultWebXmlBundleDescriptor(); webBundleDescriptor.setModuleID(DEFAULT_WEB_MODULE_NAME); webBundleDescriptor.setContextRoot(""); SecurityService securityService = Globals.get(SecurityService.class); webBundleDescriptor.getLoginConfiguration().setRealmName(securityService.getDefaultRealm()); webModuleConfig = new WebModuleConfig(); webModuleConfig.setLocation(new File(docroot)); webModuleConfig.setDescriptor(webBundleDescriptor); webModuleConfig.setParentLoader(serverContext.getCommonClassLoader()); WebappClassLoader loader = privileged(() -> new WebappClassLoader(serverContext.getCommonClassLoader(), getApplication(webBundleDescriptor))); loader.start(); webModuleConfig.setAppClassLoader(loader); } return webModuleConfig; } private Application getApplication(WebBundleDescriptorImpl webBundleDescriptor) { if (webBundleDescriptor.getApplication() == null) { Application application = Application.createApplication(); application.setVirtual(true); application.setName(DEFAULT_WEB_MODULE_NAME); webBundleDescriptor.setApplication(application); } return webBundleDescriptor.getApplication(); } /** * 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. * * @return */ protected String getDefaultWebModuleID() { String webModuleId = vsBean.getDefaultWebModule(); if ("".equals(webModuleId)) { webModuleId = null; } if (webModuleId != null && _logger.isLoggable(FINE)) { _logger.log(FINE, VS_DEFAULT_WEB_MODULE, new Object[] { webModuleId, _id }); } return webModuleId; } /** * 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. * * @param appsBean * @param id * @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 webModuleConfig = 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); Application app = appInfo != null ? appInfo.getMetaData(Application.class) : null; if (appInfo == null) { // XXX ApplicaionInfo is NULL after restart _logger.log(Level.SEVERE, LogFacade.VS_DEFAULT_WEB_MODULE_DISABLED, new Object[] { id, getID() }); return webModuleConfig; } WebBundleDescriptorImpl webBundleDescriptorImpl = app.getModuleByTypeAndUri(WebBundleDescriptorImpl.class, moduleID); String webUri = webBundleDescriptorImpl.getModuleDescriptor().getArchiveUri(); String contextRoot = webBundleDescriptorImpl.getModuleDescriptor().getContextRoot(); if (moduleID.equals(webUri)) { webBundleDescriptorImpl.setName(moduleID); webBundleDescriptorImpl.setContextRoot(contextRoot); webModuleConfig = new WebModuleConfig(); webModuleConfig.setDescriptor(webBundleDescriptorImpl); webModuleConfig.setLocation(new File(new StringBuilder(location) .append(File.separator) .append(moduleDir) .toString())); webModuleConfig.setParentLoader(EmbeddedWebContainer.class.getClassLoader()); webModuleConfig.setAppClassLoader(privileged(() -> new WebappClassLoader(EmbeddedWebContainer.class.getClassLoader(), app))); } } else { _logger.log(SEVERE, VS_DEFAULT_WEB_MODULE_DISABLED, new Object[] { id, getID() }); } } return webModuleConfig; } /** * 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. * * @param vsID * @param vsBean * @param vsDocroot * @param vsLogFile * @param logServiceFile * @param logLevel */ 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. * @param logLevel the verbosity of the logger. * @param logServiceFile the file used for the log service. */ synchronized void setLogFile(String logFile, String logLevel, String logServiceFile) { /* * Configure separate logger for this virtual server only if 'log-file' attribute of this and 'file' * attribute of are different (See 6189219). */ boolean customLog = (logFile != null && logServiceFile != null && !new File(logFile).equals(new File(logServiceFile))); boolean logFileChanged = logFile != null && ((fileLoggerHandler != null && !logFile.equals(fileLoggerHandler.getLogFile())) || fileLoggerHandler == null); /* * Exit early if the log file isn't being changed. */ if (!logFileChanged) { return; } // As it is being changed, close the old file handler if (fileLoggerHandler != null) { _logger.removeHandler(fileLoggerHandler); close(fileLoggerHandler); fileLoggerHandler = null; } // Store new logger to replace current one Logger newLogger = null; /* * If the file is being changed to the log service file, reset the logger. */ if (!customLog) { newLogger = _logger; for (Handler h : _logger.getHandlers()) { newLogger.removeHandler(h); } newLogger.setUseParentHandlers(true); } else { // append the _logger name with "._vs." if it doesn't already have it String lname = _logger.getName(); if (!lname.endsWith("._vs." + getID())) { 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(logFile); newLogger.addHandler(fileLoggerHandler); newLogger.setUseParentHandlers(false); } setLogger(newLogger, logLevel); } /** * Adds each host name from the 'hosts' attribute as an alias */ void configureAliases() { List hosts = StringUtils.parseStringList(vsBean.getHosts(), ","); for (Object host : hosts) { String alias = host.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) { _logger.finest(() -> String.format("configureAuthRealm(securityService=%s)", securityService)); List properties = vsBean.getProperty(); if (properties != null && !properties.isEmpty()) { for (Property property : properties) { if (property != null && "authRealm".equals(property.getName())) { authRealmName = property.getValue(); if (authRealmName != null) { AuthRealm validAuthRealm = null; List authRealms = securityService.getAuthRealm(); if (authRealms != null && authRealms.size() > 0) { for (AuthRealm authRealm : authRealms) { if (authRealm != null && authRealm.getName().equals(authRealmName)) { _logger.config(() -> "Using realm '" + authRealmName + "' for the security service '" + securityService + "'"); validAuthRealm = authRealm; break; } } } if (validAuthRealm == null) { _logger.log(SEVERE, 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(WARNING, 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(SEVERE, 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(SEVERE, 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 (String errorParam : errorParams) { if (errorParam.startsWith("path=")) { if (path != null) { _logger.log(Level.WARNING, LogFacade.SEND_ERROR_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "path" }); } path = errorParam.substring("path=".length()); } if (errorParam.startsWith("reason=")) { if (reason != null) { _logger.log(Level.WARNING, LogFacade.SEND_ERROR_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "reason" }); } reason = errorParam.substring("reason=".length()); } if (errorParam.startsWith("code=")) { if (status != null) { _logger.log(Level.WARNING, LogFacade.SEND_ERROR_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "code" }); } status = errorParam.substring("code=".length()); } } if (path == null || path.length() == 0) { _logger.log(Level.WARNING, LogFacade.SEND_ERROR_MISSING_PATH, new Object[] { propValue, getID() }); } errorPage = new ErrorPage(); errorPage.setLocation(path); errorPage.setErrorCode(status); errorPage.setReason(reason); addErrorPage(errorPage); } } /** * Configures this VirtualServer with its redirect properties. */ void configureRedirect() { vsPipeline.clearRedirects(); 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("redirect_")) { continue; } /* * Validate the prop value */ String from = null; String url = null; String urlPrefix = null; String escape = null; String[] redirectParams = propValue.split(" "); for (String redirectParam : redirectParams) { if (redirectParam.startsWith("from=")) { if (from != null) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "from" }); } from = redirectParam.substring("from=".length()); } if (redirectParam.startsWith("url=")) { if (url != null) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "url" }); } url = redirectParam.substring("url=".length()); } if (redirectParam.startsWith("url-prefix=")) { if (urlPrefix != null) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "url-prefix" }); } urlPrefix = redirectParam.substring("url-prefix=".length()); } if (redirectParam.startsWith("escape=")) { if (escape != null) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MULTIPLE_ELEMENT, new Object[] { propValue, getID(), "escape" }); } escape = redirectParam.substring("escape=".length()); } } if (from == null || from.length() == 0) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MULTIPLE_ELEMENT, new Object[] { propValue, getID() }); } // Either url or url-prefix (but not both!) must be present if ((url == null || url.length() == 0) && (urlPrefix == null || urlPrefix.length() == 0)) { _logger.log(Level.WARNING, LogFacade.REDIRECT_MISSING_URL_OR_URL_PREFIX, new Object[] { propValue, getID() }); } if (url != null && url.length() > 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 < valves.length; i++) { if (valves[i] instanceof SingleSignOn) { removeValve(valves[i]); hasExistingSSO = true; break; } } this.ssoFailoverEnabled = ssoFailoverEnabled; if (hasExistingSSO) { setSingleSignOnForChildren(null); } } else { /* * Enable SSO */ if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.ENABLE_SSO, getID()); } GlassFishSingleSignOn sso = null; // find existing SSO (if any), in case of a reconfig GlassFishValve[] valves = getValves(); for (int i = 0; valves != null && i < valves.length; i++) { if (valves[i] instanceof GlassFishSingleSignOn) { sso = (GlassFishSingleSignOn) valves[i]; break; } } if (sso != null && this.ssoFailoverEnabled != ssoFailoverEnabled) { removeValve(sso); sso = null; // then SSO Valve will be recreated } if (sso == null) { SSOFactory ssoFactory = webContainerFeatureFactory.getSSOFactory(); sso = ssoFactory.createSingleSignOnValve(getName()); this.ssoFailoverEnabled = ssoFailoverEnabled; setSingleSignOnForChildren(sso); addValve((GlassFishValve) sso); } // set max idle time if given Property idle = vsBean.getProperty(SSO_MAX_IDLE); if (idle != null && idle.getValue() != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.SSO_MAX_INACTIVE_SET, new Object[] { idle.getValue(), getID() }); } sso.setMaxInactive(Integer.parseInt(idle.getValue())); } // set expirer thread sleep time if given Property expireTime = vsBean.getProperty(SSO_REAP_INTERVAL); if (expireTime != null && expireTime.getValue() != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.SSO_REAP_INTERVAL_SET); } sso.setReapInterval(Integer.parseInt(expireTime.getValue())); } configureSingleSignOnCookieSecure(); configureSingleSignOnCookieHttpOnly(); } } /** * Configures this VirtualServer with its state (on | off | disabled). */ void configureState() { String stateValue = vsBean.getState(); if (!stateValue.equalsIgnoreCase(ON) && getName().equalsIgnoreCase(ADMIN_VS)) { throw new IllegalArgumentException("virtual-server " + ADMIN_VS + " state property cannot be modified"); } if (stateValue.equalsIgnoreCase(DISABLED)) { // state="disabled" setIsDisabled(true); } else if (!ConfigBeansUtilities.toBoolean(stateValue)) { // state="off" setIsOff(true); } else { setIsActive(true); } } /** * Configures the Remote Address Filter valve of this VirtualServer. * * This valve enforces request accpetance/denial based on the string representation of the remote client's IP address. */ void configureRemoteAddressFilterValve() { Property allow = vsBean.getProperty("allowRemoteAddress"); Property deny = vsBean.getProperty("denyRemoteAddress"); String allowStr = null; String denyStr = null; if (allow != null) { allowStr = allow.getValue(); } if (deny != null) { denyStr = deny.getValue(); } configureRemoteAddressFilterValve(allowStr, denyStr); } /** * Configures the Remote Address Filter valve of this VirtualServer. * * This valve enforces request accpetance/denial based on the string representation of the remote client's IP address. */ protected void configureRemoteAddressFilterValve(String allow, String deny) { RemoteAddrValve remoteAddrValve = null; if (allow != null || deny != null) { remoteAddrValve = new RemoteAddrValve(); } if (allow != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.ALLOW_ACCESS, new Object[] { getID(), allow }); } remoteAddrValve.setAllow(allow); } if (deny != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.DENY_ACCESS, new Object[] { getID(), deny }); } remoteAddrValve.setDeny(deny); } if (remoteAddrValve != null) { // Remove existing RemoteAddrValve (if any), in case of a reconfig GlassFishValve[] valves = getValves(); for (int i = 0; valves != null && i < valves.length; i++) { if (valves[i] instanceof RemoteAddrValve) { removeValve(valves[i]); break; } } addValve((GlassFishValve) remoteAddrValve); } } /** * Configures the Remote Host Filter valve of this VirtualServer. * * This valve enforces request acceptance/denial based on the name of the remote host from where the request originated. */ void configureRemoteHostFilterValve() { Property allow = vsBean.getProperty("allowRemoteHost"); Property deny = vsBean.getProperty("denyRemoteHost"); String allowStr = null; String denyStr = null; if (allow != null) { allowStr = allow.getValue(); } if (deny != null) { denyStr = deny.getValue(); } configureRemoteHostFilterValve(allowStr, denyStr); } void configureRemoteHostFilterValve(String allow, String deny) { RemoteHostValve remoteHostValve = null; if (allow != null || deny != null) { remoteHostValve = new RemoteHostValve(); } if (allow != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.ALLOW_ACCESS, new Object[] { getID(), allow }); } remoteHostValve.setAllow(allow); } if (deny != null) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.DENY_ACCESS, new Object[] { getID(), deny }); } remoteHostValve.setDeny(deny); } if (remoteHostValve != null) { // Remove existing RemoteHostValve (if any), in case of a reconfig GlassFishValve[] valves = getValves(); for (int i = 0; valves != null && i < valves.length; i++) { if (valves[i] instanceof RemoteHostValve) { removeValve(valves[i]); break; } } addValve((GlassFishValve) remoteHostValve); } } /** * Sets all the monitoring probes used in the virtual server * * @param globalAccessLoggingEnabled * @see org.glassfish.grizzly.http.HttpProbe */ void addProbes(boolean globalAccessLoggingEnabled) { for (final NetworkListener listener : getGrizzlyNetworkListeners()) { try { 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()) { // 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, String globalAccessLogPrefix) { try { if (accessLogValve.isStarted()) { accessLogValve.stop(); } boolean start = accessLogValve.updateVirtualServerProperties(vsBean.getId(), vsBean, domain, services, globalAccessLogBufferSize, globalAccessLogWriteInterval, globalAccessLogPrefix); 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 httpProbe : getHttpProbeImpl()) { httpProbe.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 (GlassFishValve valve : valves) { if (valve instanceof PEAccessLogValve) { return true; } } } } return false; } /** * Configures the cache control of this VirtualServer */ void configureCacheControl(String cacheControl) { if (cacheControl != null) { List 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 instanceof RealmAdapter)) { _logger.log(SEVERE, 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; } /** * Sets the grizzly service to be used * * @param grizzlyService */ void setGrizzlyService(GrizzlyService grizzlyService) { this.grizzlyService = grizzlyService; } /** * Sets the Web Container for the virtual server * * @param webContainer */ 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. */ @Override public void setDocRoot(File docRoot) { this.setAppBase(docRoot.getPath()); } /** * Gets the docroot of this VirtualServer. */ @Override 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. */ @Override 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. * * @throws org.glassfish.embeddable.GlassFishException */ @Override public void addContext(Context context, String contextRoot) throws ConfigException, GlassFishException { _logger.fine(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 = classLoaderHierarchy.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 = classLoaderHierarchy.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. * * @throws org.glassfish.embeddable.GlassFishException */ @Override 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. */ @Override public Context getContext(String contextRoot) { if (!contextRoot.startsWith("/")) { contextRoot = "/" + contextRoot; } return (Context) findChild(contextRoot); } /** * Gets the collection of Context instances registered with this VirtualServer. */ @Override 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. */ @Override 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. */ @Override 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 flisteners = facade.getListeners(); Map filters = facade.getAddedFilters(); Map servletNameFilterMappings = facade.getServletNameFilterMappings(); Map urlPatternFilterMappings = facade.getUrlPatternFilterMappings(); if (!filters.isEmpty() || !flisteners.isEmpty() || !servlets.isEmpty()) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, LogFacade.MODIFYING_WEB_XML, file.getAbsolutePath()); } DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setValidating(true); dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc; Element webapp; 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 < filterList.getLength(); i++) { Node filterNode = filterList.item(i); if (entry.getKey().equals(filterNode.getTextContent()) && filterNode.getParentNode().getNodeName().equals("filter")) { NodeList children = filterNode.getParentNode().getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node filterClass = children.item(j); if (filterClass.getNodeName().equals("filter-class")) { // If a filter with the given filter-name is already defined, // the given class name will be assigned according to the spec filterClass.setTextContent(entry.getValue().toString()); entryFound = true; break; } } } } if (!entryFound) { Element filter = doc.createElement("filter"); Element filterName = doc.createElement("filter-name"); filterName.setTextContent(entry.getKey().toString()); filter.appendChild(filterName); Element filterClass = doc.createElement("filter-class"); filterClass.setTextContent(entry.getValue().toString()); filter.appendChild(filterClass); Map 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 < servletList.getLength(); i++) { Node servletNode = servletList.item(i); if (entry.getKey().equals(servletNode.getTextContent()) && servletNode.getParentNode().getNodeName().equals("servlet")) { NodeList children = servletNode.getParentNode().getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node servletClass = children.item(j); if (servletClass.getNodeName().equals("servlet-class")) { // If a servlet with the given servlet-name is already defined, // the given className will be assigned according to the spec servletClass.setTextContent(entry.getValue().toString()); entryFound = true; break; } } } } if (!entryFound) { Element servlet = doc.createElement("servlet"); Element servletName = doc.createElement("servlet-name"); servletName.setTextContent(entry.getKey().toString()); servlet.appendChild(servletName); Element servletClass = doc.createElement("servlet-class"); servletClass.setTextContent(entry.getValue().toString()); servlet.appendChild(servletClass); Map 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 < servletList.getLength(); i++) { Node servletNode = servletList.item(i); if (mapping.getKey().equals(servletNode.getTextContent()) && servletNode.getParentNode().getNodeName().equals("servlet-mapping")) { NodeList children = servletNode.getParentNode().getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node urlPattern = children.item(j); if (urlPattern.getNodeName().equals("url-pattern")) { // If any of the specified URL patterns are already mapped to a different Servlet, // no updates will be performed according to the spec entryFound = true; break; } } } } if (!entryFound) { Element servletMapping = doc.createElement("servlet-mapping"); for (String pattern : mappings.get(mapping.getKey())) { Element servletName = doc.createElement("servlet-name"); servletName.setTextContent(mapping.getKey().toString()); servletMapping.appendChild(servletName); Element urlPattern = doc.createElement("url-pattern"); urlPattern.setTextContent(pattern); servletMapping.appendChild(urlPattern); } webapp.appendChild(servletMapping); } } for (String listenerStr : flisteners) { Element listener = doc.createElement("listener"); Element listenerClass = doc.createElement("listener-class"); listenerClass.setTextContent(listenerStr); listener.appendChild(listenerClass); webapp.appendChild(listener); } Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); if (file != null) { DOMSource src = new DOMSource(doc); StreamResult result = new StreamResult(file); transformer.transform(src, result); } } } private List 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) { HttpRequestPacket requestPacket = (HttpRequestPacket) packet; 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 = request.getResponse(); 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(SEVERE, UNABLE_RECONFIGURE_ACCESS_LOG, ex); } } else { _logger.log(SEVERE, UNABLE_RECONFIGURE_ACCESS_LOG); } } else { _logger.log(SEVERE, UNABLE_RECONFIGURE_ACCESS_LOG); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy