package org.jboss.mx.server;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.security.ProtectionDomain;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.JMException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.RuntimeErrorException;
import javax.management.RuntimeMBeanException;
import javax.management.RuntimeOperationsException;
import javax.management.JMRuntimeException;
import javax.management.MBeanPermission;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanTrustPermission;
import javax.management.loading.ClassLoaderRepository;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBean;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import org.jboss.logging.Logger;
import org.jboss.mx.loading.LoaderRepository;
import org.jboss.mx.modelmbean.ModelMBeanConstants;
import org.jboss.mx.modelmbean.RequiredModelMBeanInstantiator;
import org.jboss.mx.notification.MBeanServerListenerRegistry;
import org.jboss.mx.server.registry.MBeanEntry;
import org.jboss.mx.server.registry.MBeanRegistry;
import org.jboss.mx.service.ServiceConstants;
import org.jboss.mx.util.JMXExceptionDecoder;
import org.jboss.mx.util.PropertyAccess;
import org.jboss.util.NestedRuntimeException;
public class MBeanServerImpl
implements MBeanServer, ServerConstants, ServiceConstants, ModelMBeanConstants
{
private static final Object[] NOPARAMS = new Object[0];
private static final String[] NOSIG = new String[0];
protected MBeanServer outer = null;
protected MBeanRegistry registry = null;
private MBeanServerListenerRegistry listeners = new MBeanServerListenerRegistry();
private ClassLoaderRepository classLoaderRepository;
private static Logger log = Logger.getLogger(MBeanServerImpl.class);
public MBeanServerImpl(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate)
{
if (outer == null)
this.outer = this;
else
this.outer = outer;
this.classLoaderRepository = getClassLoaderRepository();
this.registry = createRegistry(defaultDomain);
try
{
HashMap valueMap = new HashMap();
valueMap.put(JMI_DOMAIN, JMI_DOMAIN);
registry.registerMBean(delegate,
new ObjectName(MBEAN_SERVER_DELEGATE),
valueMap);
ModelMBean rmm = RequiredModelMBeanInstantiator.instantiate();
rmm.setModelMBeanInfo(getRegistryManagementInterface());
rmm.setManagedResource(registry, "ObjectReference");
registry.registerMBean(rmm, new ObjectName(MBEAN_REGISTRY), valueMap);
ObjectName loaderName = new ObjectName(DEFAULT_LOADER_NAME);
registry.registerMBean(classLoaderRepository, loaderName, valueMap);
}
catch (Exception e)
{
throw new RuntimeException("Cannot create MBeanServer", e);
}
}
public Object instantiate(String className)
throws ReflectionException, MBeanException
{
return instantiate(className, (ClassLoader) null, NOPARAMS, NOSIG);
}
public Object instantiate(String className, Object[] params, String[] signature)
throws ReflectionException, MBeanException
{
return instantiate(className, (ClassLoader) null, params, signature);
}
public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException, InstanceNotFoundException
{
return instantiate(className, loaderName, NOPARAMS, NOSIG);
}
public Object instantiate(String className, ObjectName loaderName, Object[] params, String[] signature)
throws ReflectionException, MBeanException, InstanceNotFoundException
{
ClassLoader cl = null;
try
{
if (loaderName != null)
cl = (ClassLoader) registry.get(loaderName).getResourceInstance();
}
catch (ClassCastException e)
{
throw new ReflectionException(e, loaderName + " is not a class loader.");
}
if (cl == null)
cl = this.getClass().getClassLoader();
if (cl == null)
cl = ClassLoader.getSystemClassLoader();
return instantiate(className, cl, params, signature);
}
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException
{
try
{
Object mbean = instantiate(className);
return registerMBean(mbean, name, (ClassLoader) null);
}
catch (SecurityException e)
{
throw e;
}
catch (ReflectionException refex)
{
if (refex.getCause() instanceof InstantiationException)
throw new NotCompliantMBeanException("Cannot instanciate MBean: " + className);
else
throw refex;
}
}
public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException
{
try
{
Object mbean = instantiate(className, params, signature);
return registerMBean(mbean, name, (ClassLoader) null);
}
catch (ReflectionException refex)
{
return handleExceptionOnCreate(refex, className);
}
}
public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
{
try
{
Object mbean = instantiate(className, loaderName);
return registerMBean(mbean, name, loaderName);
}
catch (ReflectionException refex)
{
return handleExceptionOnCreate(refex, className);
}
}
public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
{
try
{
Object mbean = instantiate(className, loaderName, params, signature);
return registerMBean(mbean, name, loaderName);
}
catch (ReflectionException refex)
{
return handleExceptionOnCreate(refex, className);
}
}
private ObjectInstance handleExceptionOnCreate(ReflectionException refex, String className)
throws NotCompliantMBeanException, ReflectionException
{
if (refex.getCause() instanceof InstantiationException)
throw new NotCompliantMBeanException("Cannot instanciate MBean: " + className);
throw refex;
}
public ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException
{
return registerMBean(object, name, (ClassLoader) null);
}
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException
{
MBeanEntry entry = registry.get(name);
Object mbean = entry.getResourceInstance();
name = entry.getObjectName();
checkMBeanPermission(entry.getResourceClassName(), null, name, "unregisterMBean");
try
{
final Object[] args = {name};
final String[] sig = {ObjectName.class.getName()};
try
{
AccessController.doPrivileged(
new PrivilegedExceptionAction()
{
public Object run() throws Exception
{
return invoke(new ObjectName(MBEAN_REGISTRY),
"unregisterMBean", args, sig);
}
}
);
}
catch(PrivilegedActionException e)
{
throw e.getException();
}
}
catch (Throwable t)
{
Throwable result = JMXExceptionDecoder.decodeToJMXException(t);
if (result instanceof InstanceNotFoundException)
throw (InstanceNotFoundException) result;
if (result instanceof MBeanRegistrationException)
throw (MBeanRegistrationException) result;
if ( result instanceof JMRuntimeException )
throw (JMRuntimeException) result;
if (result instanceof RuntimeException)
throw new RuntimeMBeanException((RuntimeException) result);
if (result instanceof Error)
throw new RuntimeErrorException((Error) result);
throw new MBeanRegistrationException(new InvocationTargetException(t), "Cannot unregister MBean");
}
if (mbean instanceof NotificationBroadcaster)
listeners.remove(name);
}
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException
{
ObjectInstance oi = registry.getObjectInstance(name);
checkMBeanPermission(oi.getClassName(), null, name,
"getObjectInstance");
return oi;
}
public Set queryMBeans(ObjectName name, QueryExp query)
{
checkMBeanPermission(null, null, null, "queryMBeans");
Set result = new HashSet();
if (query != null)
query.setMBeanServer(outer);
SecurityManager sm = System.getSecurityManager();
List entries = registry.findEntries(name);
Iterator iterator = entries.iterator();
while (iterator.hasNext())
{
MBeanEntry entry = (MBeanEntry) iterator.next();
ObjectName objectName = entry.getObjectName();
if( sm != null )
{
try
{
checkMBeanPermission(entry.getResourceClassName(), null,
objectName, "queryMBeans");
}
catch(SecurityException e)
{
if( log.isTraceEnabled() )
log.trace("Excluded mbean due to security: "+objectName);
continue;
}
}
if (queryMBean(objectName, query) == true)
{
try
{
ObjectInstance instance = registry.getObjectInstance(objectName);
result.add(instance);
}
catch (InstanceNotFoundException ignored)
{
}
}
}
return result;
}
public Set queryNames(ObjectName name, QueryExp query)
{
checkMBeanPermission(null, null, null, "queryNames");
Set result = new HashSet();
if (query != null)
query.setMBeanServer(outer);
SecurityManager sm = System.getSecurityManager();
List entries = registry.findEntries(name);
Iterator iterator = entries.iterator();
while (iterator.hasNext())
{
MBeanEntry entry = (MBeanEntry) iterator.next();
ObjectName objectName = entry.getObjectName();
if( sm != null )
{
try
{
checkMBeanPermission(entry.getResourceClassName(), null,
objectName, "queryNames");
}
catch(SecurityException e)
{
if( log.isTraceEnabled() )
log.trace("Excluded mbean due to security: "+objectName);
continue;
}
}
if (queryMBean(objectName, query) == true)
result.add(objectName);
}
return result;
}
public boolean isRegistered(ObjectName name)
{
return registry.contains(name);
}
public java.lang.Integer getMBeanCount()
{
return new Integer(registry.getSize());
}
public Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException
{
MBeanEntry entry = registry.get(name);
checkMBeanPermission(entry.getResourceClassName(), attribute, name,
"getAttribute");
MBeanInvoker mbean = entry.getInvoker();
return mbean.getAttribute(attribute);
}
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException
{
MBeanEntry entry = registry.get(name);
String className = entry.getResourceClassName();
checkMBeanPermission(className, null, name, "getAttribute");
MBeanInvoker mbean = entry.getInvoker();
AttributeList list = mbean.getAttributes(attributes);
SecurityManager sm = System.getSecurityManager();
if( sm != null )
{
Iterator iter = list.iterator();
while( iter.hasNext() )
{
Attribute attr = (Attribute) iter.next();
String aname = attr.getName();
try
{
checkMBeanPermission(className, aname, name, "getAttribute");
}
catch(SecurityException e)
{
if( log.isTraceEnabled() )
log.trace("Excluded attribute due to security: "+aname);
iter.remove();
}
}
}
return list;
}
public void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
{
MBeanEntry entry = registry.get(name);
String attributeName = null;
if (attribute != null)
attributeName = attribute.getName();
checkMBeanPermission(entry.getResourceClassName(), attributeName,
name, "setAttribute");
MBeanInvoker mbean = entry.getInvoker();
mbean.setAttribute(attribute);
}
public AttributeList setAttributes(ObjectName name, AttributeList attributes)
throws InstanceNotFoundException, ReflectionException
{
MBeanEntry entry = registry.get(name);
String className = entry.getResourceClassName();
checkMBeanPermission(className, null, name, "setAttribute");
MBeanInvoker mbean = entry.getInvoker();
AttributeList list = mbean.setAttributes(attributes);
SecurityManager sm = System.getSecurityManager();
if( sm != null )
{
Iterator iter = list.iterator();
while( iter.hasNext() )
{
Attribute attr = (Attribute) iter.next();
String aname = attr.getName();
try
{
checkMBeanPermission(className, aname, name, "setAttribute");
}
catch(SecurityException e)
{
if( log.isTraceEnabled() )
log.trace("Excluded attribute due to security: "+aname);
iter.remove();
}
}
}
return list;
}
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException
{
MBeanEntry entry = registry.get(name);
checkMBeanPermission(entry.getResourceClassName(), operationName, name,
"invoke");
MBeanInvoker mbean = entry.getInvoker();
return mbean.invoke(operationName, params, signature);
}
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException
{
MBeanEntry entry = registry.get(name);
checkMBeanPermission(entry.getResourceClassName(), null, name,
"getMBeanInfo");
try
{
MBeanInvoker invoker = entry.getInvoker();
return invoker.getMBeanInfo();
}
catch (Exception e)
{
JMException result = ExceptionHandler.handleException(e);
if (result instanceof InstanceNotFoundException)
throw (InstanceNotFoundException) result;
if (result instanceof IntrospectionException)
throw (IntrospectionException) result;
if (result instanceof ReflectionException)
throw (ReflectionException) result;
throw new RuntimeException("Cannot obtain MBeanInfo " + name, result);
}
}
public String getDefaultDomain()
{
return registry.getDefaultDomain();
}
public String[] getDomains()
{
checkMBeanPermission(null, null, null, "getDomains");
String[] domains = registry.getDomains();
SecurityManager sm = System.getSecurityManager();
if( sm != null )
{
ArrayList tmp = new ArrayList();
int length = domains != null ? domains.length : 0;
for(int n = 0; n < length; n ++)
{
String domain = domains[n];
try
{
ObjectName name = new ObjectName(domain, "x", "x");
checkMBeanPermission(null, null, name, "getDomains");
tmp.add(domain);
}
catch(MalformedObjectNameException e)
{
}
catch(SecurityException e)
{
if( log.isTraceEnabled() )
log.trace("Excluded domain due to security: "+domain);
}
}
domains = new String[tmp.size()];
tmp.toArray(domains);
}
return domains;
}
public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)
throws InstanceNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean named exists but does not implement the NotificationBroadcaster interface."));
if (listener == null)
throw new RuntimeOperationsException(new IllegalArgumentException("Cannot add null listener"));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"addNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
NotificationBroadcaster broadcaster = entry.getInvoker();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.add(entry.getObjectName(), broadcaster, listener, filter, handback);
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)
throws InstanceNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
MBeanEntry listenerEntry = registry.get(listener);
if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"addNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
NotificationBroadcaster broadcaster = entry.getInvoker();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.add(entry.getObjectName(), broadcaster,
(NotificationListener) registry.get(listener).getResourceInstance(), filter, handback);
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public void removeNotificationListener(ObjectName name, NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"removeNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.remove(entry.getObjectName(), listener);
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
MBeanEntry listenerEntry = registry.get(listener);
if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"removeNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.remove(entry.getObjectName(), (NotificationListener) registry.get(listener).getResourceInstance());
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public void removeNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"removeNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.remove(entry.getObjectName(), listener, filter, handback);
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public void removeNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException
{
MBeanEntry entry = registry.get(name);
if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
MBeanEntry listenerEntry = registry.get(listener);
if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
checkMBeanPermission(entry.getResourceClassName(), null, name,
"removeNotificationListener");
ClassLoader newTCL = entry.getClassLoader();
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
final boolean setCl = newTCL != oldTCL && newTCL != null;
try
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(newTCL);
listeners.remove(entry.getObjectName(), (NotificationListener) registry.get(listener).getResourceInstance(),
filter, handback);
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException
{
MBeanEntry entry = registry.get(name);
String mbeanClassName = entry.getResourceClassName();
checkMBeanPermission(mbeanClassName, null, name, "isInstanceOf");
if (className.equals(mbeanClassName))
return true;
Class mbeanClass = null;
Class testClass = null;
ClassLoader cl = getClassLoaderFor(name);
try
{
mbeanClass = cl.loadClass(mbeanClassName);
testClass = cl.loadClass(className);
}
catch (ClassNotFoundException e)
{
return false;
}
if (testClass.isAssignableFrom(mbeanClass))
return true;
else
return false;
}
public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException, OperationsException
{
try
{
ClassLoader cl = this.getClassLoaderFor(name);
return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
}
catch (IOException e)
{
throw new OperationsException("I/O exception deserializing: " + e.getMessage());
}
}
public ObjectInputStream deserialize(String className, byte[] data)
throws OperationsException, ReflectionException
{
try
{
Class c = this.getClassLoaderRepository().loadClass(className);
ClassLoader cl = c.getClassLoader();
return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
}
catch (IOException e)
{
throw new OperationsException("I/O exception deserializing: " + e.getMessage());
}
catch (ClassNotFoundException e)
{
throw new ReflectionException(e, "Class not found from default repository: " + className);
}
}
public ObjectInputStream deserialize(String className, ObjectName loaderName,
byte[] data)
throws InstanceNotFoundException, OperationsException, ReflectionException
{
try
{
ClassLoader cl = this.getClassLoader(loaderName);
return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
}
catch (IOException e)
{
throw new OperationsException("I/O exception deserializing: " + e.getMessage());
}
}
public ClassLoader getClassLoaderFor(ObjectName name)
throws InstanceNotFoundException
{
MBeanEntry entry = registry.get(name);
checkMBeanPermission(entry.getResourceClassName(), null, name,
"getClassLoaderFor");
ClassLoader cl = entry.getClassLoader();
if (cl == null)
cl = entry.getResourceInstance().getClass().getClassLoader();
if (cl == null)
cl = ClassLoader.getSystemClassLoader();
return cl;
}
public ClassLoader getClassLoader(ObjectName name)
throws InstanceNotFoundException
{
Object loader = null;
if( name == null )
{
checkMBeanPermission(null, null, name, "getClassLoader");
loader = getClass().getClassLoader();
if (loader == null)
loader = ClassLoader.getSystemClassLoader();
}
else
{
MBeanEntry entry = registry.get(name);
checkMBeanPermission(entry.getResourceClassName(), null, name,
"getClassLoader");
loader = entry.getResourceInstance();
}
if ((loader instanceof ClassLoader) == false)
throw new InstanceNotFoundException("Not a classloader " + name);
return (ClassLoader) loader;
}
public ClassLoaderRepository getClassLoaderRepository()
{
checkMBeanPermission(null, null, null, "getClassLoaderRepository");
if (classLoaderRepository == null)
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String className = PropertyAccess.getProperty(LOADER_REPOSITORY_CLASS_PROPERTY, DEFAULT_LOADER_REPOSITORY_CLASS);
PropertyAccess.setProperty(LOADER_REPOSITORY_CLASS_PROPERTY, className);
try
{
Class repository = cl.loadClass(className);
classLoaderRepository = (LoaderRepository) repository.newInstance();
}
catch (ClassNotFoundException e)
{
throw new Error("Cannot instantiate loader repository class: " + className);
}
catch (ClassCastException e)
{
throw new Error("Loader repository is not an instance of LoaderRepository: " + className);
}
catch (Exception e)
{
throw new Error("Error creating loader repository: " + e);
}
}
return classLoaderRepository;
}
public void releaseServer()
{
registry.releaseRegistry();
listeners.removeAll();
listeners = null;
registry = null;
}
protected Object instantiate(String className, ClassLoader cl, Object[] params, String[] signature)
throws ReflectionException, MBeanException
{
if (className == null)
throw new RuntimeOperationsException(new IllegalArgumentException("Null className"));
if (className.equals(""))
throw new ReflectionException(new ClassNotFoundException("empty class name"));
if (params == null)
params = NOPARAMS;
if (signature == null)
signature = NOSIG;
checkMBeanPermission(className, null, null, "instantiate");
ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
boolean setCl = false;
try
{
Class clazz = null;
if (cl != null)
{
if (cl != oldTCL)
{
setCl = true;
TCLAction.UTIL.setContextClassLoader(cl);
}
clazz = cl.loadClass(className);
}
else
clazz = classLoaderRepository.loadClass(className);
Class[] sign = new Class[signature.length];
for (int i = 0; i < signature.length; ++i)
{
if (LoaderRepository.getNativeClassForName(signature[i]) == null)
{
try
{
if (cl != null)
sign[i] = cl.loadClass(signature[i]);
else
sign[i] = classLoaderRepository.loadClass(signature[i]);
}
catch (ClassNotFoundException e)
{
throw new ReflectionException(e, "Constructor parameter class not found: " + signature[i]);
}
}
else
{
sign[i] = LoaderRepository.getNativeClassForName(signature[i]);
}
}
Constructor constructor = clazz.getConstructor(sign);
return constructor.newInstance(params);
}
catch (Throwable t)
{
handleInstantiateExceptions(t, className);
log.error("Unhandled exception instantiating class: " + className, t);
return null;
}
finally
{
if (setCl)
TCLAction.UTIL.setContextClassLoader(oldTCL);
}
}
protected void handleInstantiateExceptions(Throwable t, String className)
throws ReflectionException, MBeanException
{
if (t instanceof ReflectionException)
throw (ReflectionException) t;
else if (t instanceof ClassNotFoundException)
throw new ReflectionException((Exception) t, "Class not found: " + className);
else if (t instanceof InstantiationException)
throw new ReflectionException((Exception) t, "Cannot instantiate: " + className);
else if (t instanceof IllegalAccessException)
throw new ReflectionException((Exception) t, "Illegal access to constructor: " + className);
else if (t instanceof NoSuchMethodException)
throw new ReflectionException((Exception) t, "Cannot find such a public constructor: " + className);
else if (t instanceof SecurityException)
throw new ReflectionException((Exception) t, "Can't access constructor for " + className);
else if (t instanceof InvocationTargetException)
{
Throwable root = ((InvocationTargetException) t).getTargetException();
if (root instanceof RuntimeException)
throw new RuntimeMBeanException((RuntimeException) root, className + " constructor has thrown an exception: " + root.toString());
else if (root instanceof Error)
throw new RuntimeErrorException((Error) root, className + " constructor has thrown an error: " + root.toString());
else if (root instanceof Exception)
throw new MBeanException((Exception) root, className + " constructor has thrown an exception: " + root.toString());
throw new Error("Something went wrong with handling the exception from " + className + " default constructor.");
}
else if (t instanceof ExceptionInInitializerError)
{
Throwable root = ((ExceptionInInitializerError) t).getException();
if (root instanceof RuntimeException)
throw new RuntimeMBeanException((RuntimeException) root, "Exception in class " + className + " static initializer: " + root.toString());
else
throw new Error("ERROR: it turns out the root cause is not always a runtime exception!");
}
else if (t instanceof IllegalArgumentException)
{
throw new Error("Error in the server: mismatch between expected constructor arguments and supplied arguments.");
}
else if (t instanceof Error)
{
throw new RuntimeErrorException((Error) t, "instantiating " + className + " failed: " + t.toString());
}
}
protected ObjectInstance registerMBean(Object mbean, ObjectName name, ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
{
ClassLoader cl = null;
if (loaderName == null)
{
cl = getClass().getClassLoader();
if (cl == null)
cl = ClassLoader.getSystemClassLoader();
}
else
{
try
{
cl = (ClassLoader) registry.get(loaderName).getResourceInstance();
}
catch (ClassCastException e)
{
throw new ReflectionException(e, loaderName + " is not a class loader.");
}
}
return registerMBean(mbean, name, cl);
}
protected ObjectInstance registerMBean(Object object, ObjectName name,
ClassLoader cl)
throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException
{
final Class objectClass = object.getClass();
String className = objectClass.getName();
checkMBeanPermission(className, null, name, "registerMBean");
if( System.getSecurityManager() != null )
{
ProtectionDomain pd = (ProtectionDomain) AccessController.doPrivileged(
new PrivilegedAction()
{
public Object run()
{
return objectClass.getProtectionDomain();
}
}
);
if( pd != null )
{
MBeanTrustPermission p = new MBeanTrustPermission("register");
if( pd.implies(p) == false )
{
String msg = "MBeanTrustPermission(register) not implied by "
+ "protection domain of mbean class: "+className+", pd: "+pd;
throw new SecurityException(msg);
}
}
}
HashMap valueMap = null;
if (cl != null)
{
valueMap = new HashMap();
valueMap.put(CLASSLOADER, cl);
}
try
{
final Object[] args = {object, name, valueMap};
final String[] sig = {Object.class.getName(),
ObjectName.class.getName(), Map.class.getName()};
try
{
ObjectInstance oi = (ObjectInstance) AccessController.doPrivileged(
new PrivilegedExceptionAction()
{
public Object run() throws Exception
{
return invoke(new ObjectName(MBEAN_REGISTRY),
"registerMBean", args, sig);
}
}
);
return oi;
}
catch(PrivilegedActionException e)
{
throw e.getException();
}
}
catch (Throwable t)
{
Throwable result = JMXExceptionDecoder.decodeToJMXException(t);
if (result instanceof InstanceAlreadyExistsException)
throw (InstanceAlreadyExistsException) result;
if (result instanceof MBeanRegistrationException)
throw (MBeanRegistrationException) result;
if (result instanceof NotCompliantMBeanException)
throw (NotCompliantMBeanException) result;
if ( result instanceof JMRuntimeException )
throw (JMRuntimeException) result;
if (result instanceof RuntimeException)
throw new RuntimeMBeanException((RuntimeException) result);
if (result instanceof Error)
throw new RuntimeErrorException((Error) result);
throw new MBeanRegistrationException(new InvocationTargetException(t), "Cannot register MBean");
}
}
protected boolean queryMBean(ObjectName objectName, QueryExp queryExp)
{
if (queryExp == null)
return true;
try
{
return queryExp.apply(objectName);
}
catch (Exception e)
{
return false;
}
}
protected MBeanRegistry createRegistry(String defaultDomain)
{
String registryClass = PropertyAccess.getProperty(ServerConstants.MBEAN_REGISTRY_CLASS_PROPERTY,
ServerConstants.DEFAULT_MBEAN_REGISTRY_CLASS);
try
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass(registryClass);
Constructor constructor = clazz.getConstructor(new Class[] {MBeanServer.class, String.class, ClassLoaderRepository.class});
return (MBeanRegistry) constructor.newInstance(new Object[] {outer, defaultDomain, classLoaderRepository});
}
catch (ClassNotFoundException e)
{
throw new NestedRuntimeException("The MBean registry implementation class " + registryClass +
" was not found: ", e);
}
catch (NoSuchMethodException e)
{
throw new NestedRuntimeException("The MBean registry implementation class " + registryClass +
" must contain a default <init>(MBeanServer srvr, String domain) " +
" constructor.", e);
}
catch (InstantiationException e)
{
throw new NestedRuntimeException("Cannot instantiate class " + registryClass + ": ", e);
}
catch (IllegalAccessException e)
{
throw new NestedRuntimeException("Unable to create the MBean registry instance. Illegal access " +
"to class " + registryClass + " constructor: ", e);
}
catch (InvocationTargetException e)
{
throw new NestedRuntimeException("Unable to create the MBean registry instance. Class " + registryClass +
" has raised an exception in constructor: ", e.getTargetException());
}
}
private ModelMBeanInfo getRegistryManagementInterface()
{
final boolean READABLE = true;
final boolean WRITABLE = true;
final boolean BOOLEAN = true;
DescriptorSupport descDefaultDomain = new DescriptorSupport();
descDefaultDomain.setField("name", "DefaultDomain");
descDefaultDomain.setField("descriptorType", "attribute");
descDefaultDomain.setField("displayName", "Default Domain");
descDefaultDomain.setField("default", getDefaultDomain());
descDefaultDomain.setField("currencyTimeLimit", "-1");
ModelMBeanAttributeInfo defaultDomainInfo =
new ModelMBeanAttributeInfo
("DefaultDomain", String.class.getName(),
"The domain to use when an object name has no domain",
READABLE, !WRITABLE, !BOOLEAN,
descDefaultDomain);
DescriptorSupport descSize = new DescriptorSupport();
descSize.setField("name", "Size");
descSize.setField("descriptorType", "attribute");
descSize.setField("displayName", "Size");
descSize.setField("getMethod", "getSize");
ModelMBeanAttributeInfo sizeInfo =
new ModelMBeanAttributeInfo
("Size", Integer.TYPE.getName(),
"The number of MBeans registered in the MBean Server",
READABLE, !WRITABLE, !BOOLEAN,
descSize);
DescriptorSupport descRegisterMBean = new DescriptorSupport();
descRegisterMBean.setField("name", "registerMBean");
descRegisterMBean.setField("descriptorType", "operation");
descRegisterMBean.setField("role", "operation");
MBeanParameterInfo[] registerMBeanParms =
new MBeanParameterInfo[]
{
new MBeanParameterInfo
("Resource",
Object.class.getName(),
"A compliant MBean to be registered in the MBean Server"),
new MBeanParameterInfo
("ObjectName",
ObjectName.class.getName(),
"The object name of the MBean"),
new MBeanParameterInfo
("ValueMap",
Map.class.getName(),
"Values associated with the registration"),
};
ModelMBeanOperationInfo registerMBeanInfo =
new ModelMBeanOperationInfo
("registerMBean",
"Adds an MBean in the MBeanServer",
registerMBeanParms,
ObjectInstance.class.getName(),
ModelMBeanOperationInfo.ACTION_INFO,
descRegisterMBean);
DescriptorSupport descUnregisterMBean = new DescriptorSupport();
descUnregisterMBean.setField("name", "unregisterMBean");
descUnregisterMBean.setField("descriptorType", "operation");
descUnregisterMBean.setField("role", "operation");
MBeanParameterInfo[] unregisterMBeanParms =
new MBeanParameterInfo[]
{
new MBeanParameterInfo
("ObjectName",
ObjectName.class.getName(),
"The object name of the MBean to remove")
};
ModelMBeanOperationInfo unregisterMBeanInfo =
new ModelMBeanOperationInfo
("unregisterMBean",
"Removes an MBean from the MBeanServer",
unregisterMBeanParms,
Void.TYPE.getName(),
ModelMBeanOperationInfo.ACTION,
descUnregisterMBean);
DescriptorSupport descGetSize = new DescriptorSupport();
descGetSize.setField("name", "getSize");
descGetSize.setField("descriptorType", "operation");
descGetSize.setField("role", "getter");
MBeanParameterInfo[] getSizeParms = new MBeanParameterInfo[0];
ModelMBeanOperationInfo getSizeInfo =
new ModelMBeanOperationInfo
("getSize",
"Gets the number of MBeans registered",
getSizeParms,
Integer.TYPE.getName(),
ModelMBeanOperationInfo.INFO,
descGetSize);
DescriptorSupport descGet = new DescriptorSupport();
descGet.setField("name", "get");
descGet.setField("descriptorType", "operation");
descGet.setField("role", "operation");
MBeanParameterInfo[] getParam = new MBeanParameterInfo[1];
getParam[0] = new MBeanParameterInfo("ObjectName", ObjectName.class.getName(), "object name to find");
ModelMBeanOperationInfo getInfo =
new ModelMBeanOperationInfo
("get",
"Gets the MBeanEntry for a given ObjectName",
getParam,
MBeanEntry.class.getName(),
ModelMBeanOperationInfo.INFO,
descGet);
DescriptorSupport descGetValue = new DescriptorSupport();
descGetValue.setField("name", "getValue");
descGetValue.setField("descriptorType", "operation");
descGetValue.setField("role", "operation");
MBeanParameterInfo[] getValueParms = new MBeanParameterInfo[]
{
new MBeanParameterInfo
("ObjectName",
ObjectName.class.getName(),
"The object name of the registered MBean"),
new MBeanParameterInfo
("Key",
String.class.getName(),
"The key to the value stored")
};
ModelMBeanOperationInfo getValueInfo =
new ModelMBeanOperationInfo
("getValue",
"Get a value stored in the MBean's registration",
getValueParms,
Object.class.getName(),
ModelMBeanOperationInfo.INFO,
descGetValue);
DescriptorSupport descMBean = new DescriptorSupport();
descMBean.setField("name", RequiredModelMBeanInstantiator.getClassName());
descMBean.setField("descriptorType", "MBean");
descMBean.setField("displayName", "MBeanServer Registry");
ModelMBeanAttributeInfo[] attrInfo = new ModelMBeanAttributeInfo[]
{
defaultDomainInfo,
sizeInfo
};
ModelMBeanConstructorInfo[] ctorInfo = null;
ModelMBeanOperationInfo[] opInfo = new ModelMBeanOperationInfo[]
{
registerMBeanInfo,
unregisterMBeanInfo,
getSizeInfo,
getValueInfo,
getInfo
};
ModelMBeanNotificationInfo[] notifyInfo = null;
ModelMBeanInfoSupport info = new ModelMBeanInfoSupport
(RequiredModelMBeanInstantiator.getClassName(),
"Managed Bean Registry",
attrInfo,
ctorInfo,
opInfo,
notifyInfo,
descMBean);
return info;
}
private void checkMBeanPermission(String className, String member,
ObjectName objectName, String action)
{
SecurityManager sm = System.getSecurityManager();
if( sm != null )
{
MBeanPermission p = new MBeanPermission(className, member, objectName,
action);
sm.checkPermission(p);
}
}
public String toString()
{
return super.toString() + "[ defaultDomain='" + this.getDefaultDomain() + "' ]";
}
}