| /* |
| * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.enterprise.web; |
| |
| import com.sun.enterprise.config.serverbeans.Application; |
| import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities; |
| import com.sun.enterprise.config.serverbeans.ServerTags; |
| import com.sun.enterprise.container.common.spi.util.JavaEEIOUtils; |
| import com.sun.enterprise.deployment.*; |
| import org.glassfish.web.deployment.annotation.handlers.ServletSecurityHandler; |
| import com.sun.enterprise.deployment.runtime.web.SunWebApp; |
| import com.sun.enterprise.deployment.web.*; |
| import com.sun.enterprise.security.integration.RealmInitializer; |
| import com.sun.enterprise.universal.GFBase64Decoder; |
| import com.sun.enterprise.universal.GFBase64Encoder; |
| import com.sun.enterprise.util.StringUtils; |
| import com.sun.enterprise.web.deploy.LoginConfigDecorator; |
| import com.sun.enterprise.web.pwc.PwcWebModule; |
| import com.sun.enterprise.web.session.PersistenceType; |
| import com.sun.enterprise.web.session.SessionCookieConfig; |
| import com.sun.web.security.RealmAdapter; |
| import org.apache.catalina.*; |
| import org.apache.catalina.Valve; |
| import org.apache.catalina.core.*; |
| import org.apache.catalina.deploy.FilterMaps; |
| import org.apache.catalina.loader.WebappLoader; |
| import org.apache.catalina.servlets.DefaultServlet; |
| import org.apache.catalina.session.StandardManager; |
| import org.apache.jasper.servlet.JspServlet; |
| import org.glassfish.api.deployment.DeploymentContext; |
| import org.glassfish.embeddable.web.Context; |
| import org.glassfish.embeddable.web.config.FormLoginConfig; |
| import org.glassfish.embeddable.web.config.LoginConfig; |
| import org.glassfish.embeddable.web.config.SecurityConfig; |
| import org.glassfish.embeddable.web.config.TransportGuarantee; |
| import org.glassfish.hk2.classmodel.reflect.Types; |
| import org.glassfish.internal.api.ServerContext; |
| import org.glassfish.security.common.Role; |
| import org.glassfish.web.LogFacade; |
| 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.deployment.descriptor.*; |
| import org.glassfish.web.deployment.runtime.CookieProperties; |
| import org.glassfish.web.deployment.runtime.LocaleCharsetInfo; |
| import org.glassfish.web.deployment.runtime.LocaleCharsetMap; |
| import org.glassfish.web.deployment.runtime.SessionConfig; |
| import org.glassfish.web.deployment.runtime.SessionManager; |
| import org.glassfish.web.deployment.runtime.SessionProperties; |
| import org.glassfish.web.deployment.runtime.SunWebAppImpl; |
| import org.glassfish.web.deployment.runtime.WebProperty; |
| import org.glassfish.web.loader.ServletContainerInitializerUtil; |
| import org.glassfish.web.valve.GlassFishValve; |
| import org.glassfish.hk2.api.ServiceLocator; |
| import org.jvnet.hk2.config.types.Property; |
| |
| |
| import jakarta.annotation.security.DeclareRoles; |
| import jakarta.annotation.security.RunAs; |
| import jakarta.servlet.*; |
| import jakarta.servlet.Servlet; |
| import jakarta.servlet.http.HttpUpgradeHandler; |
| import jakarta.servlet.annotation.MultipartConfig; |
| import jakarta.servlet.annotation.ServletSecurity; |
| import jakarta.servlet.http.HttpSession; |
| import java.io.*; |
| import java.lang.reflect.Method; |
| import java.net.*; |
| import java.text.MessageFormat; |
| import java.util.*; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| /** |
| * Class representing a web module for use by the Application Server. |
| */ |
| |
| public class WebModule extends PwcWebModule implements Context { |
| |
| // ----------------------------------------------------- Class Variables |
| |
| private static final Logger logger = LogFacade.getLogger(); |
| |
| protected static final ResourceBundle rb = logger.getResourceBundle(); |
| |
| private static final String ALTERNATE_FROM = "from="; |
| private static final String ALTERNATE_DOCBASE = "dir="; |
| |
| private static final GFBase64Encoder gfEncoder = new GFBase64Encoder(); |
| private static final GFBase64Decoder gfDecoder = new GFBase64Decoder(); |
| |
| private static final String WS_SERVLET_CONTEXT_LISTENER = |
| "com.sun.xml.ws.transport.http.servlet.WSServletContextListener"; |
| |
| // ----------------------------------------------------- Instance Variables |
| |
| // Object containing sun-web.xml information |
| private SunWebAppImpl iasBean = null; |
| |
| //locale-charset-info tag from sun-web.xml |
| private LocaleCharsetMap[] _lcMap = null; |
| |
| /** |
| * Is the default-web.xml parsed? |
| */ |
| private boolean hasBeenXmlConfigured = false; |
| |
| private WebContainer webContainer; |
| |
| private final Map<String,AdHocServletInfo> adHocPaths; |
| private boolean hasAdHocPaths; |
| |
| private final Map<String,AdHocServletInfo> adHocSubtrees; |
| private boolean hasAdHocSubtrees; |
| |
| private StandardPipeline adHocPipeline; |
| |
| // File encoding of static resources |
| private String fileEncoding; |
| |
| /** |
| * Cached findXXX results |
| */ |
| protected Object[] cachedFinds; |
| |
| private Application bean; |
| |
| private WebBundleDescriptor webBundleDescriptor; |
| |
| private boolean hasStarted = false; |
| private String compEnvId = null; |
| private ServerContext serverContext = null; |
| |
| private ServletProbeProvider servletProbeProvider = null; |
| private SessionProbeProvider sessionProbeProvider = null; |
| private WebModuleProbeProvider webModuleProbeProvider = null; |
| |
| private JavaEEIOUtils javaEEIOUtils; |
| |
| // The id of the parent container (i.e., virtual server) on which this |
| // web module was deployed |
| private String vsId; |
| |
| private String monitoringNodeName; |
| |
| private WebModuleConfig wmInfo; |
| |
| // true if standalone WAR, false if embedded in EAR file |
| private boolean isStandalone = true; |
| |
| private ServiceLocator services; |
| |
| /** |
| * Constructor. |
| */ |
| public WebModule() { |
| this(null); |
| } |
| |
| public WebModule(ServiceLocator services) { |
| super(); |
| this.services = services; |
| this.adHocPaths = new HashMap<String,AdHocServletInfo>(); |
| this.adHocSubtrees = new HashMap<String,AdHocServletInfo>(); |
| |
| this.adHocPipeline = new StandardPipeline(this); |
| this.adHocPipeline.setBasic(new AdHocContextValve(this)); |
| |
| notifyContainerListeners = false; |
| } |
| |
| |
| /** |
| * set the sun-web.xml config bean |
| */ |
| public void setIasWebAppConfigBean(SunWebAppImpl iasBean) { |
| this.iasBean = iasBean; |
| } |
| |
| /** |
| * gets the sun-web.xml config bean |
| */ |
| public SunWebAppImpl getIasWebAppConfigBean() { |
| return iasBean; |
| } |
| |
| /** |
| * Gets the web container in which this web module was loaded. |
| * |
| * @return the web container in which this web module was loaded |
| */ |
| public WebContainer getWebContainer() { |
| return webContainer; |
| } |
| |
| /** |
| * Sets the web container in which this web module was loaded. |
| * |
| */ |
| public void setWebContainer(WebContainer webContainer) { |
| this.webContainer = webContainer; |
| this.servletProbeProvider = webContainer.getServletProbeProvider(); |
| this.sessionProbeProvider = webContainer.getSessionProbeProvider(); |
| this.webModuleProbeProvider = |
| webContainer.getWebModuleProbeProvider(); |
| this.javaEEIOUtils = |
| webContainer.getJavaEEIOUtils(); |
| } |
| |
| public void setWebModuleConfig(WebModuleConfig wmInfo) { |
| this.wmInfo = wmInfo; |
| } |
| |
| public WebModuleConfig getWebModuleConfig() { |
| return wmInfo; |
| } |
| |
| void setMonitoringNodeName(String monitoringNodeName) { |
| this.monitoringNodeName = monitoringNodeName; |
| } |
| |
| public String getMonitoringNodeName() { |
| return monitoringNodeName; |
| } |
| |
| /** |
| * Sets the parameter encoding (i18n) info from web.xml and sun-web.xml. |
| */ |
| public void setI18nInfo() { |
| if (webBundleDescriptor != null) { |
| String reqEncoding = webBundleDescriptor.getRequestCharacterEncoding(); |
| if (reqEncoding != null) { |
| setRequestCharacterEncoding(reqEncoding); |
| } |
| String resEncoding = webBundleDescriptor.getResponseCharacterEncoding(); |
| if (resEncoding != null) { |
| setResponseCharacterEncoding(resEncoding); |
| } |
| } |
| |
| if (iasBean == null) { |
| return; |
| } |
| |
| if (iasBean.isParameterEncoding()) { |
| formHintField = iasBean.getAttributeValue( |
| SunWebApp.PARAMETER_ENCODING, |
| SunWebApp.FORM_HINT_FIELD); |
| defaultCharset = iasBean.getAttributeValue( |
| SunWebApp.PARAMETER_ENCODING, |
| SunWebApp.DEFAULT_CHARSET); |
| } |
| |
| LocaleCharsetInfo lcinfo = iasBean.getLocaleCharsetInfo(); |
| if (lcinfo != null) { |
| if (lcinfo.getAttributeValue( |
| LocaleCharsetInfo.DEFAULT_LOCALE) != null) { |
| logger.warning(LogFacade.DEFAULT_LOCALE_DEPRECATED); |
| } |
| /* |
| * <parameter-encoding> subelem of <sun-web-app> takes precedence |
| * over that of <locale-charset-info> |
| */ |
| if (lcinfo.isParameterEncoding() |
| && !iasBean.isParameterEncoding()) { |
| formHintField = lcinfo.getAttributeValue( |
| LocaleCharsetInfo.PARAMETER_ENCODING, |
| LocaleCharsetInfo.FORM_HINT_FIELD); |
| defaultCharset = lcinfo.getAttributeValue( |
| LocaleCharsetInfo.PARAMETER_ENCODING, |
| LocaleCharsetInfo.DEFAULT_CHARSET); |
| } |
| _lcMap = lcinfo.getLocaleCharsetMap(); |
| } |
| |
| if (defaultCharset != null) { |
| setRequestCharacterEncoding(defaultCharset); |
| } |
| } |
| |
| /** |
| * return locale-charset-map |
| */ |
| public LocaleCharsetMap[] getLocaleCharsetMap() { |
| return _lcMap; |
| } |
| |
| /** |
| * Returns true if this web module specifies a locale-charset-map in its |
| * sun-web.xml, false otherwise. |
| * |
| * @return true if this web module specifies a locale-charset-map in its |
| * sun-web.xml, false otherwise |
| */ |
| @Override |
| public boolean hasLocaleToCharsetMapping() { |
| LocaleCharsetMap[] locCharsetMap = getLocaleCharsetMap(); |
| return (locCharsetMap != null && locCharsetMap.length > 0); |
| } |
| |
| /** |
| * Matches the given request locales against the charsets specified in |
| * the locale-charset-map of this web module's sun-web.xml, and returns |
| * the first matching charset. |
| * |
| * @param locales Request locales |
| * |
| * @return First matching charset, or null if this web module does not |
| * specify any locale-charset-map in its sun-web.xml, or no match was |
| * found |
| */ |
| @Override |
| public String mapLocalesToCharset(Enumeration locales) { |
| |
| String encoding = null; |
| |
| LocaleCharsetMap[] locCharsetMap = getLocaleCharsetMap(); |
| if (locCharsetMap != null && locCharsetMap.length > 0) { |
| /* |
| * Check to see if there is a match between the request |
| * locales (in preference order) and the locales in the |
| * locale-charset-map. |
| */ |
| boolean matchFound = false; |
| while (locales.hasMoreElements() && !matchFound) { |
| Locale reqLoc = (Locale) locales.nextElement(); |
| for (int i=0; i<locCharsetMap.length && !matchFound; i++) { |
| String language = locCharsetMap[i].getAttributeValue( |
| LocaleCharsetMap.LOCALE); |
| if (language == null || "".equals(language)) { |
| continue; |
| } |
| String country = null; |
| int index = language.indexOf('_'); |
| if (index != -1) { |
| country = language.substring(index+1); |
| language = language.substring(0, index); |
| } |
| Locale mapLoc = null; |
| if (country != null) { |
| mapLoc = new Locale(language, country); |
| } else { |
| mapLoc = new Locale(language); |
| } |
| if (mapLoc.equals(reqLoc)) { |
| /* |
| * Match found. Get the charset to which the |
| * matched locale maps. |
| */ |
| encoding = locCharsetMap[i].getAttributeValue( |
| LocaleCharsetMap.CHARSET); |
| matchFound = true; |
| } |
| } |
| } |
| } |
| |
| return encoding; |
| } |
| |
| /** |
| * Creates an ObjectInputStream that provides special deserialization |
| * logic for classes that are normally not serializable (such as |
| * javax.naming.Context). |
| */ |
| @Override |
| public ObjectInputStream createObjectInputStream(InputStream is) |
| throws IOException { |
| |
| ObjectInputStream ois = null; |
| |
| Loader loader = getLoader(); |
| if (loader != null) { |
| ClassLoader classLoader = loader.getClassLoader(); |
| if (classLoader != null) { |
| try { |
| ois = javaEEIOUtils.createObjectInputStream( |
| is, true, classLoader); |
| } catch (Exception e) { |
| logger.log(Level.SEVERE, |
| LogFacade.CREATE_CUSTOM_OBJECT_INTPUT_STREAM_ERROR, e); |
| } |
| } |
| } |
| |
| if (ois == null) { |
| ois = new ObjectInputStream(is); |
| } |
| |
| return ois; |
| } |
| |
| /** |
| * Creates an ObjectOutputStream that provides special serialization |
| * logic for classes that are normally not serializable (such as |
| * javax.naming.Context). |
| */ |
| @Override |
| public ObjectOutputStream createObjectOutputStream(OutputStream os) |
| throws IOException { |
| |
| ObjectOutputStream oos = null; |
| |
| try { |
| oos = javaEEIOUtils.createObjectOutputStream(os, true); |
| } catch (IOException ioe) { |
| logger.log(Level.SEVERE, |
| LogFacade.CREATE_CUSTOM_BOJECT_OUTPUT_STREAM_ERROR, ioe); |
| oos = new ObjectOutputStream(os); |
| } |
| |
| return oos; |
| } |
| |
| /** |
| * Set to <code>true</code> when the default-web.xml has been read for |
| * this module. |
| */ |
| public void setXmlConfigured(boolean hasBeenXmlConfigured){ |
| this.hasBeenXmlConfigured = hasBeenXmlConfigured; |
| } |
| |
| /** |
| * Return <code>true</code> if the default=web.xml has been read for |
| * this module. |
| */ |
| public boolean hasBeenXmlConfigured(){ |
| return hasBeenXmlConfigured; |
| } |
| |
| /** |
| * Cache the result of doing findXX on this object |
| * NOTE: this method MUST be used only when loading/using |
| * the content of default-web.xml |
| */ |
| public void setCachedFindOperation(Object[] cachedFinds){ |
| this.cachedFinds = cachedFinds; |
| } |
| |
| /** |
| * Return the cached result of doing findXX on this object |
| * NOTE: this method MUST be used only when loading/using |
| * the content of default-web.xml |
| */ |
| public Object[] getCachedFindOperation(){ |
| return cachedFinds; |
| } |
| |
| @Override |
| public void setRealm(Realm realm) { |
| if ((realm != null) && !(realm instanceof RealmAdapter)) { |
| logger.log(Level.SEVERE, LogFacade.IGNORE_INVALID_REALM, |
| new Object[] { realm.getClass().getName(), |
| RealmAdapter.class.getName() }); |
| } else { |
| super.setRealm(realm); |
| } |
| } |
| |
| /** |
| * Starts this web module. |
| */ |
| @Override |
| public synchronized void start() throws LifecycleException { |
| // Get interestList of ServletContainerInitializers present, if any. |
| List<Object> orderingList = null; |
| boolean hasOthers = false; |
| Map<String, String> webFragmentMap = Collections.emptyMap(); |
| if (webBundleDescriptor != null) { |
| AbsoluteOrderingDescriptor aod = |
| ((WebBundleDescriptorImpl)webBundleDescriptor).getAbsoluteOrderingDescriptor(); |
| if (aod != null) { |
| orderingList = aod.getOrdering(); |
| hasOthers = aod.hasOthers(); |
| } |
| webFragmentMap = webBundleDescriptor.getJarNameToWebFragmentNameMap(); |
| } |
| |
| Iterable<ServletContainerInitializer> allInitializers = |
| ServletContainerInitializerUtil.getServletContainerInitializers( |
| webFragmentMap, orderingList, hasOthers, |
| wmInfo.getAppClassLoader()); |
| setServletContainerInitializerInterestList(allInitializers); |
| |
| DeploymentContext dc = getWebModuleConfig().getDeploymentContext(); |
| if (dc != null) { |
| directoryDeployed = |
| Boolean.valueOf(dc.getAppProps().getProperty(ServerTags.DIRECTORY_DEPLOYED)); |
| } |
| if (webBundleDescriptor != null) { |
| showArchivedRealPathEnabled = webBundleDescriptor.isShowArchivedRealPathEnabled(); |
| servletReloadCheckSecs = webBundleDescriptor.getServletReloadCheckSecs(); |
| } |
| |
| // Start and register Tomcat mbeans |
| super.start(); |
| |
| // Configure catalina listeners and valves. This can only happen |
| // after this web module has been started, in order to be able to |
| // load the specified listener and valve classes. |
| configureValves(); |
| configureCatalinaProperties(); |
| webModuleStartedEvent(); |
| if (directoryListing) { |
| setDirectoryListing(directoryListing); |
| } |
| |
| hasStarted = true; |
| } |
| |
| /** |
| * Stops this web module. |
| */ |
| @Override |
| public void stop() throws LifecycleException { |
| // Unregister monitoring mbeans only if this web module was |
| // successfully started, because if stop() is called during an |
| // aborted start(), no monitoring mbeans will have been registered |
| if (hasStarted) { |
| webModuleStoppedEvent(); |
| hasStarted = false; |
| } |
| |
| // Stop and unregister Tomcat mbeans |
| super.stop(getWebContainer().isShutdown()); |
| } |
| |
| @Override |
| protected void contextListenerStart() { |
| ServletContext servletContext = getServletContext(); |
| WebBundleDescriptor wbd = getWebBundleDescriptor(); |
| try { |
| // for jsf injection |
| servletContext.setAttribute( |
| Constants.DEPLOYMENT_CONTEXT_ATTRIBUTE, |
| getWebModuleConfig().getDeploymentContext()); |
| // null check for OSGi/HTTP |
| if (wbd != null) { |
| servletContext.setAttribute( |
| Constants.IS_DISTRIBUTABLE_ATTRIBUTE, |
| wbd.isDistributable()); |
| } |
| servletContext.setAttribute( |
| Constants.ENABLE_HA_ATTRIBUTE, |
| Boolean.valueOf( |
| webContainer.getServerConfigLookup().calculateWebAvailabilityEnabledFromConfig(this))); |
| |
| super.contextListenerStart(); |
| } finally { |
| servletContext.removeAttribute( |
| Constants.DEPLOYMENT_CONTEXT_ATTRIBUTE); |
| servletContext.removeAttribute( |
| Constants.IS_DISTRIBUTABLE_ATTRIBUTE); |
| servletContext.removeAttribute( |
| Constants.ENABLE_HA_ATTRIBUTE); |
| } |
| for (ServletRegistrationImpl srImpl : servletRegisMap.values()) { |
| if (srImpl instanceof DynamicWebServletRegistrationImpl) { |
| DynamicWebServletRegistrationImpl dwsrImpl = |
| (DynamicWebServletRegistrationImpl)srImpl; |
| dwsrImpl.postProcessAnnotations(); |
| } |
| } |
| webContainer.afterServletContextInitializedEvent(wbd); |
| } |
| |
| @Override |
| protected Types getTypes() { |
| if (wmInfo.getDeploymentContext()!=null) { |
| return wmInfo.getDeploymentContext().getTransientAppMetaData(Types.class.getName(), Types.class); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| protected void callServletContainerInitializers() |
| throws LifecycleException { |
| super.callServletContainerInitializers(); |
| if (!isJsfApplication() && !contextListeners.isEmpty()) { |
| /* |
| * Remove any JSF related ServletContextListeners from |
| * non-JSF apps. |
| * This can be done reliably only after all |
| * ServletContainerInitializers have been invoked, because |
| * system-wide ServletContainerInitializers may be invoked in |
| * any order, and it is only after JSF's FacesInitializer has |
| * been invoked that isJsfApplication(), which checks for the |
| * existence of a mapping to the FacesServlet in the app, may |
| * be used reliably because such mapping would have been added |
| * by JSF's FacesInitializer. See also IT 10223 |
| */ |
| ArrayList<ServletContextListener> listeners = |
| new ArrayList<ServletContextListener>(contextListeners); |
| String listenerClassName = null; |
| for (ServletContextListener listener : listeners) { |
| if (listener instanceof |
| StandardContext.RestrictedServletContextListener) { |
| listenerClassName = ((StandardContext.RestrictedServletContextListener) listener).getNestedListener().getClass().getName(); |
| } else { |
| listenerClassName = listener.getClass().getName(); |
| } |
| /* |
| * TBD: Retrieve listener class name from JSF's TldProvider |
| */ |
| if ("com.sun.faces.config.ConfigureListener".equals( |
| listenerClassName)) { |
| contextListeners.remove(listener); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Sets the virtual server parent of this web module, and passes it on to |
| * this web module's realm adapter.. |
| * |
| * @param container The virtual server parent |
| */ |
| @Override |
| public void setParent(Container container) { |
| super.setParent(container); |
| |
| if (container instanceof VirtualServer) { |
| vsId = ((VirtualServer) container).getID(); |
| } |
| |
| // The following assumes that the realm has been set on this WebModule |
| // before the WebModule is added as a child to the virtual server on |
| // which it is being deployed. |
| /*RealmAdapter ra = (RealmAdapter) getRealm(); |
| if (ra != null) { |
| 1 ra.setVirtualServer(container); |
| }*/ |
| Realm ra = getRealm(); |
| if (ra != null && ra instanceof RealmInitializer) { |
| ((RealmInitializer) ra).setVirtualServer(container); |
| } |
| } |
| |
| /** |
| * Indicates whether this web module contains any ad-hoc paths. |
| * |
| * An ad-hoc path is a servlet path that is mapped to a servlet |
| * not declared in the web module's deployment descriptor. |
| * |
| * A web module all of whose mappings are for ad-hoc paths is called an |
| * ad-hoc web module. |
| * |
| * @return true if this web module contains any ad-hoc paths, false |
| * otherwise |
| */ |
| @Override |
| public boolean hasAdHocPaths() { |
| return this.hasAdHocPaths; |
| } |
| |
| /** |
| * Indicates whether this web module contains any ad-hoc subtrees. |
| * |
| * @return true if this web module contains any ad-hoc subtrees, false |
| * otherwise |
| */ |
| public boolean hasAdHocSubtrees() { |
| return this.hasAdHocSubtrees; |
| } |
| |
| /* |
| * Adds the given ad-hoc path and subtree, along with information about |
| * the servlet that will be responsible for servicing it, to this web |
| * module. |
| * |
| * @param path The ad-hoc path to add |
| * @param subtree The ad-hoc subtree path to add |
| * @param servletInfo Information about the servlet that is responsible |
| * for servicing the given ad-hoc path |
| */ |
| void addAdHocPathAndSubtree(String path, |
| String subtree, |
| AdHocServletInfo servletInfo) { |
| |
| if (path == null && subtree == null) { |
| return; |
| } |
| |
| Wrapper adHocWrapper = (Wrapper) |
| findChild(servletInfo.getServletName()); |
| if (adHocWrapper == null) { |
| adHocWrapper = createAdHocWrapper(servletInfo); |
| addChild(adHocWrapper); |
| } |
| |
| if (path != null) { |
| adHocPaths.put(path, servletInfo); |
| hasAdHocPaths = true; |
| } |
| |
| if (subtree != null) { |
| adHocSubtrees.put(subtree, servletInfo); |
| hasAdHocSubtrees = true; |
| } |
| } |
| |
| /* |
| * Adds the given ad-hoc path to servlet mappings to this web module. |
| * |
| * @param newPaths Mappings of ad-hoc paths to the servlets responsible |
| * for servicing them |
| */ |
| void addAdHocPaths(Map<String, AdHocServletInfo> newPaths) { |
| |
| if (newPaths == null || newPaths.isEmpty()) { |
| return; |
| } |
| for (Map.Entry<String, AdHocServletInfo> entry : newPaths.entrySet()) { |
| AdHocServletInfo servletInfo = entry.getValue(); |
| Wrapper adHocWrapper = (Wrapper) |
| findChild(servletInfo.getServletName()); |
| if(adHocWrapper == null) { |
| adHocWrapper = createAdHocWrapper(servletInfo); |
| addChild(adHocWrapper); |
| } |
| adHocPaths.put(entry.getKey(), servletInfo); |
| } |
| |
| hasAdHocPaths = true; |
| } |
| |
| /* |
| * Adds the given ad-hoc subtree path to servlet mappings to this web |
| * module. |
| * |
| * @param newSubtrees Mappings of ad-hoc subtree paths to the servlets |
| * responsible for servicing them |
| */ |
| void addAdHocSubtrees(Map<String, AdHocServletInfo> newSubtrees) { |
| |
| if (newSubtrees == null || newSubtrees.isEmpty()) { |
| return; |
| } |
| for (Map.Entry<String, AdHocServletInfo> entry : newSubtrees.entrySet()) { |
| AdHocServletInfo servletInfo = entry.getValue(); |
| Wrapper adHocWrapper = (Wrapper)findChild(servletInfo.getServletName()); |
| if(adHocWrapper == null) { |
| adHocWrapper = createAdHocWrapper(servletInfo); |
| addChild(adHocWrapper); |
| } |
| adHocSubtrees.put(entry.getKey(), servletInfo); |
| } |
| |
| hasAdHocSubtrees = true; |
| } |
| |
| /* |
| * Gets the ad-hoc path to servlet mappings managed by this web module. |
| * |
| * @return The ad-hoc path to servlet mappings managed by this web |
| * module. |
| */ |
| Map<String, AdHocServletInfo> getAdHocPaths() { |
| return adHocPaths; |
| } |
| |
| /* |
| * Gets the ad-hoc subtree path to servlet mappings managed by this |
| * web module. |
| * |
| * @return The ad-hoc subtree path to servlet mappings managed by |
| * this web module. |
| */ |
| Map<String, AdHocServletInfo> getAdHocSubtrees() { |
| return adHocSubtrees; |
| } |
| |
| /** |
| * Returns the name of the ad-hoc servlet responsible for servicing the |
| * given path. |
| * |
| * @param path The path whose associated ad-hoc servlet is needed |
| * |
| * @return The name of the ad-hoc servlet responsible for servicing the |
| * given path, or null if the given path does not represent an ad-hoc |
| * path |
| */ |
| @Override |
| public String getAdHocServletName(String path) { |
| |
| if (!hasAdHocPaths() && !hasAdHocSubtrees()) { |
| return null; |
| } |
| |
| AdHocServletInfo servletInfo = null; |
| |
| // Check if given path matches any of the ad-hoc paths (exact match) |
| if (path == null) { |
| servletInfo = adHocPaths.get(""); |
| } else { |
| servletInfo = adHocPaths.get(path); |
| } |
| |
| // Check if given path starts with any of the ad-hoc subtree paths |
| if (servletInfo == null && path != null && hasAdHocSubtrees()) { |
| for(String adHocSubtree : adHocSubtrees.keySet()) { |
| if(path.startsWith(adHocSubtree)) { |
| servletInfo = adHocSubtrees.get(adHocSubtree); |
| break; |
| } |
| } |
| } |
| |
| if (servletInfo != null) { |
| return servletInfo.getServletName(); |
| } else { |
| return null; |
| } |
| } |
| |
| /* |
| * Removes the given ad-hoc path from this web module. |
| * |
| * @param path The ad-hoc path to remove |
| */ |
| void removeAdHocPath(String path) { |
| if (path == null) { |
| return; |
| } |
| adHocPaths.remove(path); |
| if (adHocPaths.isEmpty()) { |
| this.hasAdHocPaths = false; |
| } |
| } |
| |
| /* |
| * Removes the given ad-hoc path from this web module. |
| * |
| * @param subtree The ad-hoc subtree to remove |
| */ |
| void removeAdHocSubtree(String subtree) { |
| if (subtree == null) { |
| return; |
| } |
| adHocSubtrees.remove(subtree); |
| if (adHocSubtrees.isEmpty()) { |
| this.hasAdHocSubtrees = false; |
| } |
| } |
| |
| /** |
| * Adds the given valve to this web module's ad-hoc pipeline. |
| * |
| * @param valve The valve to add |
| */ |
| public void addAdHocValve(GlassFishValve valve) { |
| adHocPipeline.addValve(valve); |
| } |
| |
| /** |
| * Removes the given valve from this web module's ad-hoc pipeline. |
| * |
| * @param valve The valve to remove |
| */ |
| public void removeAdHocValve(GlassFishValve valve) { |
| adHocPipeline.removeValve(valve); |
| } |
| |
| /** |
| * Gets this web module's ad-hoc pipeline. |
| * |
| * @return This web module's ad-hoc pipeline |
| */ |
| public Pipeline getAdHocPipeline() { |
| return adHocPipeline; |
| } |
| |
| /** |
| * Sets the file encoding of all static resources of this web module. |
| * |
| * @param enc The file encoding of static resources of this web module |
| */ |
| public void setFileEncoding(String enc) { |
| this.fileEncoding = enc; |
| } |
| |
| /** |
| * Gets the file encoding of all static resources of this web module. |
| * |
| * @return The file encoding of static resources of this web module |
| */ |
| public String getFileEncoding() { |
| return fileEncoding; |
| } |
| |
| /** |
| * Configures this web module with the filter mappings specified in the |
| * deployment descriptor. |
| * |
| * @param sfm The filter mappings of this web module as specified in the |
| * deployment descriptor |
| */ |
| @SuppressWarnings({"unchecked"}) |
| void addFilterMap(ServletFilterMapping sfm) { |
| |
| FilterMaps filterMaps = new FilterMaps(); |
| filterMaps.setFilterName(sfm.getName()); |
| filterMaps.setDispatcherTypes(sfm.getDispatchers()); |
| |
| List<String> servletNames = sfm.getServletNames(); |
| if (servletNames != null) { |
| for(String servletName : servletNames) { |
| filterMaps.addServletName(servletName); |
| } |
| } |
| |
| List<String> urlPatterns = sfm.getUrlPatterns(); |
| if (urlPatterns != null) { |
| for(String urlPattern : urlPatterns) { |
| filterMaps.addURLPattern(urlPattern); |
| } |
| } |
| |
| addFilterMaps(filterMaps); |
| } |
| |
| /** |
| * Creates an ad-hoc servlet wrapper from the given ad-hoc servlet info. |
| * |
| * @param servletInfo Ad-hoc servlet info from which to generate |
| * ad-hoc servlet wrapper |
| * |
| * @return The generated ad-hoc servlet wrapper |
| */ |
| private Wrapper createAdHocWrapper(AdHocServletInfo servletInfo) { |
| |
| Wrapper adHocWrapper = new StandardWrapper(); |
| adHocWrapper.setServletClassName( |
| servletInfo.getServletClass().getName()); |
| adHocWrapper.setName(servletInfo.getServletName()); |
| Map<String,String> initParams = servletInfo.getServletInitParams(); |
| if (initParams != null && !initParams.isEmpty()) { |
| for(Map.Entry<String,String> entry : initParams.entrySet()) { |
| adHocWrapper.addInitParameter(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| return adHocWrapper; |
| } |
| |
| /** |
| * Configure the <code>WebModule</code> valves. |
| */ |
| protected void configureValves(){ |
| if (iasBean != null && iasBean.getValve() != null && iasBean.sizeValve() > 0) { |
| org.glassfish.web.deployment.runtime.Valve[] valves = iasBean.getValve(); |
| for (org.glassfish.web.deployment.runtime.Valve valve: valves) { |
| addValve(valve); |
| } |
| } |
| |
| } |
| |
| /** |
| * Configure the <code>WebModule</code< properties. |
| */ |
| protected void configureCatalinaProperties(){ |
| String propName = null; |
| String propValue = null; |
| if (bean != null) { |
| List<Property> props = bean.getProperty(); |
| if (props != null) { |
| for (Property prop : props) { |
| propName = prop.getName(); |
| propValue = prop.getValue(); |
| configureCatalinaProperties(propName,propValue); |
| } |
| } |
| } |
| |
| if (iasBean != null && iasBean.sizeWebProperty() > 0) { |
| WebProperty[] wprops = iasBean.getWebProperty(); |
| for(WebProperty wprop : wprops) { |
| propName = wprop.getAttributeValue("name"); |
| propValue = wprop.getAttributeValue("value"); |
| configureCatalinaProperties(propName, propValue); |
| } |
| } |
| } |
| |
| /** |
| * Configure the <code>WebModule</code< properties. |
| * @param propName the property name |
| * @param propValue the property value |
| */ |
| protected void configureCatalinaProperties(String propName, |
| String propValue){ |
| if (propName == null || propValue == null) { |
| logger.log(Level.WARNING, |
| LogFacade.NULL_WEB_MODULE_PROPERTY, |
| getName()); |
| return; |
| } |
| |
| if (propName.startsWith("valve_")) { |
| addValve(propValue); |
| } else if (propName.startsWith("listener_")) { |
| addCatalinaListener(propValue); |
| } |
| } |
| |
| /** |
| * Instantiates a <tt>Valve</tt> from the given <tt>className</tt> |
| * and adds it to the <tt>Pipeline</tt> of this WebModule. |
| * |
| * @param className the fully qualified class name of the <tt>Valve</tt> |
| */ |
| protected void addValve(String className) { |
| Object valve = loadInstance(className); |
| if (valve instanceof Valve) { |
| super.addValve((Valve) valve); |
| } else if (valve instanceof GlassFishValve) { |
| super.addValve((GlassFishValve) valve); |
| } else { |
| logger.log(Level.WARNING, LogFacade.VALVE_CLASS_NAME_NO_VALVE, |
| className); |
| } |
| } |
| |
| /** |
| * Constructs a <tt>Valve</tt> from the given <tt>valveDescriptor</tt> |
| * and adds it to the <tt>Pipeline</tt> of this WebModule. |
| * @param valveDescriptor the object containing the information to |
| * create the valve. |
| */ |
| protected void addValve(org.glassfish.web.deployment.runtime.Valve valveDescriptor) { |
| String valveName = valveDescriptor.getAttributeValue( |
| org.glassfish.web.deployment.runtime.Valve.NAME); |
| String className = valveDescriptor.getAttributeValue( |
| org.glassfish.web.deployment.runtime.Valve.CLASS_NAME); |
| if (valveName == null) { |
| logger.log(Level.WARNING, LogFacade.VALVE_MISSING_NAME, |
| getName()); |
| return; |
| } |
| if (className == null) { |
| logger.log(Level.WARNING, LogFacade.VALVE_MISSING_CLASS_NAME, |
| new Object[]{valveName, getName()}); |
| return; |
| } |
| Object valve = loadInstance(className); |
| if (valve == null) { |
| return; |
| } |
| if (!(valve instanceof GlassFishValve) && |
| !(valve instanceof Valve)) { |
| logger.log(Level.WARNING, LogFacade.VALVE_CLASS_NAME_NO_VALVE, |
| className); |
| return; |
| } |
| WebProperty[] props = valveDescriptor.getWebProperty(); |
| if (props != null && props.length > 0) { |
| for (WebProperty property: props) { |
| String propName = getSetterName( |
| property.getAttributeValue(WebProperty.NAME)); |
| if (propName != null && propName.length() != 0) { |
| String value = property.getAttributeValue( |
| WebProperty.VALUE); |
| try { |
| Method method = valve.getClass().getMethod( |
| propName, String.class); |
| method.invoke(valve, value); |
| } catch (NoSuchMethodException ex) { |
| String msg = rb.getString(LogFacade.VALVE_SPECIFIED_METHOD_MISSING); |
| msg = MessageFormat.format(msg, |
| new Object[] { propName, valveName, getName()}); |
| logger.log(Level.SEVERE, msg, ex); |
| } catch (Throwable t) { |
| String msg = rb.getString(LogFacade.VALVE_SETTER_CAUSED_EXCEPTION); |
| msg = MessageFormat.format(msg, |
| new Object[] { propName, valveName, getName()}); |
| logger.log(Level.SEVERE, msg, t); |
| } |
| } else { |
| logger.log(Level.WARNING, |
| LogFacade.VALVE_MISSING_PROPERTY_NAME, |
| new Object[]{valveName, getName()}); |
| return; |
| } |
| } |
| } |
| if (valve instanceof Valve) { |
| super.addValve((Valve) valve); |
| } else if (valve instanceof GlassFishValve) { |
| super.addValve((GlassFishValve) valve); |
| } |
| } |
| |
| /** |
| * Adds the Catalina listener with the given class name to this |
| * WebModule. |
| * |
| * @param listenerName The fully qualified class name of the listener |
| */ |
| protected void addCatalinaListener(String listenerName) { |
| Object listener = loadInstance(listenerName); |
| |
| if ( listener == null ) return; |
| |
| if (listener instanceof ContainerListener) { |
| addContainerListener((ContainerListener)listener); |
| } else if (listener instanceof LifecycleListener ){ |
| addLifecycleListener((LifecycleListener)listener); |
| } else if (listener instanceof InstanceListener){ |
| addInstanceListener(listenerName); |
| } else { |
| logger.log(Level.SEVERE, LogFacade.INVALID_LISTENER, |
| new Object[] {listenerName, getName()}); |
| } |
| } |
| |
| private Object loadInstance(String className){ |
| try{ |
| Class clazz = getLoader().getClassLoader().loadClass(className); |
| return clazz.newInstance(); |
| } catch (Throwable ex){ |
| String msg = rb.getString(LogFacade.UNABLE_TO_LOAD_EXTENSION); |
| msg = MessageFormat.format(msg, new Object[] { className, getName() }); |
| logger.log(Level.SEVERE, msg, ex); |
| } |
| return null; |
| } |
| |
| private String getSetterName(String propName) { |
| if (propName != null) { |
| if (propName.length() > 1) { |
| propName = "set" + Character.toUpperCase(propName.charAt(0)) + |
| propName.substring(1); |
| } |
| else { |
| propName = "set" + Character.toUpperCase(propName.charAt(0)); |
| } |
| } |
| return propName; |
| } |
| |
| public Application getBean() { |
| return bean; |
| } |
| |
| public void setBean(Application bean) { |
| this.bean = bean; |
| } |
| |
| void setStandalone(boolean isStandalone) { |
| this.isStandalone = isStandalone; |
| } |
| |
| boolean isStandalone() { |
| return isStandalone; |
| } |
| |
| /** |
| * Sets the WebBundleDescriptor (web.xml) for this WebModule. |
| * |
| * @param wbd The WebBundleDescriptor |
| */ |
| void setWebBundleDescriptor(WebBundleDescriptor wbd) { |
| this.webBundleDescriptor = wbd; |
| } |
| |
| /** |
| * Gets the WebBundleDesciptor (web.xml) for this WebModule. |
| */ |
| public WebBundleDescriptor getWebBundleDescriptor() { |
| return this.webBundleDescriptor; |
| } |
| |
| /** |
| * Gets ComponentId for Invocation. |
| */ |
| public String getComponentId() { |
| return compEnvId; |
| } |
| |
| /** |
| * Sets ComponentId for Invocation. |
| */ |
| void setComponentId(String compEnvId) { |
| this.compEnvId = compEnvId; |
| } |
| |
| /** |
| * Gets ServerContext. |
| */ |
| public ServerContext getServerContext() { |
| return serverContext; |
| } |
| |
| /** |
| * Sets ServerContext. |
| */ |
| void setServerContext(ServerContext serverContext) { |
| this.serverContext = serverContext; |
| } |
| |
| /** |
| * Sets the alternate docroots of this web module from the given |
| * "alternatedocroot_" properties. |
| */ |
| void setAlternateDocBases(List <Property> props) { |
| |
| if (props == null) { |
| return; |
| } |
| |
| for (Property prop : props) { |
| parseAlternateDocBase(prop.getName(), prop.getValue()); |
| } |
| } |
| |
| void parseAlternateDocBase(String propName, String propValue) { |
| |
| if (propName == null || propValue == null) { |
| logger.log(Level.WARNING, LogFacade.ALTERNATE_DOC_BASE_NULL_PROPERTY_NAME_VALVE); |
| return; |
| } |
| |
| if (!propName.startsWith("alternatedocroot_")) { |
| return; |
| } |
| |
| /* |
| * Validate the prop value |
| */ |
| String urlPattern = null; |
| String docBase = null; |
| |
| int fromIndex = propValue.indexOf(ALTERNATE_FROM); |
| int dirIndex = propValue.indexOf(ALTERNATE_DOCBASE); |
| |
| if (fromIndex < 0 || dirIndex < 0) { |
| logger.log( |
| Level.WARNING, |
| LogFacade.ALTERNATE_DOC_BASE_MISSING_PATH_OR_URL_PATTERN, |
| propValue); |
| return; |
| } |
| |
| if (fromIndex > dirIndex) { |
| urlPattern = propValue.substring( |
| fromIndex + ALTERNATE_FROM.length()); |
| docBase = propValue.substring( |
| dirIndex + ALTERNATE_DOCBASE.length(), |
| fromIndex); |
| } else { |
| urlPattern = propValue.substring( |
| fromIndex + ALTERNATE_FROM.length(), |
| dirIndex); |
| docBase = propValue.substring( |
| dirIndex + ALTERNATE_DOCBASE.length()); |
| } |
| |
| urlPattern = urlPattern.trim(); |
| if (!validateURLPattern(urlPattern)) { |
| logger.log(Level.WARNING, |
| LogFacade.ALTERNATE_DOC_BASE_ILLEGAL_URL_PATTERN, |
| urlPattern); |
| return; |
| } |
| |
| docBase = docBase.trim(); |
| |
| addAlternateDocBase(urlPattern, docBase); |
| } |
| |
| List<URI> getDeployAppLibs() { |
| List<URI> uris = null; |
| if (wmInfo.getDeploymentContext() != null) { |
| try { |
| uris = wmInfo.getDeploymentContext().getAppLibs(); |
| } catch(URISyntaxException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| return uris; |
| } |
| |
| |
| /** |
| * Configure miscellaneous settings such as the pool size for |
| * single threaded servlets, specifying a temporary directory other |
| * than the default etc. |
| * |
| * Since the work directory is used when configuring the session manager |
| * persistence settings, this method must be invoked prior to |
| * <code>configureSessionSettings</code>. |
| */ |
| void configureMiscSettings(SunWebAppImpl bean, VirtualServer vs, |
| String contextPath) { |
| |
| /* |
| * Web app inherits setting of allowLinking property from vs on which |
| * it is being deployed, but may override it using allowLinking |
| * property in its sun-web.xml |
| */ |
| boolean allowLinking = vs.getAllowLinking(); |
| |
| if ((bean != null) && (bean.sizeWebProperty() > 0)) { |
| WebProperty[] props = bean.getWebProperty(); |
| for (WebProperty prop : props) { |
| String name = prop.getAttributeValue("name"); |
| String value = prop.getAttributeValue("value"); |
| if (name == null || value == null) { |
| throw new IllegalArgumentException( |
| rb.getString(LogFacade.NULL_WEB_MODULE_PROPERTY)); |
| } |
| if ("singleThreadedServletPoolSize".equalsIgnoreCase(name)) { |
| int poolSize = getSTMPoolSize(); |
| try { |
| poolSize = Integer.parseInt(value); |
| } catch(NumberFormatException e) { |
| String msg = rb.getString(LogFacade.INVALID_SERVLET_POOL_SIZE); |
| msg = MessageFormat.format(msg, value, contextPath, Integer.toString(poolSize)); |
| logger.log(Level.WARNING, msg, e); |
| } |
| if (poolSize > 0) { |
| setSTMPoolSize(poolSize); |
| } |
| |
| } else if("tempdir".equalsIgnoreCase(name)) { |
| setWorkDir(value); |
| } else if("crossContextAllowed".equalsIgnoreCase(name)) { |
| boolean crossContext = Boolean.parseBoolean(value); |
| setCrossContext(crossContext); |
| } else if("allowLinking".equalsIgnoreCase(name)) { |
| allowLinking = ConfigBeansUtilities.toBoolean(value); |
| // START S1AS8PE 4817642 |
| } else if("reuseSessionID".equalsIgnoreCase(name)) { |
| boolean reuse = ConfigBeansUtilities.toBoolean(value); |
| setReuseSessionID(reuse); |
| if (reuse) { |
| String msg = rb.getString(LogFacade.SESSION_IDS_REUSED); |
| msg = MessageFormat.format(msg, contextPath, vs.getID()); |
| logger.log(Level.WARNING, msg); |
| } |
| // END S1AS8PE 4817642 |
| } else if("useResponseCTForHeaders".equalsIgnoreCase(name)) { |
| if("true".equalsIgnoreCase(value)) { |
| setResponseCTForHeaders(); |
| } |
| } else if("encodeCookies".equalsIgnoreCase(name)) { |
| boolean flag = ConfigBeansUtilities.toBoolean(value); |
| setEncodeCookies(flag); |
| // START RIMOD 4642650 |
| } else if("relativeRedirectAllowed".equalsIgnoreCase(name)) { |
| boolean relativeRedirect = ConfigBeansUtilities.toBoolean(value); |
| setAllowRelativeRedirect(relativeRedirect); |
| // END RIMOD 4642650 |
| } else if("fileEncoding".equalsIgnoreCase(name)) { |
| setFileEncoding(value); |
| } else if("enableTldValidation".equalsIgnoreCase(name) |
| && ConfigBeansUtilities.toBoolean(value)) { |
| setTldValidation(true); |
| } else if("enableTldNamespaceAware".equalsIgnoreCase(name) |
| && ConfigBeansUtilities.toBoolean(value)) { |
| setTldNamespaceAware(true); |
| } else if("securePagesWithPragma".equalsIgnoreCase(name)) { |
| boolean securePagesWithPragma = ConfigBeansUtilities.toBoolean(value); |
| setSecurePagesWithPragma(securePagesWithPragma); |
| } else if("useMyFaces".equalsIgnoreCase(name)) { |
| setUseMyFaces(ConfigBeansUtilities.toBoolean(value)); |
| } else if("useBundledJsf".equalsIgnoreCase(name)) { |
| setUseMyFaces(ConfigBeansUtilities.toBoolean(value)); |
| } else if(name.startsWith("alternatedocroot_")) { |
| parseAlternateDocBase(name, value); |
| } else if(name.startsWith("valve_") || |
| name.startsWith("listener_")) { |
| // do nothing; these properties are dealt with |
| // in configureCatalinaProperties() |
| } else { |
| Object[] params = {name, value}; |
| logger.log(Level.WARNING, LogFacade.INVALID_PROPERTY, |
| params); |
| } |
| } |
| } |
| |
| setAllowLinking(allowLinking); |
| } |
| |
| /** |
| * Determines and sets the alternate deployment descriptor for |
| * this web module. |
| */ |
| void configureAlternateDD(WebBundleDescriptor wbd) { |
| |
| String altDDName = |
| wbd.getModuleDescriptor().getAlternateDescriptor(); |
| if (altDDName == null) { |
| return; |
| } |
| |
| com.sun.enterprise.deployment.Application app = wbd.getApplication(); |
| if (app == null || app.isVirtual()) { |
| // Alternate deployment descriptors are only supported for |
| // WAR files embedded inside EAR files |
| return; |
| } |
| |
| DeploymentContext dc = getWebModuleConfig().getDeploymentContext(); |
| if (dc == null) { |
| return; |
| } |
| |
| altDDName = altDDName.trim(); |
| if (altDDName.startsWith("/")) { |
| altDDName = altDDName.substring(1); |
| } |
| |
| String appLoc = dc.getSource().getParentArchive().getURI().getPath(); |
| altDDName = appLoc + altDDName; |
| |
| if (logger.isLoggable(Level.FINE)) { |
| Object[] objs = {altDDName, wmInfo.getName()}; |
| logger.log(Level.FINE, LogFacade.ALT_DD_NAME, objs); |
| } |
| |
| setAltDDName(altDDName); |
| } |
| |
| /* |
| * Configures this web module with its web services, based on its |
| * "hasWebServices" and "endpointAddresses" properties |
| */ |
| void configureWebServices(WebBundleDescriptor wbd) { |
| |
| if (wbd.hasWebServices()) { |
| |
| setHasWebServices(true); |
| |
| // creates the list of endpoint addresses |
| String[] endpointAddresses; |
| WebServicesDescriptor webService = wbd.getWebServices(); |
| Vector<String> endpointList = new Vector<String>(); |
| for(WebServiceEndpoint wse : webService.getEndpoints()) { |
| if(wbd.getContextRoot() != null) { |
| endpointList.add(wbd.getContextRoot() + "/" + |
| wse.getEndpointAddressUri()); |
| } else { |
| endpointList.add(wse.getEndpointAddressUri()); |
| } |
| } |
| endpointAddresses = new String[endpointList.size()]; |
| endpointList.copyInto(endpointAddresses); |
| |
| setEndpointAddresses(endpointAddresses); |
| |
| } else { |
| setHasWebServices(false); |
| } |
| } |
| |
| /** |
| * Configure the class loader for the web module based on the |
| * settings in sun-web.xml's class-loader element (if any). |
| */ |
| Loader configureLoader(SunWebApp bean) { |
| |
| org.glassfish.web.deployment.runtime.ClassLoader clBean = null; |
| |
| WebappLoader loader = new V3WebappLoader(wmInfo.getAppClassLoader()); |
| |
| loader.setUseMyFaces(isUseMyFaces()); |
| |
| if (bean != null) { |
| clBean = ((SunWebAppImpl)bean).getClassLoader(); |
| } |
| if (clBean != null) { |
| configureLoaderAttributes(loader, clBean); |
| configureLoaderProperties(loader, clBean); |
| } else { |
| loader.setDelegate(true); |
| } |
| |
| // START S1AS 6178005 |
| String stubPath = wmInfo.getStubPath(); |
| if (stubPath != null && stubPath.length() > 0) { |
| if (stubPath.charAt(0) != '/') { |
| stubPath = "/" + stubPath; |
| } |
| loader.addRepository("file:" + stubPath + File.separator); |
| } |
| // END S1AS 6178005 |
| |
| // START PE 4985680 |
| /** |
| * Adds the given package name to the list of packages that may |
| * always be overriden, regardless of whether they belong to a |
| * protected namespace |
| */ |
| String packagesName = |
| System.getProperty("com.sun.enterprise.overrideablejavaxpackages"); |
| |
| if (packagesName != null) { |
| List<String> overridablePackages = |
| StringUtils.parseStringList(packagesName, " ,"); |
| for(String overridablePackage : overridablePackages) { |
| loader.addOverridablePackage(overridablePackage); |
| } |
| } |
| // END PE 4985680 |
| |
| setLoader(loader); |
| |
| return loader; |
| } |
| |
| /** |
| * Saves all active sessions to the given deployment context, so they |
| * can be restored following a redeployment. |
| * |
| * @param props the deployment context properties to which to save the |
| * sessions |
| */ |
| void saveSessions(Properties props) { |
| if (props == null) { |
| return; |
| } |
| |
| StandardManager manager = (StandardManager) getManager(); |
| if (manager == null) { |
| return; |
| } |
| |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| try { |
| manager.writeSessions(baos, false); |
| props.setProperty(getObjectName(), |
| gfEncoder.encode(baos.toByteArray())); |
| } catch (Exception ex) { |
| String msg = rb.getString(LogFacade.UNABLE_TO_SAVE_SESSIONS_DURING_REDEPLOY); |
| msg = MessageFormat.format(msg, getName()); |
| logger.log(Level.WARNING, msg, ex); |
| } |
| } |
| |
| /** |
| * Loads any sessions that were stored in the given deployment context |
| * prior to a redeployment of this web module. |
| * |
| * @param deploymentProperties the deployment context properties from |
| * which to load the sessions |
| */ |
| void loadSessions(Properties deploymentProperties) { |
| if (deploymentProperties == null) { |
| return; |
| } |
| |
| StandardManager manager = (StandardManager) getManager(); |
| if (manager == null) { |
| return; |
| } |
| |
| String sessions = deploymentProperties.getProperty(getObjectName()); |
| if (sessions != null) { |
| try { |
| ByteArrayInputStream bais = new ByteArrayInputStream( |
| gfDecoder.decodeBuffer(sessions)); |
| manager.readSessions(bais); |
| } catch (Exception ex) { |
| String msg = rb.getString(LogFacade.UNABLE_TO_RESTORE_SESSIONS_DURING_REDEPLOY); |
| msg = MessageFormat.format(msg, getName()); |
| logger.log(Level.WARNING, msg, ex); |
| } |
| deploymentProperties.remove(getObjectName()); |
| } |
| } |
| |
| /** |
| * Loads and instantiates the listener with the specified classname. |
| * |
| * @param loader the classloader to use |
| * @param listenerClassName the fully qualified classname to instantiate |
| * |
| * @return the instantiated listener |
| * |
| * @throws Exception if the specified classname fails to be loaded or |
| * instantiated |
| */ |
| @Override |
| protected EventListener loadListener(ClassLoader loader, |
| String listenerClassName) |
| throws Exception { |
| try { |
| return super.loadListener(loader, listenerClassName); |
| } catch (Exception e) { |
| if (WS_SERVLET_CONTEXT_LISTENER.equals(listenerClassName)) { |
| logger.log(Level.WARNING, LogFacade.MISSING_METRO, e); |
| } |
| throw e; |
| } |
| } |
| |
| /** |
| * Create and configure the session manager for this web application |
| * according to the persistence type specified. |
| * |
| * Also configure the other aspects of session management for this |
| * web application according to the values specified in the session-config |
| * element of sun-web.xml (and whether app is distributable) |
| */ |
| protected void configureSessionSettings(WebBundleDescriptor wbd, |
| WebModuleConfig wmInfo) { |
| |
| SessionConfig cfg = null; |
| SessionManager smBean = null; |
| SessionProperties sessionPropsBean = null; |
| CookieProperties cookieBean = null; |
| |
| if (iasBean != null) { |
| cfg = iasBean.getSessionConfig(); |
| if (cfg != null) { |
| smBean = cfg.getSessionManager(); |
| sessionPropsBean = cfg.getSessionProperties(); |
| cookieBean = cfg.getCookieProperties(); |
| } |
| } |
| |
| configureSessionManager(smBean, wbd, wmInfo); |
| configureSession(sessionPropsBean, wbd); |
| configureCookieProperties(cookieBean); |
| } |
| |
| /** |
| * Configures the given classloader with its attributes specified in |
| * sun-web.xml. |
| * |
| * @param loader The classloader to configure |
| * @param clBean The class-loader info from sun-web.xml |
| */ |
| private void configureLoaderAttributes( |
| Loader loader, |
| org.glassfish.web.deployment.runtime.ClassLoader clBean) { |
| |
| String value = clBean.getAttributeValue( |
| org.glassfish.web.deployment.runtime.ClassLoader.DELEGATE); |
| |
| /* |
| * The DOL will *always* return a value: If 'delegate' has not been |
| * configured in sun-web.xml, its default value will be returned, |
| * which is FALSE in the case of sun-web-app_2_2-0.dtd and |
| * sun-web-app_2_3-0.dtd, and TRUE in the case of |
| * sun-web-app_2_4-0.dtd. |
| */ |
| boolean delegate = ConfigBeansUtilities.toBoolean(value); |
| loader.setDelegate(delegate); |
| if (logger.isLoggable(Level.FINE)) { |
| logger.log(Level.FINE, LogFacade.SETTING_DELEGATE, new Object[]{getPath(), delegate}); |
| } |
| |
| // Get any extra paths to be added to the class path of this |
| // class loader |
| value = clBean.getAttributeValue( |
| org.glassfish.web.deployment.runtime.ClassLoader.EXTRA_CLASS_PATH); |
| if (value != null) { |
| // Parse the extra classpath into its ':' and ';' separated |
| // components. Ignore ':' as a separator if it is preceded by |
| // '\' |
| String[] pathElements = value.split(";|((?<!\\\\):)"); |
| if (pathElements != null) { |
| for (String path : pathElements) { |
| path = path.replace("\\:", ":"); |
| if (logger.isLoggable(Level.FINE)) { |
| logger.log(Level.FINE, LogFacade.ADDING_CLASSPATH, new Object[]{getPath(), path}); |
| } |
| |
| try { |
| URL url = new URL(path); |
| loader.addRepository(path); |
| } catch (MalformedURLException mue1) { |
| // Not a URL, interpret as file |
| File file = new File(path); |
| // START GlassFish 904 |
| if (!file.isAbsolute()) { |
| // Resolve relative extra class path to the |
| // context's docroot |
| file = new File(getDocBase(), path); |
| } |
| // END GlassFish 904 |
| |
| try { |
| URL url = file.toURI().toURL(); |
| loader.addRepository(url.toString()); |
| } catch (MalformedURLException mue2) { |
| String msg = rb.getString(LogFacade.CLASSPATH_ERROR); |
| Object[] params = { path }; |
| msg = MessageFormat.format(msg, params); |
| logger.log(Level.SEVERE, msg, mue2); |
| } |
| } |
| } |
| } |
| } |
| |
| value = clBean.getAttributeValue( |
| org.glassfish.web.deployment.runtime.ClassLoader.DYNAMIC_RELOAD_INTERVAL); |
| if (value != null) { |
| // Log warning if dynamic-reload-interval is specified |
| // in sun-web.xml since it is not supported |
| logger.log(Level.WARNING, LogFacade.DYNAMIC_RELOAD_INTERVAL); |
| } |
| } |
| |
| /** |
| * Configures the given classloader with its properties specified in |
| * sun-web.xml. |
| * |
| * @param loader The classloader to configure |
| * @param clBean The class-loader info from sun-web.xml |
| */ |
| private void configureLoaderProperties( |
| Loader loader, |
| org.glassfish.web.deployment.runtime.ClassLoader clBean) { |
| |
| String name = null; |
| String value = null; |
| |
| WebProperty[] props = clBean.getWebProperty(); |
| if (props == null || props.length == 0) { |
| return; |
| } |
| for(WebProperty prop : props) { |
| name = prop.getAttributeValue(WebProperty.NAME); |
| value = prop.getAttributeValue(WebProperty.VALUE); |
| if(name == null || value == null) { |
| throw new IllegalArgumentException(rb.getString(LogFacade.NULL_WEB_MODULE_PROPERTY)); |
| } |
| if("ignoreHiddenJarFiles".equalsIgnoreCase(name)) { |
| loader.setIgnoreHiddenJarFiles(ConfigBeansUtilities.toBoolean(value)); |
| } else { |
| Object[] params = {name, value}; |
| logger.log(Level.WARNING, LogFacade.INVALID_PROPERTY, |
| params); |
| } |
| } |
| } |
| |
| /** |
| * Configure the session manager according to the persistence-type |
| * specified in the <session-manager> element and the related |
| * settings in the <manager-properties> and <store-properties> elements |
| * in sun-web.xml. |
| */ |
| private void configureSessionManager(SessionManager smBean, |
| WebBundleDescriptor wbd, |
| WebModuleConfig wmInfo) { |
| |
| SessionManagerConfigurationHelper configHelper = |
| new SessionManagerConfigurationHelper( |
| this, smBean, wbd, wmInfo, |
| webContainer.getServerConfigLookup()); |
| |
| PersistenceType persistence = configHelper.getPersistenceType(); |
| String frequency = configHelper.getPersistenceFrequency(); |
| String scope = configHelper.getPersistenceScope(); |
| |
| if (logger.isLoggable(Level.FINEST)) { |
| logger.log(Level.FINEST, LogFacade.CONFIGURE_SESSION_MANAGER, new Object[]{persistence.getType(), frequency, scope}); |
| } |
| |
| PersistenceStrategyBuilderFactory factory = |
| new PersistenceStrategyBuilderFactory( |
| webContainer.getServerConfigLookup(), services); |
| PersistenceStrategyBuilder builder = |
| factory.createPersistenceStrategyBuilder(persistence.getType(), |
| frequency, scope, this); |
| if (logger.isLoggable(Level.FINEST)) { |
| logger.log(Level.FINEST, LogFacade.PERSISTENCE_STRATEGY_BUILDER, builder.getClass().getName()); |
| } |
| |
| builder.initializePersistenceStrategy(this, smBean, |
| webContainer.getServerConfigLookup()); |
| } |
| |
| @Override |
| protected ServletRegistrationImpl createServletRegistrationImpl( |
| StandardWrapper wrapper) { |
| return new WebServletRegistrationImpl(wrapper, this); |
| } |
| |
| @Override |
| protected ServletRegistrationImpl createDynamicServletRegistrationImpl( |
| StandardWrapper wrapper) { |
| return new DynamicWebServletRegistrationImpl(wrapper, this); |
| } |
| |
| @Override |
| protected void removePatternFromServlet(Wrapper wrapper, String pattern) { |
| super.removePatternFromServlet(wrapper, pattern); |
| WebBundleDescriptor wbd = getWebBundleDescriptor(); |
| if (wbd == null) { |
| throw new IllegalStateException( |
| "Missing WebBundleDescriptor for " + getName()); |
| } |
| WebComponentDescriptor wcd = |
| wbd.getWebComponentByCanonicalName(wrapper.getName()); |
| if (wcd == null) { |
| throw new IllegalStateException( |
| "Missing WebComponentDescriptor for " + wrapper.getName()); |
| } |
| wcd.removeUrlPattern(pattern); |
| } |
| |
| /** |
| * Configure the properties of the session, such as the timeout, |
| * whether to force URL rewriting etc. |
| * HERCULES:mod passing in new param wbd |
| */ |
| private void configureSession(SessionProperties spBean, |
| WebBundleDescriptor wbd) { |
| |
| boolean timeoutConfigured = false; |
| int timeoutSeconds = 1800; // tomcat default (see StandardContext) |
| |
| setCookies(webContainer.instanceEnableCookies); |
| |
| if ((spBean != null) && (spBean.sizeWebProperty() > 0)) { |
| for(WebProperty prop : spBean.getWebProperty()) { |
| String name = prop.getAttributeValue(WebProperty.NAME); |
| String value = prop.getAttributeValue(WebProperty.VALUE); |
| if(name == null || value == null) { |
| throw new IllegalArgumentException(rb.getString(LogFacade.NULL_WEB_MODULE_PROPERTY)); |
| } |
| if("timeoutSeconds".equalsIgnoreCase(name)) { |
| try { |
| timeoutSeconds = Integer.parseInt(value); |
| timeoutConfigured = true; |
| } catch(NumberFormatException e) { |
| // XXX need error message |
| } |
| } else if("enableCookies".equalsIgnoreCase(name)) { |
| setCookies(ConfigBeansUtilities.toBoolean(value)); |
| } else if("enableURLRewriting".equalsIgnoreCase(name)) { |
| setEnableURLRewriting(ConfigBeansUtilities.toBoolean(value)); |
| } else { |
| if (logger.isLoggable(Level.INFO)) { |
| logger.log(Level.INFO, LogFacade.PROP_NOT_YET_SUPPORTED, name); |
| } |
| } |
| } |
| } |
| |
| int webXmlTimeoutSeconds = -1; |
| if (wbd != null) { |
| webXmlTimeoutSeconds = wbd.getSessionConfig().getSessionTimeout() * 60; |
| } |
| |
| //web.xml setting has precedence if it exists |
| //ignore if the value is the 30 min default |
| if (webXmlTimeoutSeconds != -1 && webXmlTimeoutSeconds != 1800) { |
| getManager().setMaxInactiveIntervalSeconds(webXmlTimeoutSeconds); |
| } else { |
| /* |
| * Do not override Tomcat default, unless 'timeoutSeconds' was |
| * specified in sun-web.xml |
| */ |
| if (timeoutConfigured) { |
| getManager().setMaxInactiveIntervalSeconds(timeoutSeconds); |
| } |
| } |
| } |
| |
| /** |
| * Configure the settings for the session cookie using the values |
| * in sun-web.xml's cookie-property |
| */ |
| private void configureCookieProperties(CookieProperties bean) { |
| if (bean != null) { |
| WebProperty[] props = bean.getWebProperty(); |
| if (props != null) { |
| SessionCookieConfig cookieConfig = new SessionCookieConfig(); |
| for(WebProperty prop : props) { |
| String name = prop.getAttributeValue(WebProperty.NAME); |
| String value = prop.getAttributeValue(WebProperty.VALUE); |
| if(name == null || value == null) { |
| throw new IllegalArgumentException(rb.getString(LogFacade.NULL_WEB_MODULE_PROPERTY)); |
| } |
| if("cookieName".equalsIgnoreCase(name)) { |
| cookieConfig.setName(value); |
| } else if("cookiePath".equalsIgnoreCase(name)) { |
| cookieConfig.setPath(value); |
| } else if("cookieMaxAgeSeconds".equalsIgnoreCase(name)) { |
| try { |
| cookieConfig.setMaxAge(Integer.parseInt(value)); |
| } catch(NumberFormatException e) { |
| // XXX need error message |
| } |
| } else if("cookieDomain".equalsIgnoreCase(name)) { |
| cookieConfig.setDomain(value); |
| } else if("cookieComment".equalsIgnoreCase(name)) { |
| cookieConfig.setComment(value); |
| } else if("cookieSecure".equalsIgnoreCase(name)) { |
| cookieConfig.setSecure(value); |
| } else if("cookieHttpOnly".equalsIgnoreCase(name)) { |
| cookieConfig.setHttpOnly(Boolean.valueOf(value)); |
| } else { |
| Object[] params = {name, value}; |
| logger.log(Level.WARNING, |
| LogFacade.INVALID_PROPERTY, |
| params); |
| } |
| } |
| if (props.length > 0) { |
| if (logger.isLoggable(Level.FINE)) { |
| logger.log(Level.FINE, LogFacade.CONFIGURE_COOKIE_PROPERTIES, new Object[]{getPath(), cookieConfig}); |
| } |
| setSessionCookieConfigFromSunWebXml(cookieConfig); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Instantiates the given Servlet class. |
| * |
| * @return the new Servlet instance |
| */ |
| @Override |
| protected <T extends Servlet> T createServletInstance(Class<T> clazz) |
| throws Exception { |
| if (DefaultServlet.class.equals(clazz) || |
| JspServlet.class.equals(clazz) || |
| webContainer == null) { |
| // Container-provided servlets, skip injection |
| return super.createServletInstance(clazz); |
| } else { |
| return webContainer.createServletInstance(this, clazz); |
| } |
| } |
| |
| /** |
| * Instantiates the given Filter class. |
| * |
| * @return the new Filter instance |
| */ |
| @Override |
| protected <T extends Filter> T createFilterInstance(Class<T> clazz) |
| throws Exception { |
| if (webContainer != null) { |
| return webContainer.createFilterInstance(this, clazz); |
| } else { |
| return super.createFilterInstance(clazz); |
| } |
| } |
| |
| /** |
| * Instantiates the given EventListener class. |
| * |
| * @return the new EventListener instance |
| */ |
| @Override |
| public <T extends EventListener> T createListenerInstance( |
| Class<T> clazz) throws Exception { |
| if (webContainer != null) { |
| return webContainer.createListenerInstance(this, clazz); |
| } else { |
| return super.createListenerInstance(clazz); |
| } |
| } |
| |
| /** |
| * Create an instance of a given class. |
| * |
| * @param clazz |
| * |
| * @return an instance of the given class |
| * @throws Exception |
| */ |
| @Override |
| public <T extends HttpUpgradeHandler> T createHttpUpgradeHandlerInstance(Class<T> clazz) throws Exception { |
| if (webContainer != null) { |
| return webContainer.createHttpUpgradeHandlerInstance(this, clazz); |
| } else { |
| return super.createHttpUpgradeHandlerInstance(clazz); |
| } |
| } |
| |
| |
| /* |
| * Servlet related probe events |
| */ |
| |
| public void servletInitializedEvent(String servletName) { |
| servletProbeProvider.servletInitializedEvent(servletName, |
| monitoringNodeName, vsId); |
| } |
| |
| public void servletDestroyedEvent(String servletName) { |
| servletProbeProvider.servletDestroyedEvent(servletName, |
| monitoringNodeName, vsId); |
| } |
| |
| public void beforeServiceEvent(String servletName) { |
| servletProbeProvider.beforeServiceEvent(servletName, |
| monitoringNodeName, vsId); |
| } |
| |
| public void afterServiceEvent(String servletName, int status) { |
| servletProbeProvider.afterServiceEvent(servletName, |
| status, monitoringNodeName, vsId); |
| } |
| |
| |
| /* |
| * HTTP session related probe events |
| */ |
| |
| @Override |
| public void sessionCreatedEvent(HttpSession session) { |
| sessionProbeProvider.sessionCreatedEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionDestroyedEvent(HttpSession session) { |
| sessionProbeProvider.sessionDestroyedEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionRejectedEvent(int maxSessions) { |
| sessionProbeProvider.sessionRejectedEvent(maxSessions, |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionExpiredEvent(HttpSession session) { |
| sessionProbeProvider.sessionExpiredEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionPersistedStartEvent(HttpSession session) { |
| sessionProbeProvider.sessionPersistedStartEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionPersistedEndEvent(HttpSession session) { |
| sessionProbeProvider.sessionPersistedEndEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionActivatedStartEvent(HttpSession session) { |
| sessionProbeProvider.sessionActivatedStartEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionActivatedEndEvent(HttpSession session) { |
| sessionProbeProvider.sessionActivatedEndEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionPassivatedStartEvent(HttpSession session) { |
| sessionProbeProvider.sessionPassivatedStartEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| @Override |
| public void sessionPassivatedEndEvent(HttpSession session) { |
| sessionProbeProvider.sessionPassivatedEndEvent(session.getId(), |
| monitoringNodeName, vsId); |
| } |
| |
| |
| /* |
| * Web module lifecycle related probe events |
| */ |
| |
| public void webModuleStartedEvent() { |
| webModuleProbeProvider.webModuleStartedEvent(monitoringNodeName, |
| vsId); |
| } |
| |
| public void webModuleStoppedEvent() { |
| webModuleProbeProvider.webModuleStoppedEvent(monitoringNodeName, |
| vsId); |
| } |
| |
| void processServletSecurityElement(ServletSecurityElement servletSecurityElement, |
| WebBundleDescriptor wbd, WebComponentDescriptor wcd) { |
| |
| Set<String> urlPatterns = |
| ServletSecurityHandler.getUrlPatternsWithoutSecurityConstraint(wcd); |
| |
| if (urlPatterns.size() > 0) { |
| SecurityConstraint securityConstraint = |
| ServletSecurityHandler.createSecurityConstraint(wbd, |
| urlPatterns, servletSecurityElement.getRolesAllowed(), |
| servletSecurityElement.getEmptyRoleSemantic(), |
| servletSecurityElement.getTransportGuarantee(), |
| null); |
| |
| //we know there is one WebResourceCollection there |
| WebResourceCollection webResColl = |
| securityConstraint.getWebResourceCollections().iterator().next(); |
| for (HttpMethodConstraintElement httpMethodConstraintElement : |
| servletSecurityElement.getHttpMethodConstraints()) { |
| String httpMethod = httpMethodConstraintElement.getMethodName(); |
| ServletSecurityHandler.createSecurityConstraint(wbd, |
| urlPatterns, httpMethodConstraintElement.getRolesAllowed(), |
| httpMethodConstraintElement.getEmptyRoleSemantic(), |
| httpMethodConstraintElement.getTransportGuarantee(), |
| httpMethod); |
| |
| //exclude this from the top level constraint |
| webResColl.addHttpMethodOmission(httpMethod); |
| } |
| } |
| } |
| |
| private SecurityConfig config = null; |
| |
| public SecurityConfig getSecurityConfig() { |
| return config; |
| } |
| |
| public void setSecurityConfig(SecurityConfig config) { |
| |
| if (config == null) { |
| return; |
| } |
| this.config = config; |
| |
| LoginConfig lc = config.getLoginConfig(); |
| if (lc != null) { |
| LoginConfiguration loginConf = new LoginConfigurationImpl(); |
| loginConf.setAuthenticationMethod(lc.getAuthMethod().name()); |
| loginConf.setRealmName(lc.getRealmName()); |
| |
| FormLoginConfig form = lc.getFormLoginConfig(); |
| if (form != null) { |
| loginConf.setFormErrorPage(form.getFormErrorPage()); |
| loginConf.setFormLoginPage(form.getFormLoginPage()); |
| } |
| |
| LoginConfigDecorator decorator = new LoginConfigDecorator(loginConf); |
| setLoginConfig(decorator); |
| getWebBundleDescriptor().setLoginConfiguration(loginConf); |
| } |
| |
| Set<org.glassfish.embeddable.web.config.SecurityConstraint> securityConstraints = |
| config.getSecurityConstraints(); |
| for (org.glassfish.embeddable.web.config.SecurityConstraint sc : securityConstraints) { |
| |
| com.sun.enterprise.deployment.web.SecurityConstraint securityConstraint = new SecurityConstraintImpl(); |
| |
| Set<org.glassfish.embeddable.web.config.WebResourceCollection> wrcs = |
| sc.getWebResourceCollection(); |
| for (org.glassfish.embeddable.web.config.WebResourceCollection wrc : wrcs) { |
| |
| WebResourceCollectionImpl webResourceColl = new WebResourceCollectionImpl(); |
| webResourceColl.setDisplayName(wrc.getName()); |
| for (String urlPattern : wrc.getUrlPatterns()) { |
| webResourceColl.addUrlPattern(urlPattern); |
| } |
| securityConstraint.addWebResourceCollection(webResourceColl); |
| |
| AuthorizationConstraintImpl ac = null; |
| if (sc.getAuthConstraint() != null && sc.getAuthConstraint().length > 0) { |
| ac = new AuthorizationConstraintImpl(); |
| for (String roleName : sc.getAuthConstraint()) { |
| Role role = new Role(roleName); |
| getWebBundleDescriptor().addRole(role); |
| ac.addSecurityRole(roleName); |
| } |
| } else { // DENY |
| ac = new AuthorizationConstraintImpl(); |
| } |
| securityConstraint.setAuthorizationConstraint(ac); |
| |
| UserDataConstraint udc = new UserDataConstraintImpl(); |
| udc.setTransportGuarantee( |
| ((sc.getDataConstraint() == TransportGuarantee.CONFIDENTIAL) ? |
| UserDataConstraint.CONFIDENTIAL_TRANSPORT : |
| UserDataConstraint.NONE_TRANSPORT)); |
| securityConstraint.setUserDataConstraint(udc); |
| |
| if (wrc.getHttpMethods() != null) { |
| for (String httpMethod : wrc.getHttpMethods()) { |
| webResourceColl.addHttpMethod(httpMethod); |
| } |
| } |
| |
| if (wrc.getHttpMethodOmissions() != null) { |
| for (String httpMethod : wrc.getHttpMethodOmissions()) { |
| webResourceColl.addHttpMethodOmission(httpMethod); |
| } |
| } |
| |
| getWebBundleDescriptor().addSecurityConstraint(securityConstraint); |
| TomcatDeploymentConfig.configureSecurityConstraint(this, getWebBundleDescriptor()); |
| } |
| } |
| |
| if (pipeline != null) { |
| GlassFishValve basic = pipeline.getBasic(); |
| if ((basic != null) && (basic instanceof java.net.Authenticator)) { |
| removeValve(basic); |
| } |
| GlassFishValve valves[] = pipeline.getValves(); |
| for (int i = 0; i < valves.length; i++) { |
| if (valves[i] instanceof java.net.Authenticator) { |
| removeValve(valves[i]); |
| } |
| } |
| } |
| |
| if (realm != null && realm instanceof RealmInitializer) { |
| ((RealmInitializer) realm).initializeRealm( |
| this.getWebBundleDescriptor(), |
| false, |
| ((VirtualServer)parent).getAuthRealmName()); |
| ((RealmInitializer)realm).setVirtualServer(getParent()); |
| ((RealmInitializer)realm).updateWebSecurityManager(); |
| setRealm(realm); |
| } |
| |
| } |
| |
| } |
| |
| class V3WebappLoader extends WebappLoader { |
| |
| final ClassLoader cl; |
| |
| V3WebappLoader(ClassLoader cl) { |
| this.cl = cl; |
| } |
| |
| @Override |
| protected ClassLoader createClassLoader() throws Exception { |
| return cl; |
| } |
| |
| /** |
| * Stops the nested classloader |
| */ |
| @Override |
| public void stopNestedClassLoader() { |
| // Do nothing. The nested (Webapp)ClassLoader is stopped in |
| // WebApplication.stop() |
| } |
| } |
| |
| /** |
| * Implementation of jakarta.servlet.ServletRegistration whose addMapping also |
| * updates the WebBundleDescriptor from the deployment backend. |
| */ |
| class WebServletRegistrationImpl extends ServletRegistrationImpl { |
| |
| public WebServletRegistrationImpl(StandardWrapper wrapper, |
| StandardContext context) { |
| super(wrapper, context); |
| } |
| |
| @Override |
| public Set<String> addMapping(String... urlPatterns) { |
| Set<String> conflicts = super.addMapping(urlPatterns); |
| if (conflicts.isEmpty() && urlPatterns != null && |
| urlPatterns.length > 0) { |
| /* |
| * Propagate the new mappings to the underlying |
| * WebBundleDescriptor provided by the deployment backend, |
| * so that corresponding security constraints may be calculated |
| * by the security subsystem, which uses the |
| * WebBundleDescriptor as its input |
| */ |
| WebBundleDescriptor wbd = ((WebModule) getContext()).getWebBundleDescriptor(); |
| if (wbd == null) { |
| throw new IllegalStateException( |
| "Missing WebBundleDescriptor for " + getContext().getName()); |
| } |
| WebComponentDescriptor wcd = |
| wbd.getWebComponentByCanonicalName(getName()); |
| if (wcd == null) { |
| throw new IllegalStateException( |
| "Missing WebComponentDescriptor for " + getName()); |
| } |
| for (String urlPattern : urlPatterns) { |
| wcd.addUrlPattern(urlPattern); |
| } |
| } |
| return conflicts; |
| } |
| } |
| |
| /** |
| * Implementation of ServletRegistration.Dynamic whose addMapping also |
| * updates the WebBundleDescriptor from the deployment backend. |
| */ |
| class DynamicWebServletRegistrationImpl |
| extends DynamicServletRegistrationImpl { |
| |
| private WebBundleDescriptor wbd; |
| private WebComponentDescriptor wcd; |
| private WebModule webModule; |
| |
| private String runAsRoleName = null; |
| private ServletSecurityElement servletSecurityElement = null; |
| |
| public DynamicWebServletRegistrationImpl(StandardWrapper wrapper, |
| WebModule webModule) { |
| super(wrapper, webModule); |
| this.webModule = webModule; |
| wbd = webModule.getWebBundleDescriptor(); |
| if (wbd == null) { |
| throw new IllegalStateException( |
| "Missing WebBundleDescriptor for " + |
| getContext().getName()); |
| } |
| wbd.setPolicyModified(true); |
| wcd = wbd.getWebComponentByCanonicalName(wrapper.getName()); |
| if (wcd == null) { |
| /* |
| * Servlet not present in the WebBundleDescriptor provided |
| * by the deployment backend, which means we are dealing with |
| * the dynamic registration for a programmtically added Servlet, |
| * as opposed to the dynamic registration for a Servlet with a |
| * preliminary declaration (that is, one without any class name). |
| * |
| * Propagate the new Servlet to the WebBundleDescriptor, so that |
| * corresponding security constraints may be calculated by the |
| * security subsystem, which uses the WebBundleDescriptor as its |
| * input. |
| */ |
| wcd = new WebComponentDescriptorImpl(); |
| wcd.setName(wrapper.getName()); |
| wcd.setCanonicalName(wrapper.getName()); |
| wbd.addWebComponentDescriptor(wcd); |
| String servletClassName = wrapper.getServletClassName(); |
| if (servletClassName != null) { |
| Class<? extends Servlet> clazz = wrapper.getServletClass(); |
| if (clazz == null) { |
| if (wrapper.getServlet() != null) { |
| clazz = wrapper.getServlet().getClass(); |
| } else { |
| try { |
| clazz = loadServletClass(servletClassName); |
| } catch(Exception ex) { |
| throw new IllegalArgumentException(ex); |
| } |
| } |
| wrapper.setServletClass(clazz); |
| } |
| processServletAnnotations(clazz, wbd, wcd, wrapper); |
| } else if (wrapper.getJspFile() == null) { |
| // Should never happen |
| throw new RuntimeException( |
| "Programmatic servlet registration without any " + |
| "supporting servlet class or jsp file"); |
| } |
| } |
| } |
| |
| @Override |
| public Set<String> addMapping(String... urlPatterns) { |
| Set<String> conflicts = super.addMapping(urlPatterns); |
| if (conflicts.isEmpty() && urlPatterns != null && |
| urlPatterns.length > 0) { |
| /* |
| * Propagate the new mappings to the underlying |
| * WebBundleDescriptor provided by the deployment backend, |
| * so that corresponding security constraints may be calculated |
| * by the security subsystem, which uses the |
| * WebBundleDescriptor as its input |
| */ |
| for (String urlPattern : urlPatterns) { |
| wcd.addUrlPattern(urlPattern); |
| } |
| } |
| return conflicts; |
| } |
| |
| @Override |
| public void setRunAsRole(String roleName) { |
| super.setRunAsRole(roleName); |
| // postpone processing as we can only setRunAsIdentity in WebComponentDescriptor once |
| this.runAsRoleName = roleName; |
| } |
| |
| @Override |
| public Set<String> setServletSecurity(ServletSecurityElement constraint) { |
| this.servletSecurityElement = constraint; |
| |
| Set<String> conflictUrls = new HashSet<String>(wcd.getUrlPatternsSet()); |
| conflictUrls.removeAll(ServletSecurityHandler.getUrlPatternsWithoutSecurityConstraint(wcd)); |
| conflictUrls.addAll(super.setServletSecurity(constraint)); |
| return conflictUrls; |
| } |
| |
| /** |
| * Completes preliminary servlet registration by loading the class with |
| * the given name and scanning it for servlet annotations |
| */ |
| @Override |
| protected void setServletClassName(String className) { |
| super.setServletClassName(className); |
| try { |
| Class <? extends Servlet> clazz = loadServletClass(className); |
| super.setServletClass(clazz); |
| processServletAnnotations(clazz, wbd, wcd, wrapper); |
| } catch(Exception ex) { |
| throw new IllegalArgumentException(ex); |
| } |
| } |
| |
| /** |
| * Completes preliminary servlet registration by scanning the supplied |
| * servlet class for servlet annotations |
| */ |
| @Override |
| protected void setServletClass(Class <? extends Servlet> clazz) { |
| super.setServletClass(clazz); |
| processServletAnnotations(clazz, wbd, wcd, wrapper); |
| } |
| |
| private void processServletAnnotations( |
| Class <? extends Servlet> clazz, |
| WebBundleDescriptor webBundleDescriptor, |
| WebComponentDescriptor wcd, StandardWrapper wrapper) { |
| |
| // Process DeclareRoles annotation |
| if (clazz.isAnnotationPresent(DeclareRoles.class)) { |
| DeclareRoles declareRoles = (DeclareRoles) |
| clazz.getAnnotation(DeclareRoles.class); |
| for (String roleName : declareRoles.value()) { |
| webBundleDescriptor.addRole(new Role(roleName)); |
| webModule.declareRoles(roleName); |
| } |
| } |
| // Process MultipartConfig annotation |
| if (clazz.isAnnotationPresent(MultipartConfig.class)) { |
| MultipartConfig mpConfig = (MultipartConfig) |
| clazz.getAnnotation(MultipartConfig.class); |
| wrapper.setMultipartLocation(mpConfig.location()); |
| wrapper.setMultipartMaxFileSize(mpConfig.maxFileSize()); |
| wrapper.setMultipartMaxRequestSize(mpConfig.maxRequestSize()); |
| wrapper.setMultipartFileSizeThreshold( |
| mpConfig.fileSizeThreshold()); |
| } |
| } |
| |
| void postProcessAnnotations() { |
| Class<? extends Servlet> clazz = wrapper.getServletClass(); |
| if (clazz == null) { // setJspFile |
| return; |
| } |
| |
| // Process RunAs |
| if (wcd.getRunAsIdentity() == null) { |
| String roleName = runAsRoleName; |
| if (roleName == null && clazz.isAnnotationPresent(RunAs.class)) { |
| RunAs runAs = (RunAs)clazz.getAnnotation(RunAs.class); |
| roleName = runAs.value(); |
| } |
| if (roleName != null) { |
| super.setRunAsRole(roleName); |
| |
| wbd.addRole(new Role(roleName)); |
| RunAsIdentityDescriptor runAsDesc = |
| new RunAsIdentityDescriptor(); |
| runAsDesc.setRoleName(roleName); |
| wcd.setRunAsIdentity(runAsDesc); |
| } |
| } |
| |
| // Process ServletSecurity |
| ServletSecurityElement ssElement = servletSecurityElement; |
| if (servletSecurityElement == null && |
| clazz.isAnnotationPresent(ServletSecurity.class)) { |
| ServletSecurity servletSecurity = (ServletSecurity) |
| clazz.getAnnotation(ServletSecurity.class); |
| ssElement = new ServletSecurityElement(servletSecurity); |
| } |
| if (ssElement != null) { |
| webModule.processServletSecurityElement( |
| ssElement, wbd, wcd); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private Class<? extends Servlet> loadServletClass(String className) |
| throws ClassNotFoundException { |
| return (Class <? extends Servlet>) |
| ctx.getLoader().getClassLoader().loadClass(className); |
| } |
| } |