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

com.sun.enterprise.web.WebContainer 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-2016 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-2017] [Payara Foundation and/or its affiliates]

package com.sun.enterprise.web;

import java.io.File;
import java.net.BindException;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.ResourceBundle;

import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.tagext.JspTag;

import org.apache.catalina.Connector;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Deployer;
import org.apache.catalina.Engine;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Loader;
import org.apache.catalina.Realm;
import org.apache.catalina.connector.Request;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.jasper.runtime.JspFactoryImpl;
import org.apache.jasper.xmlparser.ParserUtils;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.api.web.TldProvider;
import org.glassfish.grizzly.config.ContextRootInfo;
import org.glassfish.grizzly.config.dom.NetworkConfig;
import org.glassfish.grizzly.config.dom.NetworkListener;
import org.glassfish.grizzly.config.dom.NetworkListeners;
import org.glassfish.grizzly.http.server.util.Mapper;
import org.glassfish.grizzly.http.server.util.MappingData;
import org.glassfish.grizzly.http.util.DataChunk;
import org.glassfish.hk2.api.DynamicConfiguration;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.PreDestroy;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.api.ServerContext;
import org.glassfish.internal.data.ApplicationRegistry;
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.grizzly.ContextMapper;
import org.glassfish.web.LogFacade;
import org.glassfish.web.admin.monitor.HttpServiceStatsProviderBootstrap;
import org.glassfish.web.admin.monitor.JspProbeProvider;
import org.glassfish.web.admin.monitor.RequestProbeProvider;
import org.glassfish.web.admin.monitor.ServletProbeProvider;
import org.glassfish.web.admin.monitor.SessionProbeProvider;
import org.glassfish.web.admin.monitor.WebModuleProbeProvider;
import org.glassfish.web.admin.monitor.WebStatsProviderBootstrap;
import org.glassfish.web.config.serverbeans.SessionProperties;
import org.glassfish.web.deployment.archivist.WebArchivist;
import org.glassfish.web.deployment.runtime.SunWebAppImpl;
import org.glassfish.web.deployment.util.WebValidatorWithoutCL;
import org.glassfish.web.valve.GlassFishValve;
import org.jvnet.hk2.annotations.Optional;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.ObservableBean;
import org.jvnet.hk2.config.Transactions;
import org.jvnet.hk2.config.types.Property;
import org.xml.sax.EntityResolver;

import com.sun.appserv.server.util.Version;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.config.serverbeans.Configs;
import com.sun.enterprise.config.serverbeans.DasConfig;
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.Server;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.container.common.spi.JCDIService;
import com.sun.enterprise.container.common.spi.util.ComponentEnvManager;
import com.sun.enterprise.container.common.spi.util.InjectionManager;
import com.sun.enterprise.container.common.spi.util.JavaEEIOUtils;
import com.sun.enterprise.deployment.WebBundleDescriptor;
import com.sun.enterprise.deployment.WebComponentDescriptor;
import com.sun.enterprise.security.integration.RealmInitializer;
import com.sun.enterprise.server.logging.LoggingRuntime;
import com.sun.enterprise.util.Result;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.v3.services.impl.ContainerMapper;
import com.sun.enterprise.v3.services.impl.GrizzlyService;
import com.sun.enterprise.web.connector.coyote.PECoyoteConnector;
import com.sun.enterprise.web.logger.FileLoggerHandlerFactory;
import com.sun.enterprise.web.logger.IASLogger;
import com.sun.enterprise.web.pluggable.WebContainerFeatureFactory;
import com.sun.enterprise.web.reconfig.WebConfigListener;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.naming.NamingException;
import org.glassfish.api.deployment.DeploymentContext;

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

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

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

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

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

    private static final String MONITORING_NODE_SEPARATOR = "/";

    private static final Logger logger = LogFacade.getLogger();

    private static final ResourceBundle rb = logger.getResourceBundle();

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

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

    @Inject
    private ApplicationRegistry appRegistry;

    @Inject
    private ClassLoaderHierarchy clh;

    @Inject
    private ComponentEnvManager componentEnvManager;

    @Inject
    private Configs configs;

    @Inject @Optional
    private DasConfig dasConfig;

    @Inject
    private Domain domain;

    @Inject
    private Events events;

    @Inject
    private FileLoggerHandlerFactory fileLoggerHandlerFactory;

    @Inject
    private GrizzlyService grizzlyService;

    @Inject
    private ServiceLocator habitat;

    @Inject
    private JavaEEIOUtils javaEEIOUtils;

    @Inject @Optional
    private JCDIService jcdiService;

    @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    private Config serverConfig;

    @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    private Server server;

    @Inject
    private ServerContext _serverContext;

    @Inject
    private Transactions transactions;
    
    @Inject
    private LoggingRuntime loggingRuntime;

    private HashMap connectorMap = new HashMap();

    private EmbeddedWebContainer _embedded;

    private Engine engine;

    private String instanceName;

    private WebConnector jkConnector;

    private String logLevel = "INFO";
    /**
     * Allow disabling accessLog mechanism
     */
    protected boolean globalAccessLoggingEnabled = true;

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

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

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

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

    @Inject
    protected ServerEnvironment instance = null;

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

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

    /**
     * Controls the verbosity of the web container subsystem's debug messages.
     * 

* This value is non-zero only when the iAS level is one of FINE, FINER * or FINEST. */ protected int _debug = 0; /** * Top-level directory for files generated (compiled JSPs) by * standalone web modules. */ private String _modulesWorkRoot = null; /** * Absolute path for location where all the deployed * standalone modules are stored for this Server Instance. */ protected File _modulesRoot = null; /** * Top-level directory for files generated by application web modules. */ private String _appsWorkRoot = null; // START S1AS 6178005 /** * Top-level directory where ejb stubs for applications are stored. */ private String appsStubRoot = null; // END S1AS 6178005 /** * Indicates whether dynamic reloading is enabled (as specified by * the dynamic-reload-enabled attribute of in server.xml) */ private boolean _reloadingEnabled = false; /** * The number of seconds between checks for modified classes (if * dynamic reloading is enabled). *

