package org.jboss.ejb;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.management.ObjectName;
import javax.security.jacc.PolicyContext;
import javax.transaction.TransactionManager;
import org.jboss.deployment.DeploymentException;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.deployment.J2eeApplicationMetaData;
import org.jboss.deployment.SubDeployerSupport;
import org.jboss.ejb.plugins.EnterpriseBeanPolicyContextHandler;
import org.jboss.logging.Logger;
import org.jboss.metadata.ApplicationMetaData;
import org.jboss.metadata.MetaData;
import org.jboss.metadata.XmlFileLoader;
import org.jboss.mx.loading.LoaderRepositoryFactory;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.mx.util.ObjectNameConverter;
import org.jboss.system.ServiceControllerMBean;
import org.jboss.verifier.BeanVerifier;
import org.jboss.verifier.event.VerificationEvent;
import org.jboss.verifier.event.VerificationListener;
import org.w3c.dom.Element;
public class EJBDeployer
extends SubDeployerSupport
implements EJBDeployerMBean
{
private ServiceControllerMBean serviceController;
private HashMap deployments = new HashMap();
private boolean verifyDeployments;
private boolean verifierVerbose;
private boolean strictVerifier;
private boolean metricsEnabled;
private boolean validateDTDs;
private ObjectName webServiceName;
private ObjectName transactionManagerServiceName;
private TransactionManager tm;
private boolean callByValue;
public boolean isCallByValue()
{
return callByValue;
}
public void setCallByValue(boolean callByValue)
{
this.callByValue = callByValue;
}
public Iterator listDeployedApplications()
{
return deployments.values().iterator();
}
protected void startService() throws Exception
{
serviceController = (ServiceControllerMBean)
MBeanProxyExt.create(ServiceControllerMBean.class,
ServiceControllerMBean.OBJECT_NAME, server);
tm = (TransactionManager)getServer().getAttribute(transactionManagerServiceName,
"TransactionManager");
EnterpriseBeanPolicyContextHandler beanHandler = new EnterpriseBeanPolicyContextHandler();
PolicyContext.registerHandler(EnterpriseBeanPolicyContextHandler.EJB_CONTEXT_KEY,
beanHandler, false);
BeanMetaDataPolicyContextHandler metadataHandler = new BeanMetaDataPolicyContextHandler();
PolicyContext.registerHandler(BeanMetaDataPolicyContextHandler.METADATA_CONTEXT_KEY,
metadataHandler, false);
EJBArgsPolicyContextHandler argsHandler = new EJBArgsPolicyContextHandler();
PolicyContext.registerHandler(EJBArgsPolicyContextHandler.EJB_ARGS_KEY,
argsHandler, false);
SOAPMsgPolicyContextHandler msgHandler = new SOAPMsgPolicyContextHandler();
PolicyContext.registerHandler(SOAPMsgPolicyContextHandler.SEI_ARGS_KEY,
msgHandler, false);
super.startService();
}
protected void stopService() throws Exception
{
for( Iterator modules = deployments.values().iterator();
modules.hasNext(); )
{
DeploymentInfo di = (DeploymentInfo) modules.next();
stop(di);
}
for( Iterator modules = new ArrayList(deployments.values()).iterator();
modules.hasNext(); )
{
DeploymentInfo di = (DeploymentInfo) modules.next();
destroy(di);
}
deployments.clear();
super.stopService();
serviceController = null;
tm = null;
}
public void setVerifyDeployments( boolean verify )
{
verifyDeployments = verify;
}
public boolean getVerifyDeployments()
{
return verifyDeployments;
}
public void setVerifierVerbose(boolean verbose)
{
verifierVerbose = verbose;
}
public boolean getVerifierVerbose()
{
return verifierVerbose;
}
public void setStrictVerifier( boolean strictVerifier )
{
this.strictVerifier = strictVerifier;
}
public boolean getStrictVerifier()
{
return strictVerifier;
}
public void setMetricsEnabled(boolean enable)
{
metricsEnabled = enable;
}
public boolean isMetricsEnabled()
{
return metricsEnabled;
}
public boolean getValidateDTDs()
{
return validateDTDs;
}
public void setValidateDTDs(boolean validate)
{
this.validateDTDs = validate;
}
public ObjectName getWebServiceName()
{
return webServiceName;
}
public void setWebServiceName(ObjectName webServiceName)
{
this.webServiceName = webServiceName;
}
public ObjectName getTransactionManagerServiceName()
{
return transactionManagerServiceName;
}
public void setTransactionManagerServiceName(ObjectName transactionManagerServiceName)
{
this.transactionManagerServiceName = transactionManagerServiceName;
}
public boolean accepts(DeploymentInfo di)
{
String urlStr = di.url.getFile();
if( !urlStr.endsWith("jar") && !urlStr.endsWith("jar/") )
{
return false;
}
boolean accepts = false;
try
{
URL dd = di.localCl.findResource("META-INF/ejb-jar.xml");
if (dd == null)
{
return false;
}
if( di.localUrl != null )
{
urlStr = di.localUrl.toString();
}
String ddStr = dd.toString();
if ( ddStr.indexOf(urlStr) >= 0 )
{
accepts = true;
}
}
catch( Exception ignore )
{
}
return accepts;
}
public void init(DeploymentInfo di)
throws DeploymentException
{
log.debug("init, "+di.shortName);
try
{
if( di.url.getProtocol().equalsIgnoreCase("file") )
{
File file = new File(di.url.getFile());
if( !file.isDirectory() )
{
di.watch = di.url;
}
else
{
di.watch = new URL(di.url, "META-INF/ejb-jar.xml");
}
}
else
{
di.watch = di.url;
}
XmlFileLoader xfl = new XmlFileLoader();
InputStream in = di.localCl.getResourceAsStream("META-INF/jboss.xml");
if( in != null )
{
try
{
Element jboss = xfl.getDocument(in, "META-INF/jboss.xml").getDocumentElement();
Element loader = MetaData.getOptionalChild(jboss, "loader-repository");
if( loader != null )
{
LoaderRepositoryFactory.LoaderRepositoryConfig config =
LoaderRepositoryFactory.parseRepositoryConfig(loader);
di.setRepositoryInfo(config);
}
}
finally
{
in.close();
}
}
}
catch (Exception e)
{
if (e instanceof DeploymentException)
throw (DeploymentException)e;
throw new DeploymentException( "failed to initialize", e );
}
super.init(di);
}
protected void processNestedDeployments(DeploymentInfo di)
throws DeploymentException
{
super.processNestedDeployments(di);
}
public synchronized void create(DeploymentInfo di)
throws DeploymentException
{
log.debug("create, "+di.shortName);
ApplicationMetaData ejbMetaData = null;
try
{
XmlFileLoader efm = new XmlFileLoader(validateDTDs);
efm.setClassLoader(di.localCl);
URL alternativeDD = null;
if (di.alternativeDD != null)
{
String contentsDir = new File(di.url.getPath()).getParent();
alternativeDD = new URL("file:/" + contentsDir + "/" + di.alternativeDD);
}
di.metaData = ejbMetaData = efm.load(alternativeDD);
if (di.parent != null && di.parent.metaData instanceof J2eeApplicationMetaData)
{
J2eeApplicationMetaData appMetaData = (J2eeApplicationMetaData)di.parent.metaData;
if (ejbMetaData.getSecurityDomain() == null)
ejbMetaData.setSecurityDomain(appMetaData.getSecurityDomain());
if (ejbMetaData.getUnauthenticatedPrincipal() == null)
ejbMetaData.setUnauthenticatedPrincipal(appMetaData.getUnauthenticatedPrincipal());
ejbMetaData.getAssemblyDescriptor().mergeSecurityRoles(appMetaData.getSecurityRoles());
}
}
catch (Exception e)
{
if (e instanceof DeploymentException)
throw (DeploymentException)e;
throw new DeploymentException( "Failed to load metaData", e );
}
if( verifyDeployments )
{
boolean allOK = true;
try
{
BeanVerifier verifier = new BeanVerifier();
verifier.addVerificationListener(new VerificationListener()
{
Logger verifierLog = Logger.getLogger(EJBDeployer.class,
"verifier" );
public void beanChecked(VerificationEvent event)
{
verifierLog.debug( "Bean checked: " + event.getMessage() );
}
public void specViolation(VerificationEvent event)
{
verifierLog.warn( "EJB spec violation: " +
(verifierVerbose ? event.getVerbose() : event.getMessage()));
}
});
log.debug("Verifying " + di.url);
verifier.verify( di.url, (ApplicationMetaData) di.metaData,
di.ucl );
allOK = verifier.getSuccess();
}
catch (Throwable t)
{
log.warn("Verify failed; continuing", t );
allOK = false;
}
if( strictVerifier && !allOK )
{
throw new DeploymentException( "Verification of Enterprise " +
"Beans failed, see above for error messages." );
}
}
try
{
EjbModule ejbModule = new EjbModule(di, tm, webServiceName);
String name = ejbMetaData.getJmxName();
if( name == null )
{
name = EjbModule.BASE_EJB_MODULE_NAME + ",module=" + di.shortName;
}
ObjectName ejbModuleName = ObjectNameConverter.convert(name);
if( server.isRegistered(ejbModuleName) == true )
{
log.debug("The EJBModule name: "+ejbModuleName
+"is already registered, adding uid="+System.identityHashCode(ejbModule));
name = name + ",uid="+System.identityHashCode(ejbModule);
ejbModuleName = ObjectNameConverter.convert(name);
}
server.registerMBean(ejbModule, ejbModuleName);
di.deployedObject = ejbModuleName;
log.debug( "Deploying: " + di.url );
serviceController.create(di.deployedObject);
}
catch (Exception e)
{
throw new DeploymentException("Error during create of EjbModule: "
+ di.url, e);
}
super.create(di);
}
public synchronized void start(DeploymentInfo di)
throws DeploymentException
{
try
{
log.debug( "start application, deploymentInfo: " + di +
", short name: " + di.shortName +
", parent short name: " +
(di.parent == null ? "null" : di.parent.shortName) );
serviceController.start(di.deployedObject);
log.info( "Deployed: " + di.url );
deployments.put(di.url, di);
}
catch (Exception e)
{
stop(di);
destroy(di);
throw new DeploymentException( "Could not deploy " + di.url, e );
}
super.start(di);
}
public void stop(DeploymentInfo di)
throws DeploymentException
{
log.info( "Undeploying: " + di.url );
try
{
serviceController.stop(di.deployedObject);
}
catch (Exception e)
{
throw new DeploymentException( "problem stopping ejb module: " +
di.url, e );
}
super.stop(di);
}
public void destroy(DeploymentInfo di)
throws DeploymentException
{
deployments.remove(di.url);
try
{
serviceController.destroy( di.deployedObject );
serviceController.remove( di.deployedObject );
}
catch (Exception e)
{
throw new DeploymentException( "problem destroying ejb module: " +
di.url, e );
}
super.destroy(di);
}
}