package org.jboss.deployment;
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.HashMap;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.jboss.logging.Logger;
import org.jboss.mx.loading.LoaderRepositoryFactory;
import org.jboss.mx.loading.RepositoryClassLoader;
import org.jboss.mx.loading.LoaderRepositoryFactory.LoaderRepositoryConfig;
import org.jboss.util.collection.ListSet;
import org.jboss.util.file.Files;
import org.w3c.dom.Document;
public class DeploymentInfo implements Serializable
{
static final long serialVersionUID = 1131841473723490707L;
private static final Logger log = Logger.getLogger(DeploymentInfo.class);
public Date date = new Date();
public URL url;
public URL localUrl;
public URL watch;
public String shortName;
public long lastDeployed = 0;
public long lastModified = 0;
public String status;
public DeploymentState state = DeploymentState.CONSTRUCTED;
public transient SubDeployer deployer;
public transient RepositoryClassLoader ucl;
public transient URLClassLoader localCl;
public final Collection classpath = new ArrayList();
public final List mbeans = new ArrayList();
public final Set subDeployments = new ListSet();
public DeploymentInfo parent = null;
public String webContext;
public transient Manifest manifest;
public Document document;
public URL documentUrl;
public transient Object metaData;
public String alternativeDD;
public transient HashMap context = new HashMap();
public boolean isXML;
public boolean isScript;
public boolean isDirectory;
public ObjectName deployedObject;
public LoaderRepositoryConfig repositoryConfig;
private transient MBeanServer server;
public DeploymentInfo(final URL url, final DeploymentInfo parent, final MBeanServer server)
throws DeploymentException
{
this.server = server;
this.url = url;
this.watch = url;
this.parent = parent;
if (url.getProtocol().startsWith("file") && new File(url.getFile()).isDirectory())
this.isDirectory = true;
if (!isDirectory)
{
try
{
url.openStream().close();
}
catch (Exception e)
{
throw new DeploymentException("url " + url + " could not be opened, does it exist?");
}
}
if (parent != null)
{
parent.subDeployments.add(this);
repositoryConfig = getTopRepositoryConfig();
}
shortName = getShortName(url.getFile());
isXML = shortName.toLowerCase().endsWith("xml");
isScript = shortName.toLowerCase().endsWith("bsh");
}
public MBeanServer getServer()
{
return server;
}
public void setServer(MBeanServer server)
{
this.server = server;
}
public void createClassLoaders() throws Exception
{
if( localCl == null )
localCl = new URLClassLoader(new URL[] {localUrl});
URL origUrl = url;
DeploymentInfo current = this;
while (current.parent != null)
{
current = current.parent;
}
origUrl = current.url;
repositoryConfig = current.repositoryConfig;
if( parent == null )
{
if( repositoryConfig == null )
repositoryConfig = new LoaderRepositoryConfig();
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
log.debug("createLoaderRepository from config: "+repositoryConfig);
Object[] args = {localUrl, origUrl, Boolean.TRUE};
String[] sig = {"java.net.URL", "java.net.URL", "boolean"};
ucl = (RepositoryClassLoader) server.invoke(repositoryConfig.repositoryName,
"newClassLoader",args, sig);
}
else
{
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
ucl = parent.ucl;
ucl.addURL(localUrl);
}
if( classpath.size() > 0 )
{
Iterator jars = classpath.iterator();
while( jars.hasNext() )
{
URL jar = (URL) jars.next();
ucl.addURL(jar);
}
}
}
public void setRepositoryInfo(LoaderRepositoryConfig config)
throws Exception
{
if( parent != null )
{
log.warn("Only the root deployment can set the loader repository, "
+ "ignoring config="+config);
return;
}
this.repositoryConfig = config;
if( ucl != null )
{
ucl.unregister();
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
log.debug("createLoaderRepository from config: "+repositoryConfig);
Object[] args = {localUrl, url, Boolean.TRUE};
String[] sig = {"java.net.URL", "java.net.URL", "boolean"};
ucl = (RepositoryClassLoader) server.invoke(repositoryConfig.repositoryName,
"newClassLoader",args, sig);
}
}
public void addLibraryJar(URL libJar)
{
DeploymentInfo current = this;
while (current.parent != null)
{
current = current.parent;
}
if( current.ucl != null )
current.ucl.addURL(libJar);
else
classpath.add(libJar);
}
public LoaderRepositoryConfig getTopRepositoryConfig()
{
LoaderRepositoryConfig topConfig = repositoryConfig;
DeploymentInfo info = this;
while( info.parent != null )
{
info = info.parent;
topConfig = info.repositoryConfig;
}
return topConfig;
}
public Manifest getManifest()
{
try
{
if (manifest == null)
{
File file = new File(localUrl.getFile());
if (file.isDirectory())
{
FileInputStream fis = new FileInputStream(new File(file, "META-INF/MANIFEST.MF"));
manifest = new Manifest(fis);
fis.close();
}
else manifest = new JarFile(file).getManifest();
}
return manifest;
}
catch (Exception ignored) { return null;}
}
public void cleanup()
{
if( parent == null && ucl != null )
ucl.unregister();
ucl = null;
if ( repositoryConfig != null )
{
LoaderRepositoryFactory.destroyLoaderRepository(server,
repositoryConfig.repositoryName);
}
subDeployments.clear();
mbeans.clear();
context.clear();
if (localUrl == null || localUrl.equals(url))
{
log.debug("Not deleting localUrl, it is null or not a copy: " + localUrl);
}
else if (Files.delete(localUrl.getFile()))
{
log.debug("Cleaned Deployment: " + localUrl);
}
else
{
log.warn("Could not delete " + localUrl + " restart will delete it");
}
localCl = null;
localUrl = null;
repositoryConfig = null;
watch = null;
parent = null;
manifest = null;
document = null;
metaData = null;
server = null;
classpath.clear();
state = DeploymentState.DESTROYED;
}
public String getCanonicalName()
{
String name = shortName;
if (parent != null)
name = parent.getCanonicalName() + "/" + name;
return name;
}
private String getShortName(String name)
{
if (name.endsWith("/")) name = name.substring(0, name.length() - 1);
name = name.substring(name.lastIndexOf("/") + 1);
return name;
}
public int hashCode()
{
return url.hashCode();
}
public boolean equals(Object other)
{
if (other instanceof DeploymentInfo)
{
return ((DeploymentInfo) other).url.equals(this.url);
}
return false;
}
public String toString()
{
StringBuffer s = new StringBuffer(super.toString());
s.append(" { url=" + url + " }\n");
s.append(" deployer: " + deployer + "\n");
s.append(" status: " + status + "\n");
s.append(" state: " + state + "\n");
s.append(" watch: " + watch + "\n");
s.append(" altDD: " + alternativeDD + "\n");
s.append(" lastDeployed: " + lastDeployed + "\n");
s.append(" lastModified: " + lastModified + "\n");
s.append(" mbeans:\n");
for (Iterator i = mbeans.iterator(); i.hasNext(); )
{
ObjectName o = (ObjectName)i.next();
try
{
String state = (String)server.getAttribute(o, "StateString");
s.append(" " + o + " state: " + state + "\n");
}
catch (Exception e)
{
s.append(" " + o + " (state not available)\n");
}
}
return s.toString();
}
}