/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.web.tomcat.service.deployers;
// $Id: JBossContextConfig.java 97419 2009-12-03 17:06:50Z scott.stark@jboss.org $
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.xml.namespace.QName;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.SessionCookie;
import org.apache.catalina.startup.ContextConfig;
import org.apache.tomcat.util.IntrospectionUtils;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
import org.jboss.kernel.Kernel;
import org.jboss.kernel.plugins.bootstrap.basic.KernelConstants;
import org.jboss.logging.Logger;
import org.jboss.metadata.javaee.spec.DescriptionGroupMetaData;
import org.jboss.metadata.javaee.spec.ParamValueMetaData;
import org.jboss.metadata.javaee.spec.SecurityRoleMetaData;
import org.jboss.metadata.javaee.spec.SecurityRoleRefMetaData;
import org.jboss.metadata.javaee.spec.SecurityRoleRefsMetaData;
import org.jboss.metadata.javaee.spec.SecurityRolesMetaData;
import org.jboss.metadata.web.jboss.JBossServletMetaData;
import org.jboss.metadata.web.jboss.JBossServletsMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.metadata.web.spec.AuthConstraintMetaData;
import org.jboss.metadata.web.spec.DispatcherType;
import org.jboss.metadata.web.spec.ErrorPageMetaData;
import org.jboss.metadata.web.spec.FilterMappingMetaData;
import org.jboss.metadata.web.spec.FilterMetaData;
import org.jboss.metadata.web.spec.FiltersMetaData;
import org.jboss.metadata.web.spec.JspConfigMetaData;
import org.jboss.metadata.web.spec.JspPropertyGroup;
import org.jboss.metadata.web.spec.ListenerMetaData;
import org.jboss.metadata.web.spec.LocaleEncodingMetaData;
import org.jboss.metadata.web.spec.LocaleEncodingsMetaData;
import org.jboss.metadata.web.spec.LoginConfigMetaData;
import org.jboss.metadata.web.spec.MimeMappingMetaData;
import org.jboss.metadata.web.spec.SecurityConstraintMetaData;
import org.jboss.metadata.web.spec.ServletMappingMetaData;
import org.jboss.metadata.web.spec.SessionConfigMetaData;
import org.jboss.metadata.web.spec.TaglibMetaData;
import org.jboss.metadata.web.spec.TransportGuaranteeType;
import org.jboss.metadata.web.spec.WebResourceCollectionMetaData;
import org.jboss.metadata.web.spec.WebResourceCollectionsMetaData;
import org.jboss.metadata.web.spec.WelcomeFileListMetaData;
import org.jboss.util.StringPropertyReplacer;
import org.jboss.util.xml.JBossEntityResolver;
import org.jboss.virtual.VirtualFile;
import org.jboss.web.tomcat.metadata.ContextMetaData;
import org.jboss.web.tomcat.metadata.ParameterMetaData;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;
import org.jboss.xb.binding.sunday.unmarshalling.SchemaBinding;
import org.jboss.xb.builder.JBossXBBuilder;
@SuppressWarnings("unchecked")
public class JBossContextConfig extends ContextConfig
{
public static ThreadLocal<JBossWebMetaData> metaDataLocal = new ThreadLocal<JBossWebMetaData>();
public static ThreadLocal<JBossWebMetaData> metaDataShared = new ThreadLocal<JBossWebMetaData>();
public static ThreadLocal<DeployerConfig> deployerConfig = new ThreadLocal<DeployerConfig>();
public static ThreadLocal<Kernel> kernelLocal = new ThreadLocal<Kernel>();
public static ThreadLocal<DeploymentUnit> deploymentUnitLocal = new ThreadLocal<DeploymentUnit>();
private static Logger log = Logger.getLogger(JBossContextConfig.class);
private boolean runDestroy = false;
/**
* <p>
* Creates a new instance of {@code JBossContextConfig}.
* </p>
*/
public JBossContextConfig()
{
super();
try
{
Map authMap = this.getAuthenticators();
if (authMap.size() > 0)
customAuthenticators = authMap;
}
catch (Exception e)
{
log.debug("Failed to load the customized authenticators", e);
}
runDestroy = deployerConfig.get().isDeleteWorkDirs();
}
@Override
protected void applicationWebConfig()
{
processWebMetaData(metaDataLocal.get());
processContextParameters();
}
@Override
protected void defaultWebConfig()
{
processWebMetaData(metaDataShared.get());
ServletContext servletContext = context.getServletContext();
Kernel kernel = kernelLocal.get();
DeploymentUnit unit = deploymentUnitLocal.get();
log.debug("Setting MC attributes, kernel: " + kernel + ", unit: " + unit);
servletContext.setAttribute(KernelConstants.KERNEL_NAME, kernel);
servletContext.setAttribute(DeploymentUnit.class.getName(), unit);
}
protected void processWebMetaData(JBossWebMetaData metaData)
{
if (context instanceof StandardContext)
{
((StandardContext)context).setReplaceWelcomeFiles(true);
}
// Metadata complete
context.setIgnoreAnnotations(metaData.isMetadataComplete());
// SetPublicId
if (metaData.is25())
context.setPublicId("/javax/servlet/resources/web-app_2_5.dtd");
else if (metaData.is24())
context.setPublicId("/javax/servlet/resources/web-app_2_4.dtd");
else if (metaData.is23())
context.setPublicId(org.apache.catalina.startup.Constants.WebDtdPublicId_23);
else
context.setPublicId(org.apache.catalina.startup.Constants.WebDtdPublicId_22);
// processContextParameters() provides a merged view of the context params
// Display name
DescriptionGroupMetaData dg = metaData.getDescriptionGroup();
if (dg != null)
{
String displayName = dg.getDisplayName();
if (displayName != null)
{
context.setDisplayName(displayName);
}
}
// Distributable
if (metaData.getDistributable() != null)
context.setDistributable(true);
// Error pages
List<ErrorPageMetaData> errorPages = metaData.getErrorPages();
if (errorPages != null)
{
for (ErrorPageMetaData value : errorPages)
{
org.apache.catalina.deploy.ErrorPage errorPage = new org.apache.catalina.deploy.ErrorPage();
errorPage.setErrorCode(value.getErrorCode());
errorPage.setExceptionType(value.getExceptionType());
errorPage.setLocation(value.getLocation());
context.addErrorPage(errorPage);
}
}
// Filter definitions
FiltersMetaData filters = metaData.getFilters();
if (filters != null)
{
for (FilterMetaData value : filters)
{
org.apache.catalina.deploy.FilterDef filterDef = new org.apache.catalina.deploy.FilterDef();
filterDef.setFilterName(value.getName());
filterDef.setFilterClass(value.getFilterClass());
if (value.getInitParam() != null)
for (ParamValueMetaData param : value.getInitParam())
{
filterDef.addInitParameter(param.getParamName(), param.getParamValue());
}
context.addFilterDef(filterDef);
}
}
// Filter mappings
List<FilterMappingMetaData> filtersMappings = metaData.getFilterMappings();
if (filtersMappings != null)
{
for (FilterMappingMetaData value : filtersMappings)
{
org.apache.catalina.deploy.FilterMap filterMap = new org.apache.catalina.deploy.FilterMap();
filterMap.setFilterName(value.getFilterName());
List<String> servletNames = value.getServletNames();
if (servletNames != null)
{
for (String name : servletNames)
filterMap.addServletName(name);
}
List<String> urlPatterns = value.getUrlPatterns();
if (urlPatterns != null)
{
for (String pattern : urlPatterns)
filterMap.addURLPattern(pattern);
}
List<DispatcherType> dispatchers = value.getDispatchers();
if (dispatchers != null)
{
for (DispatcherType type : dispatchers)
filterMap.setDispatcher(type.name());
}
context.addFilterMap(filterMap);
}
}
// Listeners
List<ListenerMetaData> listeners = metaData.getListeners();
if (listeners != null)
{
for (ListenerMetaData value : listeners)
{
context.addApplicationListener(value.getListenerClass());
}
}
// Login configuration
LoginConfigMetaData loginConfig = metaData.getLoginConfig();
if (loginConfig != null)
{
org.apache.catalina.deploy.LoginConfig loginConfig2 = new org.apache.catalina.deploy.LoginConfig();
loginConfig2.setAuthMethod(loginConfig.getAuthMethod());
loginConfig2.setRealmName(loginConfig.getRealmName());
if (loginConfig.getFormLoginConfig() != null)
{
loginConfig2.setLoginPage(loginConfig.getFormLoginConfig().getLoginPage());
loginConfig2.setErrorPage(loginConfig.getFormLoginConfig().getErrorPage());
}
context.setLoginConfig(loginConfig2);
}
// MIME mappings
List<MimeMappingMetaData> mimes = metaData.getMimeMappings();
if (mimes != null)
{
for (MimeMappingMetaData value : mimes)
{
context.addMimeMapping(value.getExtension(), value.getMimeType());
}
}
// Security constraints
List<SecurityConstraintMetaData> scs = metaData.getSecurityContraints();
if (scs != null)
{
for (SecurityConstraintMetaData value : scs)
{
org.apache.catalina.deploy.SecurityConstraint constraint = new org.apache.catalina.deploy.SecurityConstraint();
TransportGuaranteeType tg = value.getTransportGuarantee();
constraint.setUserConstraint(tg.name());
AuthConstraintMetaData acmd = value.getAuthConstraint();
constraint.setAuthConstraint(acmd != null);
if (acmd != null)
{
if (acmd.getRoleNames() != null)
for (String role : acmd.getRoleNames())
{
constraint.addAuthRole(role);
}
}
WebResourceCollectionsMetaData wrcs = value.getResourceCollections();
if (wrcs != null)
{
for (WebResourceCollectionMetaData wrc : wrcs)
{
org.apache.catalina.deploy.SecurityCollection collection2 = new org.apache.catalina.deploy.SecurityCollection();
collection2.setName(wrc.getName());
List<String> methods = wrc.getHttpMethods();
if (methods != null)
{
for (String method : wrc.getHttpMethods())
{
collection2.addMethod(method);
}
}
List<String> patterns = wrc.getUrlPatterns();
if (patterns != null)
{
for (String pattern : patterns)
{
collection2.addPattern(pattern);
}
}
constraint.addCollection(collection2);
}
}
context.addConstraint(constraint);
}
}
// Security roles
SecurityRolesMetaData roles = metaData.getSecurityRoles();
if (roles != null)
{
for (SecurityRoleMetaData value : roles)
{
context.addSecurityRole(value.getRoleName());
}
}
// Servlet
JBossServletsMetaData servlets = metaData.getServlets();
if (servlets != null)
{
for (JBossServletMetaData value : servlets)
{
org.apache.catalina.Wrapper wrapper = context.createWrapper();
wrapper.setName(value.getName());
wrapper.setServletClass(value.getServletClass());
if (value.getJspFile() != null)
{
wrapper.setJspFile(value.getJspFile());
}
wrapper.setLoadOnStartup(value.getLoadOnStartup());
if (value.getRunAs() != null)
{
wrapper.setRunAs(value.getRunAs().getRoleName());
}
List<ParamValueMetaData> params = value.getInitParam();
if (params != null)
{
for (ParamValueMetaData param : params)
{
wrapper.addInitParameter(param.getParamName(), param.getParamValue());
}
}
SecurityRoleRefsMetaData refs = value.getSecurityRoleRefs();
if (refs != null)
{
for (SecurityRoleRefMetaData ref : refs)
{
wrapper.addSecurityReference(ref.getRoleName(), ref.getRoleLink());
}
}
context.addChild(wrapper);
}
}
// Servlet mapping
List<ServletMappingMetaData> smappings = metaData.getServletMappings();
if (smappings != null)
{
for (ServletMappingMetaData value : smappings)
{
List<String> urlPatterns = value.getUrlPatterns();
if (urlPatterns != null)
{
for (String pattern : urlPatterns)
context.addServletMapping(pattern, value.getServletName());
}
}
}
// JSP mappings
JspConfigMetaData config = metaData.getJspConfig();
if (config != null)
{
List<JspPropertyGroup> groups = config.getPropertyGroups();
if (groups != null)
{
for (JspPropertyGroup group : groups)
{
for (String pattern : group.getUrlPatterns())
{
context.addJspMapping(pattern);
}
}
}
// Taglib
List<TaglibMetaData> taglibs = config.getTaglibs();
if (taglibs != null)
{
for (TaglibMetaData taglib : taglibs)
{
context.addTaglib(taglib.getTaglibUri(), taglib.getTaglibLocation());
}
}
}
// Locale encoding mapping
LocaleEncodingsMetaData locales = metaData.getLocalEncodings();
if (locales != null)
{
for (LocaleEncodingMetaData value : locales.getMappings())
{
context.addLocaleEncodingMappingParameter(value.getLocale(), value.getEncoding());
}
}
// Welcome files
WelcomeFileListMetaData welcomeFiles = metaData.getWelcomeFileList();
if (welcomeFiles != null)
{
for (String value : welcomeFiles.getWelcomeFiles())
context.addWelcomeFile(value);
}
// Session timeout
SessionConfigMetaData scmd = metaData.getSessionConfig();
if (scmd != null)
{
context.setSessionTimeout(scmd.getSessionTimeout());
}
}
/**
* <p>
* Retrieves the map of authenticators according to the settings made available by {@code TomcatService}.
* </p>
*
* @return a {@code Map} containing the authenticator that must be used for each authentication method.
* @throws Exception if an error occurs while getting the authenticators.
*/
protected Map getAuthenticators() throws Exception
{
Map authenticators = new HashMap();
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
Properties authProps = this.getAuthenticatorsFromJndi();
if (authProps != null)
{
Set keys = authProps.keySet();
Iterator iter = keys != null ? keys.iterator() : null;
while (iter != null && iter.hasNext())
{
String key = (String)iter.next();
String authenticatorStr = (String)authProps.get(key);
Class authClass = tcl.loadClass(authenticatorStr);
authenticators.put(key, authClass.newInstance());
}
}
if (log.isTraceEnabled())
log.trace("Authenticators plugged in::" + authenticators);
return authenticators;
}
/**
* <p>
* Get the key-pair of authenticators from the JNDI.
* </p>
*
* @return a {@code Properties} object containing the authenticator class name for each authentication method.
* @throws NamingException if an error occurs while looking up the JNDI.
*/
private Properties getAuthenticatorsFromJndi() throws NamingException
{
return (Properties)new InitialContext().lookup("TomcatAuthenticators");
}
/**
* Process the context parameters. Let a user application
* override the sharedMetaData values.
*/
protected void processContextParameters()
{
JBossWebMetaData local = metaDataLocal.get();
JBossWebMetaData shared = metaDataShared.get();
Map<String, String> overrideParams = new HashMap<String, String>();
List<ParamValueMetaData> params = local.getContextParams();
if (params != null)
{
for (ParamValueMetaData param : params)
{
overrideParams.put(param.getParamName(), param.getParamValue());
}
}
params = shared.getContextParams();
if (params != null)
{
for (ParamValueMetaData param : params)
{
if (overrideParams.get(param.getParamName()) == null)
{
overrideParams.put(param.getParamName(), param.getParamValue());
}
}
}
for (String key : overrideParams.keySet())
{
context.addParameter(key, overrideParams.get(key));
}
}
/**
* Process a "init" event for this Context.
*/
protected void init()
{
context.setConfigured(false);
ok = true;
if (!context.getOverride())
{
processContextConfig("context.xml", false);
processContextConfig(getHostConfigPath(org.apache.catalina.startup.Constants.HostContextXml), false);
}
// This should come from the deployment unit
processContextConfig(context.getConfigFile(), true);
}
protected void processContextConfig(String resourceName, boolean local)
{
ClassLoader oldCl = SecurityActions.getContextClassLoader();
SecurityActions.setContextClassLoader(this.getClass().getClassLoader());
ContextMetaData contextMetaData = null;
try
{
SchemaBinding schema = JBossXBBuilder.build(ContextMetaData.class);
Unmarshaller u = UnmarshallerFactory.newInstance().newUnmarshaller();
u.setSchemaValidation(false);
u.setValidation(false);
u.setEntityResolver(new JBossEntityResolver());
InputStream is = null;
try
{
if (local)
{
DeploymentUnit localUnit = deploymentUnitLocal.get();
if (localUnit instanceof VFSDeploymentUnit)
{
VFSDeploymentUnit vfsUnit = (VFSDeploymentUnit)localUnit;
VirtualFile vf = vfsUnit.getFile(resourceName);
if (vf != null)
is = vf.openStream();
}
}
if (is == null)
is = getClass().getClassLoader().getResourceAsStream(resourceName);
if (is != null)
contextMetaData = ContextMetaData.class.cast(u.unmarshal(is, schema));
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
// Ignore
}
}
}
}
catch (Exception e)
{
log.error("XML error parsing: " + resourceName, e);
ok = false;
return;
}
finally
{
SecurityActions.setContextClassLoader(oldCl);
}
if (contextMetaData != null)
{
try
{
if (contextMetaData.getAttributes() != null)
{
Iterator<QName> names = contextMetaData.getAttributes().keySet().iterator();
while (names.hasNext())
{
QName name = names.next();
String value = (String)contextMetaData.getAttributes().get(name);
// FIXME: This should be done by XB
value = StringPropertyReplacer.replaceProperties(value);
IntrospectionUtils.setProperty(context, name.getLocalPart(), value);
}
}
TomcatService.addLifecycleListeners(context, contextMetaData.getListeners());
// Context/Realm
if (contextMetaData.getRealm() != null)
{
context.setRealm((org.apache.catalina.Realm)TomcatService.getInstance(contextMetaData.getRealm(), null));
}
// Context/Valve
TomcatService.addValves(context, contextMetaData.getValves());
// Context/InstanceListener
if (contextMetaData.getInstanceListeners() != null)
{
Iterator<String> listeners = contextMetaData.getInstanceListeners().iterator();
while (listeners.hasNext())
{
context.addInstanceListener(listeners.next());
}
}
// Context/Loader
if (contextMetaData.getLoader() != null)
{
// This probably won't work very well in JBoss
context.setLoader((org.apache.catalina.Loader)TomcatService.getInstance(contextMetaData.getLoader(), "org.apache.catalina.loader.WebappLoader"));
}
// Context/Manager
if (contextMetaData.getManager() != null)
{
context.setManager((org.apache.catalina.Manager)TomcatService.getInstance(contextMetaData.getManager(),
"org.apache.catalina.session.StandardManager"));
}
// Context/Parameter
if (contextMetaData.getParameters() != null)
{
Iterator<ParameterMetaData> parameterMetaDatas = contextMetaData.getParameters().iterator();
while (parameterMetaDatas.hasNext())
{
ParameterMetaData parameterMetaData = parameterMetaDatas.next();
context.addApplicationParameter((org.apache.catalina.deploy.ApplicationParameter)TomcatService.getInstance(parameterMetaData, null));
}
}
// Context/Resources
if (contextMetaData.getResources() != null)
{
context.setResources((javax.naming.directory.DirContext)TomcatService.getInstance(contextMetaData.getResources(),
"org.apache.naming.resources.FileDirContext"));
}
// Context/SessionCookie
if (contextMetaData.getSessionCookie() != null)
{
SessionCookie sessionCookie = new SessionCookie();
sessionCookie.setComment(contextMetaData.getSessionCookie().getComment());
sessionCookie.setDomain(contextMetaData.getSessionCookie().getDomain());
sessionCookie.setHttpOnly(contextMetaData.getSessionCookie().getHttpOnly());
sessionCookie.setPath(contextMetaData.getSessionCookie().getPath());
sessionCookie.setSecure(contextMetaData.getSessionCookie().getSecure());
context.setSessionCookie(sessionCookie);
}
}
catch (Exception e)
{
log.error("Error processing: " + resourceName, e);
ok = false;
}
}
}
protected void destroy()
{
if (runDestroy)
{
super.destroy();
}
}
}