/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.enterprise.web; import com.sun.appserv.web.cache.CacheManager; import com.sun.enterprise.container.common.spi.JCDIService; import com.sun.enterprise.deployment.WebBundleDescriptor; import com.sun.enterprise.deployment.WebComponentDescriptor; import com.sun.enterprise.deployment.runtime.web.SunWebApp; import com.sun.enterprise.deployment.web.InitializationParameter; import com.sun.enterprise.util.net.JarURIPattern; import com.sun.enterprise.web.jsp.JspProbeEmitterImpl; import com.sun.enterprise.web.jsp.ResourceInjectorImpl; import org.apache.catalina.*; import org.glassfish.api.invocation.InvocationManager; import org.glassfish.api.web.TldProvider; import org.glassfish.logging.annotation.LogMessageInfo; import org.glassfish.web.deployment.runtime.WebProperty; import org.glassfish.web.deployment.runtime.SunWebAppImpl; import org.glassfish.web.deployment.util.WebValidatorWithCL; import org.glassfish.loader.util.ASClassLoaderUtil; import org.glassfish.hk2.api.ServiceLocator; import javax.naming.NamingException; import javax.servlet.ServletContext; import java.net.URI; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import java.util.StringTokenizer; import java.util.regex.Pattern; //import com.sun.enterprise.server.PersistenceUnitLoaderImpl; //import com.sun.enterprise.server.PersistenceUnitLoader; //import com.sun.enterprise.config.ConfigException; /** * Startup event listener for a <b>Context</b> that configures the properties * of that Jsp Servlet from sun-web.xml */ final class WebModuleListener implements LifecycleListener { /** * The logger used to log messages */ private static final Logger _logger = com.sun.enterprise.web.WebContainer.logger; @LogMessageInfo( message = "Lifecycle event data object [{0}] is not a WebModule", level = "WARNING") public static final String CLASS_CAST_EXCEPTION = "AS-WEB-GLUE-00259"; @LogMessageInfo( message = "jsp-config property for {0} ", level = "FINE") public static final String JSP_CONFIG_PROPERTY = "AS-WEB-GLUE-00260"; @LogMessageInfo( message = "sysClasspath for {0} ", level = "FINE") public static final String SYS_CLASSPATH = "AS-WEB-GLUE-00261"; @LogMessageInfo( message = "Error creating cache manager and configuring the servlet caching subsystem", level = "WARNING") public static final String CACHE_MRG_EXCEPTION = "AS-WEB-GLUE-00262"; @LogMessageInfo( message = "Cache Manager started", level = "FINE") public static final String CACHE_MANAGER_STARTED = "AS-WEB-GLUE-00263"; @LogMessageInfo( message = "Cache Manager stopped", level = "FINE") public static final String CACHE_MANAGER_STOPPED = "AS-WEB-GLUE-00264"; /** * Descriptor object associated with this web application. * Used for loading persistence units. */ private WebBundleDescriptor wbd; private WebContainer webContainer; /** * Constructor. * * @param webContainer * @param explodedLocation The location where this web module is exploded * @param wbd descriptor for this module. */ public WebModuleListener(WebContainer webContainer, WebBundleDescriptor wbd) { this.webContainer = webContainer; this.wbd = wbd; } /** * Process the START event for an associated WebModule * @param event The lifecycle event that has occurred */ public void lifecycleEvent(LifecycleEvent event) { // Identify the context we are associated with WebModule webModule; try { webModule = (WebModule) event.getLifecycle(); } catch (ClassCastException e) { _logger.log(Level.WARNING, CLASS_CAST_EXCEPTION, event.getLifecycle()); return; } // Process the event that has occurred if (event.getType().equals(Lifecycle.START_EVENT)) { // post processing DOL object for standalone web module if (wbd != null && wbd.getApplication() != null && wbd.getApplication().isVirtual()) { wbd.setClassLoader(webModule.getLoader().getClassLoader()); wbd.visit(new WebValidatorWithCL()); } //loadPersistenceUnits(webModule); configureDefaultServlet(webModule); configureJsp(webModule); startCacheManager(webModule); } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { //unloadPersistenceUnits(webModule); stopCacheManager(webModule); } } //------------------------------------------------------- Private Methods /** * Configure all JSP related aspects of the web module, including * any relevant TLDs as well as the jsp config settings of the * JspServlet (using the values from sun-web.xml's jsp-config). */ private void configureJsp(WebModule webModule) { ServletContext servletContext = webModule.getServletContext(); servletContext.setAttribute( "org.glassfish.jsp.isStandaloneWebapp", Boolean.valueOf(webModule.isStandalone())); // Find tld URI and set it to ServletContext attribute List<URI> appLibUris = webModule.getDeployAppLibs(); Map<URI, List<String>> appLibTldMap = new HashMap<URI, List<String>>(); if (appLibUris != null && appLibUris.size() > 0) { Pattern pattern = Pattern.compile("META-INF/.*\\.tld"); for (URI uri : appLibUris) { List<String> entries = JarURIPattern.getJarEntries(uri, pattern); if (entries != null && entries.size() > 0) { appLibTldMap.put(uri, entries); } } } Collection<TldProvider> tldProviders = webContainer.getTldProviders(); Map<URI, List<String>> tldMap = new HashMap<URI, List<String>>(); for (TldProvider tldProvider : tldProviders) { // Skip any JSF related TLDs for non-JSF apps if ("jsfTld".equals(tldProvider.getName()) && !webModule.isJsfApplication()) { continue; } Map<URI, List<String>> tmap = tldProvider.getTldMap(); if (tmap != null) { tldMap.putAll(tmap); } } tldMap.putAll(appLibTldMap); servletContext.setAttribute( "com.sun.appserv.tld.map", tldMap); /* * Discover all TLDs that are known to contain listener * declarations, and store the resulting map as a * ServletContext attribute */ Map<URI, List<String>> tldListenerMap = new HashMap<URI, List<String>>(); for (TldProvider tldProvider : tldProviders) { // Skip any JSF related TLDs for non-JSF apps if ("jsfTld".equals(tldProvider.getName()) && !webModule.isJsfApplication()) { continue; } Map<URI, List<String>> tmap = tldProvider.getTldListenerMap(); if (tmap != null) { tldListenerMap.putAll(tmap); } } tldListenerMap.putAll(appLibTldMap); servletContext.setAttribute( "com.sun.appserv.tldlistener.map", tldListenerMap); ServiceLocator defaultServices = webContainer.getServerContext().getDefaultServices(); // set services for jsf injection servletContext.setAttribute( Constants.HABITAT_ATTRIBUTE, defaultServices); SunWebAppImpl bean = webModule.getIasWebAppConfigBean(); // Find the default jsp servlet Wrapper wrapper = (Wrapper) webModule.findChild( org.apache.catalina.core.Constants.JSP_SERVLET_NAME); if (wrapper == null) { return; } if (webModule.getTldValidation()) { wrapper.addInitParameter("enableTldValidation", "true"); } if (bean != null && bean.getJspConfig() != null) { WebProperty[] props = bean.getJspConfig().getWebProperty(); for (int i = 0; i < props.length; i++) { String pname = props[i].getAttributeValue("name"); String pvalue = props[i].getAttributeValue("value"); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, JSP_CONFIG_PROPERTY, "[" + webModule.getID() + "] is [" + pname + "] = [" + pvalue + "]"); } wrapper.addInitParameter(pname, pvalue); } } // Override any log setting with the container wide logging level wrapper.addInitParameter("logVerbosityLevel",getJasperLogLevel()); ResourceInjectorImpl resourceInjector = new ResourceInjectorImpl( webModule); servletContext.setAttribute( "com.sun.appserv.jsp.resource.injector", resourceInjector); // START SJSAS 6311155 String sysClassPath = ASClassLoaderUtil.getModuleClassPath( (ServiceLocator) defaultServices, webModule.getID(), null ); // If the configuration flag usMyFaces is set, remove javax.faces.jar // from the system class path Boolean useMyFaces = (Boolean) servletContext.getAttribute("com.sun.faces.useMyFaces"); if (useMyFaces != null && useMyFaces) { sysClassPath = sysClassPath.replace("javax.faces.jar", "$disabled$.raj"); // jsf-connector.jar manifest has a Class-Path to javax.faces.jar sysClassPath = sysClassPath.replace("jsf-connector.jar", "$disabled$.raj"); } // TODO: combine with classpath from // servletContext.getAttribute(("org.apache.catalina.jsp_classpath") if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, SYS_CLASSPATH, webModule.getID() + " is " + sysClassPath); } if (sysClassPath.equals("")) { // In embedded mode, services returns SingleModulesRegistry and // it has no modules. // Try "java.class.path" system property instead. sysClassPath = System.getProperty("java.class.path"); } sysClassPath = trimSysClassPath(sysClassPath); wrapper.addInitParameter("com.sun.appserv.jsp.classpath", sysClassPath); // END SJSAS 6311155 // Configure JSP monitoring servletContext.setAttribute( "org.glassfish.jsp.monitor.probeEmitter", new JspProbeEmitterImpl(webModule)); // Pass BeanManager's ELResolver as ServletContext attribute // (see IT 11168) InvocationManager invocationMgr = webContainer.getInvocationManager(); WebComponentInvocation inv = new WebComponentInvocation(webModule); try { invocationMgr.preInvoke(inv); JCDIService jcdiService = defaultServices.getService(JCDIService.class); // JCDIService can be absent if weld integration is missing in the runtime, so check for null is needed. if (jcdiService != null && jcdiService.isCurrentModuleJCDIEnabled()) { jcdiService.setELResolver(servletContext); } } catch (NamingException e) { // Ignore } finally { invocationMgr.postInvoke(inv); } } private boolean includeInitialized; private List<String> includeJars; private void initIncludeJars() { if (includeInitialized) { return; } String includeJarsString = null;; for (WebComponentDescriptor wcd: wbd.getWebComponentDescriptors()) { if ("jsp".equals(wcd.getCanonicalName())) { InitializationParameter initp = wcd.getInitializationParameterByName("system-jar-includes"); if (initp != null) { includeJarsString = initp.getValue(); break; } } } includeInitialized = true; if (includeJarsString == null) { includeJars = null; return; } includeJars = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(includeJarsString); while (tokenizer.hasMoreElements()) { includeJars.add(tokenizer.nextToken()); } } private boolean included(String path) { for (String item: includeJars) { if (path.contains(item)) { return true; } } return false; } /* * Remove unnecessary system jars, to improve performance */ private String trimSysClassPath(String sysClassPath) { if (sysClassPath == null || sysClassPath.equals("")) { return ""; } initIncludeJars(); if (includeJars == null || includeJars.size() == 0) { // revert to previous behavior, i.e. no trimming return sysClassPath; } String sep = System.getProperty("path.separator"); StringBuilder ret = new StringBuilder(); StringTokenizer tokenizer = new StringTokenizer(sysClassPath, sep); String mySep = ""; while (tokenizer.hasMoreElements()) { String path = tokenizer.nextToken(); if (included(path)) { ret.append(mySep); ret.append(path); mySep = sep; } } return ret.toString(); } /** * Determine the debug setting for JspServlet based on the iAS log * level. */ private String getJasperLogLevel() { Level level = _logger.getLevel(); if (level == null ) return "warning"; if (level.equals(Level.WARNING)) return "warning"; else if (level.equals(Level.FINE)) return "information"; else if (level.equals(Level.FINER) || level.equals(Level.FINEST)) return "debug"; else return "warning"; } private void startCacheManager(WebModule webModule) { SunWebApp bean = webModule.getIasWebAppConfigBean(); // Configure the cache, cache-mapping and other settings if (bean != null) { CacheManager cm = null; try { cm = CacheModule.configureResponseCache(webModule, bean); } catch (Exception ee) { _logger.log(Level.WARNING, CACHE_MRG_EXCEPTION, ee); } if (cm != null) { try { // first start the CacheManager, if enabled cm.start(); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, CACHE_MANAGER_STARTED); } // set this manager as a context attribute so that // caching filters/tags can find it ServletContext ctxt = webModule.getServletContext(); ctxt.setAttribute(CacheManager.CACHE_MANAGER_ATTR_NAME, cm); } catch (LifecycleException ee) { _logger.log(Level.WARNING, ee.getMessage(), ee.getCause()); } } } } private void stopCacheManager(WebModule webModule) { ServletContext ctxt = webModule.getServletContext(); CacheManager cm = (CacheManager)ctxt.getAttribute( CacheManager.CACHE_MANAGER_ATTR_NAME); if (cm != null) { try { cm.stop(); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, CACHE_MANAGER_STOPPED); } ctxt.removeAttribute(CacheManager.CACHE_MANAGER_ATTR_NAME); } catch (LifecycleException ee) { _logger.log(Level.WARNING, ee.getMessage(), ee.getCause()); } } } /** * Configures the given web module's DefaultServlet with the * applicable web properties from sun-web.xml. */ private void configureDefaultServlet(WebModule webModule) { // Find the DefaultServlet Wrapper wrapper = (Wrapper)webModule.findChild("default"); if (wrapper == null) { return; } String servletClass = wrapper.getServletClassName(); if (servletClass == null || !servletClass.equals(Globals.DEFAULT_SERVLET_CLASS_NAME)) { return; } String fileEncoding = webModule.getFileEncoding(); if (fileEncoding != null) { wrapper.addInitParameter("fileEncoding", fileEncoding); } } }