* This value is specified by the reload-poll-interval attribute of * in server.xml. */ private int _pollInterval = 2; /** * Has this component been started yet? */ protected boolean _started = false; /** * The global (at the http-service level) ssoEnabled property. */ protected boolean globalSSOEnabled = true; protected volatile WebContainerFeatureFactory webContainerFeatureFactory; /** * The value of the instance-level session property named "enableCookies" */ boolean instanceEnableCookies = true; @Inject ServerConfigLookup serverConfigLookup; protected JspProbeProvider jspProbeProvider = null; protected RequestProbeProvider requestProbeProvider = null; protected ServletProbeProvider servletProbeProvider = null; protected SessionProbeProvider sessionProbeProvider = null; protected WebModuleProbeProvider webModuleProbeProvider = null; protected WebConfigListener configListener = null; // Indicates whether we are being shut down private boolean isShutdown = false; private final Object mapperUpdateSync = new Object(); private SecurityService securityService = null; protected HttpServiceStatsProviderBootstrap httpStatsProviderBootstrap = null; private WebStatsProviderBootstrap webStatsProviderBootstrap = null; private InjectionManager injectionMgr; private InvocationManager invocationMgr; private Collection tldProviders; private String logServiceFile = null; /** * Static initialization */ static { if (System.getProperty(DOL_DEPLOYMENT) != null) { useDOLforDeployment = Boolean.valueOf(System.getProperty(DOL_DEPLOYMENT)); } } private WebConfigListener addAndGetWebConfigListener() { ServiceLocator locator = (ServiceLocator) habitat; DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class); DynamicConfiguration config = dcs.createDynamicConfiguration(); config.addActiveDescriptor(WebConfigListener.class); config.commit(); return locator.getService(WebConfigListener.class); } public void postConstruct() { final ReentrantReadWriteLock mapperLock = grizzlyService.obtainMapperLock(); mapperLock.writeLock().lock(); try { createProbeProviders(); injectionMgr = habitat.getService(InjectionManager.class); invocationMgr = habitat.getService(InvocationManager.class); tldProviders = habitat.getAllServices(TldProvider.class); createStatsProviders(); setJspFactory(); _appsWorkRoot = instance.getApplicationCompileJspPath().getAbsolutePath(); _modulesRoot = instance.getApplicationRepositoryPath(); // START S1AS 6178005 appsStubRoot = instance.getApplicationStubPath().getAbsolutePath(); // END S1AS 6178005 // TODO: ParserUtils should become a @Service and it should initialize itself. // TODO: there should be only one EntityResolver for both DigesterFactory // and ParserUtils File root = _serverContext.getInstallRoot(); File libRoot = new File(root, "lib"); File schemas = new File(libRoot, "schemas"); File dtds = new File(libRoot, "dtds"); try { ParserUtils.setSchemaResourcePrefix(schemas.toURI().toURL().toString()); ParserUtils.setDtdResourcePrefix(dtds.toURI().toURL().toString()); ParserUtils.setEntityResolver(habitat.getService(EntityResolver.class, "web")); } catch (MalformedURLException e) { logger.log(Level.SEVERE, LogFacade.EXCEPTION_SET_SCHEMAS_DTDS_LOCATION, e); } instanceName = _serverContext.getInstanceName(); webContainerFeatureFactory = getWebContainerFeatureFactory(); configureDynamicReloadingSettings(); setDebugLevel(); String maxDepth = null; org.glassfish.web.config.serverbeans.WebContainer configWC = serverConfig.getExtensionByType( org.glassfish.web.config.serverbeans.WebContainer.class); if (configWC != null) maxDepth = configWC.getPropertyValue(DISPATCHER_MAX_DEPTH); if (maxDepth != null) { int depth = -1; try { depth = Integer.parseInt(maxDepth); } catch (NumberFormatException e) { } if (depth > 0) { Request.setMaxDispatchDepth(depth); if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.MAX_DISPATCH_DEPTH_SET, maxDepth); } } } File currentLogFile = loggingRuntime.getCurrentLogFile(); if (currentLogFile != null) { logServiceFile = currentLogFile.getAbsolutePath(); } Level level = Logger.getLogger("org.apache.catalina.level").getLevel(); if (level != null) { logLevel = level.getName(); } _embedded = habitat.getService(EmbeddedWebContainer.class); _embedded.setWebContainer(this); _embedded.setLogServiceFile(logServiceFile); _embedded.setLogLevel(logLevel); _embedded.setFileLoggerHandlerFactory(fileLoggerHandlerFactory); _embedded.setWebContainerFeatureFactory(webContainerFeatureFactory); _embedded.setCatalinaHome(instance.getDomainRoot().getAbsolutePath()); _embedded.setCatalinaBase(instance.getDomainRoot().getAbsolutePath()); _embedded.setUseNaming(false); if (_debug > 1) _embedded.setDebug(_debug); _embedded.setLogger(new IASLogger(logger)); engine = _embedded.createEngine(); engine.setParentClassLoader(EmbeddedWebContainer.class.getClassLoader()); engine.setService(_embedded); _embedded.addEngine(engine); ((StandardEngine) engine).setDomain(_serverContext.getDefaultDomainName()); engine.setName(_serverContext.getDefaultDomainName()); /* * Set the server info. * By default, the server info is taken from Version#getVersion. * However, customers may override it via the product.name system * property. * Some customers prefer not to disclose the server info * for security reasons, in which case they would set the value of the * product.name system property to the empty string. In this case, * the server name will not be publicly disclosed via the "Server" * HTTP response header (which will be suppressed) or any container * generated error pages. However, it will still appear in the * server logs (see IT 6900). */ String serverInfo = System.getProperty("product.name"); if (serverInfo == null) { ServerInfo.setServerInfo(Version.getVersion()); ServerInfo.setPublicServerInfo(Version.getVersion()); } else if (serverInfo.isEmpty()) { ServerInfo.setServerInfo(Version.getVersion()); ServerInfo.setPublicServerInfo(serverInfo); } else { ServerInfo.setServerInfo(serverInfo); ServerInfo.setPublicServerInfo(serverInfo); } initInstanceSessionProperties(); configListener = addAndGetWebConfigListener(); ObservableBean bean = (ObservableBean) ConfigSupport.getImpl( serverConfig.getHttpService()); bean.addListener(configListener); bean = (ObservableBean) ConfigSupport.getImpl( serverConfig.getNetworkConfig().getNetworkListeners()); bean.addListener(configListener); if (serverConfig.getAvailabilityService() != null) { bean = (ObservableBean) ConfigSupport.getImpl( serverConfig.getAvailabilityService()); bean.addListener(configListener); } transactions.addListenerForType(SystemProperty.class, configListener); configListener.setNetworkConfig(serverConfig.getNetworkConfig()); // embedded mode does not have manager-propertie in domain.xml if (configListener.managerProperties != null) { ObservableBean managerBean = (ObservableBean) ConfigSupport.getImpl( configListener.managerProperties); managerBean.addListener(configListener); } if (serverConfig.getJavaConfig() != null) { ((ObservableBean)ConfigSupport.getImpl( serverConfig.getJavaConfig())).addListener(configListener); } configListener.setContainer(this); configListener.setLogger(logger); events.register(this); grizzlyService.addMapperUpdateListener(configListener); HttpService httpService = serverConfig.getHttpService(); NetworkConfig networkConfig = serverConfig.getNetworkConfig(); if (networkConfig != null) { //continue; securityService = serverConfig.getSecurityService(); // Configure HTTP listeners NetworkListeners networkListeners = networkConfig.getNetworkListeners(); if (networkListeners != null) { List listeners = networkListeners.getNetworkListener(); for (NetworkListener listener : listeners) { createHttpListener(listener, httpService); } } setDefaultRedirectPort(defaultRedirectPort); // Configure virtual servers createHosts(httpService, securityService); } loadSystemDefaultWebModules(); //_lifecycle.fireLifecycleEvent(START_EVENT, null); _started = true; /* * Start the embedded container. * Make sure to set the thread's context classloader to the * classloader of this class (see IT 8866 for details) */ ClassLoader current = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader( getClass().getClassLoader()); try { /* * Trigger a call to sun.awt.AppContext.getAppContext(). * This will pin the classloader of this class in memory * and fix a memory leak affecting instances of WebappClassLoader * that was caused by a JRE implementation change in 1.6.0_15 * onwards. See IT 11110 */ ImageIO.getCacheDirectory(); _embedded.start(); } catch (LifecycleException le) { logger.log(Level.SEVERE, LogFacade.UNABLE_TO_START_WEB_CONTAINER, le); return; } finally { // Restore original context classloader Thread.currentThread().setContextClassLoader(current); } } finally { mapperLock.writeLock().unlock(); } } public void event(Event event) { if (event.is(Deployment.ALL_APPLICATIONS_PROCESSED)) { // configure default web modules for virtual servers after all // applications are processed loadDefaultWebModulesAfterAllAppsProcessed(); } else if (event.is(EventTypes.PREPARE_SHUTDOWN)) { isShutdown = true; } else if(event.is(Deployment.DEPLOYMENT_FAILURE) || event.is(Deployment.UNDEPLOYMENT_FAILURE)) { DeploymentContext dc = (DeploymentContext)event.hook(); try { // Fix https://github.com/payara/Payara/issues/315 WebBundleDescriptor wbd = dc.getModuleMetaData(WebBundleDescriptor.class); if(wbd != null) { componentEnvManager.unbindFromComponentNamespace(wbd); } } catch (NamingException ex) { logger.log(Level.SEVERE, LogFacade.EXCEPTION_DURING_DESTROY, ex); } } } /** * Notifies any interested listeners that all ServletContextListeners * of the web module represented by the given WebBundleDescriptor * have been invoked at their contextInitialized method */ void afterServletContextInitializedEvent(WebBundleDescriptor wbd) { events.send(new Event( WebBundleDescriptor.AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT, wbd), false); } public void preDestroy() { try { for (Connector con : _embedded.findConnectors()) { deleteConnector((WebConnector)con); } _embedded.removeEngine(getEngine()); _embedded.destroy(); } catch (LifecycleException le) { logger.log(Level.SEVERE, LogFacade.UNABLE_TO_STOP_WEB_CONTAINER, le); return; } } JavaEEIOUtils getJavaEEIOUtils() { return javaEEIOUtils; } public boolean isShutdown() { return isShutdown; } Collection getTldProviders() { return tldProviders; } /** * Gets the probe provider for servlet related events. */ public ServletProbeProvider getServletProbeProvider() { return servletProbeProvider; } /** * Gets the probe provider for jsp related events. */ public JspProbeProvider getJspProbeProvider() { return jspProbeProvider; } /** * Gets the probe provider for session related events. */ public SessionProbeProvider getSessionProbeProvider() { return sessionProbeProvider; } /** * Gets the probe provider for request/response related events. */ public RequestProbeProvider getRequestProbeProvider() { return requestProbeProvider; } /** * Gets the probe provider for web module related events. */ public WebModuleProbeProvider getWebModuleProbeProvider() { return webModuleProbeProvider; } public String getName() { return "Web"; } public Class getDeployer() { return WebDeployer.class; } InvocationManager getInvocationManager() { return invocationMgr; } public WebConnector getJkConnector() { return jkConnector; } public HashMap getConnectorMap() { return connectorMap; } /** * Instantiates and injects the given Servlet class for the given * WebModule */ T createServletInstance(WebModule module, Class clazz) throws Exception { validateJSR299Scope(clazz); WebComponentInvocation inv = new WebComponentInvocation(module); try { invocationMgr.preInvoke(inv); return injectionMgr.createManagedObject(clazz); } finally { invocationMgr.postInvoke(inv); } } /** * Instantiates and injects the given Filter class for the given * WebModule */ T createFilterInstance(WebModule module, Class clazz) throws Exception { validateJSR299Scope(clazz); WebComponentInvocation inv = new WebComponentInvocation(module); try { invocationMgr.preInvoke(inv); return injectionMgr.createManagedObject(clazz); } finally { invocationMgr.postInvoke(inv); } } /** * Instantiates and injects the given EventListener class for the * given WebModule */ T createListenerInstance( WebModule module, Class clazz) throws Exception { validateJSR299Scope(clazz); WebComponentInvocation inv = new WebComponentInvocation(module); try { invocationMgr.preInvoke(inv); return injectionMgr.createManagedObject(clazz); } finally { invocationMgr.postInvoke(inv); } } /** * Instantiates and injects the given HttpUpgradeHandler class for the * given WebModule */ T createHttpUpgradeHandlerInstance( WebModule module, Class clazz) throws Exception { validateJSR299Scope(clazz); WebComponentInvocation inv = new WebComponentInvocation(module); try { invocationMgr.preInvoke(inv); return injectionMgr.createManagedObject(clazz); } finally { invocationMgr.postInvoke(inv); } } /** * Instantiates and injects the given tag handler class for the given * WebModule */ public T createTagHandlerInstance(WebModule module, Class clazz) throws Exception { WebComponentInvocation inv = new WebComponentInvocation(module); try { invocationMgr.preInvoke(inv); return injectionMgr.createManagedObject(clazz); } finally { invocationMgr.postInvoke(inv); } } /** * Use an network-listener subelements and creates a corresponding * Tomcat Connector for each. * * @param httpService The http-service element * @param listener the configuration element. */ protected WebConnector createHttpListener(NetworkListener listener, HttpService httpService) { return createHttpListener(listener, httpService, null); } protected WebConnector createHttpListener(NetworkListener listener, HttpService httpService, Mapper mapper) { if (!Boolean.valueOf(listener.getEnabled())) { return null; } int port = 8080; WebConnector connector; checkHostnameUniqueness(listener.getName(), httpService); try { port = Integer.parseInt(listener.getPort()); } catch (NumberFormatException nfe) { String msg = rb.getString(LogFacade.HTTP_LISTENER_INVALID_PORT); msg = MessageFormat.format(msg, listener.getPort(), listener.getName()); throw new IllegalArgumentException(msg); } if (mapper == null) { for (Mapper m : habitat.getAllServices(Mapper.class)) { if (m.getPort() == port && m instanceof ContextMapper) { ContextMapper cm = (ContextMapper) m; if (listener.getName().equals(cm.getId())) { mapper = m; break; } } } } String defaultVS = listener.findHttpProtocol().getHttp().getDefaultVirtualServer(); if (!defaultVS.equals(org.glassfish.api.web.Constants.ADMIN_VS)) { // Before we start a WebConnector, let's makes sure there is // not another Container already listening on that port DataChunk host = DataChunk.newInstance(); char[] c = defaultVS.toCharArray(); host.setChars(c, 0, c.length); DataChunk mb = DataChunk.newInstance(); mb.setChars(new char[]{'/'}, 0, 1); MappingData md = new MappingData(); try { mapper.map(host, mb, md); } catch (Exception e) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "", e); } } if (md.context != null && md.context instanceof ContextRootInfo) { ContextRootInfo r = (ContextRootInfo) md.context; if (!(r.getHttpHandler() instanceof ContainerMapper)){ new BindException("Port " + port + " is already used by Container: " + r.getHttpHandler() + " and will not get started.").printStackTrace(); return null; } } } /* * Create Connector. Connector is SSL-enabled if * 'security-enabled' attribute in * element is set to TRUE. */ boolean isSecure = Boolean.valueOf(listener.findHttpProtocol().getSecurityEnabled()); if (isSecure && defaultRedirectPort == -1) { defaultRedirectPort = port; } String address = listener.getAddress(); if ("any".equals(address) || "ANY".equals(address) || "INADDR_ANY".equals(address)) { address = null; /* * Setting 'address' to NULL will cause Tomcat to pass a * NULL InetAddress argument to the java.net.ServerSocket * constructor, meaning that the server socket will accept * connections on any/all local addresses. */ } connector = (WebConnector) _embedded.createConnector( address, port, isSecure); connector.setMapper(mapper); connector.setJvmRoute(engine.getJvmRoute()); if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.HTTP_LISTENER_CREATED, new Object[]{listener.getName(), listener.getAddress(), listener.getPort()}); } connector.setDefaultHost(listener.findHttpProtocol().getHttp().getDefaultVirtualServer()); connector.setName(listener.getName()); connector.setInstanceName(instanceName); connector.configure(listener, isSecure, httpService); _embedded.addConnector(connector); connectorMap.put(listener.getName(), connector); // If we already know the redirect port, then set it now // This situation will occurs when dynamic reconfiguration occurs String redirectPort = listener.findHttpProtocol().getHttp().getRedirectPort(); if (redirectPort != null) { connector.setRedirectPort(Integer.parseInt(redirectPort)); } else if (defaultRedirectPort != -1) { connector.setRedirectPort(defaultRedirectPort); } ObservableBean httpListenerBean = (ObservableBean) ConfigSupport.getImpl( listener); httpListenerBean.addListener(configListener); return connector; } /** * Starts the AJP connector that will listen to call from Apache using * mod_jk, mod_jk2 or mod_ajp. */ protected WebConnector createJKConnector(NetworkListener listener, HttpService httpService) { int port = 8009; boolean isSecure = false; String address = null; if (listener == null) { String portString = System.getProperty("com.sun.enterprise.web.connector.enableJK"); if (portString == null) { // do not create JK Connector if property is not set return null; } else { try { port = Integer.parseInt(portString); } catch (NumberFormatException ex) { // use default port 8009 port = 8009; } } } else { port = Integer.parseInt(listener.getPort()); isSecure = Boolean.valueOf(listener.findHttpProtocol().getSecurityEnabled()); address = listener.getAddress(); } if (isSecure && defaultRedirectPort == -1) { defaultRedirectPort = port; } if ("any".equals(address) || "ANY".equals(address) || "INADDR_ANY".equals(address)) { address = null; /* * Setting 'address' to NULL will cause Tomcat to pass a * NULL InetAddress argument to the java.net.ServerSocket * constructor, meaning that the server socket will accept * connections on any/all local addresses. */ } jkConnector = (WebConnector) _embedded.createConnector(address, port, "ajp"); jkConnector.configureJKProperties(listener); String defaultHost = "server"; String jkConnectorName = "jk-connector"; if (listener != null) { defaultHost = listener.findHttpProtocol().getHttp().getDefaultVirtualServer(); jkConnectorName = listener.getName(); } jkConnector.setDefaultHost(defaultHost); jkConnector.setName(jkConnectorName); jkConnector.setDomain(_serverContext.getDefaultDomainName()); jkConnector.setInstanceName(instanceName); if (listener != null) { jkConnector.configure(listener, isSecure, httpService); connectorMap.put(listener.getName(), jkConnector); } if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.JK_LISTENER_CREATED, new Object[]{listener.getName(), listener.getAddress(), listener.getPort()}); } for (Mapper m : habitat.getAllServices(Mapper.class)) { if (m.getPort() == port && m instanceof ContextMapper) { ContextMapper cm = (ContextMapper) m; if (listener.getName().equals(cm.getId())) { jkConnector.setMapper(m); break; } } } _embedded.addConnector(jkConnector); return jkConnector; } /** * Assigns the given redirect port to each Connector whose corresponding * http-listener element in domain.xml does not specify its own * redirect-port attribute. *

