package org.jboss.system;
import java.net.URL;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.UndeclaredThrowableException;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import org.jboss.deployment.DeploymentException;
import org.jboss.logging.Logger;
import org.jboss.mx.util.JMXExceptionDecoder;
import org.jboss.mx.service.ServiceConstants;
import org.jboss.util.Classes;
import org.jboss.util.StringPropertyReplacer;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Attr;
public class ServiceCreator
{
private static final String XMBEAN_CODE = "org.jboss.mx.modelmbean.XMBean";
private static final Logger log = Logger.getLogger(ServiceCreator.class);
private MBeanServer server;
public ServiceCreator(final MBeanServer server)
{
this.server = server;
}
public ObjectInstance install(ObjectName mbeanName, ObjectName loaderName,
Element mbeanElement) throws Exception
{
if (server.isRegistered(mbeanName))
{
throw new DeploymentException("Trying to install an already registered mbean: " + mbeanName);
}
String code = mbeanElement.getAttribute("code");
if ( code == null || "".equals(code))
{
throw new ConfigurationException("missing 'code' attribute");
}
ConstructorInfo constructor = ConstructorInfo.create(mbeanElement);
String xmbeandd = null;
Attr xmbeanddAttr = mbeanElement.getAttributeNode("xmbean-dd");
if( xmbeanddAttr != null )
xmbeandd = xmbeanddAttr.getValue();
String xmbeanCode = mbeanElement.getAttribute("xmbean-code");
if( xmbeanCode.length() == 0 )
xmbeanCode = XMBEAN_CODE;
ObjectInstance instance = null;
try
{
if ( xmbeandd == null )
{
Attr itfAttr = mbeanElement.getAttributeNode("interface");
if (itfAttr != null)
{
ClassLoader classLoader = server.getClassLoader(loaderName);
String itf = itfAttr.getValue();
Class itfClass = classLoader.loadClass(itf);
log.debug("About to create bean resource: " + mbeanName + " with code: " + code);
Object resource = server.instantiate(code,
loaderName,
constructor.params,
constructor.signature);
log.debug("About to register StandardMBean : " + mbeanName);
instance = server.createMBean("javax.management.StandardMBean",
mbeanName,
loaderName,
new Object[]{resource,itfClass},
new String[]{Object.class.getName(),Class.class.getName()});
}
else
{
log.debug("About to create bean: " + mbeanName + " with code: " + code);
instance = server.createMBean(code,
mbeanName,
loaderName,
constructor.params,
constructor.signature);
}
} else if( xmbeandd.length() == 0 )
{
log.debug("About to create xmbean object: " + mbeanName
+ " with code: " + code + " with embedded descriptor");
Object resource = server.instantiate(code, loaderName,
constructor.params, constructor.signature);
NodeList mbeans = mbeanElement.getElementsByTagName("xmbean");
if( mbeans.getLength() == 0 )
throw new ConfigurationException("No nested mbean element given for xmbean");
Element mbeanDescriptor = (Element) mbeans.item(0);
Object[] args = {resource, mbeanDescriptor,
ServiceConstants.PUBLIC_JBOSSMX_XMBEAN_DTD_1_0};
String[] sig = {Object.class.getName(), Element.class.getName(),
String.class.getName()};
instance = server.createMBean(xmbeanCode,
mbeanName,
loaderName,
args,
sig);
}
else
{
log.debug("About to create xmbean object: " + mbeanName
+ " with code: " + code + " with descriptor: "+xmbeandd);
Object resource = server.instantiate(code, loaderName,
constructor.params, constructor.signature);
URL xmbeanddUrl = null;
try
{
xmbeanddUrl = resource.getClass().getClassLoader().getResource(xmbeandd);
}
catch (Exception e)
{
} if (xmbeanddUrl == null)
{
xmbeanddUrl = new URL(xmbeandd);
}
Object[] args = {resource, xmbeanddUrl};
String[] sig = {Object.class.getName(), URL.class.getName()};
instance = server.createMBean(xmbeanCode,
mbeanName,
loaderName,
args,
sig);
} }
catch (Throwable e)
{
Throwable newE = JMXExceptionDecoder.decode(e);
try
{
server.unregisterMBean(mbeanName);
}
catch (Throwable ignore)
{
}
if (newE instanceof Exception)
{
throw (Exception)newE;
} throw new UndeclaredThrowableException(newE);
}
log.debug("Created bean: "+mbeanName);
return instance;
}
public void remove(ObjectName name) throws Exception
{
String domain = name.getDomain();
if (domain == null || "".equals(domain))
{
name = new ObjectName(server.getDefaultDomain() + name);
}
server.unregisterMBean(name);
}
private static class ConstructorInfo
{
public static final Object EMPTY_PARAMS[] = {};
public static final String EMPTY_SIGNATURE[] = {};
public String[] signature = EMPTY_SIGNATURE;
public Object[] params = EMPTY_PARAMS;
public static ConstructorInfo create(Element element)
throws ConfigurationException
{
ConstructorInfo info = new ConstructorInfo();
NodeList list = element.getElementsByTagName("constructor");
if (list.getLength() > 1 && list.item(0).getParentNode() == element)
{
throw new ConfigurationException
("only one <constructor> element may be defined");
}
else if (list.getLength() == 1)
{
element = (Element)list.item(0);
list = element.getElementsByTagName("arg");
int length = list.getLength();
info.params = new Object[length];
info.signature = new String[length];
ClassLoader loader = Thread.currentThread().getContextClassLoader();
for (int j=0; j<length; j++)
{
Element arg = (Element)list.item(j);
String signature = arg.getAttribute("type");
String value = arg.getAttribute("value");
value = StringPropertyReplacer.replaceProperties(arg.getAttribute("value"));
Object realValue = value;
if( signature != null )
{
Class typeClass = Classes.getPrimitiveTypeForName(signature);
if (typeClass == null)
{
try
{
typeClass = loader.loadClass(signature);
}
catch (ClassNotFoundException e)
{
throw new ConfigurationException
("Class not found for type: " + signature, e);
}
}
PropertyEditor editor = PropertyEditorManager.findEditor(typeClass);
if (editor == null)
{
try
{
Class[] sig = {String.class};
Constructor ctor = typeClass.getConstructor(sig);
Object[] args = {value};
realValue = ctor.newInstance(args);
}
catch (Exception e)
{
throw new ConfigurationException("No property editor for type: " + typeClass);
}
}
else
{
editor.setAsText(value);
realValue = editor.getValue();
}
}
info.signature[j] = signature;
info.params[j] = realValue;
}
}
return info;
}
}
}