package org.jboss.deployment;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.security.Policy;
import javax.management.ObjectName;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyConfiguration;
import org.jboss.metadata.MetaData;
import org.jboss.metadata.XmlFileLoader;
import org.jboss.mx.loading.LoaderRepositoryFactory;
import org.jboss.mx.loading.LoaderRepositoryFactory.LoaderRepositoryConfig;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.system.ServiceControllerMBean;
import org.jboss.util.file.JarUtils;
import org.w3c.dom.Element;
public class EARDeployer
extends SubDeployerSupport
implements EARDeployerMBean
{
private ServiceControllerMBean serviceController;
private boolean isolated = false;
private boolean callByValue = false;
public EARDeployer()
{
super();
}
public boolean isIsolated()
{
return isolated;
}
public void setIsolated(boolean isolated)
{
this.isolated = isolated;
}
public boolean isCallByValue()
{
return callByValue;
}
public void setCallByValue(boolean callByValue)
{
this.callByValue = callByValue;
}
protected void startService() throws Exception
{
serviceController = (ServiceControllerMBean)
MBeanProxyExt.create(ServiceControllerMBean.class,
ServiceControllerMBean.OBJECT_NAME, server);
super.startService();
}
public boolean accepts(DeploymentInfo di)
{
String urlStr = di.url.getFile();
return urlStr.endsWith("ear") || urlStr.endsWith("ear/");
}
public void init(DeploymentInfo di)
throws DeploymentException
{
try
{
log.info("Init J2EE application: " + di.url);
InputStream in = di.localCl.getResourceAsStream("META-INF/application.xml");
if( in == null )
throw new DeploymentException("No META-INF/application.xml found");
XmlFileLoader xfl = new XmlFileLoader(false);
J2eeApplicationMetaData metaData = new J2eeApplicationMetaData();
Element application = xfl.getDocument(in, "META-INF/application.xml").getDocumentElement();
metaData.importXml(application);
di.metaData = metaData;
in.close();
Element loader = null;
in = di.localCl.getResourceAsStream("META-INF/jboss-app.xml");
if( in != null )
{
xfl = new XmlFileLoader(true);
Element jbossApp = xfl.getDocument(in, "META-INF/jboss-app.xml").getDocumentElement();
in.close();
metaData.importXml(jbossApp);
loader = MetaData.getOptionalChild(jbossApp, "loader-repository");
}
initLoaderRepository(di, loader);
if (di.url.getProtocol().equals("file"))
{
File file = new File(di.url.getFile());
if (!file.isDirectory())
{
di.watch = di.url;
}
else
{
di.watch = new URL(di.url, "META-INF/application.xml");
}
}
else
{
di.watch = di.url;
}
File parentDir = null;
HashMap extractedJars = new HashMap();
if (di.isDirectory)
{
parentDir = new File(di.localUrl.getFile());
}
else
{
String urlPrefix = "jar:" + di.localUrl + "!/";
JarFile jarFile = new JarFile(di.localUrl.getFile());
for (Enumeration e = jarFile.entries(); e.hasMoreElements();)
{
JarEntry entry = (JarEntry)e.nextElement();
String name = entry.getName();
try
{
URL url = new URL(urlPrefix + name);
if (isDeployable(name, url))
{
URL nestedURL = JarUtils.extractNestedJar(url, this.tempDeployDir);
extractedJars.put(name, nestedURL);
log.debug("Extracted deployable content: "+name);
}
else if( entry.isDirectory() == false )
{
URL nestedURL = JarUtils.extractNestedJar(url, this.tempDeployDir);
log.debug("Extracted non-deployable content: "+name);
}
}
catch (MalformedURLException mue)
{
log.warn("Jar entry invalid. Ignoring: " + name, mue);
}
catch (IOException ex)
{
log.warn("Failed to extract nested jar. Ignoring: " + name, ex);
}
}
}
String contextID = di.shortName;
PolicyConfigurationFactory pcFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
PolicyConfiguration pc = pcFactory.getPolicyConfiguration(contextID, true);
di.context.put("javax.security.jacc.PolicyConfiguration", pc);
for (Iterator iter = metaData.getModules(); iter.hasNext(); )
{
J2eeModuleMetaData mod = (J2eeModuleMetaData)iter.next();
String fileName = mod.getFileName();
if (fileName != null && (fileName = fileName.trim()).length() > 0)
{
DeploymentInfo sub = null;
if (di.isDirectory)
{
File f = new File(parentDir, fileName);
sub = new DeploymentInfo(f.toURL(), di, getServer());
}
else
{
URL nestedURL = (URL) extractedJars.get(fileName);
if( nestedURL == null )
throw new DeploymentException("Failed to find module file: "+fileName);
sub = new DeploymentInfo(nestedURL, di, getServer());
}
if( mod.isWeb() )
sub.webContext = mod.getWebContext();
if (mod.alternativeDD != null)
sub.alternativeDD = mod.alternativeDD;
log.debug("Deployment Info: " + sub + ", isDirectory: " + sub.isDirectory);
}
}
EARDeployment earDeployment = new EARDeployment(di);
String name = earDeployment.getJMXName();
ObjectName objectName = new ObjectName(name);
di.deployedObject = objectName;
server.registerMBean(earDeployment, objectName);
}
catch (DeploymentException e)
{
throw e;
}
catch (Exception e)
{
throw new DeploymentException("Error in accessing application metadata: ", e);
}
super.init(di);
}
public void create(DeploymentInfo di) throws DeploymentException
{
super.create(di);
try
{
serviceController.create(di.deployedObject);
}
catch (Exception e)
{
DeploymentException.rethrowAsDeploymentException("Error during create of EARDeployment: " + di.url, e);
}
}
public void start(DeploymentInfo di)
throws DeploymentException
{
super.start (di);
try
{
PolicyConfiguration pc = (PolicyConfiguration)
di.context.get("javax.security.jacc.PolicyConfiguration");
pc.commit();
Policy.getPolicy().refresh();
serviceController.start(di.deployedObject);
}
catch (Exception e)
{
DeploymentException.rethrowAsDeploymentException("Error during start of EARDeployment: " + di.url, e);
}
log.info ("Started J2EE application: " + di.url);
}
public void stop(DeploymentInfo di) throws DeploymentException
{
try
{
serviceController.stop(di.deployedObject);
}
catch (Exception e)
{
DeploymentException.rethrowAsDeploymentException("Error during stop of EARDeployment: " + di.url, e);
}
super.stop(di);
}
public void destroy(DeploymentInfo di) throws DeploymentException
{
log.info("Undeploying J2EE application, destroy step: " + di.url);
try
{
serviceController.destroy(di.deployedObject);
serviceController.remove(di.deployedObject);
}
catch (Exception e)
{
DeploymentException.rethrowAsDeploymentException("Error during destroy of EARDeployment: " + di.url, e);
}
super.destroy(di);
}
protected void initLoaderRepository(DeploymentInfo di, Element loader)
throws Exception
{
if (loader == null)
{
if (isolated && di.parent == null)
{
J2eeApplicationMetaData metaData = (J2eeApplicationMetaData) di.metaData;
String name = EARDeployment.getJMXName(metaData, di) + ",extension=LoaderRepository";
ObjectName objectName = new ObjectName(name);
LoaderRepositoryConfig config = new LoaderRepositoryFactory.LoaderRepositoryConfig();
config.repositoryName = objectName;
di.setRepositoryInfo(config);
}
return;
}
LoaderRepositoryConfig config = LoaderRepositoryFactory.parseRepositoryConfig(loader);
di.setRepositoryInfo(config);
}
protected boolean isDeployable(String name, URL url)
{
return super.isDeployable(name, url) ||
name.endsWith("-ds.xml") ||
name.endsWith("-service.xml") ||
name.endsWith(".har");
}
protected void processNestedDeployments(DeploymentInfo di)
{
}
}