* The given defaultRedirectPort corresponds to the port number of the * first security-enabled http-listener in domain.xml. *

* This method does nothing if none of the http-listener elements is * security-enabled, in which case Tomcat's default redirect port (443) * will be used. * * @param defaultRedirectPort The redirect port to be assigned to any * Connector object that doesn't specify its own */ private void setDefaultRedirectPort(int defaultRedirectPort) { if (defaultRedirectPort != -1) { Connector[] connectors = _embedded.getConnectors(); for (Connector connector : connectors) { if (connector.getRedirectPort() == -1) { connector.setRedirectPort(defaultRedirectPort); } } } } /** * Configure http-service properties. * * @deprecated most of these properties are handled elsewhere. validate and remove outdated properties checks */ public void configureHttpServiceProperties(HttpService httpService, PECoyoteConnector connector) { // Configure Connector with properties List httpServiceProps = httpService.getProperty(); // Set default ProxyHandler impl, may be overriden by // proxyHandler property connector.setProxyHandler(new ProxyHandlerImpl()); globalSSOEnabled = ConfigBeansUtilities.toBoolean(httpService.getSsoEnabled()); globalAccessLoggingEnabled = ConfigBeansUtilities.toBoolean(httpService.getAccessLoggingEnabled()); globalAccessLogWriteInterval = httpService.getAccessLog().getWriteIntervalSeconds(); globalAccessLogBufferSize = httpService.getAccessLog().getBufferSizeBytes(); if (httpServiceProps != null) { for (Property httpServiceProp : httpServiceProps) { String propName = httpServiceProp.getName(); String propValue = httpServiceProp.getValue(); if (connector.configureHttpListenerProperty(propName, propValue)) { continue; } if ("connectionTimeout".equals(propName)) { connector.setConnectionTimeout(Integer.parseInt(propValue)); } else if ("tcpNoDelay".equals(propName)) { connector.setTcpNoDelay(ConfigBeansUtilities.toBoolean(propValue)); } else if ("traceEnabled".equals(propName)) { connector.setAllowTrace(ConfigBeansUtilities.toBoolean(propValue)); } else if ("ssl-session-timeout".equals(propName)) { connector.setSslSessionTimeout(propValue); } else if ("ssl3-session-timeout".equals(propName)) { connector.setSsl3SessionTimeout(propValue); } else if ("ssl-cache-entries".equals(propName)) { connector.setSslSessionCacheSize(propValue); } else if ("proxyHandler".equals(propName)) { connector.setProxyHandler(propValue); } else { String msg = rb.getString(LogFacade.INVALID_HTTP_SERVICE_PROPERTY); logger.log(Level.WARNING, MessageFormat.format(msg, httpServiceProp.getName()));; } } } } /* * Ensures that the host names of all virtual servers associated with the * HTTP listener with the given listener id are unique. * * @param listenerId The id of the HTTP listener whose associated virtual * servers are checked for uniqueness of host names * @param httpService The http-service element whose virtual servers are * checked */ private void checkHostnameUniqueness(String listenerId, HttpService httpService) { List listenerVses = null; // Determine all the virtual servers associated with the given listener for (com.sun.enterprise.config.serverbeans.VirtualServer vse : httpService.getVirtualServer()) { List vsListeners = StringUtils.parseStringList(vse.getNetworkListeners(), ","); for (int j = 0; vsListeners != null && j < vsListeners.size(); j++) { if (listenerId.equals(vsListeners.get(j))) { if (listenerVses == null) { listenerVses = new ArrayList(); } listenerVses.add(vse); break; } } } if (listenerVses == null) { return; } for (int i = 0; i < listenerVses.size(); i++) { com.sun.enterprise.config.serverbeans.VirtualServer vs = listenerVses.get(i); List hosts = StringUtils.parseStringList(vs.getHosts(), ","); for (int j = 0; hosts != null && j < hosts.size(); j++) { String host = (String) hosts.get(j); for (int k = 0; k < listenerVses.size(); k++) { if (k <= i) { continue; } com.sun.enterprise.config.serverbeans.VirtualServer otherVs = listenerVses.get(k); List otherHosts = StringUtils.parseStringList(otherVs.getHosts(), ","); for (int l = 0; otherHosts != null && l < otherHosts.size(); l++) { if (host.equals(otherHosts.get(l))) { logger.log(Level.SEVERE, LogFacade.DUPLICATE_HOST_NAME, new Object[]{host, vs.getId(), otherVs.getId(), listenerId}); } } } } } } /** * Enumerates the virtual-server subelements of the given http-service * element, and creates a corresponding Host for each. * * @param httpService The http-service element * @param securityService The security-service element */ protected void createHosts(HttpService httpService, SecurityService securityService) { List virtualServers = httpService.getVirtualServer(); for (com.sun.enterprise.config.serverbeans.VirtualServer vs : virtualServers) { createHost(vs, httpService, securityService); if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.VIRTUAL_SERVER_CREATED, vs.getId()); } } } /** * Creates a Host from a virtual-server config bean. * * @param vsBean The virtual-server configuration bean * @param httpService The http-service element. * @param securityService The security-service element */ public VirtualServer createHost( com.sun.enterprise.config.serverbeans.VirtualServer vsBean, HttpService httpService, SecurityService securityService) { String vs_id = vsBean.getId(); String docroot = vsBean.getPropertyValue("docroot"); if (docroot == null) { docroot = vsBean.getDocroot(); } validateDocroot(docroot, vs_id, vsBean.getDefaultWebModule()); VirtualServer vs = createHost(vs_id, vsBean, docroot, null ); // cache control Property cacheProp = vsBean.getProperty("setCacheControl"); if (cacheProp != null) { vs.configureCacheControl(cacheProp.getValue()); } PEAccessLogValve accessLogValve = vs.getAccessLogValve(); boolean startAccessLog = accessLogValve.configure( vs_id, vsBean, httpService, domain, habitat, webContainerFeatureFactory, globalAccessLogBufferSize, globalAccessLogWriteInterval); if (startAccessLog && vs.isAccessLoggingEnabled(globalAccessLoggingEnabled)) { vs.addValve((GlassFishValve) accessLogValve); } if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, LogFacade.VIRTUAL_SERVER_CREATED, vs_id); } /* * We must configure the Host with its associated port numbers and * alias names before adding it as an engine child and thereby * starting it, because a MapperListener, which is associated with * an HTTP listener and receives notifications about Host * registrations, relies on these Host properties in order to determine * whether a new Host needs to be added to the HTTP listener's Mapper. */ configureHost(vs, securityService); vs.setDomain(domain); vs.setServices(habitat); vs.setClassLoaderHierarchy(clh); // Add Host to Engine engine.addChild(vs); ObservableBean virtualServerBean = (ObservableBean) ConfigSupport.getImpl(vsBean); virtualServerBean.addListener(configListener); return vs; } /** * Validate the docroot properties of a virtual-server. */ protected void validateDocroot(String docroot, String vs_id, String defaultWebModule) { if (docroot == null) { return; } boolean isValid = new File(docroot).exists(); if (!isValid) { String msg = rb.getString(LogFacade.VIRTUAL_SERVER_INVALID_DOCROOT); msg = MessageFormat.format(msg, vs_id, docroot); throw new IllegalArgumentException(msg); } } /** * Configures the given virtual server. * * @param vs The virtual server to be configured * @param securityService The security-service element */ protected void configureHost(VirtualServer vs, SecurityService securityService) { com.sun.enterprise.config.serverbeans.VirtualServer vsBean = vs.getBean(); vs.configureAliases(); // Set the ports with which this virtual server is associated List listeners = StringUtils.parseStringList( vsBean.getNetworkListeners(), ","); if (listeners == null) { return; } HashSet httpListeners = new HashSet(); for (String listener : listeners) { boolean found = false; for (NetworkListener httpListener : serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener()) { if (httpListener.getName().equals(listener)) { httpListeners.add(httpListener); found = true; break; } } if (!found) { String msg = rb.getString(LogFacade.LISTENER_REFERENCED_BY_HOST_NOT_EXIST); msg = MessageFormat.format(msg, listener, vs.getName()); logger.log(Level.SEVERE, msg); } } configureHostPortNumbers(vs, httpListeners); vs.configureCatalinaProperties(); vs.configureAuthRealm(securityService); vs.addProbes(globalAccessLoggingEnabled); } /** * Configures the given virtual server with the port numbers of its * associated http listeners. * * @param vs The virtual server to configure * @param listeners The http listeners with which the given virtual * server is associated */ protected void configureHostPortNumbers(VirtualServer vs, HashSet listeners) { boolean addJkListenerName = jkConnector != null && !vs.getName().equalsIgnoreCase( org.glassfish.api.web.Constants.ADMIN_VS); List listenerNames = new ArrayList(); for (NetworkListener listener : listeners) { if (Boolean.valueOf(listener.getEnabled())) { listenerNames.add(listener.getName()); if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.VIRTUAL_SERVER_SET_LISTENER_NAME); } } else { if (vs.getName().equalsIgnoreCase( org.glassfish.api.web.Constants.ADMIN_VS)) { String msg = rb.getString(LogFacade.MUST_NOT_DISABLE); msg = MessageFormat.format(msg, listener.getName(), vs.getName()); throw new IllegalArgumentException(msg); } } } if (addJkListenerName && (!listenerNames.contains(jkConnector.getName()))) { listenerNames.add(jkConnector.getName()); if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.VIRTUAL_SERVER_SET_JK_LISTENER_NAME, new Object[]{vs.getID(), jkConnector.getName()}); } } vs.setNetworkListenerNames( listenerNames.toArray(new String[listenerNames.size()])); } // ------------------------------------------------------ Public Methods /** * Create a virtual server/host. */ public VirtualServer createHost(String vsID, com.sun.enterprise.config.serverbeans.VirtualServer vsBean, String docroot, MimeMap mimeMap) { // Initialize the docroot VirtualServer vs = (VirtualServer) _embedded.createHost(vsID, vsBean, docroot, vsBean.getLogFile(), mimeMap); vs.configureState(); vs.configureRemoteAddressFilterValve(); vs.configureRemoteHostFilterValve(); vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled()); vs.configureRedirect(); vs.configureErrorPage(); vs.configureErrorReportValve(); vs.setServerContext(getServerContext()); vs.setServerConfig(serverConfig); vs.setGrizzlyService(grizzlyService); vs.setWebContainer(this); return vs; } /** * Gracefully terminate the active use of the public methods of this * component. This method should be the last one called on a given * instance of this component. * * @throws IllegalStateException if this component has not been started * @throws LifecycleException if this component detects a fatal error * that needs to be reported */ public void stop() throws LifecycleException { // Validate and update our current component state if (!_started) { String msg = rb.getString(LogFacade.WEB_CONTAINER_NOT_STARTED); throw new LifecycleException(msg); } _started = false; // stop the embedded container try { _embedded.stop(); } catch (LifecycleException ex) { if (!ex.getMessage().contains("has not been started")) { throw ex; } } } // ------------------------------------------------------ Private Methods /** * Configures a default web module for each virtual server based on the * virtual server's docroot if a virtual server does not specify * any default-web-module, and none of its web modules are loaded at "/" *

* Needed in postConstruct before Deployment.ALL_APPLICATIONS_PROCESSED * for "jsp from docroot before web container start" scenario */ public void loadSystemDefaultWebModules() { WebModuleConfig wmInfo = null; String defaultPath = null; Container[] vsArray = getEngine().findChildren(); for (Container aVsArray : vsArray) { if (aVsArray instanceof VirtualServer) { VirtualServer vs = (VirtualServer) aVsArray; /* * Let AdminConsoleAdapter handle any requests for * the root context of the '__asadmin' virtual-server, see * https://glassfish.dev.java.net/issues/show_bug.cgi?id=5664 */ if (org.glassfish.api.web.Constants.ADMIN_VS.equals( vs.getName())) { continue; } // Create default web module off of virtual // server's docroot if necessary wmInfo = vs.createSystemDefaultWebModuleIfNecessary( habitat.getService( WebArchivist.class)); if (wmInfo != null) { defaultPath = wmInfo.getContextPath(); loadStandaloneWebModule(vs, wmInfo); } if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.VIRTUAL_SERVER_LOADED_DEFAULT_WEB_MODULE, new Object[]{vs.getName(), defaultPath}); } } } } /** * Configures a default web module for each virtual server * if default-web-module is defined. */ public void loadDefaultWebModulesAfterAllAppsProcessed() { String defaultPath = null; Container[] vsArray = getEngine().findChildren(); for (Container aVsArray : vsArray) { if (aVsArray instanceof VirtualServer) { VirtualServer vs = (VirtualServer) aVsArray; /* * Let AdminConsoleAdapter handle any requests for * the root context of the '__asadmin' virtual-server, see * https://glassfish.dev.java.net/issues/show_bug.cgi?id=5664 */ if (org.glassfish.api.web.Constants.ADMIN_VS.equals( vs.getName())) { continue; } WebModuleConfig wmInfo = vs.getDefaultWebModule(domain, habitat.getService( WebArchivist.class), appRegistry); if (wmInfo != null) { defaultPath = wmInfo.getContextPath(); // Virtual server declares default-web-module try { updateDefaultWebModule(vs, vs.getNetworkListenerNames(), wmInfo); } catch (LifecycleException le) { String msg = rb.getString(LogFacade.DEFAULT_WEB_MODULE_ERROR); msg = MessageFormat.format(msg, defaultPath, vs.getName()); logger.log(Level.SEVERE, msg, le); } if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.VIRTUAL_SERVER_LOADED_DEFAULT_WEB_MODULE, new Object[]{vs.getName(), defaultPath}); } } else { // No need to create default web module off of virtual // server's docroot since system web modules are already // created in WebContainer.postConstruct } } } } /** * Load a default-web-module on the specified virtual server. */ public void loadDefaultWebModule( com.sun.enterprise.config.serverbeans.VirtualServer vsBean) { VirtualServer virtualServer = (VirtualServer) getEngine().findChild(vsBean.getId()); if (virtualServer != null) { loadDefaultWebModule(virtualServer); } } /** * Load a default-web-module on the specified virtual server. */ public void loadDefaultWebModule(VirtualServer vs) { String defaultPath = null; WebModuleConfig wmInfo = vs.getDefaultWebModule(domain, habitat.getService( WebArchivist.class), appRegistry); if (wmInfo != null) { defaultPath = wmInfo.getContextPath(); // Virtual server declares default-web-module try { updateDefaultWebModule(vs, vs.getNetworkListenerNames(), wmInfo); } catch (LifecycleException le) { String msg = rb.getString(LogFacade.DEFAULT_WEB_MODULE_ERROR); msg = MessageFormat.format(msg, defaultPath, vs.getName()); logger.log(Level.SEVERE, msg, le); } } else { // Create default web module off of virtual // server's docroot if necessary wmInfo = vs.createSystemDefaultWebModuleIfNecessary( habitat.getService( WebArchivist.class)); if (wmInfo != null) { defaultPath = wmInfo.getContextPath(); loadStandaloneWebModule(vs, wmInfo); } } if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.VIRTUAL_SERVER_LOADED_DEFAULT_WEB_MODULE, new Object[]{vs.getName(), defaultPath}); } } /** * Load the specified web module as a standalone module on the specified * virtual server. */ protected void loadStandaloneWebModule(VirtualServer vs, WebModuleConfig wmInfo) { try { loadWebModule(vs, wmInfo, "null", null); } catch (Throwable t) { String msg = rb.getString(LogFacade.LOAD_WEB_MODULE_ERROR); msg = MessageFormat.format(msg, wmInfo.getName()); logger.log(Level.SEVERE, msg, t); } } /** * Whether or not a component (either an application or a module) should be * enabled is defined by the "enable" attribute on both the * application/module element and the application-ref element. * * @param moduleName The name of the component (application or module) * @return boolean */ protected boolean isEnabled(String moduleName) { // TODO dochez : optimize /* Domain domain = habitat.getService(Domain.class); applications = domain.getApplications().getLifecycleModuleOrJ2EeApplicationOrEjbModuleOrWebModuleOrConnectorModuleOrAppclientModuleOrMbeanOrExtensionModule(); com.sun.enterprise.config.serverbeans.WebModule webModule = null; for (Object module : applications) { if (module instanceof WebModule) { if (moduleName.equals(((com.sun.enterprise.config.serverbeans.WebModule) module).getName())) { webModule = (com.sun.enterprise.config.serverbeans.WebModule) module; } } } em ServerContext env = habitat.getService(ServerContext.class); List servers = domain.getServers().getServer(); Server thisServer = null; for (Server server : servers) { if (env.getInstanceName().equals(server.getName())) { thisServer = server; } } List appRefs = thisServer.getApplicationRef(); ApplicationRef appRef = null; for (ApplicationRef ar : appRefs) { if (ar.getRef().equals(moduleName)) { appRef = ar; } } return ((webModule != null && Boolean.valueOf(webModule.getEnabled())) && (appRef != null && Boolean.valueOf(appRef.getEnabled()))); */ return true; } /** * Creates and configures a web module for each virtual server * that the web module is hosted under. *

* If no virtual servers have been specified, then the web module will * not be loaded. */ public List> loadWebModule( WebModuleConfig wmInfo, String j2eeApplication, Properties deploymentProperties) { List> results = new ArrayList>(); String vsIDs = wmInfo.getVirtualServers(); List vsList = StringUtils.parseStringList(vsIDs, " ,"); if (vsList == null || vsList.isEmpty()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.WEB_MODULE_NOT_LOADED_NO_VIRTUAL_SERVERS, wmInfo.getName()); } return results; } if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.LOADING_WEB_MODULE, vsIDs); } List nonProcessedVSList = new ArrayList(vsList); Container[] vsArray = getEngine().findChildren(); for (Container aVsArray : vsArray) { if (aVsArray instanceof VirtualServer) { VirtualServer vs = (VirtualServer) aVsArray; boolean eqVS = vsList.contains(vs.getID()); if (eqVS) { nonProcessedVSList.remove(vs.getID()); } Set matchedAliases = matchAlias(vsList, vs); boolean hasMatchedAlias = (matchedAliases.size() > 0); if (hasMatchedAlias) { nonProcessedVSList.removeAll(matchedAliases); } if (eqVS || hasMatchedAlias) { WebModule ctx = null; try { ctx = loadWebModule(vs, wmInfo, j2eeApplication, deploymentProperties); results.add(new Result(ctx)); } catch (Throwable t) { if (ctx != null) { ctx.setAvailable(false); } results.add(new Result(t)); } } } } if (nonProcessedVSList.size() > 0) { StringBuilder sb = new StringBuilder(); boolean follow = false; for (String alias : nonProcessedVSList) { if (follow) { sb.append(","); } sb.append(alias); follow = true; } Object[] params = {wmInfo.getName(), sb.toString()}; logger.log(Level.SEVERE, LogFacade.WEB_MODULE_NOT_LOADED_TO_VS, params); } return results; } /** * Deploy on aliases as well as host. */ private boolean verifyAlias(List vsList, VirtualServer vs) { for (int i = 0; i < vs.getAliases().length; i++) { if (vsList.contains(vs.getAliases()[i])) { return true; } } return false; } /** * Find all matched aliases. * This is more expensive than verifyAlias. */ private Set matchAlias(List vsList, VirtualServer vs) { Set matched = new HashSet(); for (String alias : vs.getAliases()) { if (vsList.contains(alias)) { matched.add(alias); } } return matched; } /** * Creates and configures a web module and adds it to the specified * virtual server. */ private WebModule loadWebModule( VirtualServer vs, WebModuleConfig wmInfo, String j2eeApplication, Properties deploymentProperties) throws Exception { String wmName = wmInfo.getName(); String wmContextPath = wmInfo.getContextPath(); if (wmContextPath.indexOf('%') != -1) { try { RequestUtil.urlDecode(wmContextPath, "UTF-8"); } catch (Exception e) { String msg = rb.getString(LogFacade.INVALID_ENCODED_CONTEXT_ROOT); msg = MessageFormat.format(msg, wmName, wmContextPath); throw new Exception(msg); } } if (wmContextPath.length() == 0 && vs.getDefaultWebModuleID() != null) { String msg = rb.getString(LogFacade.DEFAULT_WEB_MODULE_CONFLICT); msg = MessageFormat.format(msg, new Object[]{wmName, vs.getID()}); throw new Exception(msg); } wmInfo.setWorkDirBase(_appsWorkRoot); // START S1AS 6178005 wmInfo.setStubBaseDir(appsStubRoot); // END S1AS 6178005 String displayContextPath = null; if (wmContextPath.length() == 0) displayContextPath = "/"; else displayContextPath = wmContextPath; Map adHocPaths = null; Map adHocSubtrees = null; WebModule ctx = (WebModule) vs.findChild(wmContextPath); if (ctx != null) { if (ctx instanceof AdHocWebModule) { /* * Found ad-hoc web module which has been created by web * container in order to store mappings for ad-hoc paths * and subtrees. * All these mappings must be propagated to the context * that is being deployed. */ if (ctx.hasAdHocPaths()) { adHocPaths = ctx.getAdHocPaths(); } if (ctx.hasAdHocSubtrees()) { adHocSubtrees = ctx.getAdHocSubtrees(); } vs.removeChild(ctx); } else if (Constants.DEFAULT_WEB_MODULE_NAME .equals(ctx.getModuleName())) { /* * Dummy context that was created just off of a docroot, * (see * VirtualServer.createSystemDefaultWebModuleIfNecessary()). * Unload it so it can be replaced with the web module to be * loaded */ unloadWebModule(wmContextPath, ctx.getWebBundleDescriptor().getApplication().getRegistrationName(), vs.getName(), true, null); } else if (!ctx.getAvailable()) { /* * Context has been marked unavailable by a previous * call to disableWebModule. Mark the context as available and * return */ ctx.setAvailable(true); return ctx; } else { String msg = rb.getString(LogFacade.DUPLICATE_CONTEXT_ROOT); throw new Exception(MessageFormat.format(msg, vs.getID(), ctx.getModuleName(), displayContextPath, wmName)); } } if (logger.isLoggable(Level.FINEST)) { Object[] params = {wmName, vs.getID(), displayContextPath}; logger.log(Level.FINEST, LogFacade.WEB_MODULE_LOADING, params); } File docBase = null; if (JWS_APPCLIENT_MODULE_NAME.equals(wmName)) { docBase = new File(System.getProperty("com.sun.aas.installRoot")); } else { docBase = wmInfo.getLocation(); } ctx = (WebModule) _embedded.createContext( wmName, wmContextPath, docBase, vs.getDefaultContextXmlLocation(), vs.getDefaultWebXmlLocation(), useDOLforDeployment, wmInfo); // for now disable JNDI ctx.setUseNaming(false); // Set JSR 77 object name and attributes Engine engine = (Engine) vs.getParent(); if (engine != null) { ctx.setEngineName(engine.getName()); ctx.setJvmRoute(engine.getJvmRoute()); } String j2eeServer = _serverContext.getInstanceName(); String domain = _serverContext.getDefaultDomainName(); // String[] javaVMs = J2EEModuleUtil.getjavaVMs(); ctx.setDomain(domain); ctx.setJ2EEServer(j2eeServer); ctx.setJ2EEApplication(j2eeApplication); //turn on container internal cache by default as in v2 //ctx.setCachingAllowed(false); ctx.setCacheControls(vs.getCacheControls()); ctx.setBean(wmInfo.getBean()); if (adHocPaths != null) { ctx.addAdHocPaths(adHocPaths); } if (adHocSubtrees != null) { ctx.addAdHocSubtrees(adHocSubtrees); } // Object containing web.xml information WebBundleDescriptor wbd = wmInfo.getDescriptor(); // Set the context root if (wbd != null) { ctx.setContextRoot(wbd.getContextRoot()); } else { // Should never happen. logger.log(Level.WARNING, LogFacade.UNABLE_TO_SET_CONTEXT_ROOT, wmInfo); } // // Ensure that the generated directory for JSPs in the document root // (i.e. those that are serviced by a system default-web-module) // is different for each virtual server. String wmInfoWorkDir = wmInfo.getWorkDir(); if (wmInfoWorkDir != null) { StringBuilder workDir = new StringBuilder(wmInfo.getWorkDir()); if (wmName.equals(Constants.DEFAULT_WEB_MODULE_NAME)) { workDir.append("-"); workDir.append(FileUtils.makeFriendlyFilename(vs.getID())); } ctx.setWorkDir(workDir.toString()); } ClassLoader parentLoader = wmInfo.getParentLoader(); if (parentLoader == null) { // Use the shared classloader as the parent for all // standalone web-modules parentLoader = _serverContext.getSharedClassLoader(); } ctx.setParentClassLoader(parentLoader); if (wbd != null) { // Determine if an alternate DD is set for this web-module in // the application ctx.configureAlternateDD(wbd); ctx.configureWebServices(wbd); } // Object containing sun-web.xml information SunWebAppImpl iasBean = null; // The default context is the only case when wbd == null if (wbd != null) { iasBean = (SunWebAppImpl) wbd.getSunDescriptor(); } // set the sun-web config bean ctx.setIasWebAppConfigBean(iasBean); // Configure SingleThreadedServletPools, work/tmp directory etc ctx.configureMiscSettings(iasBean, vs, displayContextPath); // Configure alternate docroots if dummy web module if (ctx.getID().startsWith(Constants.DEFAULT_WEB_MODULE_NAME)) { ctx.setAlternateDocBases(vs.getProperties()); } // Configure the class loader delegation model, classpath etc Loader loader = ctx.configureLoader(iasBean); // Set the class loader on the DOL object if (wbd != null && wbd.hasWebServices()) { wbd.addExtraAttribute("WEBLOADER", loader); } for (LifecycleListener listener : ctx.findLifecycleListeners()) { if (listener instanceof ContextConfig) { ((ContextConfig) listener).setClassLoader(wmInfo.getAppClassLoader()); } } // Configure the session manager and other related settings ctx.configureSessionSettings(wbd, wmInfo); // set i18n info from locale-charset-info tag in sun-web.xml ctx.setI18nInfo(); if (wbd != null) { String resourceType = wmInfo.getObjectType(); boolean isSystem = resourceType != null && resourceType.startsWith("system-"); // security will generate policy for system default web module if (!wmName.startsWith(Constants.DEFAULT_WEB_MODULE_NAME)) { // TODO : v3 : dochez Need to remove dependency on security Realm realm = habitat.getService(Realm.class); if ("null".equals(j2eeApplication)) { /* * Standalone webapps inherit the realm referenced by * the virtual server on which they are being deployed, * unless they specify their own */ if (realm != null && realm instanceof RealmInitializer) { ((RealmInitializer) realm).initializeRealm( wbd, isSystem, vs.getAuthRealmName()); ctx.setRealm(realm); } } else { if (realm != null && realm instanceof RealmInitializer) { ((RealmInitializer) realm).initializeRealm( wbd, isSystem, null); ctx.setRealm(realm); } } } // post processing DOL object for standalone web module if (wbd.getApplication() != null && wbd.getApplication().isVirtual()) { wbd.visit(new WebValidatorWithoutCL()); } } // Add virtual server mime mappings, if present addMimeMappings(ctx, vs.getMimeMap()); String moduleName = Constants.DEFAULT_WEB_MODULE_NAME; String monitoringNodeName = moduleName; if (wbd != null && wbd.getApplication() != null) { // Not a dummy web module com.sun.enterprise.deployment.Application app = wbd.getApplication(); ctx.setStandalone(app.isVirtual()); // S1AS BEGIN WORKAROUND FOR 6174360 if (app.isVirtual()) { // Standalone web module moduleName = app.getRegistrationName(); monitoringNodeName = wbd.getModuleID(); } else { // Nested (inside EAR) web module moduleName = wbd.getModuleDescriptor().getArchiveUri(); StringBuilder sb = new StringBuilder(); sb.append(app.getRegistrationName()). append(MONITORING_NODE_SEPARATOR).append(moduleName); monitoringNodeName = sb.toString().replaceAll("\\.", "\\\\."). replaceAll("_war", "\\\\.war"); } // S1AS END WORKAROUND FOR 6174360 } ctx.setModuleName(moduleName); ctx.setMonitoringNodeName(monitoringNodeName); List servletNames = new ArrayList(); if (wbd != null) { for (WebComponentDescriptor webCompDesc : wbd.getWebComponentDescriptors()) { if (webCompDesc.isServlet()) { servletNames.add(webCompDesc.getCanonicalName()); } } } webStatsProviderBootstrap.registerApplicationStatsProviders(monitoringNodeName, vs.getName(), servletNames); vs.addChild(ctx); ctx.loadSessions(deploymentProperties); return ctx; } /* * Updates the given virtual server with the given default path. * * The given default path corresponds to the context path of one of the * web contexts deployed on the virtual server that has been designated * as the virtual server's new default-web-module. * * @param virtualServer The virtual server to update * @param ports The port numbers of the HTTP listeners with which the * given virtual server is associated * @param defaultContextPath The context path of the web module that has * been designated as the virtual server's new default web module, or null * if the virtual server no longer has any default-web-module */ protected void updateDefaultWebModule(VirtualServer virtualServer, String[] listenerNames, WebModuleConfig wmInfo) throws LifecycleException { String defaultContextPath = null; if (wmInfo != null) { defaultContextPath = wmInfo.getContextPath(); } if (defaultContextPath != null && !defaultContextPath.startsWith("/")) { defaultContextPath = "/" + defaultContextPath; wmInfo.getDescriptor().setContextRoot(defaultContextPath); } Connector[] connectors = _embedded.findConnectors(); for (Connector connector : connectors) { PECoyoteConnector conn = (PECoyoteConnector) connector; String name = conn.getName(); for (String listenerName : listenerNames) { if (name.equals(listenerName)) { Mapper mapper = conn.getMapper(); try { mapper.setDefaultContextPath(virtualServer.getName(), defaultContextPath); for (String alias : virtualServer.findAliases()) { mapper.setDefaultContextPath(alias, defaultContextPath); } virtualServer.setDefaultContextPath(defaultContextPath); } catch (Exception e) { throw new LifecycleException(e); } } } } } /** * Utility Method to access the ServerContext */ public ServerContext getServerContext() { return _serverContext; } ServerConfigLookup getServerConfigLookup() { return serverConfigLookup; } File getLibPath() { return instance.getLibPath(); } /** * The application id for this web module * HERCULES:add */ public String getApplicationId(WebModule wm) { return wm.getID(); } /** * Return the Absolute path for location where all the deployed * standalone modules are stored for this Server Instance. */ public File getModulesRoot() { return _modulesRoot; } /** * Undeploy a web application. * * @param contextRoot the context's name to undeploy * @param appName the J2EE appname used at deployment time * @param virtualServers List of current virtual-server object. */ public void unloadWebModule(String contextRoot, String appName, String virtualServers, Properties props) { unloadWebModule(contextRoot, appName, virtualServers, false, props); } /** * Undeploy a web application. * * @param contextRoot the context's name to undeploy * @param appName the J2EE appname used at deployment time * @param virtualServers List of current virtual-server object. * @param dummy true if the web module to be undeployed is a dummy web * module, that is, a web module created off of a virtual server's * docroot */ public void unloadWebModule(String contextRoot, String appName, String virtualServers, boolean dummy, Properties props) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, LogFacade.LOADING_WEB_MODULE, new Object[]{contextRoot, virtualServers}); } // tomcat contextRoot starts with "/" if (contextRoot.length() != 0 && !contextRoot.startsWith("/")) { contextRoot = "/" + contextRoot; } else if ("/".equals(contextRoot)) { // Make corresponding change as in WebModuleConfig.getContextPath() contextRoot = ""; } List hostList = StringUtils.parseStringList(virtualServers, " ,"); boolean unloadFromAll = hostList == null || hostList.isEmpty(); boolean hasBeenUndeployed = false; VirtualServer host = null; WebModule context = null; Container[] hostArray = getEngine().findChildren(); for (Container aHostArray : hostArray) { host = (VirtualServer) aHostArray; if (unloadFromAll || hostList.contains(host.getName()) || verifyAlias(hostList, host)) { context = (WebModule) host.findChild(contextRoot); if (context != null && context.getWebBundleDescriptor().getApplication().getRegistrationName().equals(appName)) { context.saveSessions(props); host.removeChild(context); webStatsProviderBootstrap.unregisterApplicationStatsProviders( context.getMonitoringNodeName(), host.getName()); try { /* * If the webapp is being undeployed as part of a * domain shutdown, we don't want to destroy it, * as that would remove any sessions persisted to * file. Any active sessions need to survive the * domain shutdown, so that they may be resumed * after the domain has been restarted. */ if (!isShutdown) { context.destroy(); } } catch (Exception ex) { String msg = rb.getString(LogFacade.EXCEPTION_DURING_DESTROY); msg = MessageFormat.format(msg, contextRoot, host.getName()); logger.log(Level.WARNING, msg, ex); } if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, LogFacade.CONTEXT_UNDEPLOYED, new Object[]{contextRoot, host}); } hasBeenUndeployed = true; host.fireContainerEvent(Deployer.REMOVE_EVENT, context); /* * If the web module that has been unloaded * contained any mappings for ad-hoc paths, * those mappings must be preserved by registering an * ad-hoc web module at the same context root */ if (context.hasAdHocPaths() || context.hasAdHocSubtrees()) { WebModule wm = createAdHocWebModule( context.getID(), host, contextRoot, context.getJ2EEApplication()); wm.addAdHocPaths(context.getAdHocPaths()); wm.addAdHocSubtrees(context.getAdHocSubtrees()); } // START GlassFish 141 if (!dummy && !isShutdown) { WebModuleConfig wmInfo = host.createSystemDefaultWebModuleIfNecessary( habitat.getService( WebArchivist.class)); if (wmInfo != null) { loadStandaloneWebModule(host, wmInfo); } } // END GlassFish 141 } } } if (!hasBeenUndeployed) { logger.log(Level.SEVERE, LogFacade.UNDEPLOY_ERROR, contextRoot); } } /** * Suspends the web application with the given appName that has been * deployed at the given contextRoot on the given virtual servers. * * @param contextRoot the context root * @param appName the J2EE appname used at deployment time * @param hosts the list of virtual servers */ public boolean suspendWebModule(String contextRoot, String appName, String hosts) { boolean hasBeenSuspended = false; List hostList = StringUtils.parseStringList(hosts, " ,"); if (hostList == null || hostList.isEmpty()) { return hasBeenSuspended; } // tomcat contextRoot starts with "/" if (contextRoot.length() != 0 && !contextRoot.startsWith("/")) { contextRoot = "/" + contextRoot; } VirtualServer host = null; Context context = null; for (Container aHostArray : getEngine().findChildren()) { host = (VirtualServer) aHostArray; if (hostList.contains(host.getName()) || verifyAlias(hostList, host)) { context = (Context) host.findChild(contextRoot); if (context != null) { context.setAvailable(false); if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, LogFacade.CONTEXT_DISABLED, new Object[]{contextRoot, host}); } hasBeenSuspended = true; } } } if (!hasBeenSuspended) { logger.log(Level.WARNING, LogFacade.DISABLE_WEB_MODULE_ERROR, contextRoot); } return hasBeenSuspended; } /** * Save the server-wide dynamic reloading settings for use when * configuring each web module. */ private void configureDynamicReloadingSettings() { if (dasConfig != null) { _reloadingEnabled = Boolean.parseBoolean(dasConfig.getDynamicReloadEnabled()); String seconds = dasConfig.getDynamicReloadPollIntervalInSeconds(); if (seconds != null) { try { _pollInterval = Integer.parseInt(seconds); } catch (NumberFormatException e) { } } } } /** * Sets the debug level for Catalina's containers based on the logger's * log level. */ private void setDebugLevel() { Level logLevel = logger.getLevel() != null ? logger.getLevel() : Level.INFO; if (logLevel.equals(Level.FINE)) _debug = 1; else if (logLevel.equals(Level.FINER)) _debug = 2; else if (logLevel.equals(Level.FINEST)) _debug = 5; else _debug = 0; } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return new LifecycleListener[0]; } /** * Gets all the virtual servers whose http-listeners attribute value * contains the given http-listener id. */ List getVirtualServersForHttpListenerId( HttpService httpService, String httpListenerId) { if (httpListenerId == null) { return null; } List result = new ArrayList(); for (com.sun.enterprise.config.serverbeans.VirtualServer vs : httpService.getVirtualServer()) { List listeners = StringUtils.parseStringList(vs.getNetworkListeners(), ","); if (listeners != null) { ListIterator iter = listeners.listIterator(); while (iter.hasNext()) { if (httpListenerId.equals(iter.next())) { VirtualServer match = (VirtualServer) getEngine().findChild(vs.getId()); if (match != null) { result.add(match); } break; } } } } return result; } /** * Adds the given mime mappings to those of the specified context, unless * they're already present in the context (that is, the mime mappings of * the specified context, which correspond to those in default-web.xml, * can't be overridden). * * @param ctx The StandardContext to whose mime mappings to add * @param mimeMap The mime mappings to be added */ private void addMimeMappings(StandardContext ctx, MimeMap mimeMap) { if (mimeMap == null) { return; } for (Iterator itr = mimeMap.getExtensions(); itr.hasNext();) { String extension = itr.next(); if (ctx.findMimeMapping(extension) == null) { ctx.addMimeMapping(extension, mimeMap.getType(extension)); } } } /** * Return the parent/top-level container in _embedded for virtual * servers. */ public Engine getEngine() { return _embedded.getEngines()[0]; } public HttpService getHttpService() { return serverConfig.getHttpService(); } /** * Registers the given ad-hoc path at the given context root. * * @param path The ad-hoc path to register * @param ctxtRoot The context root at which to register * @param appName The name of the application with which the ad-hoc path is * associated * @param servletInfo Info about the ad-hoc servlet that will service * requests on the given path */ public void registerAdHocPath( String path, String ctxtRoot, String appName, AdHocServletInfo servletInfo) { registerAdHocPathAndSubtree(path, null, ctxtRoot, appName, servletInfo); } /** * Registers the given ad-hoc path and subtree at the given context root. * * @param path The ad-hoc path to register * @param subtree The ad-hoc subtree path to register * @param ctxtRoot The context root at which to register * @param appName The name of the application with which the ad-hoc path * and subtree are associated * @param servletInfo Info about the ad-hoc servlet that will service * requests on the given ad-hoc path and subtree */ public void registerAdHocPathAndSubtree( String path, String subtree, String ctxtRoot, String appName, AdHocServletInfo servletInfo) { WebModule wm = null; Container[] vsList = getEngine().findChildren(); for (Container aVsList : vsList) { VirtualServer vs = (VirtualServer) aVsList; if (vs.getName().equalsIgnoreCase( org.glassfish.api.web.Constants.ADMIN_VS)) { // Do not deploy on admin vs continue; } wm = (WebModule) vs.findChild(ctxtRoot); if (wm == null) { wm = createAdHocWebModule(vs, ctxtRoot, appName); } wm.addAdHocPathAndSubtree(path, subtree, servletInfo); } } /** * Unregisters the given ad-hoc path from the given context root. * * @param path The ad-hoc path to unregister * @param ctxtRoot The context root from which to unregister */ public void unregisterAdHocPath(String path, String ctxtRoot) { unregisterAdHocPathAndSubtree(path, null, ctxtRoot); } /** * Unregisters the given ad-hoc path and subtree from the given context * root. * * @param path The ad-hoc path to unregister * @param subtree The ad-hoc subtree to unregister * @param ctxtRoot The context root from which to unregister */ public void unregisterAdHocPathAndSubtree(String path, String subtree, String ctxtRoot) { WebModule wm = null; Container[] vsList = getEngine().findChildren(); for (Container aVsList : vsList) { VirtualServer vs = (VirtualServer) aVsList; if (vs.getName().equalsIgnoreCase( org.glassfish.api.web.Constants.ADMIN_VS)) { // Do not undeploy from admin vs, because we never // deployed onto it continue; } wm = (WebModule) vs.findChild(ctxtRoot); if (wm == null) { continue; } /* * If the web module was created by the container for the * sole purpose of mapping ad-hoc paths and subtrees, * and does no longer contain any ad-hoc paths or subtrees, * remove the web module. */ wm.removeAdHocPath(path); wm.removeAdHocSubtree(subtree); if (wm instanceof AdHocWebModule && !wm.hasAdHocPaths() && !wm.hasAdHocSubtrees()) { vs.removeChild(wm); try { wm.destroy(); } catch (Exception ex) { String msg = rb.getString(LogFacade.EXCEPTION_DURING_DESTROY); msg = MessageFormat.format(msg, wm.getPath(), vs.getName()); logger.log(Level.WARNING, msg, ex); } } } } /* * Creates an ad-hoc web module and registers it on the given virtual * server at the given context root. * * @param vs The virtual server on which to add the ad-hoc web module * @param ctxtRoot The context root at which to register the ad-hoc * web module * @param appName The name of the application to which the ad-hoc module * being generated belongs * * @return The newly created ad-hoc web module */ private WebModule createAdHocWebModule( VirtualServer vs, String ctxtRoot, String appName) { return createAdHocWebModule(appName, vs, ctxtRoot, appName); } /* * Creates an ad-hoc web module and registers it on the given virtual * server at the given context root. * * @param id the id of the ad-hoc web module * @param vs The virtual server on which to add the ad-hoc web module * @param ctxtRoot The context root at which to register the ad-hoc * web module * @param appName The name of the application to which the ad-hoc module * being generated belongs * * @return The newly created ad-hoc web module */ private WebModule createAdHocWebModule( String id, VirtualServer vs, String ctxtRoot, String j2eeApplication) { AdHocWebModule wm = new AdHocWebModule(); wm.setID(id); wm.setWebContainer(this); wm.restrictedSetPipeline(new WebPipeline(wm)); // The Parent ClassLoader of the AdhocWebModule was null // [System ClassLoader]. With the new hierarchy, the thread context // classloader needs to be set. //if (Boolean.getBoolean(com.sun.enterprise.server.PELaunch.USE_NEW_CLASSLOADER_PROPERTY)) { wm.setParentClassLoader( Thread.currentThread().getContextClassLoader()); //} wm.setContextRoot(ctxtRoot); wm.setJ2EEApplication(j2eeApplication); wm.setName(ctxtRoot); wm.setDocBase(vs.getAppBase()); wm.setEngineName(vs.getParent().getName()); String domain = _serverContext.getDefaultDomainName(); wm.setDomain(domain); String j2eeServer = _serverContext.getInstanceName(); wm.setJ2EEServer(j2eeServer); wm.setCrossContext(true); //wm.setJavaVMs(J2EEModuleUtil.getjavaVMs()); vs.addChild(wm); return wm; } /** * Removes the dummy module (the module created off of a virtual server's * docroot) from the given virtual server if such a module exists. * * @param vs The virtual server whose dummy module is to be removed */ void removeDummyModule(VirtualServer vs) { WebModule ctx = (WebModule) vs.findChild(""); if (ctx != null && Constants.DEFAULT_WEB_MODULE_NAME.equals( ctx.getModuleName())) { unloadWebModule("", ctx.getWebBundleDescriptor().getApplication().getRegistrationName(), vs.getName(), true, null); } } /** * Initializes the instance-level session properties (read from * config.web-container.session-config.session-properties in domain.xml). */ private void initInstanceSessionProperties() { SessionProperties spBean = serverConfigLookup.getInstanceSessionProperties(); if (spBean == null || spBean.getProperty() == null) { return; } List props = spBean.getProperty(); if (props == null) { return; } for (Property prop : props) { String propName = prop.getName(); String propValue = prop.getValue(); if (propName == null || propValue == null) { throw new IllegalArgumentException( rb.getString(LogFacade.NULL_WEB_PROPERTY)); } if (propName.equalsIgnoreCase("enableCookies")) { instanceEnableCookies = ConfigBeansUtilities.toBoolean(propValue); } else if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LogFacade.PROPERTY_NOT_YET_SUPPORTED, propName); } } } private static synchronized void setJspFactory() { if (JspFactory.getDefaultFactory() == null) { JspFactory.setDefaultFactory(new JspFactoryImpl()); } } /** * Delete virtual-server. * * @param httpService element which contains the configuration info. */ public void deleteHost(HttpService httpService) throws LifecycleException { VirtualServer virtualServer; // First we need to find which virtual-server was deleted. In // reconfig/VirtualServerReconfig, it is impossible to lookup // the vsBean because the element is removed from domain.xml // before handleDelete is invoked. Container[] virtualServers = getEngine().findChildren(); for (int i = 0; i < virtualServers.length; i++) { for (com.sun.enterprise.config.serverbeans.VirtualServer vse : httpService.getVirtualServer()) { if (virtualServers[i].getName().equals(vse.getId())) { virtualServers[i] = null; break; } } } for (Container virtualServer1 : virtualServers) { virtualServer = (VirtualServer) virtualServer1; if (virtualServer != null) { if (virtualServer.getID().equals( org.glassfish.api.web.Constants.ADMIN_VS)) { throw new LifecycleException( "Cannot delete admin virtual-server."); } Container[] webModules = virtualServer.findChildren(); for (Container webModule : webModules) { String appName = webModule.getName(); if (webModule instanceof WebModule) { appName = ((WebModule)webModule).getWebBundleDescriptor().getApplication().getRegistrationName(); } unloadWebModule(webModule.getName(), appName, virtualServer.getID(), null); } try { virtualServer.destroy(); } catch (Exception e) { String msg = rb.getString(LogFacade.DESTROY_VS_ERROR); msg = MessageFormat.format(msg, virtualServer.getID()); logger.log(Level.WARNING, msg, e); } } } } /** * Updates a virtual-server element. * * @param vsBean the virtual-server config bean. */ public void updateHost(com.sun.enterprise.config.serverbeans.VirtualServer vsBean) throws LifecycleException { if (org.glassfish.api.web.Constants.ADMIN_VS.equals(vsBean.getId())) { return; } final VirtualServer vs = (VirtualServer) getEngine().findChild(vsBean.getId()); if (vs == null) { logger.log(Level.WARNING, LogFacade.CANNOT_UPDATE_NON_EXISTENCE_VS, vsBean.getId()); return; } boolean updateListeners = false; // Only update connectors if virtual-server.http-listeners is changed dynamically if (vs.getNetworkListeners() == null) { if (vsBean.getNetworkListeners() == null) { updateListeners = false; } else { updateListeners = true; } } else if (vs.getNetworkListeners().equals(vsBean.getNetworkListeners())) { updateListeners = false; } else { List vsList = StringUtils.parseStringList( vs.getNetworkListeners(), ","); List vsBeanList = StringUtils.parseStringList( vsBean.getNetworkListeners(), ","); for (String vsBeanName : vsBeanList) { if (!vsList.contains(vsBeanName)) { updateListeners = true; if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.UPDATE_LISTENER, new Object[]{vsBeanName, vs.getNetworkListeners()}); } break; } } } // Must retrieve the old default-web-module before updating the // virtual server with the new vsBean, because default-web-module is // read from vsBean String oldDefaultWebModule = vs.getDefaultWebModuleID(); vs.setBean(vsBean); String vsLogFile = vsBean.getLogFile(); vs.setLogFile(vsLogFile, logLevel, logServiceFile); vs.configureState(); vs.clearAliases(); vs.configureAliases(); // support both docroot property and attribute String docroot = vsBean.getPropertyValue("docroot"); if (docroot == null) { docroot = vsBean.getDocroot(); } if (docroot != null) { // Only update docroot if it is modified if (!vs.getDocRoot().getAbsolutePath().equals(docroot)) { updateDocroot(docroot, vs, vsBean); } } List props = vs.getProperties(); for (Property prop : props) { updateHostProperties(vsBean, prop.getName(), prop.getValue(), securityService, vs); } vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled()); vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); // old listener names List oldListenerList = StringUtils.parseStringList( vsBean.getNetworkListeners(), ","); String[] oldListeners = (oldListenerList != null) ? oldListenerList.toArray(new String[oldListenerList.size()]) : new String[0]; // new listener config HashSet networkListeners = new HashSet(); if (oldListenerList != null) { for (String listener : oldListeners) { boolean found = false; for (NetworkListener httpListener : serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener()) { if (httpListener.getName().equals(listener)) { networkListeners.add(httpListener); found = true; break; } } if (!found) { String msg = rb.getString(LogFacade.LISTENER_REFERENCED_BY_HOST_NOT_EXIST); msg = MessageFormat.format(msg, listener, vs.getName()); logger.log(Level.SEVERE, msg); } } // Update the port numbers with which the virtual server is // associated configureHostPortNumbers(vs, networkListeners); } else { // The virtual server is not associated with any http listeners vs.setNetworkListenerNames(new String[0]); } // Disassociate the virtual server from all http listeners that // have been removed from its http-listeners attribute for (String oldListener : oldListeners) { boolean found = false; for (NetworkListener httpListener : networkListeners) { if (httpListener.getName().equals(oldListener)) { found = true; } } if (!found) { // http listener was removed Connector[] connectors = _embedded.findConnectors(); for (Connector connector : connectors) { WebConnector conn = (WebConnector) connector; if (oldListener.equals(conn.getName())) { try { conn.getMapperListener().unregisterHost( vs.getJmxName()); } catch (Exception e) { throw new LifecycleException(e); } } } } } // Associate the virtual server with all http listeners that // have been added to its http-listeners attribute for (NetworkListener httpListener : networkListeners) { boolean found = false; for (String oldListener : oldListeners) { if (httpListener.getName().equals(oldListener)) { found = true; } } if (!found) { // http listener was added Connector[] connectors = _embedded.findConnectors(); for (Connector connector : connectors) { WebConnector conn = (WebConnector) connector; if (httpListener.getName().equals(conn.getName())) { if (!conn.isAvailable()) { conn.start(); } try { conn.getMapperListener().registerHost(vs); } catch (Exception e) { throw new LifecycleException(e); } } } } } // Remove the old default web module if one was configured, by // passing in "null" as the default context path if (oldDefaultWebModule != null) { updateDefaultWebModule(vs, oldListeners, null); } /* * Add default web module if one has been configured for the * virtual server. If the module declared as the default web module * has already been deployed at the root context, we don't have * to do anything. */ WebModuleConfig wmInfo = vs.getDefaultWebModule(domain, habitat.getService(WebArchivist.class), appRegistry); if ((wmInfo != null) && (wmInfo.getContextPath() != null) && !"".equals(wmInfo.getContextPath()) && !"/".equals(wmInfo.getContextPath())) { // Remove dummy context that was created off of docroot, if such // a context exists removeDummyModule(vs); updateDefaultWebModule(vs, vs.getNetworkListenerNames(), wmInfo); } else { WebModuleConfig wmc = vs.createSystemDefaultWebModuleIfNecessary( habitat.getService(WebArchivist.class)); if (wmc != null) { loadStandaloneWebModule(vs, wmc); } } if (updateListeners) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.VS_UPDATED_NETWORK_LISTENERS, new Object[]{vs.getName(), vs.getNetworkListeners(), vsBean.getNetworkListeners()}); } /* * Need to update connector and mapper restart is required * when virtual-server.http-listeners is changed dynamically */ List httpListeners = serverConfig.getNetworkConfig().getNetworkListeners().getNetworkListener(); if (httpListeners != null) { for (NetworkListener httpListener : httpListeners) { updateConnector(httpListener, habitat.getService(HttpService.class)); } } } } /** * Update virtual-server properties. */ public void updateHostProperties( com.sun.enterprise.config.serverbeans.VirtualServer vsBean, String name, String value, SecurityService securityService, final VirtualServer vs) { if (vs == null) { return; } vs.setBean(vsBean); if (name == null) { return; } if (name.startsWith("alternatedocroot_")) { updateAlternateDocroot(vs); } else if ("setCacheControl".equals(name)) { vs.configureCacheControl(value); } else if (Constants.ACCESS_LOGGING_ENABLED.equals(name)) { vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); } else if (Constants.ACCESS_LOG_PROPERTY.equals(name)) { vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); } else if (Constants.ACCESS_LOG_WRITE_INTERVAL_PROPERTY.equals(name)) { vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); } else if (Constants.ACCESS_LOG_BUFFER_SIZE_PROPERTY.equals(name)) { vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); } else if ("allowRemoteHost".equals(name) || "denyRemoteHost".equals(name)) { vs.configureRemoteHostFilterValve(); } else if ("allowRemoteAddress".equals(name) || "denyRemoteAddress".equals(name)) { vs.configureRemoteAddressFilterValve(); } else if (Constants.SSO_ENABLED.equals(name)) { vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled()); } else if ("authRealm".equals(name)) { vs.configureAuthRealm(securityService); } else if (name.startsWith("send-error")) { vs.configureErrorPage(); } else if (Constants.ERROR_REPORT_VALVE.equals(name)) { vs.setErrorReportValveClass(value); } else if (name.startsWith("redirect")) { vs.configureRedirect(); } else if (name.startsWith("contextXmlDefault")) { vs.setDefaultContextXmlLocation(value); } } private boolean isSsoFailoverEnabled() { boolean webContainerAvailabilityEnabled = serverConfigLookup.calculateWebAvailabilityEnabledFromConfig(); boolean isSsoFailoverEnabled = serverConfigLookup.isSsoFailoverEnabledFromConfig(); return isSsoFailoverEnabled && webContainerAvailabilityEnabled; } /** * Processes an update to the http-service element */ public void updateHttpService(HttpService httpService) throws LifecycleException { if (httpService == null) { return; } /* * Update each virtual server with the sso-enabled and * access logging related properties of the updated http-service */ globalSSOEnabled = ConfigBeansUtilities.toBoolean(httpService.getSsoEnabled()); globalAccessLogWriteInterval = httpService.getAccessLog().getWriteIntervalSeconds(); globalAccessLogBufferSize = httpService.getAccessLog().getBufferSizeBytes(); globalAccessLoggingEnabled = ConfigBeansUtilities.toBoolean(httpService.getAccessLoggingEnabled()); // for availability-service.web-container-availability webContainerFeatureFactory = getWebContainerFeatureFactory(); List virtualServers = httpService.getVirtualServer(); for (com.sun.enterprise.config.serverbeans.VirtualServer virtualServer : virtualServers) { final VirtualServer vs = (VirtualServer) getEngine().findChild(virtualServer.getId()); if (vs != null) { vs.configureSingleSignOn(globalSSOEnabled, webContainerFeatureFactory, isSsoFailoverEnabled()); vs.reconfigureAccessLog(globalAccessLogBufferSize, globalAccessLogWriteInterval, habitat, domain, globalAccessLoggingEnabled); updateHost(virtualServer); } } } /** * Update an http-listener property * * @param listener the configuration bean. * @param propName the property name * @param propValue the property value */ public void updateConnectorProperty(NetworkListener listener, String propName, String propValue) throws LifecycleException { WebConnector connector = connectorMap.get(listener.getName()); if (connector != null) { connector.configHttpProperties(listener.findHttpProtocol().getHttp(), listener.findTransport(), listener.findHttpProtocol().getSsl()); connector.configureHttpListenerProperty(propName, propValue); } } /** * Update an network-listener * * @param httpService the configuration bean. */ public void updateConnector(NetworkListener networkListener, HttpService httpService) throws LifecycleException { synchronized (mapperUpdateSync) { // Disable dynamic reconfiguration of the http listener at which // the admin related webapps (including the admingui) are accessible. // Notice that in GlassFish v3, we support a domain.xml configuration // that does not declare any admin-listener, in which case the // admin-related webapps are accessible on http-listener-1. if (networkListener.findHttpProtocol().getHttp().getDefaultVirtualServer().equals( org.glassfish.api.web.Constants.ADMIN_VS) || "http-listener-1".equals(networkListener.getName()) && connectorMap.get("admin-listener") == null) { return; } WebConnector connector = connectorMap.get(networkListener.getName()); if (connector != null) { deleteConnector(connector); } if (!Boolean.valueOf(networkListener.getEnabled())) { return; } connector = addConnector(networkListener, httpService, false); // Update the list of listener names of all associated virtual servers with // the listener's new listener name , so that the associated virtual // servers will be registered with the listener's request mapper when // the listener is started List virtualServers = getVirtualServersForHttpListenerId(httpService, networkListener.getName()); if (virtualServers != null) { for (VirtualServer vs : virtualServers) { boolean found = false; String[] listenerNames = vs.getNetworkListenerNames(); String name = connector.getName(); for (String listenerName : listenerNames) { if (listenerName.equals(name)) { found = true; break; } } if (!found) { String[] newListenerNames = new String[listenerNames.length + 1]; System.arraycopy(listenerNames, 0, newListenerNames, 0, listenerNames.length); newListenerNames[listenerNames.length] = connector.getName(); vs.setNetworkListenerNames(newListenerNames); } } } connector.start(); // GLASSFISH-20932 // Check if virtual server has default-web-module configured, // and if so, configure the http listener's mapper with this // information if (virtualServers != null) { Mapper mapper = connector.getMapper(); for (VirtualServer vs : virtualServers) { String defaultWebModulePath = vs.getDefaultContextPath( domain, appRegistry); if (defaultWebModulePath != null) { try { mapper.setDefaultContextPath(vs.getName(), defaultWebModulePath); vs.setDefaultContextPath(defaultWebModulePath); } catch (Exception e) { throw new LifecycleException(e); } } } } } } /** * Method gets called, when GrizzlyService changes HTTP Mapper, associated * with specific port. * * @param httpService {@link HttpService} * @param httpListener {@link NetworkListener}, which {@link Mapper} was changed * @param mapper new {@link Mapper} value */ public void updateMapper(HttpService httpService, NetworkListener httpListener, Mapper mapper) { synchronized (mapperUpdateSync) { WebConnector connector = connectorMap.get(httpListener.getName()); if (connector != null && connector.getMapper() != mapper) { try { updateConnector(httpListener, httpService); } catch (LifecycleException le) { logger.log(Level.SEVERE, LogFacade.EXCEPTION_CONFIG_HTTP_SERVICE, le); } } } } public WebConnector addConnector(NetworkListener httpListener, HttpService httpService, boolean start) throws LifecycleException { synchronized (mapperUpdateSync) { int port = Integer.parseInt(httpListener.getPort()); // Add the listener name of the new http-listener to its // default-virtual-server, so that when the new http-listener // and its MapperListener are started, they will recognize the // default-virtual-server as one of their own, and add it to the // Mapper String virtualServerName = httpListener.findHttpProtocol().getHttp().getDefaultVirtualServer(); VirtualServer vs = (VirtualServer) getEngine().findChild(virtualServerName); List list = Arrays.asList(vs.getNetworkListenerNames()); // Avoid adding duplicate network-listener name if (!list.contains(httpListener.getName())) { String[] oldListenerNames = vs.getNetworkListenerNames(); String[] newListenerNames = new String[oldListenerNames.length + 1]; System.arraycopy(oldListenerNames, 0, newListenerNames, 0, oldListenerNames.length); newListenerNames[oldListenerNames.length] = httpListener.getName(); vs.setNetworkListenerNames(newListenerNames); } Mapper mapper = null; for (Mapper m : habitat.getAllServices(Mapper.class)) { if (m.getPort() == port && m instanceof ContextMapper) { ContextMapper cm = (ContextMapper) m; if (httpListener.getName().equals(cm.getId())) { mapper = m; break; } } } WebConnector connector = createHttpListener(httpListener, httpService, mapper); if (connector.getRedirectPort() == -1) { connector.setRedirectPort(defaultRedirectPort); } if (start) { connector.start(); } return connector; } } /** * Stops and deletes the specified http listener. */ public void deleteConnector(WebConnector connector) throws LifecycleException { String name = connector.getName(); Connector[] connectors = _embedded.findConnectors(); for (Connector conn : connectors) { if (name.equals(conn.getName())) { _embedded.removeConnector(conn); connectorMap.remove(connector.getName()); } } } /** * Stops and deletes the specified http listener. */ public void deleteConnector(NetworkListener httpListener) throws LifecycleException { Connector[] connectors = _embedded.findConnectors(); String name = httpListener.getName(); for (Connector conn : connectors) { if (name.equals(conn.getName())) { _embedded.removeConnector(conn); connectorMap.remove(name); } } } /** * Reconfigures the access log valve of each virtual server with the * updated attributes of the element from domain.xml. */ public void updateAccessLog(HttpService httpService) { Container[] virtualServers = getEngine().findChildren(); for (Container virtualServer : virtualServers) { ((VirtualServer) virtualServer).reconfigureAccessLog( httpService, webContainerFeatureFactory); } } /** * Updates the docroot of the given virtual server */ private void updateDocroot( String docroot, VirtualServer vs, com.sun.enterprise.config.serverbeans.VirtualServer vsBean) { validateDocroot(docroot, vsBean.getId(), vsBean.getDefaultWebModule()); vs.setAppBase(docroot); removeDummyModule(vs); WebModuleConfig wmInfo = vs.createSystemDefaultWebModuleIfNecessary( habitat.getService(WebArchivist.class)); if (wmInfo != null) { loadStandaloneWebModule(vs, wmInfo); } } private void updateAlternateDocroot(VirtualServer vs) { removeDummyModule(vs); WebModuleConfig wmInfo = vs.createSystemDefaultWebModuleIfNecessary( habitat.getService(WebArchivist.class)); if (wmInfo != null) { loadStandaloneWebModule(vs, wmInfo); } } public void updateJvmRoute(HttpService httpService, String jvmOption) { String jvmRoute = null; if (jvmOption.contains("{") && jvmOption.contains("}")) { // Look up system-property jvmOption = jvmOption.substring(jvmOption.indexOf("{")+1,jvmOption.indexOf("}")); jvmRoute = server.getSystemPropertyValue(jvmOption); if (jvmRoute == null){ // Try to get it from System property if it exists jvmRoute = System.getProperty(jvmOption); } } else if (jvmOption.contains("=")) { jvmRoute = jvmOption.substring(jvmOption.indexOf("=")+1); } engine.setJvmRoute(jvmRoute); for (com.sun.enterprise.config.serverbeans.VirtualServer vsBean : httpService.getVirtualServer()) { VirtualServer vs = (VirtualServer) engine.findChild(vsBean.getId()); for (Container context : vs.findChildren()) { if (context instanceof StandardContext) { ((StandardContext)context).setJvmRoute(jvmRoute); } } } for (Connector connector : _embedded.getConnectors()) { connector.setJvmRoute(jvmRoute); } if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, LogFacade.JVM_ROUTE_UPDATED, jvmRoute); } } /** * is Tomcat using default domain name as its domain */ protected boolean isTomcatUsingDefaultDomain() { // need to be careful and make sure tomcat jmx mapping works // since setting this to true might result in undeployment problems return true; } /** * Creates probe providers for Servlet, JSP, Session, and * Request/Response related events. *

* While the Servlet, JSP, and Session related probe providers are * shared by all web applications (where every web application * qualifies its probe events with its application name), the * Request/Response related probe provider is shared by all HTTP * listeners. */ private void createProbeProviders() { webModuleProbeProvider = new WebModuleProbeProvider(); servletProbeProvider = new ServletProbeProvider(); jspProbeProvider = new JspProbeProvider(); sessionProbeProvider = new SessionProbeProvider(); requestProbeProvider = new RequestProbeProvider(); } /** * Creates statistics providers for Servlet, JSP, Session, and * Request/Response related events. */ private void createStatsProviders() { httpStatsProviderBootstrap = habitat.getService(HttpServiceStatsProviderBootstrap.class); webStatsProviderBootstrap = habitat.getService(WebStatsProviderBootstrap.class); } /* * Loads the class with the given name using the common classloader, * which is responsible for loading any classes from the domain's * lib directory * * @param className the name of the class to load */ public Class loadCommonClass(String className) throws Exception { return clh.getCommonClassLoader().loadClass(className); } /** * According to SRV 15.5.15, Servlets, Filters, Listeners can only be * without any scope annotation or are annotated with * * @Dependent scope. All other scopes are invalid and must be rejected. */ private void validateJSR299Scope(Class clazz) { if (jcdiService != null && jcdiService.isCDIScoped(clazz)) { String msg = rb.getString(LogFacade.INVALID_ANNOTATION_SCOPE); msg = MessageFormat.format(msg, clazz.getName()); throw new IllegalArgumentException(msg); } } /** * Return the WebContainerFeatureFactory according to the configuration. * @return WebContainerFeatuerFactory */ private WebContainerFeatureFactory getWebContainerFeatureFactory() { String featureFactoryName = (serverConfigLookup.calculateWebAvailabilityEnabledFromConfig() ? "ha" : "pe"); return webContainerFeatureFactory = habitat.getService( WebContainerFeatureFactory.class, featureFactoryName); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy