/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt 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;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.management.ObjectName;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
import org.jboss.metadata.web.jboss.JBoss50WebMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.metadata.web.spec.Web25MetaData;
import org.jboss.metadata.web.spec.WebMetaData;
import org.jboss.mx.util.ObjectNameFactory;
import org.jboss.security.plugins.JaasSecurityManagerServiceMBean;
import org.jboss.web.deployers.AbstractWarDeployer;
import org.jboss.web.deployers.AbstractWarDeployment;
import org.jboss.web.tomcat.service.session.SessionIDGenerator;
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;
/**
* A concrete implementation of the AbstractWarDeployer that creates {@link #TomcatDeployment} instances as the web
* application bean representation.
*
* @see #getDeployment(VFSDeploymentUnit, WebMetaData)
*
* @author Scott.Stark@jboss.org
* @author Costin Manolache
* @author Wonne.Keysers@realsoftware.be
* @author Dimitris.Andreadis@jboss.org
* @author adrian@jboss.org
* @version $Revision: 91181 $
* @see org.jboss.web.deployers.AbstractWarDeployer
*/
public class TomcatDeployer extends AbstractWarDeployer implements TomcatDeployerMBean
{
// default object name
public static final ObjectName TOMCAT_SERVICE_NAME = ObjectNameFactory.create("jboss.web:service=WebServer");
// Constants -----------------------------------------------------
public static final String NAME = "TomcatDeployer";
/** The web app context implementation class */
private String contextClassName = "org.apache.catalina.core.StandardContext";
/**
* Unmarshall factory used for parsing shared web.xml.
*/
private static final UnmarshallerFactory factory = UnmarshallerFactory.newInstance();
/**
* Configurable map of tomcat authenticators Keyed in by the http auth method that gets plugged into the Context
* Config and then into the StandardContext
*/
private Properties authenticators = null;
/**
* Domain for tomcat6 mbeans
*/
private String catalinaDomain = "Catalina";
/**
* The fully qualified name of the class that will be used for session management if <tt>distributable</tt> is set
* to true.
*/
protected String managerClass = "org.jboss.web.tomcat.service.session.JBossCacheManager";
/** Whether to override the Manager impl for distributable webapps */
private boolean overrideDistributableManager = true;
/**
* A flag indicating if the JBoss Loader should be used
*/
private boolean useJBossWebLoader = false; // set to false as it was in war-deployers-jboss-beans.xml
/**
* JBAS-3358: Work directory shouldn't be deleted on Context Destroy
*/
private boolean deleteWorkDirOnContextDestroy = false;
/**
* JBAS-2283: Provide custom header based auth support
*/
private String httpHeaderForSSOAuth = null;
private String sessionCookieForSSOAuth = null;
/**
* Shared metaData.
*/
private JBossWebMetaData sharedMetaData = null;
/**
* The server xml configuration file name
*/
private String serverConfigFile = "server.xml";
/**
* Get the request attribute name under which the JAAS Subject is store
*/
private String subjectAttributeName = null;
/**
* Flag indicating whether web-app specific context xmls may set the privileged flag.
*/
private boolean allowSelfPrivilegedWebApps = false;
/** The service used to flush authentication cache on session invalidation. */
private JaasSecurityManagerServiceMBean secMgrService;
/** The AbstractWarDeployment implementation class */
private String deploymentClass = null;
/** The classloader for the Tomcat SAR */
private ClassLoader serviceClassLoader = null;
/** The JBoss Security Manager Wrapper */
private String securityManagement;
/** FQN of the SecurityContext Class */
private String securityContextClassName;
/** */
private String[] filteredPackages;
private boolean runtimeLifecycleCoupled = false;
private String policyRegistrationName;
public TomcatDeployer()
{
}
public String getName()
{
return NAME;
}
public String getManagerClass()
{
return managerClass;
}
public void setManagerClass(String managerClass)
{
this.managerClass = managerClass;
}
/**
* Gets whether the session <code>Manager</code> implementation for
* distributable webapps should be overridden with an instance of
* {@link #getManagerClass()}.
* <p>
* Setting this to <code>false</code> allows custom configuration of
* a manager via a <code>context.xml</code>. Default is <code>true</code>.
* </p>
*
* @return <code>true</code> if the manager should be overridden,
* <code>false</code> if the existing manager should be retained.
*/
public boolean getOverrideDistributableManager()
{
return this.overrideDistributableManager;
}
/**
* Sets whether the session <code>Manager</code> implementation for
* distributable webapps should be overridden with an instance of
* {@link #getManagerClass()}.
* <p>
* Setting this to <code>false</code> allows custom configuration of
* a manager via a <code>context.xml</code>. Default is <code>true</code>.
* </p>
*
* @param override <code>true</code> if the manager should be overridden,
* <code>false</code> if the existing manager should be retained.
*/
public void setOverrideDistributableManager(boolean override)
{
this.overrideDistributableManager = override;
}
public ClassLoader getServiceClassLoader()
{
return serviceClassLoader;
}
public void setServiceClassLoader(ClassLoader serviceClassLoader)
{
this.serviceClassLoader = serviceClassLoader;
}
public String getDomain()
{
return this.catalinaDomain;
}
public Properties getAuthenticators()
{
return this.authenticators;
}
public void setAuthenticators(Properties prop)
{
this.authenticators = prop;
log.debug("Passed set of authenticators=" + prop);
}
/**
* The most important atteribute - defines the managed domain. A catalina instance (engine) corresponds to a JMX
* domain, that's how we know where to deploy webapps.
*
* @param catalinaDomain the domain portion of the JMX ObjectNames
*/
public void setDomain(String catalinaDomain)
{
this.catalinaDomain = catalinaDomain;
}
public void setContextMBeanCode(String className)
{
this.contextClassName = className;
}
public String getContextMBeanCode()
{
return contextClassName;
}
public boolean getDeleteWorkDirOnContextDestroy()
{
return deleteWorkDirOnContextDestroy;
}
public void setDeleteWorkDirOnContextDestroy(boolean deleteFlag)
{
this.deleteWorkDirOnContextDestroy = deleteFlag;
}
public String getHttpHeaderForSSOAuth()
{
return httpHeaderForSSOAuth;
}
public void setHttpHeaderForSSOAuth(String httpHeader)
{
this.httpHeaderForSSOAuth = httpHeader;
}
public String getSessionCookieForSSOAuth()
{
return sessionCookieForSSOAuth;
}
public void setSessionCookieForSSOAuth(String sessionC)
{
this.sessionCookieForSSOAuth = sessionC;
}
/**
* The SessionIdAlphabet is the set of characters used to create a session Id
*/
public void setSessionIdAlphabet(String sessionIdAlphabet)
{
SessionIDGenerator.getInstance().setSessionIdAlphabet(sessionIdAlphabet);
}
/**
* The SessionIdAlphabet is the set of characters used to create a session Id
*/
public String getSessionIdAlphabet()
{
return SessionIDGenerator.getInstance().getSessionIdAlphabet();
}
@Deprecated
public boolean getUseJBossWebLoader()
{
return useJBossWebLoader;
}
@Deprecated
public void setUseJBossWebLoader(boolean flag)
{
log.warn("This flag is ignored, see JIRA issue JBAS-6914 on the new MC JBossCL usage.");
this.useJBossWebLoader = flag;
}
public String getConfigFile()
{
return serverConfigFile;
}
public void setConfigFile(String configFile)
{
this.serverConfigFile = configFile;
}
@Override
public String getSubjectAttributeName()
{
return this.subjectAttributeName;
}
@Override
public void setSubjectAttributeName(String name)
{
this.subjectAttributeName = name;
}
public boolean isAllowSelfPrivilegedWebApps()
{
return allowSelfPrivilegedWebApps;
}
public void setAllowSelfPrivilegedWebApps(boolean allowSelfPrivilegedWebApps)
{
this.allowSelfPrivilegedWebApps = allowSelfPrivilegedWebApps;
}
public void setSecurityManagerService(JaasSecurityManagerServiceMBean mgr)
{
this.secMgrService = mgr;
}
public void setPolicyRegistrationName(String policyRegistration)
{
this.policyRegistrationName = policyRegistration;
}
public void setSecurityManagementName(String securityManagement)
{
this.securityManagement = securityManagement;
}
public void setSecurityContextClassName(String securityContextClassName)
{
this.securityContextClassName = securityContextClassName;
}
public String[] getFilteredPackages()
{
return filteredPackages;
}
public void setFilteredPackages(String[] pkgs)
{
this.filteredPackages = pkgs;
}
public String getDeploymentClass()
{
return deploymentClass;
}
public void setDeploymentClass(String deploymentClass)
{
this.deploymentClass = deploymentClass;
}
/**
* Gets whether this object should start/stop the JBoss Web runtime during execution of its own start/stop lifecycle
* callbacks.
*
* @return <code>true</code> if a call to {@link #start()} should trigger a call to {@link #startWebServer()} and a
* call to {@link #stop()} should trigger a call to {@link #stopWebServer()}; <code>false</code> if the
* webserver runtime lifecycle will be separately managed. Default is <code>false</code>.
*/
public boolean isRuntimeLifecycleCoupled()
{
return runtimeLifecycleCoupled;
}
/**
* Sets whether this object should start/stop the JBoss Web runtime during execution of its own start/stop lifecycle
* callbacks.
*
* @param coupled <code>true</code> if a call to {@link #start()} should trigger a call to
* {@link #startWebServer()} and a call to {@link #stop()} should trigger a call to
* {@link #stopWebServer()}; <code>false</code> if the webserver runtime lifecycle will be separately
* managed. Default is <code>false</code>.
*/
public void setRuntimeLifecycleCoupled(boolean coupled)
{
runtimeLifecycleCoupled = coupled;
}
/**
* Start the deployer. This sets up the tomcat core.
*/
@Override
public void start() throws Exception
{
super.start();
// Parse shared web.xml
Unmarshaller unmarshaller = factory.newUnmarshaller();
URL webXml = this.getClass().getClassLoader().getResource("web.xml");
if (webXml == null)
{
webXml = this.getClass().getClassLoader().getResource("conf/web.xml");
}
if (webXml == null)
throw new IllegalStateException("Unable to find shared web.xml or conf/web.xml");
SchemaBinding schema = JBossXBBuilder.build(Web25MetaData.class);
Web25MetaData confWebMD = (Web25MetaData) unmarshaller.unmarshal(webXml.toString(), schema);
sharedMetaData = new JBoss50WebMetaData();
sharedMetaData.merge(null, confWebMD);
}
@Override
public void stop() throws Exception
{
super.stop();
}
/**
* Create a tomcat war deployment bean for the deployment unit/metaData.
*
* @param unit - the current web app deployment unit
* @param metaData - the parsed metdata for the web app deployment
* @return TomcatDeployment instance
*/
@Override
public AbstractWarDeployment getDeployment(DeploymentUnit unit, JBossWebMetaData metaData) throws Exception
{
String className = (deploymentClass == null)
? "org.jboss.web.tomcat.service.deployers.TomcatDeployment"
: deploymentClass;
AbstractWarDeployment deployment = (AbstractWarDeployment) (getClass().getClassLoader().loadClass(className))
.newInstance();
DeployerConfig config = new DeployerConfig();
config.setDefaultSecurityDomain(defaultSecurityDomain);
config.setSubjectAttributeName(subjectAttributeName);
config.setServiceClassLoader((getServiceClassLoader() == null)
? getClass().getClassLoader()
: getServiceClassLoader());
config.setManagerClass(managerClass);
config.setOverrideDistributableManager(overrideDistributableManager);
config.setJava2ClassLoadingCompliance(java2ClassLoadingCompliance);
config.setUnpackWars(unpackWars);
config.setLenientEjbLink(this.lenientEjbLink);
config.setCatalinaDomain(catalinaDomain);
config.setContextClassName(contextClassName);
config.setServiceName(null);
config.setSubjectAttributeName(subjectAttributeName);
config.setUseJBossWebLoader(useJBossWebLoader);
config.setAllowSelfPrivilegedWebApps(allowSelfPrivilegedWebApps);
config.setSecurityManagerService(secMgrService);
config.setFilteredPackages(filteredPackages);
config.setSharedMetaData(sharedMetaData);
config.setDeleteWorkDirs(deleteWorkDirOnContextDestroy);
config.setSecurityContextClassName(securityContextClassName);
deployment.setSecurityManagementName(securityManagement);
deployment.setPolicyRegistrationName(policyRegistrationName);
// Add a dependency on the webserver itself
List<String> depends = metaData.getDepends();
if (depends == null)
{
depends = new ArrayList<String>();
metaData.setDepends(depends);
}
depends.add(TOMCAT_SERVICE_NAME.getCanonicalName());
deployment.setServer(super.getServer());
deployment.init(config);
return deployment;
}
public void create() throws Exception
{
// MBeanServer server = MBeanServerLocator.locateJBoss();
// if (server != null)
// server.registerMBean(this, OBJECT_NAME);
}
public void destroy() throws Exception
{
// MBeanServer server = MBeanServerLocator.locateJBoss();
// if (server != null)
// server.unregisterMBean(OBJECT_NAME);
}
}