0001: /*
0002: * JBoss, Home of Professional Open Source.
0003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004: * as indicated by the @author tags. See the copyright.txt file in the
0005: * distribution for a full listing of individual contributors.
0006: *
0007: * This is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU Lesser General Public License as
0009: * published by the Free Software Foundation; either version 2.1 of
0010: * the License, or (at your option) any later version.
0011: *
0012: * This software is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this software; if not, write to the Free
0019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021: */
0022: package org.jboss.mx.server;
0023:
0024: import java.io.ByteArrayInputStream;
0025: import java.io.IOException;
0026: import java.io.ObjectInputStream;
0027: import java.lang.reflect.Constructor;
0028: import java.lang.reflect.InvocationTargetException;
0029: import java.util.ArrayList;
0030: import java.util.HashMap;
0031: import java.util.HashSet;
0032: import java.util.Iterator;
0033: import java.util.List;
0034: import java.util.Map;
0035: import java.util.Set;
0036: import java.security.ProtectionDomain;
0037: import java.security.AccessController;
0038: import java.security.PrivilegedAction;
0039: import java.security.PrivilegedExceptionAction;
0040: import java.security.PrivilegedActionException;
0041:
0042: import javax.management.Attribute;
0043: import javax.management.AttributeList;
0044: import javax.management.AttributeNotFoundException;
0045: import javax.management.InstanceAlreadyExistsException;
0046: import javax.management.InstanceNotFoundException;
0047: import javax.management.IntrospectionException;
0048: import javax.management.InvalidAttributeValueException;
0049: import javax.management.JMException;
0050: import javax.management.ListenerNotFoundException;
0051: import javax.management.MBeanException;
0052: import javax.management.MBeanInfo;
0053: import javax.management.MBeanParameterInfo;
0054: import javax.management.MBeanRegistrationException;
0055: import javax.management.MBeanServer;
0056: import javax.management.MBeanServerDelegate;
0057: import javax.management.NotCompliantMBeanException;
0058: import javax.management.NotificationBroadcaster;
0059: import javax.management.NotificationFilter;
0060: import javax.management.NotificationListener;
0061: import javax.management.ObjectInstance;
0062: import javax.management.ObjectName;
0063: import javax.management.OperationsException;
0064: import javax.management.QueryExp;
0065: import javax.management.ReflectionException;
0066: import javax.management.RuntimeErrorException;
0067: import javax.management.RuntimeMBeanException;
0068: import javax.management.RuntimeOperationsException;
0069: import javax.management.JMRuntimeException;
0070: import javax.management.MBeanPermission;
0071: import javax.management.MalformedObjectNameException;
0072: import javax.management.MBeanTrustPermission;
0073: import javax.management.loading.ClassLoaderRepository;
0074: import javax.management.modelmbean.DescriptorSupport;
0075: import javax.management.modelmbean.ModelMBean;
0076: import javax.management.modelmbean.ModelMBeanAttributeInfo;
0077: import javax.management.modelmbean.ModelMBeanConstructorInfo;
0078: import javax.management.modelmbean.ModelMBeanInfo;
0079: import javax.management.modelmbean.ModelMBeanInfoSupport;
0080: import javax.management.modelmbean.ModelMBeanNotificationInfo;
0081: import javax.management.modelmbean.ModelMBeanOperationInfo;
0082:
0083: import org.jboss.logging.Logger;
0084: import org.jboss.mx.loading.LoaderRepository;
0085: import org.jboss.mx.modelmbean.ModelMBeanConstants;
0086: import org.jboss.mx.modelmbean.RequiredModelMBeanInstantiator;
0087: import org.jboss.mx.notification.MBeanServerListenerRegistry;
0088: import org.jboss.mx.server.registry.MBeanEntry;
0089: import org.jboss.mx.server.registry.MBeanRegistry;
0090: import org.jboss.mx.service.ServiceConstants;
0091: import org.jboss.mx.util.JMXExceptionDecoder;
0092: import org.jboss.mx.util.PropertyAccess;
0093: import org.jboss.util.NestedRuntimeException;
0094:
0095: /**
0096: * MBean server implementation.
0097: *
0098: * The MBean server behaviour can be configured by setting the following
0099: * system properties: <ul>
0100: * <li><tt>jbossmx.loader.repository.class</tt>
0101: ({@link ServerConstants#LOADER_REPOSITORY_CLASS_PROPERTY LOADER_REPOSITORY_CLASS_PROPERTY})</li>
0102: * <li><tt>jbossmx.mbean.registry.class</tt>
0103: ({@link ServerConstants#MBEAN_REGISTRY_CLASS_PROPERTY MBEAN_REGISTRY_CLASS_PROPERTY})</li>
0104: * <li><tt>jbossmx.required.modelmbean.class</tt>
0105: ({@link ServerConstants#REQUIRED_MODELMBEAN_CLASS_PROPERTY REQUIRED_MODELMBEAN_CLASS_PROPERTY})</li>
0106: * </ul>
0107: *
0108: * The loader repository is used for managing class loaders in the MBean server.
0109: * The default repository uses the <tt>UnifiedLoaderRepository</tt> implementation
0110: * ({@link ServerConstants#DEFAULT_LOADER_REPOSITORY_CLASS DEFAULT_LOADER_REPOSITORY_CLASS}).<p>
0111: *
0112: * The default registry is
0113: * ({@link ServerConstants#DEFAULT_MBEAN_REGISTRY_CLASS DEFAULT_MBEAN_REGISTRY_CLASS}).<p>
0114: *
0115: * The <tt>RequiredModelMBean</tt> uses <tt>XMBean</tt> implementation by default
0116: * ({@link ServerConstants#DEFAULT_REQUIRED_MODELMBEAN_CLASS DEFAULT_REQUIRED_MODELMBEAN_CLASS}).
0117: *
0118: * @see javax.management.MBeanServer
0119: * @see javax.management.modelmbean.RequiredModelMBean
0120: * @see org.jboss.mx.server.ServerConstants
0121: * @see org.jboss.mx.loading.LoaderRepository
0122: * @see org.jboss.mx.loading.UnifiedLoaderRepository3
0123: * @see org.jboss.mx.modelmbean.XMBean
0124: *
0125: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
0126: * @author <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
0127: * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
0128: * @author <a href="mailto:thomas.diesler@jboss.com">Thomas Diesler</a>.
0129: * @author Scott.Stark@jboss.org
0130: * @version $Revision: 57200 $
0131: */
0132: public class MBeanServerImpl implements MBeanServer, ServerConstants,
0133: ServiceConstants, ModelMBeanConstants {
0134: // Constants ------------------------------------------------------
0135:
0136: /**
0137: * No parameters array
0138: */
0139: private static final Object[] NOPARAMS = new Object[0];
0140:
0141: /**
0142: * No signature array
0143: */
0144: private static final String[] NOSIG = new String[0];
0145:
0146: // Attributes ----------------------------------------------------
0147:
0148: /**
0149: * The wrapping MBeanServer
0150: */
0151: protected MBeanServer outer = null;
0152:
0153: /**
0154: * Registry used by this server to map MBean object names to resource references.
0155: */
0156: protected MBeanRegistry registry = null;
0157:
0158: /**
0159: * The notification registrations
0160: */
0161: private MBeanServerListenerRegistry listeners = new MBeanServerListenerRegistry();
0162:
0163: /**
0164: * This server's class loader repository
0165: */
0166: private ClassLoaderRepository classLoaderRepository;
0167:
0168: // Static --------------------------------------------------------
0169:
0170: /**
0171: * The logger
0172: */
0173: private static Logger log = Logger.getLogger(MBeanServerImpl.class);
0174:
0175: // Constructors --------------------------------------------------
0176:
0177: /**
0178: * Creates an MBean server implementation with a given default domain name and
0179: * registers the mandatory server delegate MBean to the server
0180: * ({@link ServerConstants#MBEAN_SERVER_DELEGATE MBEAN_SERVER_DELEGATE}).
0181: *
0182: * @param defaultDomain default domain name
0183: * @param outer the wrapping MBeanServer, passed to MBeans
0184: * at registration.
0185: * @param delegate the delegate to use
0186: * for Notifications.
0187: */
0188: public MBeanServerImpl(String defaultDomain, MBeanServer outer,
0189: MBeanServerDelegate delegate) {
0190: // Determine the MBeanServer to pass to MBeans
0191: if (outer == null)
0192: this .outer = this ;
0193: else
0194: this .outer = outer;
0195:
0196: // the very first thing to do is to create a class loader repository
0197: this .classLoaderRepository = getClassLoaderRepository();
0198:
0199: // the second first thing to do is to create a registry instance
0200: this .registry = createRegistry(defaultDomain);
0201:
0202: // The first MBean to be registered should be the server delegate
0203: // to guarantee correct functionality (other MBeans may be dependent
0204: // on the existence of the delegate).
0205: try {
0206: // the magic token that allows us to register to the
0207: // protected JMImplementation domain
0208: HashMap valueMap = new HashMap();
0209: valueMap.put(JMI_DOMAIN, JMI_DOMAIN);
0210:
0211: // register the delegate
0212: registry.registerMBean(delegate, new ObjectName(
0213: MBEAN_SERVER_DELEGATE), valueMap);
0214:
0215: // We expose the registry as an MBean for other components
0216: ModelMBean rmm = RequiredModelMBeanInstantiator
0217: .instantiate();
0218: rmm.setModelMBeanInfo(getRegistryManagementInterface());
0219: rmm.setManagedResource(registry, "ObjectReference");
0220:
0221: // register the registry MBean
0222: registry.registerMBean(rmm, new ObjectName(MBEAN_REGISTRY),
0223: valueMap);
0224:
0225: // register the loader repository
0226: //String loaderClassMBeanName = classLoaderRepository.getClass().getName() + "MBean";
0227: //ClassLoader cl = classLoaderRepository.getClass().getClassLoader();
0228: //Class mbean = cl.loadClass(loaderClassMBeanName);
0229:
0230: //there must be a class with the MBean extension.
0231: ObjectName loaderName = new ObjectName(DEFAULT_LOADER_NAME);
0232: registry.registerMBean(classLoaderRepository, loaderName,
0233: valueMap);
0234:
0235: } catch (Exception e) {
0236: throw new RuntimeException("Cannot create MBeanServer", e);
0237: }
0238: }
0239:
0240: // MBeanServer implementation ------------------------------------
0241:
0242: public Object instantiate(String className)
0243: throws ReflectionException, MBeanException {
0244: return instantiate(className, (ClassLoader) null, NOPARAMS,
0245: NOSIG);
0246: }
0247:
0248: public Object instantiate(String className, Object[] params,
0249: String[] signature) throws ReflectionException,
0250: MBeanException {
0251: return instantiate(className, (ClassLoader) null, params,
0252: signature);
0253: }
0254:
0255: public Object instantiate(String className, ObjectName loaderName)
0256: throws ReflectionException, MBeanException,
0257: InstanceNotFoundException {
0258: return instantiate(className, loaderName, NOPARAMS, NOSIG);
0259: }
0260:
0261: public Object instantiate(String className, ObjectName loaderName,
0262: Object[] params, String[] signature)
0263: throws ReflectionException, MBeanException,
0264: InstanceNotFoundException {
0265: ClassLoader cl = null;
0266:
0267: // if instantiate() is called with null loader name, we use the cl that
0268: // loaded the MBean server (see javadoc)
0269:
0270: try {
0271: if (loaderName != null)
0272: cl = (ClassLoader) registry.get(loaderName)
0273: .getResourceInstance();
0274: } catch (ClassCastException e) {
0275: throw new ReflectionException(e, loaderName
0276: + " is not a class loader.");
0277: }
0278:
0279: if (cl == null)
0280: cl = this .getClass().getClassLoader();
0281: if (cl == null)
0282: cl = ClassLoader.getSystemClassLoader();
0283:
0284: return instantiate(className, cl, params, signature);
0285: }
0286:
0287: public ObjectInstance createMBean(String className, ObjectName name)
0288: throws ReflectionException, InstanceAlreadyExistsException,
0289: MBeanRegistrationException, MBeanException,
0290: NotCompliantMBeanException {
0291: try {
0292: Object mbean = instantiate(className);
0293: return registerMBean(mbean, name, (ClassLoader) null);
0294: } catch (SecurityException e) {
0295: throw e;
0296: } catch (ReflectionException refex) {
0297: // Note, the CTS wants a NotCompliantMBeanException for this case
0298: if (refex.getCause() instanceof InstantiationException)
0299: throw new NotCompliantMBeanException(
0300: "Cannot instanciate MBean: " + className);
0301: else
0302: throw refex;
0303: }
0304: }
0305:
0306: public ObjectInstance createMBean(String className,
0307: ObjectName name, Object[] params, String[] signature)
0308: throws ReflectionException, InstanceAlreadyExistsException,
0309: MBeanRegistrationException, MBeanException,
0310: NotCompliantMBeanException {
0311: try {
0312: Object mbean = instantiate(className, params, signature);
0313: return registerMBean(mbean, name, (ClassLoader) null);
0314: } catch (ReflectionException refex) {
0315: return handleExceptionOnCreate(refex, className);
0316: }
0317: }
0318:
0319: public ObjectInstance createMBean(String className,
0320: ObjectName name, ObjectName loaderName)
0321: throws ReflectionException, InstanceAlreadyExistsException,
0322: MBeanRegistrationException, MBeanException,
0323: NotCompliantMBeanException, InstanceNotFoundException {
0324: try {
0325: Object mbean = instantiate(className, loaderName);
0326: return registerMBean(mbean, name, loaderName);
0327: } catch (ReflectionException refex) {
0328: return handleExceptionOnCreate(refex, className);
0329: }
0330: }
0331:
0332: public ObjectInstance createMBean(String className,
0333: ObjectName name, ObjectName loaderName, Object[] params,
0334: String[] signature) throws ReflectionException,
0335: InstanceAlreadyExistsException, MBeanRegistrationException,
0336: MBeanException, NotCompliantMBeanException,
0337: InstanceNotFoundException {
0338: try {
0339: Object mbean = instantiate(className, loaderName, params,
0340: signature);
0341: return registerMBean(mbean, name, loaderName);
0342: } catch (ReflectionException refex) {
0343: return handleExceptionOnCreate(refex, className);
0344: }
0345: }
0346:
0347: /**
0348: * The CTS wants a NotCompliantMBeanException in case the MBean cannot be created.
0349: * We need this, because instanciate cannot throw NotCompliantMBeanException.
0350: */
0351: private ObjectInstance handleExceptionOnCreate(
0352: ReflectionException refex, String className)
0353: throws NotCompliantMBeanException, ReflectionException {
0354: if (refex.getCause() instanceof InstantiationException)
0355: throw new NotCompliantMBeanException(
0356: "Cannot instanciate MBean: " + className);
0357:
0358: throw refex;
0359: }
0360:
0361: /**
0362: * Registers a pre-existing object as an MBean with the MBean server. If the object name given is null,
0363: * the MBean must provide its own name by implementing the MBeanRegistration interface and returning the name
0364: * from the preRegister method.
0365: */
0366: public ObjectInstance registerMBean(Object object, ObjectName name)
0367: throws InstanceAlreadyExistsException,
0368: MBeanRegistrationException, NotCompliantMBeanException {
0369: return registerMBean(object, name, (ClassLoader) null);
0370: }
0371:
0372: public void unregisterMBean(ObjectName name)
0373: throws InstanceNotFoundException,
0374: MBeanRegistrationException {
0375: // Get the mbean to remove
0376: MBeanEntry entry = registry.get(name);
0377: Object mbean = entry.getResourceInstance();
0378: name = entry.getObjectName();
0379:
0380: checkMBeanPermission(entry.getResourceClassName(), null, name,
0381: "unregisterMBean");
0382:
0383: try {
0384: final Object[] args = { name };
0385: final String[] sig = { ObjectName.class.getName() };
0386: try {
0387: AccessController
0388: .doPrivileged(new PrivilegedExceptionAction() {
0389: public Object run() throws Exception {
0390: return invoke(new ObjectName(
0391: MBEAN_REGISTRY),
0392: "unregisterMBean", args, sig);
0393: }
0394: });
0395: } catch (PrivilegedActionException e) {
0396: throw e.getException();
0397: }
0398: } catch (Throwable t) {
0399: Throwable result = JMXExceptionDecoder
0400: .decodeToJMXException(t);
0401: if (result instanceof InstanceNotFoundException)
0402: throw (InstanceNotFoundException) result;
0403: if (result instanceof MBeanRegistrationException)
0404: throw (MBeanRegistrationException) result;
0405: if (result instanceof JMRuntimeException)
0406: throw (JMRuntimeException) result;
0407: if (result instanceof RuntimeException)
0408: throw new RuntimeMBeanException(
0409: (RuntimeException) result);
0410: if (result instanceof Error)
0411: throw new RuntimeErrorException((Error) result);
0412:
0413: // for some other reason, unregistration failed
0414: throw new MBeanRegistrationException(
0415: new InvocationTargetException(t),
0416: "Cannot unregister MBean");
0417: }
0418:
0419: // Unregistration worked, remove any proxies for a broadcaster
0420: if (mbean instanceof NotificationBroadcaster)
0421: listeners.remove(name);
0422: }
0423:
0424: public ObjectInstance getObjectInstance(ObjectName name)
0425: throws InstanceNotFoundException {
0426: ObjectInstance oi = registry.getObjectInstance(name);
0427: checkMBeanPermission(oi.getClassName(), null, name,
0428: "getObjectInstance");
0429:
0430: return oi;
0431: }
0432:
0433: public Set queryMBeans(ObjectName name, QueryExp query) {
0434: // At least one mbean must be queriable
0435: checkMBeanPermission(null, null, null, "queryMBeans");
0436:
0437: // Set up the query
0438: Set result = new HashSet();
0439: if (query != null)
0440: query.setMBeanServer(outer);
0441:
0442: SecurityManager sm = System.getSecurityManager();
0443: // Get the possible MBeans
0444: List entries = registry.findEntries(name);
0445: Iterator iterator = entries.iterator();
0446: while (iterator.hasNext()) {
0447: // Check each MBean against the query
0448: MBeanEntry entry = (MBeanEntry) iterator.next();
0449: ObjectName objectName = entry.getObjectName();
0450: // The permission check must be done before the query is applied
0451: if (sm != null) {
0452: try {
0453: checkMBeanPermission(entry.getResourceClassName(),
0454: null, objectName, "queryMBeans");
0455: } catch (SecurityException e) {
0456: if (log.isTraceEnabled())
0457: log.trace("Excluded mbean due to security: "
0458: + objectName);
0459: continue;
0460: }
0461: }
0462: // Check the mbean against the query
0463: if (queryMBean(objectName, query) == true) {
0464: try {
0465: ObjectInstance instance = registry
0466: .getObjectInstance(objectName);
0467: result.add(instance);
0468: } catch (InstanceNotFoundException ignored) {
0469: }
0470: }
0471: }
0472:
0473: return result;
0474: }
0475:
0476: public Set queryNames(ObjectName name, QueryExp query) {
0477: // At least one mbean must be queriable
0478: checkMBeanPermission(null, null, null, "queryNames");
0479:
0480: // Set up the query
0481: Set result = new HashSet();
0482: if (query != null)
0483: query.setMBeanServer(outer);
0484:
0485: SecurityManager sm = System.getSecurityManager();
0486: // Get the possible MBeans
0487: List entries = registry.findEntries(name);
0488: Iterator iterator = entries.iterator();
0489: while (iterator.hasNext()) {
0490: // Check each MBean against the query
0491: MBeanEntry entry = (MBeanEntry) iterator.next();
0492: ObjectName objectName = entry.getObjectName();
0493: // The permission check must be done before the query is applied
0494: if (sm != null) {
0495: try {
0496: checkMBeanPermission(entry.getResourceClassName(),
0497: null, objectName, "queryNames");
0498: } catch (SecurityException e) {
0499: if (log.isTraceEnabled())
0500: log.trace("Excluded mbean due to security: "
0501: + objectName);
0502: continue;
0503: }
0504: }
0505: // Check the mbean against the query
0506: if (queryMBean(objectName, query) == true)
0507: result.add(objectName);
0508: }
0509:
0510: return result;
0511: }
0512:
0513: public boolean isRegistered(ObjectName name) {
0514: return registry.contains(name);
0515: }
0516:
0517: public java.lang.Integer getMBeanCount() {
0518: return new Integer(registry.getSize());
0519: }
0520:
0521: public Object getAttribute(ObjectName name, String attribute)
0522: throws MBeanException, AttributeNotFoundException,
0523: InstanceNotFoundException, ReflectionException {
0524: MBeanEntry entry = registry.get(name);
0525: checkMBeanPermission(entry.getResourceClassName(), attribute,
0526: name, "getAttribute");
0527:
0528: MBeanInvoker mbean = entry.getInvoker();
0529:
0530: return mbean.getAttribute(attribute);
0531: }
0532:
0533: public AttributeList getAttributes(ObjectName name,
0534: String[] attributes) throws InstanceNotFoundException,
0535: ReflectionException {
0536: MBeanEntry entry = registry.get(name);
0537: String className = entry.getResourceClassName();
0538: /* Access to an attribute is required and this check will fail only
0539: if access to no attributes are allowed and will result in a security
0540: exception rather than an empty list.
0541: */
0542: checkMBeanPermission(className, null, name, "getAttribute");
0543:
0544: MBeanInvoker mbean = entry.getInvoker();
0545: AttributeList list = mbean.getAttributes(attributes);
0546: SecurityManager sm = System.getSecurityManager();
0547: if (sm != null) {
0548: // Remove any attributes that are not allowed
0549: Iterator iter = list.iterator();
0550: while (iter.hasNext()) {
0551: Attribute attr = (Attribute) iter.next();
0552: String aname = attr.getName();
0553: try {
0554: checkMBeanPermission(className, aname, name,
0555: "getAttribute");
0556: } catch (SecurityException e) {
0557: if (log.isTraceEnabled())
0558: log
0559: .trace("Excluded attribute due to security: "
0560: + aname);
0561: iter.remove();
0562: }
0563: }
0564: }
0565: return list;
0566: }
0567:
0568: public void setAttribute(ObjectName name, Attribute attribute)
0569: throws InstanceNotFoundException,
0570: AttributeNotFoundException, InvalidAttributeValueException,
0571: MBeanException, ReflectionException {
0572: MBeanEntry entry = registry.get(name);
0573: String attributeName = null;
0574: if (attribute != null)
0575: attributeName = attribute.getName();
0576: checkMBeanPermission(entry.getResourceClassName(),
0577: attributeName, name, "setAttribute");
0578:
0579: MBeanInvoker mbean = entry.getInvoker();
0580:
0581: mbean.setAttribute(attribute);
0582: }
0583:
0584: public AttributeList setAttributes(ObjectName name,
0585: AttributeList attributes) throws InstanceNotFoundException,
0586: ReflectionException {
0587: MBeanEntry entry = registry.get(name);
0588:
0589: String className = entry.getResourceClassName();
0590: /* Access to an attribute is required and this check will fail only
0591: if access to no attributes are allowed and will result in a security
0592: exception rather than an empty list.
0593: */
0594: checkMBeanPermission(className, null, name, "setAttribute");
0595:
0596: MBeanInvoker mbean = entry.getInvoker();
0597: AttributeList list = mbean.setAttributes(attributes);
0598: SecurityManager sm = System.getSecurityManager();
0599: if (sm != null) {
0600: // Remove any attributes that are not allowed
0601: Iterator iter = list.iterator();
0602: while (iter.hasNext()) {
0603: Attribute attr = (Attribute) iter.next();
0604: String aname = attr.getName();
0605: try {
0606: checkMBeanPermission(className, aname, name,
0607: "setAttribute");
0608: } catch (SecurityException e) {
0609: if (log.isTraceEnabled())
0610: log
0611: .trace("Excluded attribute due to security: "
0612: + aname);
0613: iter.remove();
0614: }
0615: }
0616: }
0617: return list;
0618: }
0619:
0620: public Object invoke(ObjectName name, String operationName,
0621: Object[] params, String[] signature)
0622: throws InstanceNotFoundException, MBeanException,
0623: ReflectionException {
0624: MBeanEntry entry = registry.get(name);
0625: checkMBeanPermission(entry.getResourceClassName(),
0626: operationName, name, "invoke");
0627:
0628: MBeanInvoker mbean = entry.getInvoker();
0629:
0630: return mbean.invoke(operationName, params, signature);
0631: }
0632:
0633: public MBeanInfo getMBeanInfo(ObjectName name)
0634: throws InstanceNotFoundException, IntrospectionException,
0635: ReflectionException {
0636: MBeanEntry entry = registry.get(name);
0637: checkMBeanPermission(entry.getResourceClassName(), null, name,
0638: "getMBeanInfo");
0639: try {
0640: MBeanInvoker invoker = entry.getInvoker();
0641: return invoker.getMBeanInfo();
0642: } catch (Exception e) {
0643: JMException result = ExceptionHandler.handleException(e);
0644: if (result instanceof InstanceNotFoundException)
0645: throw (InstanceNotFoundException) result;
0646: if (result instanceof IntrospectionException)
0647: throw (IntrospectionException) result;
0648: if (result instanceof ReflectionException)
0649: throw (ReflectionException) result;
0650: throw new RuntimeException("Cannot obtain MBeanInfo "
0651: + name, result);
0652: }
0653: }
0654:
0655: public String getDefaultDomain() {
0656: return registry.getDefaultDomain();
0657: }
0658:
0659: public String[] getDomains() {
0660: checkMBeanPermission(null, null, null, "getDomains");
0661: String[] domains = registry.getDomains();
0662: SecurityManager sm = System.getSecurityManager();
0663: if (sm != null) {
0664: ArrayList tmp = new ArrayList();
0665: // Remove any domains that are not allowed
0666: int length = domains != null ? domains.length : 0;
0667: for (int n = 0; n < length; n++) {
0668: String domain = domains[n];
0669: try {
0670: ObjectName name = new ObjectName(domain, "x", "x");
0671: checkMBeanPermission(null, null, name, "getDomains");
0672: tmp.add(domain);
0673: } catch (MalformedObjectNameException e) {
0674: // Should not be possible
0675: } catch (SecurityException e) {
0676: if (log.isTraceEnabled())
0677: log.trace("Excluded domain due to security: "
0678: + domain);
0679: }
0680: }
0681: domains = new String[tmp.size()];
0682: tmp.toArray(domains);
0683: }
0684: return domains;
0685: }
0686:
0687: /**
0688: * Adds a listener to a registered MBean.
0689: *
0690: * A notification emitted by the MBean will be forwarded by the MBeanServer to the listener.
0691: * If the source of the notification is a reference to the MBean object, the MBean server will replace
0692: * it by the MBean's ObjectName. Otherwise the source is unchanged.
0693: */
0694: public void addNotificationListener(ObjectName name,
0695: NotificationListener listener, NotificationFilter filter,
0696: Object handback) throws InstanceNotFoundException {
0697: MBeanEntry entry = registry.get(name);
0698: if (NotificationBroadcaster.class.isInstance(entry
0699: .getResourceInstance()) == false)
0700: throw new RuntimeOperationsException(
0701: new IllegalArgumentException(
0702: "The MBean named exists but does not implement the NotificationBroadcaster interface."));
0703:
0704: if (listener == null)
0705: throw new RuntimeOperationsException(
0706: new IllegalArgumentException(
0707: "Cannot add null listener"));
0708:
0709: checkMBeanPermission(entry.getResourceClassName(), null, name,
0710: "addNotificationListener");
0711:
0712: ClassLoader newTCL = entry.getClassLoader();
0713: NotificationBroadcaster broadcaster = entry.getInvoker();
0714:
0715: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0716: final boolean setCl = newTCL != oldTCL && newTCL != null;
0717: try {
0718: if (setCl)
0719: TCLAction.UTIL.setContextClassLoader(newTCL);
0720:
0721: listeners.add(entry.getObjectName(), broadcaster, listener,
0722: filter, handback);
0723: } finally {
0724: if (setCl)
0725: TCLAction.UTIL.setContextClassLoader(oldTCL);
0726: }
0727: }
0728:
0729: /**
0730: * Adds a listener to a registered MBean.
0731: *
0732: * A notification emitted by the MBean will be forwarded by the MBeanServer to the listener.
0733: * If the source of the notification is a reference to the MBean object, the MBean server will replace
0734: * it by the MBean's ObjectName. Otherwise the source is unchanged.
0735: *
0736: * The listener object that receives notifications is the one that is registered with the given name at the time this
0737: * method is called. Even if it is subsequently unregistered, it will continue to receive notifications.
0738: */
0739: public void addNotificationListener(ObjectName name,
0740: ObjectName listener, NotificationFilter filter,
0741: Object handback) throws InstanceNotFoundException {
0742: MBeanEntry entry = registry.get(name);
0743: if (NotificationBroadcaster.class.isInstance(entry
0744: .getResourceInstance()) == false)
0745: throw new RuntimeOperationsException(
0746: new IllegalArgumentException(
0747: "The MBean "
0748: + name
0749: + " exists but does not implement the NotificationBroadcaster interface."));
0750:
0751: MBeanEntry listenerEntry = registry.get(listener);
0752: if (NotificationListener.class.isInstance(listenerEntry
0753: .getResourceInstance()) == false)
0754: throw new RuntimeOperationsException(
0755: new IllegalArgumentException(
0756: "The MBean "
0757: + listener
0758: + " exists but does not implement the NotificationListener interface."));
0759:
0760: checkMBeanPermission(entry.getResourceClassName(), null, name,
0761: "addNotificationListener");
0762:
0763: ClassLoader newTCL = entry.getClassLoader();
0764: NotificationBroadcaster broadcaster = entry.getInvoker();
0765:
0766: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0767: final boolean setCl = newTCL != oldTCL && newTCL != null;
0768: try {
0769: if (setCl)
0770: TCLAction.UTIL.setContextClassLoader(newTCL);
0771:
0772: listeners.add(entry.getObjectName(), broadcaster,
0773: (NotificationListener) registry.get(listener)
0774: .getResourceInstance(), filter, handback);
0775: } finally {
0776: if (setCl)
0777: TCLAction.UTIL.setContextClassLoader(oldTCL);
0778: }
0779: }
0780:
0781: /**
0782: * Removes a listener from a registered MBean.
0783: *
0784: * If the listener is registered more than once, perhaps with different filters or callbacks,
0785: * this method will remove all those registrations.
0786: */
0787: public void removeNotificationListener(ObjectName name,
0788: NotificationListener listener)
0789: throws InstanceNotFoundException, ListenerNotFoundException {
0790: MBeanEntry entry = registry.get(name);
0791: if (NotificationBroadcaster.class.isInstance(entry
0792: .getResourceInstance()) == false)
0793: throw new RuntimeOperationsException(
0794: new IllegalArgumentException(
0795: "The MBean "
0796: + name
0797: + " exists but does not implement the NotificationBroadcaster interface."));
0798:
0799: checkMBeanPermission(entry.getResourceClassName(), null, name,
0800: "removeNotificationListener");
0801:
0802: ClassLoader newTCL = entry.getClassLoader();
0803:
0804: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0805: final boolean setCl = newTCL != oldTCL && newTCL != null;
0806: try {
0807: if (setCl)
0808: TCLAction.UTIL.setContextClassLoader(newTCL);
0809:
0810: listeners.remove(entry.getObjectName(), listener);
0811: } finally {
0812: if (setCl)
0813: TCLAction.UTIL.setContextClassLoader(oldTCL);
0814: }
0815: }
0816:
0817: /**
0818: * Removes a listener from a registered MBean.
0819: *
0820: * If the listener is registered more than once, perhaps with different filters or callbacks,
0821: * this method will remove all those registrations.
0822: */
0823: public void removeNotificationListener(ObjectName name,
0824: ObjectName listener) throws InstanceNotFoundException,
0825: ListenerNotFoundException {
0826: MBeanEntry entry = registry.get(name);
0827: if (NotificationBroadcaster.class.isInstance(entry
0828: .getResourceInstance()) == false)
0829: throw new RuntimeOperationsException(
0830: new IllegalArgumentException(
0831: "The MBean "
0832: + name
0833: + " exists but does not implement the NotificationBroadcaster interface."));
0834:
0835: MBeanEntry listenerEntry = registry.get(listener);
0836: if (NotificationListener.class.isInstance(listenerEntry
0837: .getResourceInstance()) == false)
0838: throw new RuntimeOperationsException(
0839: new IllegalArgumentException(
0840: "The MBean "
0841: + listener
0842: + " exists but does not implement the NotificationListener interface."));
0843:
0844: checkMBeanPermission(entry.getResourceClassName(), null, name,
0845: "removeNotificationListener");
0846:
0847: ClassLoader newTCL = entry.getClassLoader();
0848:
0849: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0850: final boolean setCl = newTCL != oldTCL && newTCL != null;
0851: try {
0852: if (setCl)
0853: TCLAction.UTIL.setContextClassLoader(newTCL);
0854:
0855: listeners.remove(entry.getObjectName(),
0856: (NotificationListener) registry.get(listener)
0857: .getResourceInstance());
0858: } finally {
0859: if (setCl)
0860: TCLAction.UTIL.setContextClassLoader(oldTCL);
0861: }
0862: }
0863:
0864: /**
0865: * Removes a listener from a registered MBean.
0866: *
0867: * The MBean must have a listener that exactly matches the given listener, filter, and handback parameters.
0868: * If there is more than one such listener, only one is removed.
0869: *
0870: * The filter and handback parameters may be null if and only if they are null in a listener to be removed.
0871: */
0872: public void removeNotificationListener(ObjectName name,
0873: NotificationListener listener, NotificationFilter filter,
0874: Object handback) throws InstanceNotFoundException,
0875: ListenerNotFoundException {
0876: MBeanEntry entry = registry.get(name);
0877: if (NotificationBroadcaster.class.isInstance(entry
0878: .getResourceInstance()) == false)
0879: throw new RuntimeOperationsException(
0880: new IllegalArgumentException(
0881: "The MBean "
0882: + name
0883: + " exists but does not implement the NotificationBroadcaster interface."));
0884:
0885: checkMBeanPermission(entry.getResourceClassName(), null, name,
0886: "removeNotificationListener");
0887:
0888: ClassLoader newTCL = entry.getClassLoader();
0889:
0890: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0891: final boolean setCl = newTCL != oldTCL && newTCL != null;
0892: try {
0893: if (setCl)
0894: TCLAction.UTIL.setContextClassLoader(newTCL);
0895:
0896: listeners.remove(entry.getObjectName(), listener, filter,
0897: handback);
0898: } finally {
0899: if (setCl)
0900: TCLAction.UTIL.setContextClassLoader(oldTCL);
0901: }
0902: }
0903:
0904: /**
0905: * Removes a listener from a registered MBean.
0906: *
0907: * The MBean must have a listener that exactly matches the given listener, filter, and handback parameters.
0908: * If there is more than one such listener, only one is removed.
0909: *
0910: * The filter and handback parameters may be null if and only if they are null in a listener to be removed.
0911: */
0912: public void removeNotificationListener(ObjectName name,
0913: ObjectName listener, NotificationFilter filter,
0914: Object handback) throws InstanceNotFoundException,
0915: ListenerNotFoundException {
0916: MBeanEntry entry = registry.get(name);
0917: if (NotificationBroadcaster.class.isInstance(entry
0918: .getResourceInstance()) == false)
0919: throw new RuntimeOperationsException(
0920: new IllegalArgumentException(
0921: "The MBean "
0922: + name
0923: + " exists but does not implement the NotificationBroadcaster interface."));
0924:
0925: MBeanEntry listenerEntry = registry.get(listener);
0926: if (NotificationListener.class.isInstance(listenerEntry
0927: .getResourceInstance()) == false)
0928: throw new RuntimeOperationsException(
0929: new IllegalArgumentException(
0930: "The MBean "
0931: + listener
0932: + " exists but does not implement the NotificationListener interface."));
0933:
0934: checkMBeanPermission(entry.getResourceClassName(), null, name,
0935: "removeNotificationListener");
0936:
0937: ClassLoader newTCL = entry.getClassLoader();
0938:
0939: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
0940: final boolean setCl = newTCL != oldTCL && newTCL != null;
0941: try {
0942: if (setCl)
0943: TCLAction.UTIL.setContextClassLoader(newTCL);
0944:
0945: listeners.remove(entry.getObjectName(),
0946: (NotificationListener) registry.get(listener)
0947: .getResourceInstance(), filter, handback);
0948: } finally {
0949: if (setCl)
0950: TCLAction.UTIL.setContextClassLoader(oldTCL);
0951: }
0952: }
0953:
0954: public boolean isInstanceOf(ObjectName name, String className)
0955: throws InstanceNotFoundException {
0956: // Get the MBean's class name
0957: MBeanEntry entry = registry.get(name);
0958: String mbeanClassName = entry.getResourceClassName();
0959: checkMBeanPermission(mbeanClassName, null, name, "isInstanceOf");
0960:
0961: // The names are the same
0962: if (className.equals(mbeanClassName))
0963: return true;
0964:
0965: // Try to load both classes
0966: Class mbeanClass = null;
0967: Class testClass = null;
0968: ClassLoader cl = getClassLoaderFor(name);
0969: try {
0970: mbeanClass = cl.loadClass(mbeanClassName);
0971: testClass = cl.loadClass(className);
0972: } catch (ClassNotFoundException e) {
0973: return false;
0974: }
0975:
0976: // Check whether it is assignable
0977: if (testClass.isAssignableFrom(mbeanClass))
0978: return true;
0979: else
0980: return false;
0981: }
0982:
0983: /**
0984: * @deprecated
0985: */
0986: public ObjectInputStream deserialize(ObjectName name, byte[] data)
0987: throws InstanceNotFoundException, OperationsException {
0988: try {
0989: ClassLoader cl = this .getClassLoaderFor(name);
0990: return new ObjectInputStreamWithClassLoader(
0991: new ByteArrayInputStream(data), cl);
0992: } catch (IOException e) {
0993: throw new OperationsException(
0994: "I/O exception deserializing: " + e.getMessage());
0995: }
0996: }
0997:
0998: /**
0999: * @deprecated
1000: */
1001: public ObjectInputStream deserialize(String className, byte[] data)
1002: throws OperationsException, ReflectionException {
1003: try {
1004: Class c = this .getClassLoaderRepository().loadClass(
1005: className);
1006: ClassLoader cl = c.getClassLoader();
1007: return new ObjectInputStreamWithClassLoader(
1008: new ByteArrayInputStream(data), cl);
1009: } catch (IOException e) {
1010: throw new OperationsException(
1011: "I/O exception deserializing: " + e.getMessage());
1012: } catch (ClassNotFoundException e) {
1013: throw new ReflectionException(e,
1014: "Class not found from default repository: "
1015: + className);
1016: }
1017: }
1018:
1019: /**
1020: * @deprecated
1021: */
1022: public ObjectInputStream deserialize(String className,
1023: ObjectName loaderName, byte[] data)
1024: throws InstanceNotFoundException, OperationsException,
1025: ReflectionException {
1026: try {
1027: ClassLoader cl = this .getClassLoader(loaderName);
1028: return new ObjectInputStreamWithClassLoader(
1029: new ByteArrayInputStream(data), cl);
1030: } catch (IOException e) {
1031: throw new OperationsException(
1032: "I/O exception deserializing: " + e.getMessage());
1033: }
1034: }
1035:
1036: public ClassLoader getClassLoaderFor(ObjectName name)
1037: throws InstanceNotFoundException {
1038: MBeanEntry entry = registry.get(name);
1039: checkMBeanPermission(entry.getResourceClassName(), null, name,
1040: "getClassLoaderFor");
1041:
1042: ClassLoader cl = entry.getClassLoader();
1043: if (cl == null)
1044: cl = entry.getResourceInstance().getClass()
1045: .getClassLoader();
1046: if (cl == null)
1047: cl = ClassLoader.getSystemClassLoader();
1048: return cl;
1049: }
1050:
1051: /**
1052: *
1053: * @param name The ObjectName of the ClassLoader. May be null, in which case
1054: * the MBean server's own ClassLoader is returned.
1055: * @return
1056: * @throws InstanceNotFoundException
1057: */
1058: public ClassLoader getClassLoader(ObjectName name)
1059: throws InstanceNotFoundException {
1060: Object loader = null;
1061: if (name == null) {
1062: checkMBeanPermission(null, null, name, "getClassLoader");
1063: loader = getClass().getClassLoader();
1064: if (loader == null)
1065: loader = ClassLoader.getSystemClassLoader();
1066: } else {
1067: MBeanEntry entry = registry.get(name);
1068: checkMBeanPermission(entry.getResourceClassName(), null,
1069: name, "getClassLoader");
1070: loader = entry.getResourceInstance();
1071: }
1072:
1073: if ((loader instanceof ClassLoader) == false)
1074: throw new InstanceNotFoundException("Not a classloader "
1075: + name);
1076: return (ClassLoader) loader;
1077: }
1078:
1079: /**
1080: * Retrieve the classloader repository for this mbean server
1081: *
1082: * @return the classloader repository
1083: */
1084: public ClassLoaderRepository getClassLoaderRepository() {
1085: checkMBeanPermission(null, null, null,
1086: "getClassLoaderRepository");
1087:
1088: // we don't need to synchronize, because this is the first thing we do in the constructor
1089: if (classLoaderRepository == null) {
1090: ClassLoader cl = Thread.currentThread()
1091: .getContextClassLoader();
1092: String className = PropertyAccess.getProperty(
1093: LOADER_REPOSITORY_CLASS_PROPERTY,
1094: DEFAULT_LOADER_REPOSITORY_CLASS);
1095: PropertyAccess.setProperty(
1096: LOADER_REPOSITORY_CLASS_PROPERTY, className);
1097:
1098: try {
1099: Class repository = cl.loadClass(className);
1100: classLoaderRepository = (LoaderRepository) repository
1101: .newInstance();
1102: } catch (ClassNotFoundException e) {
1103: throw new Error(
1104: "Cannot instantiate loader repository class: "
1105: + className);
1106: } catch (ClassCastException e) {
1107: throw new Error(
1108: "Loader repository is not an instance of LoaderRepository: "
1109: + className);
1110: } catch (Exception e) {
1111: throw new Error("Error creating loader repository: "
1112: + e);
1113: }
1114: }
1115:
1116: return classLoaderRepository;
1117: }
1118:
1119: public void releaseServer() {
1120: // shutdown the loader repository
1121: // try
1122: // {
1123: // invoke(new ObjectName(DEFAULT_LOADER_NAME),
1124: // "releaseLoaderRepository",
1125: // new Object[0],
1126: // new String[0] );
1127: // }
1128: // catch (Exception e)
1129: // {
1130: // log.error("Unable to shutdown loader repository");
1131: // e.printStackTrace();
1132: // }
1133:
1134: registry.releaseRegistry();
1135: listeners.removeAll();
1136: listeners = null;
1137: registry = null;
1138: }
1139:
1140: // Protected -----------------------------------------------------
1141:
1142: /**
1143: * Instantiate an object, the passed classloader is set as the
1144: * thread's context classloader for the duration of this method.
1145: *
1146: * @param className the class name of the object to instantiate
1147: * @param cl the thread classloader, pass null to use the ClassLoaderRepository
1148: * @param params the parameters for the constructor
1149: * @param signature the signature of the constructor
1150: * @exception ReflectionException wraps a ClassCastException or
1151: * any Exception trying to invoke the constructor
1152: * @exception MBeanException wraps any exception thrown by the constructor
1153: * @exception RuntimeOperationsException Wraps an IllegalArgument for a
1154: * null className
1155: */
1156: protected Object instantiate(String className, ClassLoader cl,
1157: Object[] params, String[] signature)
1158: throws ReflectionException, MBeanException {
1159: if (className == null)
1160: throw new RuntimeOperationsException(
1161: new IllegalArgumentException("Null className"));
1162:
1163: if (className.equals(""))
1164: throw new ReflectionException(new ClassNotFoundException(
1165: "empty class name"));
1166:
1167: if (params == null)
1168: params = NOPARAMS;
1169:
1170: if (signature == null)
1171: signature = NOSIG;
1172:
1173: checkMBeanPermission(className, null, null, "instantiate");
1174:
1175: ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
1176:
1177: boolean setCl = false;
1178: try {
1179: Class clazz = null;
1180: if (cl != null) {
1181: if (cl != oldTCL) {
1182: setCl = true;
1183: TCLAction.UTIL.setContextClassLoader(cl);
1184: }
1185: clazz = cl.loadClass(className);
1186: } else
1187: clazz = classLoaderRepository.loadClass(className);
1188:
1189: Class[] sign = new Class[signature.length];
1190: for (int i = 0; i < signature.length; ++i) {
1191: if (LoaderRepository
1192: .getNativeClassForName(signature[i]) == null) {
1193: try {
1194: if (cl != null)
1195: sign[i] = cl.loadClass(signature[i]);
1196: else
1197: sign[i] = classLoaderRepository
1198: .loadClass(signature[i]);
1199: } catch (ClassNotFoundException e) {
1200: throw new ReflectionException(e,
1201: "Constructor parameter class not found: "
1202: + signature[i]);
1203: }
1204: } else {
1205: sign[i] = LoaderRepository
1206: .getNativeClassForName(signature[i]);
1207: }
1208: }
1209:
1210: Constructor constructor = clazz.getConstructor(sign);
1211: return constructor.newInstance(params);
1212: } catch (Throwable t) {
1213: handleInstantiateExceptions(t, className);
1214: log.error("Unhandled exception instantiating class: "
1215: + className, t);
1216: return null;
1217: } finally {
1218: if (setCl)
1219: TCLAction.UTIL.setContextClassLoader(oldTCL);
1220: }
1221: }
1222:
1223: /**
1224: * Handles errors thrown during class instantiation
1225: */
1226: protected void handleInstantiateExceptions(Throwable t,
1227: String className) throws ReflectionException,
1228: MBeanException {
1229: if (t instanceof ReflectionException)
1230: throw (ReflectionException) t;
1231:
1232: else if (t instanceof ClassNotFoundException)
1233: throw new ReflectionException((Exception) t,
1234: "Class not found: " + className);
1235:
1236: else if (t instanceof InstantiationException)
1237: throw new ReflectionException((Exception) t,
1238: "Cannot instantiate: " + className);
1239:
1240: else if (t instanceof IllegalAccessException)
1241: throw new ReflectionException((Exception) t,
1242: "Illegal access to constructor: " + className);
1243:
1244: else if (t instanceof NoSuchMethodException)
1245: throw new ReflectionException((Exception) t,
1246: "Cannot find such a public constructor: "
1247: + className);
1248:
1249: else if (t instanceof SecurityException)
1250: throw new ReflectionException((Exception) t,
1251: "Can't access constructor for " + className);
1252:
1253: else if (t instanceof InvocationTargetException) {
1254: Throwable root = ((InvocationTargetException) t)
1255: .getTargetException();
1256:
1257: if (root instanceof RuntimeException)
1258: throw new RuntimeMBeanException(
1259: (RuntimeException) root,
1260: className
1261: + " constructor has thrown an exception: "
1262: + root.toString());
1263: else if (root instanceof Error)
1264: throw new RuntimeErrorException((Error) root, className
1265: + " constructor has thrown an error: "
1266: + root.toString());
1267: else if (root instanceof Exception)
1268: throw new MBeanException((Exception) root, className
1269: + " constructor has thrown an exception: "
1270: + root.toString());
1271:
1272: throw new Error(
1273: "Something went wrong with handling the exception from "
1274: + className + " default constructor.");
1275: }
1276:
1277: else if (t instanceof ExceptionInInitializerError) {
1278: Throwable root = ((ExceptionInInitializerError) t)
1279: .getException();
1280:
1281: // the root cause can be only a runtime exception
1282: if (root instanceof RuntimeException)
1283: throw new RuntimeMBeanException(
1284: (RuntimeException) root, "Exception in class "
1285: + className + " static initializer: "
1286: + root.toString());
1287: else
1288: // shouldn't get here
1289: throw new Error(
1290: "ERROR: it turns out the root cause is not always a runtime exception!");
1291: }
1292:
1293: else if (t instanceof IllegalArgumentException) {
1294: // if mismatch between constructor instance args and supplied args -- shouldn't happen
1295: throw new Error(
1296: "Error in the server: mismatch between expected constructor arguments and supplied arguments.");
1297: }
1298:
1299: else if (t instanceof Error) {
1300: throw new RuntimeErrorException((Error) t, "instantiating "
1301: + className + " failed: " + t.toString());
1302: }
1303: }
1304:
1305: /**
1306: * Register an MBean<p>
1307: *
1308: * The classloader is used as the thread context classloader during
1309: * access to the mbean and it's interceptors
1310: *
1311: * @param mbean the mbean to register
1312: * @param name the object name to register
1313: * @param loaderName the object name of a class loader also used as
1314: * as the MBeans TCL
1315: * @exception InstanceAlreadyExistsException when already registered
1316: * @exception MBeanRegistrationException when
1317: * preRegister(MBeanServer, ObjectName) throws an exception
1318: * @exception NotCompliantMBeanException when the object is not an MBean
1319: */
1320: protected ObjectInstance registerMBean(Object mbean,
1321: ObjectName name, ObjectName loaderName)
1322: throws ReflectionException, InstanceAlreadyExistsException,
1323: MBeanRegistrationException, MBeanException,
1324: NotCompliantMBeanException, InstanceNotFoundException {
1325: ClassLoader cl = null;
1326:
1327: // If the loader name is null, the ClassLoader that loaded the MBean Server will be used.
1328: if (loaderName == null) {
1329: cl = getClass().getClassLoader();
1330: if (cl == null)
1331: cl = ClassLoader.getSystemClassLoader();
1332: } else {
1333: try {
1334: cl = (ClassLoader) registry.get(loaderName)
1335: .getResourceInstance();
1336: } catch (ClassCastException e) {
1337: throw new ReflectionException(e, loaderName
1338: + " is not a class loader.");
1339: }
1340: }
1341:
1342: return registerMBean(mbean, name, cl);
1343: }
1344:
1345: /**
1346: * Register an MBean<p>
1347: *
1348: * The classloader is used as the thread context classloader during
1349: * access to the mbean and it's interceptors
1350: *
1351: * @param object the mbean to register
1352: * @param name the object name to register
1353: * @param cl the thread classloader, pass null for the current one
1354: * @exception InstanceAlreadyExistsException when already registered
1355: * @exception MBeanRegistrationException when
1356: * preRegister(MBeanServer, ObjectName) throws an exception
1357: * @exception NotCompliantMBeanException when the object is not an MBean
1358: */
1359: protected ObjectInstance registerMBean(Object object,
1360: ObjectName name, ClassLoader cl)
1361: throws InstanceAlreadyExistsException,
1362: MBeanRegistrationException, NotCompliantMBeanException {
1363: final Class objectClass = object.getClass();
1364: String className = objectClass.getName();
1365:
1366: // Check that the caller has the ability to create/register mbeans
1367: checkMBeanPermission(className, null, name, "registerMBean");
1368:
1369: // Check that the mbean class is from a trusted source
1370: if (System.getSecurityManager() != null) {
1371: ProtectionDomain pd = (ProtectionDomain) AccessController
1372: .doPrivileged(new PrivilegedAction() {
1373: public Object run() {
1374: return objectClass.getProtectionDomain();
1375: }
1376: });
1377: if (pd != null) {
1378: MBeanTrustPermission p = new MBeanTrustPermission(
1379: "register");
1380: if (pd.implies(p) == false) {
1381: String msg = "MBeanTrustPermission(register) not implied by "
1382: + "protection domain of mbean class: "
1383: + className + ", pd: " + pd;
1384: throw new SecurityException(msg);
1385: }
1386: }
1387: }
1388:
1389: HashMap valueMap = null;
1390: if (cl != null) {
1391: valueMap = new HashMap();
1392: valueMap.put(CLASSLOADER, cl);
1393: }
1394:
1395: try {
1396: final Object[] args = { object, name, valueMap };
1397: final String[] sig = { Object.class.getName(),
1398: ObjectName.class.getName(), Map.class.getName() };
1399: try {
1400: ObjectInstance oi = (ObjectInstance) AccessController
1401: .doPrivileged(new PrivilegedExceptionAction() {
1402: public Object run() throws Exception {
1403: return invoke(new ObjectName(
1404: MBEAN_REGISTRY),
1405: "registerMBean", args, sig);
1406: }
1407: });
1408: return oi;
1409: } catch (PrivilegedActionException e) {
1410: throw e.getException();
1411: }
1412: } catch (Throwable t) {
1413: Throwable result = JMXExceptionDecoder
1414: .decodeToJMXException(t);
1415: if (result instanceof InstanceAlreadyExistsException)
1416: throw (InstanceAlreadyExistsException) result;
1417: if (result instanceof MBeanRegistrationException)
1418: throw (MBeanRegistrationException) result;
1419: if (result instanceof NotCompliantMBeanException)
1420: throw (NotCompliantMBeanException) result;
1421: if (result instanceof JMRuntimeException)
1422: throw (JMRuntimeException) result;
1423: if (result instanceof RuntimeException)
1424: throw new RuntimeMBeanException(
1425: (RuntimeException) result);
1426: if (result instanceof Error)
1427: throw new RuntimeErrorException((Error) result);
1428:
1429: // for some other reason, registration failed
1430: throw new MBeanRegistrationException(
1431: new InvocationTargetException(t),
1432: "Cannot register MBean");
1433: }
1434: }
1435:
1436: // Private -------------------------------------------------------
1437:
1438: /**
1439: * Query an MBean against the query
1440: *
1441: * @param objectName the object name of the mbean to check
1442: * @param queryExp the query expression to test
1443: * @return true when the query applies to the MBean or the query is null,
1444: * false otherwise.
1445: */
1446: protected boolean queryMBean(ObjectName objectName,
1447: QueryExp queryExp) {
1448: if (queryExp == null)
1449: return true;
1450:
1451: try {
1452: return queryExp.apply(objectName);
1453: } catch (Exception e) {
1454: return false;
1455: }
1456: }
1457:
1458: protected MBeanRegistry createRegistry(String defaultDomain) {
1459: // Find the registry implementation class: can be configured via
1460: // MBEAN_REGISTRY_CLASS_PROPERTY by the client -- if not found use
1461: // the class defined in DEFAULT_MBEAN_REGISTRY_CLASS (see ServerConstants)
1462: String registryClass = PropertyAccess.getProperty(
1463: ServerConstants.MBEAN_REGISTRY_CLASS_PROPERTY,
1464: ServerConstants.DEFAULT_MBEAN_REGISTRY_CLASS);
1465:
1466: try {
1467: // Try loading registry class via thread context classloader
1468: ClassLoader cl = Thread.currentThread()
1469: .getContextClassLoader();
1470: Class clazz = cl.loadClass(registryClass);
1471:
1472: // retrieve the constructor <init>(MBeanServer srvr, String defaultDomain, ClassLoaderRepository clr)
1473: Constructor constructor = clazz.getConstructor(new Class[] {
1474: MBeanServer.class, String.class,
1475: ClassLoaderRepository.class });
1476:
1477: // instantiate registry
1478: return (MBeanRegistry) constructor
1479: .newInstance(new Object[] { outer, defaultDomain,
1480: classLoaderRepository });
1481: }
1482: // Any exception preventing the registry to be created will cause the agent to fail.
1483: // However, try to give detailed exception messages to indicate config errors.
1484: catch (ClassNotFoundException e) {
1485: throw new NestedRuntimeException(
1486: "The MBean registry implementation class "
1487: + registryClass + " was not found: ", e);
1488: } catch (NoSuchMethodException e) {
1489: throw new NestedRuntimeException(
1490: "The MBean registry implementation class "
1491: + registryClass
1492: + " must contain a default <init>(MBeanServer srvr, String domain) "
1493: + " constructor.", e);
1494: } catch (InstantiationException e) {
1495: throw new NestedRuntimeException(
1496: "Cannot instantiate class " + registryClass + ": ",
1497: e);
1498: } catch (IllegalAccessException e) {
1499: throw new NestedRuntimeException(
1500: "Unable to create the MBean registry instance. Illegal access "
1501: + "to class " + registryClass
1502: + " constructor: ", e);
1503: } catch (InvocationTargetException e) {
1504: throw new NestedRuntimeException(
1505: "Unable to create the MBean registry instance. Class "
1506: + registryClass
1507: + " has raised an exception in constructor: ",
1508: e.getTargetException());
1509: }
1510: }
1511:
1512: // Private -------------------------------------------------------
1513:
1514: // FIXME: externalize this
1515: private ModelMBeanInfo getRegistryManagementInterface() {
1516: final boolean READABLE = true;
1517: final boolean WRITABLE = true;
1518: final boolean BOOLEAN = true;
1519:
1520: // Default Domain attribute
1521: DescriptorSupport descDefaultDomain = new DescriptorSupport();
1522: descDefaultDomain.setField("name", "DefaultDomain");
1523: descDefaultDomain.setField("descriptorType", "attribute");
1524: descDefaultDomain.setField("displayName", "Default Domain");
1525: descDefaultDomain.setField("default", getDefaultDomain());
1526: descDefaultDomain.setField("currencyTimeLimit", "-1");
1527: ModelMBeanAttributeInfo defaultDomainInfo = new ModelMBeanAttributeInfo(
1528: "DefaultDomain", String.class.getName(),
1529: "The domain to use when an object name has no domain",
1530: READABLE, !WRITABLE, !BOOLEAN, descDefaultDomain);
1531:
1532: // Size attribute
1533: DescriptorSupport descSize = new DescriptorSupport();
1534: descSize.setField("name", "Size");
1535: descSize.setField("descriptorType", "attribute");
1536: descSize.setField("displayName", "Size");
1537: descSize.setField("getMethod", "getSize");
1538: ModelMBeanAttributeInfo sizeInfo = new ModelMBeanAttributeInfo(
1539: "Size", Integer.TYPE.getName(),
1540: "The number of MBeans registered in the MBean Server",
1541: READABLE, !WRITABLE, !BOOLEAN, descSize);
1542:
1543: // registerMBean operation
1544: DescriptorSupport descRegisterMBean = new DescriptorSupport();
1545: descRegisterMBean.setField("name", "registerMBean");
1546: descRegisterMBean.setField("descriptorType", "operation");
1547: descRegisterMBean.setField("role", "operation");
1548: MBeanParameterInfo[] registerMBeanParms = new MBeanParameterInfo[] {
1549: new MBeanParameterInfo("Resource", Object.class
1550: .getName(),
1551: "A compliant MBean to be registered in the MBean Server"),
1552: new MBeanParameterInfo("ObjectName", ObjectName.class
1553: .getName(), "The object name of the MBean"),
1554: new MBeanParameterInfo("ValueMap", Map.class.getName(),
1555: "Values associated with the registration"), };
1556: ModelMBeanOperationInfo registerMBeanInfo = new ModelMBeanOperationInfo(
1557: "registerMBean", "Adds an MBean in the MBeanServer",
1558: registerMBeanParms, ObjectInstance.class.getName(),
1559: ModelMBeanOperationInfo.ACTION_INFO, descRegisterMBean);
1560:
1561: // unregisterMBean operation
1562: DescriptorSupport descUnregisterMBean = new DescriptorSupport();
1563: descUnregisterMBean.setField("name", "unregisterMBean");
1564: descUnregisterMBean.setField("descriptorType", "operation");
1565: descUnregisterMBean.setField("role", "operation");
1566: MBeanParameterInfo[] unregisterMBeanParms = new MBeanParameterInfo[] { new MBeanParameterInfo(
1567: "ObjectName", ObjectName.class.getName(),
1568: "The object name of the MBean to remove") };
1569: ModelMBeanOperationInfo unregisterMBeanInfo = new ModelMBeanOperationInfo(
1570: "unregisterMBean",
1571: "Removes an MBean from the MBeanServer",
1572: unregisterMBeanParms, Void.TYPE.getName(),
1573: ModelMBeanOperationInfo.ACTION, descUnregisterMBean);
1574:
1575: // getSize operation
1576: DescriptorSupport descGetSize = new DescriptorSupport();
1577: descGetSize.setField("name", "getSize");
1578: descGetSize.setField("descriptorType", "operation");
1579: descGetSize.setField("role", "getter");
1580: MBeanParameterInfo[] getSizeParms = new MBeanParameterInfo[0];
1581: ModelMBeanOperationInfo getSizeInfo = new ModelMBeanOperationInfo(
1582: "getSize", "Gets the number of MBeans registered",
1583: getSizeParms, Integer.TYPE.getName(),
1584: ModelMBeanOperationInfo.INFO, descGetSize);
1585:
1586: // get operation
1587: DescriptorSupport descGet = new DescriptorSupport();
1588: descGet.setField("name", "get");
1589: descGet.setField("descriptorType", "operation");
1590: descGet.setField("role", "operation");
1591: MBeanParameterInfo[] getParam = new MBeanParameterInfo[1];
1592: getParam[0] = new MBeanParameterInfo("ObjectName",
1593: ObjectName.class.getName(), "object name to find");
1594: ModelMBeanOperationInfo getInfo = new ModelMBeanOperationInfo(
1595: "get", "Gets the MBeanEntry for a given ObjectName",
1596: getParam, MBeanEntry.class.getName(),
1597: ModelMBeanOperationInfo.INFO, descGet);
1598:
1599: // getValue operation
1600: DescriptorSupport descGetValue = new DescriptorSupport();
1601: descGetValue.setField("name", "getValue");
1602: descGetValue.setField("descriptorType", "operation");
1603: descGetValue.setField("role", "operation");
1604: MBeanParameterInfo[] getValueParms = new MBeanParameterInfo[] {
1605: new MBeanParameterInfo("ObjectName", ObjectName.class
1606: .getName(),
1607: "The object name of the registered MBean"),
1608: new MBeanParameterInfo("Key", String.class.getName(),
1609: "The key to the value stored") };
1610: ModelMBeanOperationInfo getValueInfo = new ModelMBeanOperationInfo(
1611: "getValue",
1612: "Get a value stored in the MBean's registration",
1613: getValueParms, Object.class.getName(),
1614: ModelMBeanOperationInfo.INFO, descGetValue);
1615:
1616: // Construct the modelmbean
1617: DescriptorSupport descMBean = new DescriptorSupport();
1618: descMBean.setField("name", RequiredModelMBeanInstantiator
1619: .getClassName());
1620: descMBean.setField("descriptorType", "MBean");
1621: descMBean.setField("displayName", "MBeanServer Registry");
1622: ModelMBeanAttributeInfo[] attrInfo = new ModelMBeanAttributeInfo[] {
1623: defaultDomainInfo, sizeInfo };
1624: ModelMBeanConstructorInfo[] ctorInfo = null;
1625: ModelMBeanOperationInfo[] opInfo = new ModelMBeanOperationInfo[] {
1626: registerMBeanInfo, unregisterMBeanInfo, getSizeInfo,
1627: getValueInfo, getInfo };
1628: ModelMBeanNotificationInfo[] notifyInfo = null;
1629: ModelMBeanInfoSupport info = new ModelMBeanInfoSupport(
1630: RequiredModelMBeanInstantiator.getClassName(),
1631: "Managed Bean Registry", attrInfo, ctorInfo, opInfo,
1632: notifyInfo, descMBean);
1633:
1634: return info;
1635: }
1636:
1637: private void checkMBeanPermission(String className, String member,
1638: ObjectName objectName, String action) {
1639: SecurityManager sm = System.getSecurityManager();
1640: if (sm != null) {
1641: MBeanPermission p = new MBeanPermission(className, member,
1642: objectName, action);
1643: sm.checkPermission(p);
1644: }
1645: }
1646:
1647: // Object overrides ----------------------------------------------
1648:
1649: /**
1650: * Simple toString() revealing default domain
1651: */
1652: public String toString() {
1653: return super .toString() + "[ defaultDomain='"
1654: + this .getDefaultDomain() + "' ]";
1655: }
1656: }
|