Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.mx » server » [javadoc | source]
    1   /*
    2     * JBoss, Home of Professional Open Source
    3     * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4     * by the @authors tag. See the copyright.txt in the distribution for a
    5     * full listing of individual contributors.
    6     *
    7     * This is free software; you can redistribute it and/or modify it
    8     * under the terms of the GNU Lesser General Public License as
    9     * published by the Free Software Foundation; either version 2.1 of
   10     * the License, or (at your option) any later version.
   11     *
   12     * This software is distributed in the hope that it will be useful,
   13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15     * Lesser General Public License for more details.
   16     *
   17     * You should have received a copy of the GNU Lesser General Public
   18     * License along with this software; if not, write to the Free
   19     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21     */
   22   package org.jboss.mx.server;
   23   
   24   import java.io.ByteArrayInputStream;
   25   import java.io.IOException;
   26   import java.io.ObjectInputStream;
   27   import java.lang.reflect.Constructor;
   28   import java.lang.reflect.InvocationTargetException;
   29   import java.util.ArrayList;
   30   import java.util.HashMap;
   31   import java.util.HashSet;
   32   import java.util.Iterator;
   33   import java.util.List;
   34   import java.util.Map;
   35   import java.util.Set;
   36   import java.security.ProtectionDomain;
   37   import java.security.AccessController;
   38   import java.security.PrivilegedAction;
   39   import java.security.PrivilegedExceptionAction;
   40   import java.security.PrivilegedActionException;
   41   
   42   import javax.management.Attribute;
   43   import javax.management.AttributeList;
   44   import javax.management.AttributeNotFoundException;
   45   import javax.management.InstanceAlreadyExistsException;
   46   import javax.management.InstanceNotFoundException;
   47   import javax.management.IntrospectionException;
   48   import javax.management.InvalidAttributeValueException;
   49   import javax.management.JMException;
   50   import javax.management.ListenerNotFoundException;
   51   import javax.management.MBeanException;
   52   import javax.management.MBeanInfo;
   53   import javax.management.MBeanParameterInfo;
   54   import javax.management.MBeanRegistrationException;
   55   import javax.management.MBeanServer;
   56   import javax.management.MBeanServerDelegate;
   57   import javax.management.NotCompliantMBeanException;
   58   import javax.management.NotificationBroadcaster;
   59   import javax.management.NotificationFilter;
   60   import javax.management.NotificationListener;
   61   import javax.management.ObjectInstance;
   62   import javax.management.ObjectName;
   63   import javax.management.OperationsException;
   64   import javax.management.QueryExp;
   65   import javax.management.ReflectionException;
   66   import javax.management.RuntimeErrorException;
   67   import javax.management.RuntimeMBeanException;
   68   import javax.management.RuntimeOperationsException;
   69   import javax.management.JMRuntimeException;
   70   import javax.management.MBeanPermission;
   71   import javax.management.MalformedObjectNameException;
   72   import javax.management.MBeanTrustPermission;
   73   import javax.management.loading.ClassLoaderRepository;
   74   import javax.management.modelmbean.DescriptorSupport;
   75   import javax.management.modelmbean.ModelMBean;
   76   import javax.management.modelmbean.ModelMBeanAttributeInfo;
   77   import javax.management.modelmbean.ModelMBeanConstructorInfo;
   78   import javax.management.modelmbean.ModelMBeanInfo;
   79   import javax.management.modelmbean.ModelMBeanInfoSupport;
   80   import javax.management.modelmbean.ModelMBeanNotificationInfo;
   81   import javax.management.modelmbean.ModelMBeanOperationInfo;
   82   
   83   import org.jboss.logging.Logger;
   84   import org.jboss.mx.loading.LoaderRepository;
   85   import org.jboss.mx.modelmbean.ModelMBeanConstants;
   86   import org.jboss.mx.modelmbean.RequiredModelMBeanInstantiator;
   87   import org.jboss.mx.notification.MBeanServerListenerRegistry;
   88   import org.jboss.mx.server.registry.MBeanEntry;
   89   import org.jboss.mx.server.registry.MBeanRegistry;
   90   import org.jboss.mx.service.ServiceConstants;
   91   import org.jboss.mx.util.JMXExceptionDecoder;
   92   import org.jboss.mx.util.PropertyAccess;
   93   import org.jboss.util.NestedRuntimeException;
   94   
   95   /**
   96    * MBean server implementation. 
   97    *
   98    * The MBean server behaviour can be configured by setting the following
   99    * system properties: <ul>
  100    *    <li><tt>jbossmx.loader.repository.class</tt>
  101    ({@link ServerConstants#LOADER_REPOSITORY_CLASS_PROPERTY LOADER_REPOSITORY_CLASS_PROPERTY})</li>
  102    *    <li><tt>jbossmx.mbean.registry.class</tt>
  103    ({@link ServerConstants#MBEAN_REGISTRY_CLASS_PROPERTY MBEAN_REGISTRY_CLASS_PROPERTY})</li>
  104    *    <li><tt>jbossmx.required.modelmbean.class</tt>
  105    ({@link ServerConstants#REQUIRED_MODELMBEAN_CLASS_PROPERTY REQUIRED_MODELMBEAN_CLASS_PROPERTY})</li>
  106    * </ul>
  107    *
  108    * The loader repository is used for managing class loaders in the MBean server.
  109    * The default repository uses the <tt>UnifiedLoaderRepository</tt> implementation
  110    * ({@link ServerConstants#DEFAULT_LOADER_REPOSITORY_CLASS DEFAULT_LOADER_REPOSITORY_CLASS}).<p>
  111    *
  112    * The default registry is
  113    * ({@link ServerConstants#DEFAULT_MBEAN_REGISTRY_CLASS DEFAULT_MBEAN_REGISTRY_CLASS}).<p>
  114    *
  115    * The <tt>RequiredModelMBean</tt> uses <tt>XMBean</tt> implementation by default
  116    * ({@link ServerConstants#DEFAULT_REQUIRED_MODELMBEAN_CLASS DEFAULT_REQUIRED_MODELMBEAN_CLASS}).
  117    *
  118    * @see javax.management.MBeanServer
  119    * @see javax.management.modelmbean.RequiredModelMBean
  120    * @see org.jboss.mx.server.ServerConstants
  121    * @see org.jboss.mx.loading.LoaderRepository
  122    * @see org.jboss.mx.loading.UnifiedLoaderRepository3
  123    * @see org.jboss.mx.modelmbean.XMBean
  124    *
  125    * @author  <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
  126    * @author  <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
  127    * @author  <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
  128    * @author  <a href="mailto:thomas.diesler@jboss.com">Thomas Diesler</a>.
  129    * @author Scott.Stark@jboss.org
  130    * @version $Revision: 57108 $
  131    */
  132   public class MBeanServerImpl
  133      implements MBeanServer, ServerConstants, ServiceConstants, ModelMBeanConstants
  134   {
  135      // Constants ------------------------------------------------------
  136   
  137      /**
  138       * No parameters array
  139       */
  140      private static final Object[] NOPARAMS = new Object[0];
  141   
  142      /**
  143       * No signature array
  144       */
  145      private static final String[] NOSIG = new String[0];
  146   
  147      // Attributes ----------------------------------------------------
  148   
  149      /**
  150       * The wrapping MBeanServer
  151       */
  152      protected MBeanServer outer = null;
  153   
  154      /**
  155       * Registry used by this server to map MBean object names to resource references.
  156       */
  157      protected MBeanRegistry registry = null;
  158   
  159      /**
  160       * The notification registrations
  161       */
  162      private MBeanServerListenerRegistry listeners = new MBeanServerListenerRegistry();
  163   
  164      /**
  165       * This server's class loader repository
  166       */
  167      private ClassLoaderRepository classLoaderRepository;
  168   
  169      // Static --------------------------------------------------------
  170   
  171      /**
  172       * The logger
  173       */
  174      private static Logger log = Logger.getLogger(MBeanServerImpl.class);
  175   
  176      
  177      // Constructors --------------------------------------------------
  178   
  179      /**
  180       * Creates an MBean server implementation with a given default domain name and
  181       * registers the mandatory server delegate MBean to the server
  182       * ({@link ServerConstants#MBEAN_SERVER_DELEGATE MBEAN_SERVER_DELEGATE}).
  183       *
  184       * @param defaultDomain default domain name
  185       * @param outer the wrapping MBeanServer, passed to MBeans
  186       *        at registration.
  187       * @param delegate the delegate to use
  188       *        for Notifications.
  189       */
  190      public MBeanServerImpl(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate)
  191      {
  192         // Determine the MBeanServer to pass to MBeans
  193         if (outer == null)
  194            this.outer = this;
  195         else
  196            this.outer = outer;
  197   
  198         // the very first thing to do is to create a class loader repository
  199         this.classLoaderRepository = getClassLoaderRepository();
  200   
  201         // the second first thing to do is to create a registry instance
  202         this.registry = createRegistry(defaultDomain);
  203         
  204         // The first MBean to be registered should be the server delegate
  205         // to guarantee correct functionality (other MBeans may be dependent
  206         // on the existence of the delegate).
  207         try
  208         {
  209            // the magic token that allows us to register to the 
  210            // protected JMImplementation domain
  211            HashMap valueMap = new HashMap();
  212            valueMap.put(JMI_DOMAIN, JMI_DOMAIN);
  213   
  214            // register the delegate
  215            registry.registerMBean(delegate,
  216                    new ObjectName(MBEAN_SERVER_DELEGATE),
  217                    valueMap);
  218            
  219            // We expose the registry as an MBean for other components 
  220            ModelMBean rmm = RequiredModelMBeanInstantiator.instantiate();
  221            rmm.setModelMBeanInfo(getRegistryManagementInterface());
  222            rmm.setManagedResource(registry, "ObjectReference");
  223   
  224            // register the registry MBean
  225            registry.registerMBean(rmm, new ObjectName(MBEAN_REGISTRY), valueMap);
  226            
  227            // register the loader repository
  228            //String loaderClassMBeanName = classLoaderRepository.getClass().getName() + "MBean";
  229            //ClassLoader cl = classLoaderRepository.getClass().getClassLoader();
  230            //Class mbean = cl.loadClass(loaderClassMBeanName);
  231            
  232            //there must be a class with the MBean extension.
  233            ObjectName loaderName = new ObjectName(DEFAULT_LOADER_NAME);
  234            registry.registerMBean(classLoaderRepository, loaderName, valueMap);
  235   
  236         }
  237         catch (Exception e)
  238         {
  239            throw new RuntimeException("Cannot create MBeanServer", e);
  240         }
  241      }
  242   
  243      // MBeanServer implementation ------------------------------------
  244   
  245      public Object instantiate(String className)
  246              throws ReflectionException, MBeanException
  247      {
  248         return instantiate(className, (ClassLoader) null, NOPARAMS, NOSIG);
  249      }
  250   
  251      public Object instantiate(String className, Object[] params, String[] signature)
  252              throws ReflectionException, MBeanException
  253      {
  254         return instantiate(className, (ClassLoader) null, params, signature);
  255      }
  256   
  257      public Object instantiate(String className, ObjectName loaderName)
  258              throws ReflectionException, MBeanException, InstanceNotFoundException
  259      {
  260         return instantiate(className, loaderName, NOPARAMS, NOSIG);
  261      }
  262   
  263      public Object instantiate(String className, ObjectName loaderName, Object[] params, String[] signature)
  264              throws ReflectionException, MBeanException, InstanceNotFoundException
  265      {
  266         ClassLoader cl = null;
  267   
  268         // if instantiate() is called with null loader name, we use the cl that
  269         // loaded the MBean server (see javadoc)
  270   
  271         try
  272         {
  273            if (loaderName != null)
  274               cl = (ClassLoader) registry.get(loaderName).getResourceInstance();
  275         }
  276         catch (ClassCastException e)
  277         {
  278            throw new ReflectionException(e, loaderName + " is not a class loader.");
  279         }
  280   
  281         if (cl == null)
  282            cl = this.getClass().getClassLoader();
  283         if (cl == null)
  284            cl = ClassLoader.getSystemClassLoader();
  285   
  286         return instantiate(className, cl, params, signature);
  287      }
  288   
  289      public ObjectInstance createMBean(String className, ObjectName name)
  290              throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException
  291      {
  292         try
  293         {
  294            Object mbean = instantiate(className);
  295            return registerMBean(mbean, name, (ClassLoader) null);
  296         }
  297         catch (SecurityException e)
  298         {
  299            throw e;
  300         }
  301         catch (ReflectionException refex)
  302         {
  303            // Note, the CTS wants a NotCompliantMBeanException for this case
  304            if (refex.getCause() instanceof InstantiationException)
  305               throw new NotCompliantMBeanException("Cannot instanciate MBean: " + className);
  306            else
  307               throw refex;
  308         }
  309      }
  310   
  311      public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature)
  312              throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException
  313      {
  314         try
  315         {
  316            Object mbean = instantiate(className, params, signature);
  317            return registerMBean(mbean, name, (ClassLoader) null);
  318         }
  319         catch (ReflectionException refex)
  320         {
  321            return handleExceptionOnCreate(refex, className);
  322         }
  323      }
  324   
  325      public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName)
  326              throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
  327      {
  328         try
  329         {
  330            Object mbean = instantiate(className, loaderName);
  331            return registerMBean(mbean, name, loaderName);
  332         }
  333         catch (ReflectionException refex)
  334         {
  335            return handleExceptionOnCreate(refex, className);
  336         }
  337      }
  338   
  339      public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature)
  340              throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
  341      {
  342         try
  343         {
  344            Object mbean = instantiate(className, loaderName, params, signature);
  345            return registerMBean(mbean, name, loaderName);
  346         }
  347         catch (ReflectionException refex)
  348         {
  349            return handleExceptionOnCreate(refex, className);
  350         }
  351      }
  352   
  353      /**
  354       * The CTS wants a NotCompliantMBeanException in case the MBean cannot be created.
  355       * We need this, because instanciate cannot throw NotCompliantMBeanException.
  356       */
  357      private ObjectInstance handleExceptionOnCreate(ReflectionException refex, String className)
  358              throws NotCompliantMBeanException, ReflectionException
  359      {
  360         if (refex.getCause() instanceof InstantiationException)
  361            throw new NotCompliantMBeanException("Cannot instanciate MBean: " + className);
  362   
  363         throw refex;
  364      }
  365   
  366      /**
  367       * Registers a pre-existing object as an MBean with the MBean server. If the object name given is null,
  368       * the MBean must provide its own name by implementing the MBeanRegistration interface and returning the name
  369       * from the preRegister method.
  370       */
  371      public ObjectInstance registerMBean(Object object, ObjectName name)
  372              throws InstanceAlreadyExistsException,
  373              MBeanRegistrationException,
  374              NotCompliantMBeanException
  375      {
  376         return registerMBean(object, name, (ClassLoader) null);
  377      }
  378   
  379      public void unregisterMBean(ObjectName name)
  380              throws InstanceNotFoundException, MBeanRegistrationException
  381      {
  382         // Get the mbean to remove
  383         MBeanEntry entry = registry.get(name);
  384         Object mbean = entry.getResourceInstance();
  385         name = entry.getObjectName();
  386   
  387         checkMBeanPermission(entry.getResourceClassName(), null, name, "unregisterMBean");
  388   
  389         try
  390         {
  391            final Object[] args = {name};
  392            final String[] sig = {ObjectName.class.getName()};
  393            try
  394            {
  395               AccessController.doPrivileged(
  396                  new PrivilegedExceptionAction()
  397                  {
  398                     public Object run() throws Exception
  399                     {
  400                        return invoke(new ObjectName(MBEAN_REGISTRY),
  401                           "unregisterMBean", args, sig);
  402                     }
  403                  }
  404               );
  405            }
  406            catch(PrivilegedActionException e)
  407            {
  408               throw e.getException();
  409            }
  410         }
  411         catch (Throwable t)
  412         {
  413            Throwable result = JMXExceptionDecoder.decodeToJMXException(t);
  414            if (result instanceof InstanceNotFoundException)
  415               throw (InstanceNotFoundException) result;
  416            if (result instanceof MBeanRegistrationException)
  417               throw (MBeanRegistrationException) result;
  418            if ( result instanceof JMRuntimeException )
  419               throw (JMRuntimeException) result;
  420            if (result instanceof MBeanException)
  421            {
  422               MBeanException e = (MBeanException) result;
  423               t = e.getTargetException();
  424               if (t instanceof InstanceNotFoundException)
  425                  throw (InstanceNotFoundException) t;
  426               if (t instanceof MBeanRegistrationException)
  427                  throw (MBeanRegistrationException) t;
  428            }
  429            if (result instanceof RuntimeException)
  430               throw new RuntimeMBeanException((RuntimeException) result);
  431            if (result instanceof Error)
  432               throw new RuntimeErrorException((Error) result);
  433   
  434            // for some other reason, unregistration failed
  435            throw new MBeanRegistrationException(new InvocationTargetException(t), "Cannot unregister MBean");
  436         }
  437         
  438         // Unregistration worked, remove any proxies for a broadcaster
  439         if (mbean instanceof NotificationBroadcaster)
  440            listeners.remove(name);
  441      }
  442   
  443      public ObjectInstance getObjectInstance(ObjectName name)
  444              throws InstanceNotFoundException
  445      {
  446         ObjectInstance oi = registry.getObjectInstance(name);
  447         checkMBeanPermission(oi.getClassName(), null, name,
  448            "getObjectInstance");
  449   
  450         return oi;
  451      }
  452   
  453      public Set queryMBeans(ObjectName name, QueryExp query)
  454      {
  455         // At least one mbean must be queriable
  456         checkMBeanPermission(null, null, null, "queryMBeans");
  457   
  458         // Set up the query
  459         Set result = new HashSet();
  460         if (query != null)
  461            query.setMBeanServer(outer);
  462   
  463         SecurityManager sm = System.getSecurityManager();
  464         // Get the possible MBeans
  465         List entries = registry.findEntries(name);
  466         Iterator iterator = entries.iterator();
  467         while (iterator.hasNext())
  468         {
  469            // Check each MBean against the query
  470            MBeanEntry entry = (MBeanEntry) iterator.next();
  471            ObjectName objectName = entry.getObjectName();
  472            // The permission check must be done before the query is applied
  473            if( sm != null )
  474            {
  475               try
  476               {
  477                  checkMBeanPermission(entry.getResourceClassName(), null,
  478                     objectName, "queryMBeans");
  479               }
  480               catch(SecurityException e)
  481               {
  482                  if( log.isTraceEnabled() )
  483                     log.trace("Excluded mbean due to security: "+objectName);
  484                  continue;
  485               }            
  486            }
  487            // Check the mbean against the query
  488            if (queryMBean(objectName, query) == true)
  489            {
  490               try
  491               {
  492                  ObjectInstance instance = registry.getObjectInstance(objectName);
  493                  result.add(instance);
  494               }
  495               catch (InstanceNotFoundException ignored)
  496               {
  497               }
  498            }
  499         }
  500   
  501         return result;
  502      }
  503   
  504      public Set queryNames(ObjectName name, QueryExp query)
  505      {
  506         // At least one mbean must be queriable
  507         checkMBeanPermission(null, null, null, "queryNames");
  508   
  509         // Set up the query
  510         Set result = new HashSet();
  511         if (query != null)
  512            query.setMBeanServer(outer);
  513   
  514         SecurityManager sm = System.getSecurityManager();
  515         // Get the possible MBeans
  516         List entries = registry.findEntries(name);
  517         Iterator iterator = entries.iterator();
  518         while (iterator.hasNext())
  519         {
  520            // Check each MBean against the query
  521            MBeanEntry entry = (MBeanEntry) iterator.next();
  522            ObjectName objectName = entry.getObjectName();
  523            // The permission check must be done before the query is applied
  524            if( sm != null )
  525            {
  526               try
  527               {
  528                  checkMBeanPermission(entry.getResourceClassName(), null,
  529                     objectName, "queryNames");
  530               }
  531               catch(SecurityException e)
  532               {
  533                  if( log.isTraceEnabled() )
  534                     log.trace("Excluded mbean due to security: "+objectName);
  535                  continue;
  536               }            
  537            }
  538            // Check the mbean against the query
  539            if (queryMBean(objectName, query) == true)
  540               result.add(objectName);
  541         }
  542   
  543         return result;
  544      }
  545   
  546      public boolean isRegistered(ObjectName name)
  547      {
  548         return registry.contains(name);
  549      }
  550   
  551      public java.lang.Integer getMBeanCount()
  552      {
  553         return new Integer(registry.getSize());
  554      }
  555   
  556      public Object getAttribute(ObjectName name, String attribute)
  557              throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException
  558      {
  559         MBeanEntry entry = registry.get(name);
  560         checkMBeanPermission(entry.getResourceClassName(), attribute, name,
  561            "getAttribute");
  562   
  563         MBeanInvoker mbean = entry.getInvoker();
  564   
  565         return mbean.getAttribute(attribute);
  566      }
  567   
  568      public AttributeList getAttributes(ObjectName name, String[] attributes)
  569              throws InstanceNotFoundException, ReflectionException
  570      {
  571         MBeanEntry entry = registry.get(name);
  572         String className = entry.getResourceClassName();
  573         /* Access to an attribute is required and this check will fail only
  574         if access to no attributes are allowed and will result in a security
  575         exception rather than an empty list.
  576         */
  577         checkMBeanPermission(className, null, name, "getAttribute");
  578         
  579         MBeanInvoker mbean = entry.getInvoker();
  580         AttributeList list = mbean.getAttributes(attributes);
  581         SecurityManager sm = System.getSecurityManager();
  582         if( sm != null )
  583         {
  584            // Remove any attributes that are not allowed
  585            Iterator iter = list.iterator();
  586            while( iter.hasNext() )
  587            {
  588               Attribute attr = (Attribute) iter.next();
  589               String aname = attr.getName();
  590               try
  591               {
  592                  checkMBeanPermission(className, aname, name, "getAttribute");
  593               }
  594               catch(SecurityException e)
  595               {
  596                  if( log.isTraceEnabled() )
  597                     log.trace("Excluded attribute due to security: "+aname);
  598                  iter.remove();
  599               }
  600            }
  601         }
  602         return list;
  603      }
  604   
  605      public void setAttribute(ObjectName name, Attribute attribute)
  606              throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
  607      {
  608         MBeanEntry entry = registry.get(name);
  609         String attributeName = null;
  610         if (attribute != null)
  611            attributeName = attribute.getName();
  612         checkMBeanPermission(entry.getResourceClassName(), attributeName,
  613            name, "setAttribute");
  614   
  615         MBeanInvoker mbean = entry.getInvoker();
  616   
  617         mbean.setAttribute(attribute);
  618      }
  619   
  620      public AttributeList setAttributes(ObjectName name, AttributeList attributes)
  621              throws InstanceNotFoundException, ReflectionException
  622      {
  623         MBeanEntry entry = registry.get(name);
  624   
  625         String className = entry.getResourceClassName();
  626         /* Access to an attribute is required and this check will fail only
  627         if access to no attributes are allowed and will result in a security
  628         exception rather than an empty list.
  629         */
  630         checkMBeanPermission(className, null, name, "setAttribute");
  631   
  632         MBeanInvoker mbean = entry.getInvoker();
  633         AttributeList list = mbean.setAttributes(attributes);
  634         SecurityManager sm = System.getSecurityManager();
  635         if( sm != null )
  636         {
  637            // Remove any attributes that are not allowed
  638            Iterator iter = list.iterator();
  639            while( iter.hasNext() )
  640            {
  641               Attribute attr = (Attribute) iter.next();
  642               String aname = attr.getName();
  643               try
  644               {
  645                  checkMBeanPermission(className, aname, name, "setAttribute");
  646               }
  647               catch(SecurityException e)
  648               {
  649                  if( log.isTraceEnabled() )
  650                     log.trace("Excluded attribute due to security: "+aname);
  651                  iter.remove();
  652               }
  653            }
  654         }
  655         return list;
  656      }
  657   
  658      public Object invoke(ObjectName name, String operationName, Object[] params,
  659         String[] signature)
  660         throws InstanceNotFoundException, MBeanException, ReflectionException
  661      {
  662         MBeanEntry entry = registry.get(name);
  663         checkMBeanPermission(entry.getResourceClassName(), operationName, name,
  664            "invoke");
  665   
  666         MBeanInvoker mbean = entry.getInvoker();
  667   
  668         return mbean.invoke(operationName, params, signature);
  669      }
  670   
  671      public MBeanInfo getMBeanInfo(ObjectName name)
  672         throws InstanceNotFoundException, IntrospectionException,
  673         ReflectionException
  674      {
  675         MBeanEntry entry = registry.get(name);
  676         checkMBeanPermission(entry.getResourceClassName(), null, name,
  677            "getMBeanInfo");
  678         try
  679         {
  680            MBeanInvoker invoker = entry.getInvoker();
  681            return invoker.getMBeanInfo();
  682         }
  683         catch (Exception e)
  684         {
  685            JMException result = ExceptionHandler.handleException(e);
  686            if (result instanceof InstanceNotFoundException)
  687               throw (InstanceNotFoundException) result;
  688            if (result instanceof IntrospectionException)
  689               throw (IntrospectionException) result;
  690            if (result instanceof ReflectionException)
  691               throw (ReflectionException) result;
  692            throw new RuntimeException("Cannot obtain MBeanInfo " + name, result);
  693         }
  694      }
  695   
  696      public String getDefaultDomain()
  697      {
  698         return registry.getDefaultDomain();
  699      }
  700   
  701      public String[] getDomains()
  702      {
  703         checkMBeanPermission(null, null, null, "getDomains");
  704         String[] domains = registry.getDomains();
  705         SecurityManager sm = System.getSecurityManager();
  706         if( sm != null )
  707         {
  708            ArrayList tmp = new ArrayList();
  709            // Remove any domains that are not allowed
  710            int length = domains != null ? domains.length : 0;
  711            for(int n = 0; n < length; n ++)
  712            {
  713               String domain = domains[n];
  714               try
  715               {
  716                  ObjectName name = new ObjectName(domain, "x", "x");
  717                  checkMBeanPermission(null, null, name, "getDomains");
  718                  tmp.add(domain);
  719               }
  720               catch(MalformedObjectNameException e)
  721               {
  722                  // Should not be possible
  723               }
  724               catch(SecurityException e)
  725               {
  726                  if( log.isTraceEnabled() )
  727                     log.trace("Excluded domain due to security: "+domain);
  728               }
  729            }
  730            domains = new String[tmp.size()];
  731            tmp.toArray(domains);
  732         }
  733         return domains;
  734      }
  735   
  736      /**
  737       * Adds a listener to a registered MBean.
  738       *
  739       * A notification emitted by the MBean will be forwarded by the MBeanServer to the listener.
  740       * If the source of the notification is a reference to the MBean object, the MBean server will replace
  741       * it by the MBean's ObjectName. Otherwise the source is unchanged.
  742       */
  743      public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)
  744              throws InstanceNotFoundException
  745      {
  746         MBeanEntry entry = registry.get(name);
  747         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  748            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  749   
  750         if (listener == null)
  751            throw new RuntimeOperationsException(new IllegalArgumentException("Cannot add null listener"));
  752   
  753         checkMBeanPermission(entry.getResourceClassName(), null, name,
  754            "addNotificationListener");
  755   
  756         ClassLoader newTCL = entry.getClassLoader();
  757         NotificationBroadcaster broadcaster = entry.getInvoker();
  758   
  759         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  760         final boolean setCl = newTCL != oldTCL && newTCL != null;
  761         try
  762         {
  763            if (setCl)
  764               TCLAction.UTIL.setContextClassLoader(newTCL);
  765   
  766            listeners.add(entry.getObjectName(), broadcaster, listener, filter, handback);
  767         }
  768         finally
  769         {
  770            if (setCl)
  771               TCLAction.UTIL.setContextClassLoader(oldTCL);
  772         }
  773      }
  774   
  775      /**
  776       * Adds a listener to a registered MBean.
  777       *
  778       * A notification emitted by the MBean will be forwarded by the MBeanServer to the listener.
  779       * If the source of the notification is a reference to the MBean object, the MBean server will replace
  780       * it by the MBean's ObjectName. Otherwise the source is unchanged.
  781       *
  782       * The listener object that receives notifications is the one that is registered with the given name at the time this
  783       * method is called. Even if it is subsequently unregistered, it will continue to receive notifications.
  784       */
  785      public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)
  786              throws InstanceNotFoundException
  787      {
  788         MBeanEntry entry = registry.get(name);
  789         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  790            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  791   
  792         MBeanEntry listenerEntry = registry.get(listener);
  793         if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
  794            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
  795   
  796         checkMBeanPermission(entry.getResourceClassName(), null, name,
  797            "addNotificationListener");
  798   
  799         ClassLoader newTCL = entry.getClassLoader();
  800         NotificationBroadcaster broadcaster = entry.getInvoker();
  801   
  802         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  803         final boolean setCl = newTCL != oldTCL && newTCL != null;
  804         try
  805         {
  806            if (setCl)
  807               TCLAction.UTIL.setContextClassLoader(newTCL);
  808   
  809            listeners.add(entry.getObjectName(), broadcaster,
  810                    (NotificationListener) registry.get(listener).getResourceInstance(), filter, handback);
  811         }
  812         finally
  813         {
  814            if (setCl)
  815               TCLAction.UTIL.setContextClassLoader(oldTCL);
  816         }
  817      }
  818   
  819      /**
  820       * Removes a listener from a registered MBean.
  821       *
  822       * If the listener is registered more than once, perhaps with different filters or callbacks,
  823       * this method will remove all those registrations.
  824       */
  825      public void removeNotificationListener(ObjectName name, NotificationListener listener)
  826              throws InstanceNotFoundException, ListenerNotFoundException
  827      {
  828         MBeanEntry entry = registry.get(name);
  829         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  830            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  831   
  832         checkMBeanPermission(entry.getResourceClassName(), null, name,
  833            "removeNotificationListener");
  834   
  835         ClassLoader newTCL = entry.getClassLoader();
  836   
  837         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  838         final boolean setCl = newTCL != oldTCL && newTCL != null;
  839         try
  840         {
  841            if (setCl)
  842               TCLAction.UTIL.setContextClassLoader(newTCL);
  843   
  844            listeners.remove(entry.getObjectName(), listener);
  845         }
  846         finally
  847         {
  848            if (setCl)
  849               TCLAction.UTIL.setContextClassLoader(oldTCL);
  850         }
  851      }
  852   
  853      /**
  854       * Removes a listener from a registered MBean.
  855       *
  856       * If the listener is registered more than once, perhaps with different filters or callbacks,
  857       * this method will remove all those registrations.
  858       */
  859      public void removeNotificationListener(ObjectName name, ObjectName listener)
  860              throws InstanceNotFoundException, ListenerNotFoundException
  861      {
  862         MBeanEntry entry = registry.get(name);
  863         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  864            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  865   
  866         MBeanEntry listenerEntry = registry.get(listener);
  867         if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
  868            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
  869   
  870         checkMBeanPermission(entry.getResourceClassName(), null, name,
  871            "removeNotificationListener");
  872   
  873         ClassLoader newTCL = entry.getClassLoader();
  874   
  875         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  876         final boolean setCl = newTCL != oldTCL && newTCL != null;
  877         try
  878         {
  879            if (setCl)
  880               TCLAction.UTIL.setContextClassLoader(newTCL);
  881   
  882            listeners.remove(entry.getObjectName(), (NotificationListener) registry.get(listener).getResourceInstance());
  883         }
  884         finally
  885         {
  886            if (setCl)
  887               TCLAction.UTIL.setContextClassLoader(oldTCL);
  888         }
  889      }
  890   
  891      /**
  892       * Removes a listener from a registered MBean.
  893       *
  894       * The MBean must have a listener that exactly matches the given listener, filter, and handback parameters.
  895       * If there is more than one such listener, only one is removed.
  896       *
  897       * The filter and handback parameters may be null if and only if they are null in a listener to be removed.
  898       */
  899      public void removeNotificationListener(ObjectName name,
  900         NotificationListener listener, NotificationFilter filter, Object handback)
  901         throws InstanceNotFoundException, ListenerNotFoundException
  902      {
  903         MBeanEntry entry = registry.get(name);
  904         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  905            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  906   
  907         checkMBeanPermission(entry.getResourceClassName(), null, name,
  908            "removeNotificationListener");
  909   
  910         ClassLoader newTCL = entry.getClassLoader();
  911   
  912         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  913         final boolean setCl = newTCL != oldTCL && newTCL != null;
  914         try
  915         {
  916            if (setCl)
  917               TCLAction.UTIL.setContextClassLoader(newTCL);
  918   
  919            listeners.remove(entry.getObjectName(), listener, filter, handback);
  920         }
  921         finally
  922         {
  923            if (setCl)
  924               TCLAction.UTIL.setContextClassLoader(oldTCL);
  925         }
  926      }
  927   
  928      /**
  929       * Removes a listener from a registered MBean.
  930       *
  931       * The MBean must have a listener that exactly matches the given listener, filter, and handback parameters.
  932       * If there is more than one such listener, only one is removed.
  933       *
  934       * The filter and handback parameters may be null if and only if they are null in a listener to be removed.
  935       */
  936      public void removeNotificationListener(ObjectName name, ObjectName listener,
  937         NotificationFilter filter, Object handback)
  938         throws InstanceNotFoundException, ListenerNotFoundException
  939      {
  940         MBeanEntry entry = registry.get(name);
  941         if (NotificationBroadcaster.class.isInstance(entry.getResourceInstance()) == false)
  942            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + name + " exists but does not implement the NotificationBroadcaster interface."));
  943   
  944         MBeanEntry listenerEntry = registry.get(listener);
  945         if (NotificationListener.class.isInstance(listenerEntry.getResourceInstance()) == false)
  946            throw new RuntimeOperationsException(new IllegalArgumentException("The MBean " + listener + " exists but does not implement the NotificationListener interface."));
  947   
  948         checkMBeanPermission(entry.getResourceClassName(), null, name,
  949            "removeNotificationListener");
  950   
  951         ClassLoader newTCL = entry.getClassLoader();
  952   
  953         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
  954         final boolean setCl = newTCL != oldTCL && newTCL != null;
  955         try
  956         {
  957            if (setCl)
  958               TCLAction.UTIL.setContextClassLoader(newTCL);
  959   
  960            listeners.remove(entry.getObjectName(), (NotificationListener) registry.get(listener).getResourceInstance(),
  961                    filter, handback);
  962         }
  963         finally
  964         {
  965            if (setCl)
  966               TCLAction.UTIL.setContextClassLoader(oldTCL);
  967         }
  968      }
  969   
  970      public boolean isInstanceOf(ObjectName name, String className)
  971              throws InstanceNotFoundException
  972      {
  973         // Get the MBean's class name
  974         MBeanEntry entry = registry.get(name);
  975         String mbeanClassName = entry.getResourceClassName();
  976         checkMBeanPermission(mbeanClassName, null, name, "isInstanceOf");
  977   
  978         // The names are the same
  979         if (className.equals(mbeanClassName))
  980            return true;
  981   
  982         // Try to load both classes
  983         Class mbeanClass = null;
  984         Class testClass = null;
  985         ClassLoader cl = getClassLoaderFor(name);
  986         try
  987         {
  988            mbeanClass = cl.loadClass(mbeanClassName);
  989            testClass = cl.loadClass(className);
  990         }
  991         catch (ClassNotFoundException e)
  992         {
  993            return false;
  994         }
  995   
  996         // Check whether it is assignable
  997         if (testClass.isAssignableFrom(mbeanClass))
  998            return true;
  999         else
 1000            return false;
 1001      }
 1002   
 1003      /**
 1004       * @deprecated
 1005       */
 1006      public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException, OperationsException
 1007      {
 1008         try
 1009         {
 1010            ClassLoader cl = this.getClassLoaderFor(name);
 1011            return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
 1012         }
 1013         catch (IOException e)
 1014         {
 1015            throw new OperationsException("I/O exception deserializing: " + e.getMessage());
 1016         }
 1017      }
 1018   
 1019      /**
 1020       * @deprecated
 1021       */
 1022      public ObjectInputStream deserialize(String className, byte[] data)
 1023         throws OperationsException, ReflectionException
 1024      {
 1025         try
 1026         {
 1027            Class c = this.getClassLoaderRepository().loadClass(className);
 1028            ClassLoader cl = c.getClassLoader();
 1029            return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
 1030         }
 1031         catch (IOException e)
 1032         {
 1033            throw new OperationsException("I/O exception deserializing: " + e.getMessage());
 1034         }
 1035         catch (ClassNotFoundException e)
 1036         {
 1037            throw new ReflectionException(e, "Class not found from default repository: " + className);
 1038         }
 1039      }
 1040   
 1041      /**
 1042       * @deprecated
 1043       */
 1044      public ObjectInputStream deserialize(String className, ObjectName loaderName,
 1045         byte[] data)
 1046         throws InstanceNotFoundException, OperationsException, ReflectionException
 1047      {
 1048         try
 1049         {
 1050            ClassLoader cl = this.getClassLoader(loaderName);
 1051            return new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(data), cl);
 1052         }
 1053         catch (IOException e)
 1054         {
 1055            throw new OperationsException("I/O exception deserializing: " + e.getMessage());
 1056         }
 1057      }
 1058   
 1059      public ClassLoader getClassLoaderFor(ObjectName name)
 1060              throws InstanceNotFoundException
 1061      {
 1062         MBeanEntry entry = registry.get(name);
 1063         checkMBeanPermission(entry.getResourceClassName(), null, name,
 1064            "getClassLoaderFor");
 1065         
 1066         ClassLoader cl = entry.getClassLoader();
 1067         if (cl == null)
 1068            cl = entry.getResourceInstance().getClass().getClassLoader();
 1069         if (cl == null)
 1070            cl = ClassLoader.getSystemClassLoader();
 1071         return cl;
 1072      }
 1073   
 1074      /**
 1075       * 
 1076       * @param name The ObjectName of the ClassLoader. May be null, in which case
 1077       * the MBean server's own ClassLoader is returned.
 1078       * @return
 1079       * @throws InstanceNotFoundException
 1080       */ 
 1081      public ClassLoader getClassLoader(ObjectName name)
 1082              throws InstanceNotFoundException
 1083      {
 1084         Object loader = null;
 1085         if( name == null )
 1086         {
 1087            checkMBeanPermission(null, null, name, "getClassLoader");
 1088            loader = getClass().getClassLoader();
 1089            if (loader == null)
 1090               loader = ClassLoader.getSystemClassLoader();
 1091         }
 1092         else
 1093         {
 1094            MBeanEntry entry = registry.get(name);
 1095            checkMBeanPermission(entry.getResourceClassName(), null, name,
 1096               "getClassLoader");
 1097            loader = entry.getResourceInstance();
 1098         }
 1099   
 1100         if ((loader instanceof ClassLoader) == false)
 1101            throw new InstanceNotFoundException("Not a classloader " + name);
 1102         return (ClassLoader) loader;
 1103      }
 1104   
 1105      /**
 1106       * Retrieve the classloader repository for this mbean server
 1107       *
 1108       * @return the classloader repository
 1109       */
 1110      public ClassLoaderRepository getClassLoaderRepository()
 1111      {
 1112         checkMBeanPermission(null, null, null, "getClassLoaderRepository");
 1113   
 1114         // we don't need to synchronize, because this is the first thing we do in the constructor
 1115         if (classLoaderRepository == null)
 1116         {
 1117            ClassLoader cl = Thread.currentThread().getContextClassLoader();
 1118            String className = PropertyAccess.getProperty(LOADER_REPOSITORY_CLASS_PROPERTY, DEFAULT_LOADER_REPOSITORY_CLASS);
 1119            PropertyAccess.setProperty(LOADER_REPOSITORY_CLASS_PROPERTY, className);
 1120   
 1121            try
 1122            {
 1123               Class repository = cl.loadClass(className);
 1124               classLoaderRepository = (LoaderRepository) repository.newInstance();
 1125            }
 1126            catch (ClassNotFoundException e)
 1127            {
 1128               throw new Error("Cannot instantiate loader repository class: " + className);
 1129            }
 1130            catch (ClassCastException e)
 1131            {
 1132               throw new Error("Loader repository is not an instance of LoaderRepository: " + className);
 1133            }
 1134            catch (Exception e)
 1135            {
 1136               throw new Error("Error creating loader repository: " + e);
 1137            }
 1138         }
 1139   
 1140         return classLoaderRepository;
 1141      }
 1142   
 1143   
 1144      public void releaseServer()
 1145      {
 1146         //   shutdown the loader repository
 1147   //      try
 1148   //      {
 1149   //         invoke(new ObjectName(DEFAULT_LOADER_NAME),
 1150   //                "releaseLoaderRepository",
 1151   //                new Object[0],
 1152   //                new String[0] );
 1153   //      }
 1154   //      catch (Exception e)
 1155   //      {
 1156   //         log.error("Unable to shutdown loader repository");
 1157   //         e.printStackTrace();
 1158   //      }
 1159   
 1160         registry.releaseRegistry();
 1161         listeners.removeAll();
 1162         listeners = null;
 1163         registry = null;
 1164      }
 1165   
 1166   
 1167      // Protected -----------------------------------------------------
 1168   
 1169      /**
 1170       * Instantiate an object, the passed classloader is set as the
 1171       * thread's context classloader for the duration of this method.
 1172       *
 1173       * @param className the class name of the object to instantiate
 1174       * @param cl the thread classloader, pass null to use the ClassLoaderRepository
 1175       * @param params the parameters for the constructor
 1176       * @param signature the signature of the constructor
 1177       * @exception ReflectionException wraps a ClassCastException or
 1178       *            any Exception trying to invoke the constructor
 1179       * @exception MBeanException wraps any exception thrown by the constructor
 1180       * @exception RuntimeOperationsException Wraps an IllegalArgument for a
 1181       *            null className
 1182       */
 1183      protected Object instantiate(String className, ClassLoader cl, Object[] params, String[] signature)
 1184              throws ReflectionException, MBeanException
 1185      {
 1186         if (className == null)
 1187            throw new RuntimeOperationsException(new IllegalArgumentException("Null className"));
 1188   
 1189         if (className.equals(""))
 1190            throw new ReflectionException(new ClassNotFoundException("empty class name"));
 1191   
 1192         if (params == null)
 1193            params = NOPARAMS;
 1194   
 1195         if (signature == null)
 1196            signature = NOSIG;
 1197   
 1198         checkMBeanPermission(className, null, null, "instantiate");
 1199   
 1200         ClassLoader oldTCL = TCLAction.UTIL.getContextClassLoader();
 1201   
 1202         boolean setCl = false;
 1203         try
 1204         {
 1205            Class clazz = null;
 1206            if (cl != null)
 1207            {
 1208               if (cl != oldTCL)
 1209               {
 1210                  setCl = true;
 1211                  TCLAction.UTIL.setContextClassLoader(cl);
 1212               }
 1213               clazz = cl.loadClass(className);
 1214            }
 1215            else
 1216               clazz = classLoaderRepository.loadClass(className);
 1217   
 1218            Class[] sign = new Class[signature.length];
 1219            for (int i = 0; i < signature.length; ++i)
 1220            {
 1221               if (LoaderRepository.getNativeClassForName(signature[i]) == null)
 1222               {
 1223                  try
 1224                  {
 1225                     if (cl != null)
 1226                        sign[i] = cl.loadClass(signature[i]);
 1227                     else
 1228                        sign[i] = classLoaderRepository.loadClass(signature[i]);
 1229                  }
 1230                  catch (ClassNotFoundException e)
 1231                  {
 1232                     throw new ReflectionException(e, "Constructor parameter class not found: " + signature[i]);
 1233                  }
 1234               }
 1235               else
 1236               {
 1237                  sign[i] = LoaderRepository.getNativeClassForName(signature[i]);
 1238               }
 1239            }
 1240   
 1241            Constructor constructor = clazz.getConstructor(sign);
 1242            return constructor.newInstance(params);
 1243         }
 1244         catch (Throwable t)
 1245         {
 1246            handleInstantiateExceptions(t, className);
 1247            log.error("Unhandled exception instantiating class: " + className, t);
 1248            return null;
 1249         }
 1250         finally
 1251         {
 1252            if (setCl)
 1253               TCLAction.UTIL.setContextClassLoader(oldTCL);
 1254         }
 1255      }
 1256   
 1257      /**
 1258       * Handles errors thrown during class instantiation
 1259       */
 1260      protected void handleInstantiateExceptions(Throwable t, String className)
 1261              throws ReflectionException, MBeanException
 1262      {
 1263         if (t instanceof ReflectionException)
 1264            throw (ReflectionException) t;
 1265   
 1266         else if (t instanceof ClassNotFoundException)
 1267            throw new ReflectionException((Exception) t, "Class not found: " + className);
 1268   
 1269         else if (t instanceof InstantiationException)
 1270            throw new ReflectionException((Exception) t, "Cannot instantiate: " + className);
 1271   
 1272         else if (t instanceof IllegalAccessException)
 1273            throw new ReflectionException((Exception) t, "Illegal access to constructor: " + className);
 1274   
 1275         else if (t instanceof NoSuchMethodException)
 1276            throw new ReflectionException((Exception) t, "Cannot find such a public constructor: " + className);
 1277   
 1278         else if (t instanceof SecurityException)
 1279            throw new ReflectionException((Exception) t, "Can't access constructor for " + className);
 1280   
 1281         else if (t instanceof InvocationTargetException)
 1282         {
 1283            Throwable root = ((InvocationTargetException) t).getTargetException();
 1284   
 1285            if (root instanceof RuntimeException)
 1286               throw new RuntimeMBeanException((RuntimeException) root, className + " constructor has thrown an exception: " + root.toString());
 1287            else if (root instanceof Error)
 1288               throw new RuntimeErrorException((Error) root, className + " constructor has thrown an error: " + root.toString());
 1289            else if (root instanceof Exception)
 1290               throw new MBeanException((Exception) root, className + " constructor has thrown an exception: " + root.toString());
 1291   
 1292            throw new Error("Something went wrong with handling the exception from " + className + " default constructor.");
 1293         }
 1294   
 1295         else if (t instanceof ExceptionInInitializerError)
 1296         {
 1297            Throwable root = ((ExceptionInInitializerError) t).getException();
 1298   
 1299            // the root cause can be only a runtime exception
 1300            if (root instanceof RuntimeException)
 1301               throw new RuntimeMBeanException((RuntimeException) root, "Exception in class " + className + " static initializer: " + root.toString());
 1302            else
 1303            // shouldn't get here
 1304               throw new Error("ERROR: it turns out the root cause is not always a runtime exception!");
 1305         }
 1306   
 1307         else if (t instanceof IllegalArgumentException)
 1308         {
 1309            // if mismatch between constructor instance args and supplied args -- shouldn't happen
 1310            throw new Error("Error in the server: mismatch between expected constructor arguments and supplied arguments.");
 1311         }
 1312   
 1313         else if (t instanceof Error)
 1314         {
 1315            throw new RuntimeErrorException((Error) t, "instantiating " + className + " failed: " + t.toString());
 1316         }
 1317      }
 1318   
 1319   
 1320      /**
 1321       * Register an MBean<p>
 1322       *
 1323       * The classloader is used as the thread context classloader during
 1324       * access to the mbean and it's interceptors
 1325       *
 1326       * @param mbean the mbean to register
 1327       * @param name the object name to register
 1328       * @param loaderName the object name of a class loader also used as
 1329       *        as the MBeans TCL
 1330       * @exception InstanceAlreadyExistsException when already registered
 1331       * @exception MBeanRegistrationException when
 1332       *            preRegister(MBeanServer, ObjectName) throws an exception
 1333       * @exception NotCompliantMBeanException when the object is not an MBean
 1334       */
 1335      protected ObjectInstance registerMBean(Object mbean, ObjectName name, ObjectName loaderName)
 1336              throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException
 1337      {
 1338         ClassLoader cl = null;
 1339   
 1340         //  If the loader name is null, the ClassLoader that loaded the MBean Server will be used.
 1341         if (loaderName == null)
 1342         {
 1343            cl = getClass().getClassLoader();
 1344            if (cl == null)
 1345               cl = ClassLoader.getSystemClassLoader();
 1346         }
 1347         else
 1348         {
 1349            try
 1350            {
 1351               cl = (ClassLoader) registry.get(loaderName).getResourceInstance();
 1352            }
 1353            catch (ClassCastException e)
 1354            {
 1355               throw new ReflectionException(e, loaderName + " is not a class loader.");
 1356            }
 1357         }
 1358   
 1359         return registerMBean(mbean, name, cl);
 1360      }
 1361   
 1362      /**
 1363       * Register an MBean<p>
 1364       *
 1365       * The classloader is used as the thread context classloader during
 1366       * access to the mbean and it's interceptors
 1367       *
 1368       * @param object the mbean to register
 1369       * @param name the object name to register
 1370       * @param cl the thread classloader, pass null for the current one
 1371       * @exception InstanceAlreadyExistsException when already registered
 1372       * @exception MBeanRegistrationException when
 1373       *            preRegister(MBeanServer, ObjectName) throws an exception
 1374       * @exception NotCompliantMBeanException when the object is not an MBean
 1375       */
 1376      protected ObjectInstance registerMBean(Object object, ObjectName name,
 1377                                             ClassLoader cl)
 1378              throws InstanceAlreadyExistsException,
 1379              MBeanRegistrationException,
 1380              NotCompliantMBeanException
 1381      {
 1382         final Class objectClass = object.getClass();
 1383         String className = objectClass.getName();
 1384   
 1385         // Check that the caller has the ability to create/register mbeans
 1386         checkMBeanPermission(className, null, name, "registerMBean");
 1387   
 1388         // Check that the mbean class is from a trusted source
 1389         if( System.getSecurityManager() != null )
 1390         {
 1391            ProtectionDomain pd = (ProtectionDomain) AccessController.doPrivileged(
 1392               new PrivilegedAction()
 1393               {
 1394                  public Object run()
 1395                  {
 1396                     return objectClass.getProtectionDomain();
 1397                  }
 1398               }
 1399            );
 1400            if( pd != null )
 1401            {
 1402               MBeanTrustPermission p = new MBeanTrustPermission("register");
 1403               if( pd.implies(p) == false )
 1404               {
 1405                  String msg = "MBeanTrustPermission(register) not implied by "
 1406                     + "protection domain of mbean class: "+className+", pd: "+pd;
 1407                  throw new SecurityException(msg);
 1408               }
 1409            }
 1410         }
 1411   
 1412         HashMap valueMap = null;
 1413         if (cl != null)
 1414         {
 1415            valueMap = new HashMap();
 1416            valueMap.put(CLASSLOADER, cl);
 1417         }
 1418   
 1419         try
 1420         {
 1421            final Object[] args = {object, name, valueMap};
 1422            final String[] sig = {Object.class.getName(),
 1423               ObjectName.class.getName(), Map.class.getName()};
 1424            try
 1425            {
 1426               ObjectInstance oi = (ObjectInstance) AccessController.doPrivileged(
 1427                  new PrivilegedExceptionAction()
 1428                  {
 1429                     public Object run() throws Exception
 1430                     {
 1431                        return invoke(new ObjectName(MBEAN_REGISTRY),
 1432                           "registerMBean", args, sig);
 1433                     }
 1434                  }
 1435               );
 1436               return oi;
 1437            }
 1438            catch(PrivilegedActionException e)
 1439            {
 1440               throw e.getException();
 1441            }
 1442         }
 1443         catch (Throwable t)
 1444         {
 1445            Throwable result = JMXExceptionDecoder.decodeToJMXException(t);
 1446            if (result instanceof InstanceAlreadyExistsException)
 1447               throw (InstanceAlreadyExistsException) result;
 1448            if (result instanceof MBeanRegistrationException)
 1449               throw (MBeanRegistrationException) result;
 1450            if (result instanceof NotCompliantMBeanException)
 1451               throw (NotCompliantMBeanException) result;
 1452            if ( result instanceof JMRuntimeException )
 1453               throw (JMRuntimeException) result;
 1454            if (result instanceof MBeanException)
 1455            {
 1456               MBeanException e = (MBeanException) result;
 1457               t = e.getTargetException();
 1458               if (t instanceof InstanceAlreadyExistsException)
 1459                  throw (InstanceAlreadyExistsException) t;
 1460               if (t instanceof MBeanRegistrationException)
 1461                  throw (MBeanRegistrationException) t;
 1462               if (t instanceof NotCompliantMBeanException)
 1463                  throw (NotCompliantMBeanException) t;
 1464            }
 1465            if (result instanceof RuntimeException)
 1466               throw new RuntimeMBeanException((RuntimeException) result);
 1467            if (result instanceof Error)
 1468               throw new RuntimeErrorException((Error) result);
 1469   
 1470            // for some other reason, registration failed
 1471            throw new MBeanRegistrationException(new InvocationTargetException(t), "Cannot register MBean");
 1472         }
 1473      }
 1474   
 1475      // Private -------------------------------------------------------
 1476   
 1477      /**
 1478       * Query an MBean against the query
 1479       *
 1480       * @param objectName the object name of the mbean to check
 1481       * @param queryExp the query expression to test
 1482       * @return true when the query applies to the MBean or the query is null,
 1483       *         false otherwise.
 1484       */
 1485      protected boolean queryMBean(ObjectName objectName, QueryExp queryExp)
 1486      {
 1487         if (queryExp == null)
 1488            return true;
 1489   
 1490         try
 1491         {
 1492            return queryExp.apply(objectName);
 1493         }
 1494         catch (Exception e)
 1495         {
 1496            return false;
 1497         }
 1498      }
 1499   
 1500   
 1501      protected MBeanRegistry createRegistry(String defaultDomain)
 1502      {
 1503         // Find the registry implementation class: can be configured via
 1504         // MBEAN_REGISTRY_CLASS_PROPERTY by the client -- if not found use
 1505         // the class defined in DEFAULT_MBEAN_REGISTRY_CLASS (see ServerConstants)
 1506         String registryClass = PropertyAccess.getProperty(ServerConstants.MBEAN_REGISTRY_CLASS_PROPERTY,
 1507                 ServerConstants.DEFAULT_MBEAN_REGISTRY_CLASS);
 1508   
 1509         try
 1510         {
 1511            // Try loading registry class via thread context classloader
 1512            ClassLoader cl = Thread.currentThread().getContextClassLoader();
 1513            Class clazz = cl.loadClass(registryClass);
 1514   
 1515            // retrieve the constructor <init>(MBeanServer srvr, String defaultDomain, ClassLoaderRepository clr)
 1516            Constructor constructor = clazz.getConstructor(new Class[] {MBeanServer.class, String.class, ClassLoaderRepository.class});
 1517   
 1518            // instantiate registry
 1519            return (MBeanRegistry) constructor.newInstance(new Object[] {outer, defaultDomain, classLoaderRepository});
 1520         }
 1521         // Any exception preventing the registry to be created will cause the agent to fail.
 1522         // However, try to give detailed exception messages to indicate config errors.
 1523         catch (ClassNotFoundException e)
 1524         {
 1525            throw new NestedRuntimeException("The MBean registry implementation class " + registryClass +
 1526                    " was not found: ", e);
 1527         }
 1528         catch (NoSuchMethodException e)
 1529         {
 1530            throw new NestedRuntimeException("The MBean registry implementation class " + registryClass +
 1531                    " must contain a default <init>(MBeanServer srvr, String domain) " +
 1532                    " constructor.", e);
 1533         }
 1534         catch (InstantiationException e)
 1535         {
 1536            throw new NestedRuntimeException("Cannot instantiate class " + registryClass + ": ", e);
 1537         }
 1538         catch (IllegalAccessException e)
 1539         {
 1540            throw new NestedRuntimeException("Unable to create the MBean registry instance. Illegal access " +
 1541                    "to class " + registryClass + " constructor: ", e);
 1542         }
 1543         catch (InvocationTargetException e)
 1544         {
 1545            throw new NestedRuntimeException("Unable to create the MBean registry instance. Class " + registryClass +
 1546                    " has raised an exception in constructor: ", e.getTargetException());
 1547         }
 1548      }
 1549   
 1550   
 1551      // Private -------------------------------------------------------
 1552      
 1553      // FIXME: externalize this
 1554      private ModelMBeanInfo getRegistryManagementInterface()
 1555      {
 1556         final boolean READABLE = true;
 1557         final boolean WRITABLE = true;
 1558         final boolean BOOLEAN = true;
 1559   
 1560         // Default Domain attribute
 1561         DescriptorSupport descDefaultDomain = new DescriptorSupport();
 1562         descDefaultDomain.setField("name", "DefaultDomain");
 1563         descDefaultDomain.setField("descriptorType", "attribute");
 1564         descDefaultDomain.setField("displayName", "Default Domain");
 1565         descDefaultDomain.setField("default", getDefaultDomain());
 1566         descDefaultDomain.setField("currencyTimeLimit", "-1");
 1567         ModelMBeanAttributeInfo defaultDomainInfo =
 1568                 new ModelMBeanAttributeInfo
 1569                         ("DefaultDomain", String.class.getName(),
 1570                                 "The domain to use when an object name has no domain",
 1571                                 READABLE, !WRITABLE, !BOOLEAN,
 1572                                 descDefaultDomain);
 1573   
 1574         // Size attribute
 1575         DescriptorSupport descSize = new DescriptorSupport();
 1576         descSize.setField("name", "Size");
 1577         descSize.setField("descriptorType", "attribute");
 1578         descSize.setField("displayName", "Size");
 1579         descSize.setField("getMethod", "getSize");
 1580         ModelMBeanAttributeInfo sizeInfo =
 1581                 new ModelMBeanAttributeInfo
 1582                         ("Size", Integer.TYPE.getName(),
 1583                                 "The number of MBeans registered in the MBean Server",
 1584                                 READABLE, !WRITABLE, !BOOLEAN,
 1585                                 descSize);
 1586   
 1587         // registerMBean operation
 1588         DescriptorSupport descRegisterMBean = new DescriptorSupport();
 1589         descRegisterMBean.setField("name", "registerMBean");
 1590         descRegisterMBean.setField("descriptorType", "operation");
 1591         descRegisterMBean.setField("role", "operation");
 1592         MBeanParameterInfo[] registerMBeanParms =
 1593                 new MBeanParameterInfo[]
 1594                 {
 1595                    new MBeanParameterInfo
 1596                            ("Resource",
 1597                                    Object.class.getName(),
 1598                                    "A compliant MBean to be registered in the MBean Server"),
 1599                    new MBeanParameterInfo
 1600                            ("ObjectName",
 1601                                    ObjectName.class.getName(),
 1602                                    "The object name of the MBean"),
 1603                    new MBeanParameterInfo
 1604                            ("ValueMap",
 1605                                    Map.class.getName(),
 1606                                    "Values associated with the registration"),
 1607                 };
 1608         ModelMBeanOperationInfo registerMBeanInfo =
 1609                 new ModelMBeanOperationInfo
 1610                         ("registerMBean",
 1611                                 "Adds an MBean in the MBeanServer",
 1612                                 registerMBeanParms,
 1613                                 ObjectInstance.class.getName(),
 1614                                 ModelMBeanOperationInfo.ACTION_INFO,
 1615                                 descRegisterMBean);
 1616   
 1617         // unregisterMBean operation
 1618         DescriptorSupport descUnregisterMBean = new DescriptorSupport();
 1619         descUnregisterMBean.setField("name", "unregisterMBean");
 1620         descUnregisterMBean.setField("descriptorType", "operation");
 1621         descUnregisterMBean.setField("role", "operation");
 1622         MBeanParameterInfo[] unregisterMBeanParms =
 1623                 new MBeanParameterInfo[]
 1624                 {
 1625                    new MBeanParameterInfo
 1626                            ("ObjectName",
 1627                                    ObjectName.class.getName(),
 1628                                    "The object name of the MBean to remove")
 1629                 };
 1630         ModelMBeanOperationInfo unregisterMBeanInfo =
 1631                 new ModelMBeanOperationInfo
 1632                         ("unregisterMBean",
 1633                                 "Removes an MBean from the MBeanServer",
 1634                                 unregisterMBeanParms,
 1635                                 Void.TYPE.getName(),
 1636                                 ModelMBeanOperationInfo.ACTION,
 1637                                 descUnregisterMBean);
 1638   
 1639         // getSize operation
 1640         DescriptorSupport descGetSize = new DescriptorSupport();
 1641         descGetSize.setField("name", "getSize");
 1642         descGetSize.setField("descriptorType", "operation");
 1643         descGetSize.setField("role", "getter");
 1644         MBeanParameterInfo[] getSizeParms = new MBeanParameterInfo[0];
 1645         ModelMBeanOperationInfo getSizeInfo =
 1646                 new ModelMBeanOperationInfo
 1647                         ("getSize",
 1648                                 "Gets the number of MBeans registered",
 1649                                 getSizeParms,
 1650                                 Integer.TYPE.getName(),
 1651                                 ModelMBeanOperationInfo.INFO,
 1652                                 descGetSize);
 1653   
 1654         // get operation
 1655         DescriptorSupport descGet = new DescriptorSupport();
 1656         descGet.setField("name", "get");
 1657         descGet.setField("descriptorType", "operation");
 1658         descGet.setField("role", "operation");
 1659         MBeanParameterInfo[] getParam = new MBeanParameterInfo[1];
 1660         getParam[0] = new MBeanParameterInfo("ObjectName", ObjectName.class.getName(), "object name to find");
 1661         ModelMBeanOperationInfo getInfo =
 1662                 new ModelMBeanOperationInfo
 1663                         ("get",
 1664                                 "Gets the MBeanEntry for a given ObjectName",
 1665                                 getParam,
 1666                                 MBeanEntry.class.getName(),
 1667                                 ModelMBeanOperationInfo.INFO,
 1668                                 descGet);
 1669   
 1670         // getValue operation
 1671         DescriptorSupport descGetValue = new DescriptorSupport();
 1672         descGetValue.setField("name", "getValue");
 1673         descGetValue.setField("descriptorType", "operation");
 1674         descGetValue.setField("role", "operation");
 1675         MBeanParameterInfo[] getValueParms = new MBeanParameterInfo[]
 1676         {
 1677            new MBeanParameterInfo
 1678                    ("ObjectName",
 1679                            ObjectName.class.getName(),
 1680                            "The object name of the registered MBean"),
 1681            new MBeanParameterInfo
 1682                    ("Key",
 1683                            String.class.getName(),
 1684                            "The key to the value stored")
 1685         };
 1686         ModelMBeanOperationInfo getValueInfo =
 1687                 new ModelMBeanOperationInfo
 1688                         ("getValue",
 1689                                 "Get a value stored in the MBean's registration",
 1690                                 getValueParms,
 1691                                 Object.class.getName(),
 1692                                 ModelMBeanOperationInfo.INFO,
 1693                                 descGetValue);
 1694   
 1695         // Construct the modelmbean
 1696         DescriptorSupport descMBean = new DescriptorSupport();
 1697         descMBean.setField("name", RequiredModelMBeanInstantiator.getClassName());
 1698         descMBean.setField("descriptorType", "MBean");
 1699         descMBean.setField("displayName", "MBeanServer Registry");
 1700         ModelMBeanAttributeInfo[] attrInfo = new ModelMBeanAttributeInfo[]
 1701         {
 1702            defaultDomainInfo,
 1703            sizeInfo
 1704         };
 1705         ModelMBeanConstructorInfo[] ctorInfo = null;
 1706         ModelMBeanOperationInfo[] opInfo = new ModelMBeanOperationInfo[]
 1707         {
 1708            registerMBeanInfo,
 1709            unregisterMBeanInfo,
 1710            getSizeInfo,
 1711            getValueInfo,
 1712            getInfo
 1713         };
 1714         ModelMBeanNotificationInfo[] notifyInfo = null;
 1715         ModelMBeanInfoSupport info = new ModelMBeanInfoSupport
 1716                 (RequiredModelMBeanInstantiator.getClassName(),
 1717                         "Managed Bean Registry",
 1718                         attrInfo,
 1719                         ctorInfo,
 1720                         opInfo,
 1721                         notifyInfo,
 1722                         descMBean);
 1723   
 1724         return info;
 1725      }
 1726   
 1727      private void checkMBeanPermission(String className, String member,
 1728         ObjectName objectName, String action)
 1729      {
 1730         SecurityManager sm = System.getSecurityManager();
 1731         if( sm != null )
 1732         {
 1733            MBeanPermission p = new MBeanPermission(className, member, objectName,
 1734               action);
 1735            sm.checkPermission(p);
 1736         }
 1737      }
 1738      
 1739      // Object overrides ----------------------------------------------
 1740      
 1741      /**
 1742       * Simple toString() revealing default domain
 1743       */
 1744      public String toString()
 1745      {
 1746         return super.toString() + "[ defaultDomain='" + this.getDefaultDomain() + "' ]";
 1747      }   
 1748   }

Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.mx » server » [javadoc | source]