package javax.management.loading;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.ServiceNotFoundException;
import org.jboss.logging.Logger;
import org.jboss.mx.loading.MBeanElement;
import org.jboss.mx.loading.MBeanFileParser;
import org.jboss.mx.loading.MLetParser;
import org.jboss.mx.loading.RepositoryClassLoader;
import org.jboss.mx.server.ServerConstants;
import org.jboss.mx.util.MBeanInstaller;
import org.jboss.mx.util.ObjectNameFactory;
import org.jboss.util.NestedRuntimeException;
import org.jboss.util.id.SerialVersion;
public class MLet extends URLClassLoader
implements MLetMBean, MBeanRegistration, Externalizable
{
private static final long serialVersionUID;
static
{
if (SerialVersion.version == SerialVersion.LEGACY)
serialVersionUID = -3671491454721196053L;
else
serialVersionUID = 3636148327800330130L;
}
private static final Logger log = Logger.getLogger(MLet.class);
private MBeanServer server = null;
private MBeanInstaller installer = null;
private RepositoryClassLoader rcl = null;
private boolean delegateToCLR = true;
private String libraryDir = null;
public MLet()
{
super(new URL[0], Thread.currentThread().getContextClassLoader());
}
public MLet(URL[] urls)
{
super(urls, Thread.currentThread().getContextClassLoader());
}
public MLet(URL[] urls, ClassLoader parent)
{
super(urls, parent);
}
public MLet(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)
{
super(urls, parent, factory);
}
public MLet(URL[] urls, boolean delegateToCLR)
{
super(urls, Thread.currentThread().getContextClassLoader());
this.delegateToCLR = delegateToCLR;
}
public MLet(URL[] urls, ClassLoader parent, boolean delegateToCLR)
{
super(urls, parent);
this.delegateToCLR = delegateToCLR;
}
public MLet(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory, boolean delegateToCLR)
{
super(urls, parent, factory);
this.delegateToCLR = delegateToCLR;
}
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
{
if (name == null)
{
String defaultDomain = server.getDefaultDomain();
name = new ObjectName(defaultDomain + ":type=MLet");
}
this.server = server;
this.installer = new MBeanInstaller(server, this, name);
return name;
}
public void postRegister(Boolean registrationDone)
{
}
public void preDeregister() throws Exception
{
}
public void postDeregister()
{
server = null;
rcl = null;
installer = null;
}
public Set getMBeansFromURL(String url) throws ServiceNotFoundException
{
try
{
return getMBeansFromURL(new URL(url));
}
catch (MalformedURLException e)
{
throw new ServiceNotFoundException("Malformed URL:" + url);
}
}
public Set getMBeansFromURL(URL url) throws ServiceNotFoundException
{
if (server == null)
throw new ServiceNotFoundException("Loader must be registered to the server before loading the MBeans.");
HashSet mbeans = new HashSet();
MBeanElement element = null;
try
{
MBeanFileParser parser = new MLetParser();
Set mlets = parser.parseMBeanFile(url);
if (mlets.size() == 0)
throw new ServiceNotFoundException("The specified URL '" + url + "' does not contain MLET tags.");
Iterator it = mlets.iterator();
while (it.hasNext())
{
element = (MBeanElement)it.next();
element.setProperty(MBeanElement.MLET_DELEGATE_TO_CLR,
new Boolean(delegateToCLR));
String codebase = element.getCodebase();
if (codebase == null)
codebase = url.toString().substring(0, url.toString().lastIndexOf('/'));
Iterator archives = element.getArchives().iterator();
String codebaseURL = null;
while (archives.hasNext())
{
try
{
codebaseURL = codebase + ((codebase.endsWith("/")) ? "" : "/") + archives.next();
addURL(new URL(url, codebaseURL));
}
catch (MalformedURLException e)
{
log.error("MLET ERROR: malformed codebase URL: '" + codebaseURL + "'");
}
}
try
{
mbeans.add(installer.installMBean(element));
}
catch (Throwable t)
{
mbeans.add(t);
log.error("MLET ERROR: can't create MBean: ", t);
}
}
}
catch (ParseException e)
{
throw new ServiceNotFoundException(e.getMessage());
}
return mbeans;
}
public void addURL(URL url)
{
super.addURL(url);
if (rcl == null && server != null)
getRepositoryClassLoader();
rcl.addURL(url);
}
public void addURL(String url) throws ServiceNotFoundException
{
try
{
this.addURL(new URL(url));
}
catch (MalformedURLException e)
{
throw new ServiceNotFoundException("Malformed URL: " + url);
}
}
public URL[] getURLs()
{
return super.getURLs();
}
public String getLibraryDirectory()
{
return libraryDir;
}
public void setLibraryDirectory(String libdir)
{
this.libraryDir = libdir;
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException, UnsupportedOperationException
{
throw new UnsupportedOperationException("MLet serialization not supported.");
}
public void writeExternal(ObjectOutput out)
throws IOException, UnsupportedOperationException
{
throw new UnsupportedOperationException("MLet serialization not supported.");
}
public Class loadClass(String name, ClassLoaderRepository clr)
throws ClassNotFoundException
{
Class c = null;
try
{
c = loadClass(name);
}
catch(ClassNotFoundException e)
{
if( clr != null )
c = clr.loadClass(name);
else
throw e;
}
return c;
}
protected URL check(String version, URL codebase, String jarfile,
MLetContent mlet)
throws Exception
{
return codebase;
}
protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
boolean trace = log.isTraceEnabled();
if (trace)
log.trace("loadClass " + this + " name=" + name);
Class clazz = null;
try
{
clazz = super.loadClass(name, resolve);
return clazz;
}
finally
{
if (trace)
{
if (clazz != null)
log.trace("loadClass " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader());
else
log.trace("loadClass " + this + " name=" + name + " not found");
}
}
}
protected Class findClass(final String name)
throws ClassNotFoundException
{
try
{
return super.findClass(name);
}
catch (ClassNotFoundException e)
{
if (delegateToCLR)
{
try
{
return (Class) AccessController.doPrivileged(new PrivilegedExceptionAction()
{
public Object run() throws ClassNotFoundException
{
return server.getClassLoaderRepository().loadClassBefore(MLet.this, name);
}
});
}
catch (PrivilegedActionException pe)
{
throw (ClassNotFoundException) pe.getException();
}
}
else
throw e;
}
}
protected String findLibrary(String libname)
{
return super.findLibrary(libname);
}
private void getRepositoryClassLoader()
{
try
{
ObjectName loader = ObjectNameFactory.create(ServerConstants.DEFAULT_LOADER_NAME);
rcl = (RepositoryClassLoader) server.invoke(loader, "getWrappingClassLoader",
new Object[] { this }, new String[] { ClassLoader.class.getName() });
log.debug("MLet " + this + " using wrapper " + rcl);
}
catch (Exception e)
{
throw new NestedRuntimeException(e);
}
}
}