package org.jboss.mx.util;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.ObjectInstance;
import javax.management.ReflectionException;
import org.jboss.logging.Logger;
import org.jboss.mx.server.ObjectInputStreamWithClassLoader;
import org.jboss.mx.server.ServerConstants;
import org.jboss.mx.loading.MBeanElement;
import org.jboss.util.UnreachableStatementException;
public class MBeanInstaller
{
public static final String VERSIONS = "versions";
public static final String DATE = "date";
private static final Logger log = Logger.getLogger(MBeanInstaller.class);
static
{
Class c = org.jboss.util.propertyeditor.PropertyEditors.class;
if (c == null)
throw new UnreachableStatementException();
}
private MBeanServer server;
private ClassLoader ctxClassLoader;
private ObjectName loaderName;
private ObjectName registryName;
public MBeanInstaller(MBeanServer server, ClassLoader ctxClassLoader, ObjectName loaderName)
throws Exception
{
this.server = server;
this.ctxClassLoader = ctxClassLoader;
this.loaderName = loaderName;
this.registryName = new ObjectName(ServerConstants.MBEAN_REGISTRY);
}
public ObjectInstance installMBean(MBeanElement element)
throws MBeanException,
ReflectionException,
InstanceNotFoundException,
MalformedObjectNameException
{
log.debug("Installing MBean: " + element);
ObjectInstance instance = null;
ObjectName elementName = getElementName(element);
if (element.getVersions().isEmpty() || !server.isRegistered(elementName))
{
if (element.getCode() != null)
instance = createMBean(element);
else if (element.getObject() != null)
instance = deserialize(element);
else
throw new MBeanException(new IllegalArgumentException("No code or object tag"));
}
else
instance = updateMBean(element);
return instance;
}
public ObjectInstance createMBean(MBeanElement element)
throws MBeanException,
ReflectionException,
InstanceNotFoundException,
MalformedObjectNameException
{
log.debug("Creating MBean.. ");
ObjectName elementName = getElementName(element);
Map valueMap = createValueMap(element);
String[] classes = element.getConstructorTypes();
String[] paramStrings = element.getConstructorValues();
Object[] params = new Object[paramStrings.length];
for (int i = 0; i < paramStrings.length; ++i)
{
try
{
Class typeClass = server.getClassLoaderRepository().loadClass(classes[i]);
PropertyEditor editor = PropertyEditorManager.findEditor(typeClass);
if (editor == null)
throw new IllegalArgumentException("No property editor for type=" + typeClass);
editor.setAsText(paramStrings[i]);
params[i] = editor.getValue();
}
catch (Exception e)
{
throw new MBeanException(e);
}
}
Object instance = server.instantiate(
element.getCode(),
loaderName,
params,
classes);
return registerMBean(instance, elementName, valueMap);
}
public ObjectInstance deserialize(MBeanElement element) throws MBeanException,
ReflectionException,
InstanceNotFoundException,
MalformedObjectNameException
{
InputStream is = null;
Object instance = null;
try
{
is = ctxClassLoader.getResourceAsStream(element.getObject());
if (is == null)
throw new IllegalArgumentException("Object not found " + element.getObject());
ObjectInputStreamWithClassLoader ois = new ObjectInputStreamWithClassLoader(is, ctxClassLoader);
instance = ois.readObject();
}
catch (Exception e)
{
throw new MBeanException(e);
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (Exception ignored)
{
}
}
}
ObjectName elementName = getElementName(element);
Map valueMap = createValueMap(element);
return registerMBean(instance, elementName, valueMap);
}
public ObjectInstance updateMBean(MBeanElement element)
throws MBeanException,
ReflectionException,
InstanceNotFoundException,
MalformedObjectNameException
{
log.debug("updating MBean... ");
ObjectName elementName = getElementName(element);
MLetVersion preVersion = new MLetVersion(getVersions(elementName));
MLetVersion newVersion = new MLetVersion(element.getVersions());
log.debug("Installed version : " + preVersion);
log.debug("Loaded version : " + newVersion);
if (!preVersion.isNull() && !newVersion.isNull() && preVersion.compareTo(newVersion) < 0)
{
if (server.isRegistered(elementName))
{
unregisterMBean(elementName);
log.debug("Unregistering previous version " + preVersion);
}
log.debug("Installing newer version " + newVersion);
return createMBean(element);
}
return server.getObjectInstance(elementName);
}
private ObjectName getElementName(MBeanElement element)
throws MalformedObjectNameException
{
return (element.getName() != null) ? new ObjectName(element.getName()) : null;
}
private Map createValueMap(MBeanElement element)
{
HashMap valueMap = new HashMap();
if (element.getVersions() != null && !element.getVersions().isEmpty())
valueMap.put(VERSIONS, element.getVersions());
valueMap.put(DATE, new Date(System.currentTimeMillis()));
valueMap.put(ServerConstants.CLASSLOADER, ctxClassLoader);
return valueMap;
}
private List getVersions(ObjectName name)
throws MBeanException, ReflectionException, InstanceNotFoundException
{
if (!server.isRegistered(name))
return null;
return (List) getValue(name, VERSIONS);
}
private Object getValue(ObjectName name, String key)
throws MBeanException, ReflectionException, InstanceNotFoundException
{
Object value =
server.invoke(registryName, "getValue",
new Object[]
{
name,
key
},
new String[]
{
ObjectName.class.getName(),
String.class.getName()
}
);
return value;
}
private ObjectInstance registerMBean(Object object, ObjectName name, Map valueMap)
throws MBeanException, ReflectionException, InstanceNotFoundException
{
if (object == null)
{
throw new ReflectionException(new IllegalArgumentException(
"Attempting to register a null object"
));
}
return (ObjectInstance)
server.invoke(registryName, "registerMBean",
new Object[]
{
object,
name,
valueMap
},
new String[]
{
Object.class.getName(),
ObjectName.class.getName(),
Map.class.getName()
}
);
}
private void unregisterMBean(ObjectName name)
throws MBeanException, ReflectionException, InstanceNotFoundException
{
server.invoke(registryName, "unregisterMBean",
new Object[]
{
name,
},
new String[]
{
ObjectName.class.getName(),
}
);
}
}
class MLetVersion implements Comparable
{
protected List versions;
public MLetVersion(List versions)
{
this.versions = versions;
}
public List getVersions()
{
return versions;
}
public boolean isNull()
{
return versions == null || versions.isEmpty();
}
public int compareTo(Object o)
{
MLetVersion other = (MLetVersion) o;
if (isNull() || other.isNull())
throw new IllegalArgumentException("MLet versions is null");
String thisVersion = (String) versions.get(0);
String otherVersion = (String) other.getVersions().get(0);
return (thisVersion.compareTo(otherVersion));
}
public String toString()
{
return "Version " + versions.get(0);
}
}