package org.jboss.mx.loading;
import java.lang.reflect.Constructor;
import java.io.Serializable;
import java.util.HashMap;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import org.jboss.logging.Logger;
import org.jboss.mx.server.ServerConstants;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
public class LoaderRepositoryFactory
{
public static ObjectName DEFAULT_LOADER_REPOSITORY;
private static Logger log = Logger.getLogger(LoaderRepositoryFactory.class);
private static HashMap referenceCountMap = new HashMap();
static
{
try
{
DEFAULT_LOADER_REPOSITORY = new ObjectName(ServerConstants.DEFAULT_LOADER_NAME);
}
catch(Exception e)
{
log.error("Failed to init DEFAULT_LOADER_REPOSITORY name", e);
}
}
public static class LoaderRepositoryConfig implements Serializable
{
static final long serialVersionUID = 4226952985429700362L;
public ObjectName repositoryName = DEFAULT_LOADER_REPOSITORY;
public String repositoryClassName;
public String configParserClassName;
public String repositoryConfig;
public String toString()
{
StringBuffer tmp = new StringBuffer("LoaderRepositoryConfig(");
tmp.append("repositoryName: ");
tmp.append(repositoryName);
tmp.append(", repositoryClassName: ");
tmp.append(repositoryClassName);
tmp.append(", configParserClassName: ");
tmp.append(configParserClassName);
tmp.append(", repositoryConfig: ");
tmp.append(repositoryConfig);
tmp.append(")");
return tmp.toString();
}
}
static public interface LoaderRepositoryConfigParser
{
public void configure(LoaderRepository repository, String config)
throws Exception;
}
public static LoaderRepositoryConfig parseRepositoryConfig(Element config)
throws MalformedObjectNameException
{
LoaderRepositoryConfig repositoryConfig = new LoaderRepositoryConfig();
repositoryConfig.repositoryClassName = config.getAttribute("loaderRepositoryClass");
if( repositoryConfig.repositoryClassName.length() == 0 )
repositoryConfig.repositoryClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_CLASS;
NodeList children = config.getChildNodes();
int count = children.getLength();
if( count > 0 )
{
for(int n = 0; n < count; n ++)
{
Node node = children.item(n);
int type = node.getNodeType();
if( type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE )
{
String objectName = node.getNodeValue().trim();
repositoryConfig.repositoryName = new ObjectName(objectName);
break;
}
}
children = config.getElementsByTagName("loader-repository-config");
count = children.getLength();
if( count > 0 )
{
Element loaderRepositoryConfig = (Element) children.item(0);
children = loaderRepositoryConfig.getChildNodes();
count = children.getLength();
repositoryConfig.configParserClassName = loaderRepositoryConfig.getAttribute("configParserClass");
if( repositoryConfig.configParserClassName.length() == 0 )
repositoryConfig.configParserClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_PARSER_CLASS;
StringBuffer configData = new StringBuffer();
for(int n = 0; n < count; n ++)
{
Node node = children.item(n);
int type = node.getNodeType();
if( type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE )
{
configData.append(node.getNodeValue());
}
}
repositoryConfig.repositoryConfig = configData.toString().trim();
}
}
return repositoryConfig;
}
public static synchronized void createLoaderRepository(MBeanServer server,
String repositoryClassName,
ObjectName repositoryName) throws JMException
{
LoaderRepositoryConfig config = new LoaderRepositoryConfig();
config.repositoryClassName = repositoryClassName;
config.repositoryName = repositoryName;
createLoaderRepository(server, config);
}
public static synchronized void createLoaderRepository(MBeanServer server,
LoaderRepositoryConfig config) throws JMException
{
if( config == null )
config = new LoaderRepositoryConfig();
String repositoryClassName = config.repositoryClassName;
ObjectName repositoryName = config.repositoryName;
try
{
ObjectInstance oi = server.getObjectInstance(repositoryName);
if ( (repositoryClassName != null) &&
!oi.getClassName().equals(repositoryClassName) )
{
throw new JMException("Inconsistent LoaderRepository class specification in repository: " + repositoryName);
} }
catch (InstanceNotFoundException e)
{
if( repositoryClassName == null )
repositoryClassName = ServerConstants.DEFAULT_SCOPED_REPOSITORY_CLASS;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
LoaderRepository repository = null;
try
{
Class repositoryClass = loader.loadClass(repositoryClassName);
Class[] ctorSig = {MBeanServer.class, ObjectName.class};
Constructor ctor = repositoryClass.getConstructor(ctorSig);
Object[] args = {server, DEFAULT_LOADER_REPOSITORY};
repository = (LoaderRepository) ctor.newInstance(args);
server.registerMBean(repository, repositoryName);
}
catch(Exception e2)
{
log.debug("Failed to create loader repository: ", e2);
throw new JMException("Failed to create loader repository:" + e2);
}
try
{
if( config.configParserClassName != null && config.repositoryConfig != null )
{
Class parserClass = loader.loadClass(config.configParserClassName);
LoaderRepositoryConfigParser parser = (LoaderRepositoryConfigParser)
parserClass.newInstance();
parser.configure(repository, config.repositoryConfig);
}
}
catch(Exception e2)
{
log.debug("Failed to configure loader repository: ", e2);
throw new JMException("Failed to configure loader repository: "+e2);
}
}
Integer activeCount = (Integer) referenceCountMap.get(repositoryName);
if( activeCount == null )
activeCount = new Integer(1);
else
activeCount = new Integer(activeCount.intValue() + 1);
referenceCountMap.put(repositoryName, activeCount);
}
public static synchronized void destroyLoaderRepository(MBeanServer server,
ObjectName repositoryName)
{
if( repositoryName.equals(DEFAULT_LOADER_REPOSITORY) == false )
{
try
{
Integer activeCount = (Integer) referenceCountMap.get(repositoryName);
if( activeCount != null )
{
if( activeCount.intValue() == 1 )
{
server.unregisterMBean(repositoryName);
referenceCountMap.remove(repositoryName);
log.debug("Unregistered repository: "+repositoryName);
}
else
{
activeCount = new Integer(activeCount.intValue() - 1);
referenceCountMap.put(repositoryName, activeCount);
}
}
}
catch(Exception e)
{
log.warn("Failed to unregister ear loader repository", e);
}
}
}
private LoaderRepositoryFactory()
{
}
}