Save This Page
Home » JBoss-5.1.0 » org.jboss.mx » modelmbean » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source.
    3    * Copyright 2008, Red Hat Middleware LLC, and individual contributors
    4    * as indicated by the @author tags. See the copyright.txt file in the
    5    * distribution for a 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.modelmbean;
   23   
   24   import java.beans.BeanInfo;
   25   import java.beans.IntrospectionException;
   26   import java.beans.Introspector;
   27   import java.beans.PropertyDescriptor;
   28   import java.beans.PropertyEditor;
   29   import java.beans.PropertyEditorManager;
   30   import java.lang.reflect.Constructor;
   31   import java.lang.reflect.Method;
   32   import java.util.ArrayList;
   33   import java.util.HashMap;
   34   import java.util.Iterator;
   35   import java.util.List;
   36   import java.util.Map;
   37   
   38   import javax.management.Attribute;
   39   import javax.management.AttributeChangeNotification;
   40   import javax.management.AttributeChangeNotificationFilter;
   41   import javax.management.Descriptor;
   42   import javax.management.InstanceNotFoundException;
   43   import javax.management.JMException;
   44   import javax.management.ListenerNotFoundException;
   45   import javax.management.MBeanAttributeInfo;
   46   import javax.management.MBeanException;
   47   import javax.management.MBeanInfo;
   48   import javax.management.MBeanNotificationInfo;
   49   import javax.management.MBeanOperationInfo;
   50   import javax.management.MBeanServer;
   51   import javax.management.Notification;
   52   import javax.management.NotificationFilter;
   53   import javax.management.NotificationListener;
   54   import javax.management.ObjectName;
   55   import javax.management.RuntimeErrorException;
   56   import javax.management.RuntimeOperationsException;
   57   import javax.management.modelmbean.InvalidTargetObjectTypeException;
   58   import javax.management.modelmbean.ModelMBean;
   59   import javax.management.modelmbean.ModelMBeanAttributeInfo;
   60   import javax.management.modelmbean.ModelMBeanInfo;
   61   import javax.management.modelmbean.ModelMBeanInfoSupport;
   62   import javax.management.modelmbean.ModelMBeanOperationInfo;
   63   
   64   import org.jboss.logging.Logger;
   65   import org.jboss.mx.interceptor.AbstractInterceptor;
   66   import org.jboss.mx.interceptor.Interceptor;
   67   import org.jboss.mx.interceptor.ModelMBeanAttributeInterceptor;
   68   import org.jboss.mx.interceptor.ModelMBeanInfoInterceptor;
   69   import org.jboss.mx.interceptor.ModelMBeanInterceptor;
   70   import org.jboss.mx.interceptor.ModelMBeanOperationInterceptor;
   71   import org.jboss.mx.interceptor.NullInterceptor;
   72   import org.jboss.mx.interceptor.ObjectReferenceInterceptor;
   73   import org.jboss.mx.interceptor.PersistenceInterceptor;
   74   import org.jboss.mx.interceptor.PersistenceInterceptor2;
   75   import org.jboss.mx.persistence.NullPersistence;
   76   import org.jboss.mx.persistence.PersistenceManager;
   77   import org.jboss.mx.server.AbstractMBeanInvoker;
   78   import org.jboss.mx.server.Invocation;
   79   import org.jboss.mx.server.InvocationContext;
   80   import org.jboss.mx.server.MBeanInvoker;
   81   import org.jboss.mx.util.JBossNotificationBroadcasterSupport;
   82   
   83   /**
   84    * An extension of the {@link org.jboss.mx.server.MBeanInvoker MBeanInvoker}
   85    * that implements the base Model MBean functionality, essentially making the
   86    * Model MBean just another invoker of managed resources.
   87    *
   88    * @see javax.management.modelmbean.ModelMBean
   89    * @see org.jboss.mx.server.MBeanInvoker
   90    *
   91    * @author  <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
   92    * @author  <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
   93    * @author Matt Munz
   94    * @version $Revision: 81026 $
   95    */
   96   public abstract class ModelMBeanInvoker extends AbstractMBeanInvoker
   97      implements ModelMBean, ModelMBeanConstants
   98   {
   99      Logger log = Logger.getLogger(ModelMBeanInvoker.class.getName());
  100   
  101      // Attributes ----------------------------------------------------
  102   
  103      /**
  104       * The resource type string of the managed resource, such as
  105       * {@link ModelMBeanConstants#OBJECT_REF} or
  106       * {@link XMBeanConstants#STANDARD_INTERFACE}. This type string can be
  107       * used by the invoker to determine the behavior implemented by the
  108       * invocation chain and how the managed resource is exposed to the client
  109       * programs.
  110       */
  111      protected String resourceType = null;
  112      
  113      /**
  114       * Persistence manager.
  115       */
  116      protected PersistenceManager persistence = new NullPersistence();
  117   
  118      /**
  119       * Notification broadcaster for this Model MBean.
  120       */
  121      protected JBossNotificationBroadcasterSupport notifier = new JBossNotificationBroadcasterSupport();
  122   
  123      /**
  124       * Notification sequence number for generic Model MBean notifications.
  125       */
  126      protected long notifierSequence = 1;
  127   
  128      /**
  129       * Notification sequence number for attribute change notifications.
  130       */
  131      protected long attrNotifierSequence = 1;
  132   
  133   
  134      // Constructors --------------------------------------------------
  135   
  136      /**
  137       * Default constructor.
  138       */
  139      public ModelMBeanInvoker()
  140      {
  141      }
  142   
  143      /**
  144       * Creates a Model MBean instance and initializes it with the given
  145       * Model MBean metadata.
  146       *
  147       * @param   info  Model MBean metadata
  148       */
  149      public ModelMBeanInvoker(ModelMBeanInfo info) throws MBeanException
  150      {
  151         setModelMBeanInfo(info);
  152      }
  153   
  154   
  155   
  156      // ModelMBean implementation -------------------------------------
  157   
  158      /**
  159       * Sets the MBean metadata for this Model MBean instance.
  160       *
  161       * @param   info  Model MBean metadata
  162       */
  163      public void setModelMBeanInfo(ModelMBeanInfo info)
  164         throws MBeanException, RuntimeOperationsException
  165      {
  166         if (info == null)
  167            throw new RuntimeOperationsException(new IllegalArgumentException("MBeanInfo cannot be null"));
  168   
  169         // need to type to an instance of MBeanInfo -- therefore the extra copy here
  170         this.info = new ModelMBeanInfoSupport(info);
  171   
  172         // Apply the MBeanInfo injection if requested
  173         ModelMBeanInfo minfo = info;
  174         Descriptor mbeanDescriptor = null;
  175         try
  176         {
  177            mbeanDescriptor = minfo.getDescriptor("",
  178                           ModelMBeanConstants.MBEAN_DESCRIPTOR);
  179         }
  180         catch (MBeanException e)
  181         {
  182            log.warn("Failed to obtain descriptor: "+ModelMBeanConstants.MBEAN_DESCRIPTOR, e);
  183            return;
  184         }
  185   
  186         String type = (String) mbeanDescriptor.getFieldValue(
  187            ModelMBeanConstants.MBEAN_INFO_INJECTION_TYPE);
  188         if( type != null )
  189         {
  190            inject(ModelMBeanConstants.MBEAN_INFO_INJECTION_TYPE,
  191               type, MBeanInfo.class, info);
  192         }
  193      }
  194   
  195      /**
  196       * Sets the managed resource for this Model MBean instance. The resource
  197       * type must be known to the Model MBean implementation (see
  198       * {@link #isSupportedResourceType} for more information).
  199       *
  200       * @param   ref            reference to the managed resource
  201       * @param   resourceType   resource type identification string
  202       */
  203      public void setManagedResource(Object ref, String resourceType)
  204         throws MBeanException, InstanceNotFoundException, InvalidTargetObjectTypeException
  205      {
  206         if (!isSupportedResourceType(ref, resourceType))
  207            throw new InvalidTargetObjectTypeException("Unsupported resource type: " + resourceType);
  208   
  209         setResource(ref);
  210         this.resourceType = resourceType;
  211   
  212         if (getServer() != null)
  213         {
  214            try
  215            {
  216               this.init(getServer(), resourceEntry.getObjectName());
  217            }
  218            catch(Exception e)
  219            {
  220               throw new MBeanException(e, "Failed to init from resource");
  221            }
  222         }
  223      }
  224   
  225      // ModelMBeanNotificationBroadcaster implementation --------------
  226   
  227      public void addNotificationListener(NotificationListener listener,
  228         NotificationFilter filter,
  229         Object handback)
  230      {
  231         notifier.addNotificationListener(listener, filter, handback);
  232      }
  233   
  234      public void removeNotificationListener(NotificationListener listener)
  235         throws ListenerNotFoundException
  236      {
  237         notifier.removeNotificationListener(listener);
  238      }
  239   
  240      public void removeNotificationListener(NotificationListener listener,
  241         NotificationFilter filter,
  242         Object handback)
  243         throws ListenerNotFoundException
  244      {
  245         notifier.removeNotificationListener(listener, filter, handback);
  246      }
  247   
  248      /**
  249       * Sends a notification with a given string message. The notification
  250       * type will be set as
  251       * {@link ModelMBeanConstants#GENERIC_MODELMBEAN_NOTIFICATION GENERIC_MODELMBEAN_NOTIFICATION}.
  252       *
  253       * @param ntfyText notification message
  254       */
  255      public void sendNotification(String ntfyText)
  256         throws MBeanException, RuntimeOperationsException
  257      {
  258         if( ntfyText == null )
  259         {
  260            throw new RuntimeOperationsException(
  261              new IllegalArgumentException("ntfyText cannot be null")
  262            );
  263         }
  264         Notification notif = new Notification(
  265            GENERIC_MODELMBEAN_NOTIFICATION, // type
  266            this, // source
  267            1, // always 1 - by spec
  268            ntfyText            // message
  269         );
  270   
  271         sendNotification(notif);
  272      }
  273   
  274      /**
  275       * Sends a notification.
  276       *
  277       * @param ntfyObj notification to send
  278       */
  279      public void sendNotification(Notification ntfyObj)
  280         throws MBeanException, RuntimeOperationsException
  281      {
  282         if( ntfyObj == null )
  283         {
  284            throw new RuntimeOperationsException(
  285               new IllegalArgumentException("ntfyText cannot be null")
  286            );
  287         }
  288         notifier.sendNotification(ntfyObj);
  289      }
  290   
  291      /**
  292       * Sends an attribute change notification.
  293       *
  294       * @param   notification attribute change notification to send
  295       */
  296      public void sendAttributeChangeNotification(AttributeChangeNotification notification)
  297         throws MBeanException
  298      {
  299         if( notification == null )
  300         {
  301            throw new RuntimeOperationsException(
  302               new IllegalArgumentException("notification cannot be null")
  303            );
  304         }
  305         notifier.sendNotification(notification);
  306      }
  307   
  308      /**
  309       * Sends an attribute change notification.
  310       *
  311       * @param   oldValue attribute with the old value
  312       * @param   newValue attribute with the new value
  313       * @throws IllegalArgumentException - An Attribute object passed in parameter
  314       * is null or the names of the two Attribute objects in parameter are not
  315       * the same.
  316       */
  317      public void sendAttributeChangeNotification(Attribute oldValue, Attribute newValue)
  318         throws MBeanException, RuntimeOperationsException
  319      {
  320         if( oldValue == null || newValue == null )
  321         {
  322            throw new RuntimeOperationsException(
  323               new IllegalArgumentException("Attribute cannot be null")
  324            );
  325         }
  326         if (!(oldValue.getName().equals(newValue.getName())))
  327         {
  328            throw new RuntimeOperationsException(
  329               new IllegalArgumentException("Attribute name mismatch between oldvalue and newvalue")
  330            );
  331         }
  332   
  333         String attr = oldValue.getName();
  334         String type = ((ModelMBeanInfo) info).getAttribute(attr).getType();
  335   
  336         AttributeChangeNotification notif = new AttributeChangeNotification(
  337            this, // source
  338            1, // always 1 - by spec
  339            System.currentTimeMillis(), // time stamp
  340            "" + attr + " changed from " + oldValue + " to " + newValue,
  341            attr, type, // name & type
  342            oldValue.getValue(),
  343            newValue.getValue()            // values
  344         );
  345   
  346         notifier.sendNotification(notif);
  347      }
  348   
  349      public MBeanNotificationInfo[] getNotificationInfo()
  350      {
  351         return info.getNotifications();
  352      }
  353   
  354      /**
  355       */
  356      public void addAttributeChangeNotificationListener(
  357         NotificationListener listener,
  358         String attributeName,
  359         Object handback) throws MBeanException
  360      {
  361         // Check the attribute info
  362         ModelMBeanInfo minfo = (ModelMBeanInfo) info;
  363         AttributeChangeNotificationFilter filter = null;
  364         if (attributeName != null)
  365         {
  366            ModelMBeanAttributeInfo ainfo = minfo.getAttribute(attributeName);
  367            if( ainfo == null )
  368            {
  369               throw new RuntimeOperationsException(
  370                  new IllegalArgumentException("Attribute does not exist: "+attributeName));         
  371            }
  372            filter = new AttributeChangeNotificationFilter();
  373            filter.enableAttribute(attributeName);
  374         }
  375         else
  376         {
  377            filter = new AttributeChangeNotificationFilter();
  378            MBeanAttributeInfo[] allAttributes = minfo.getAttributes();
  379            for (int i = 0; i < allAttributes.length; ++i)
  380               filter.enableAttribute(allAttributes[i].getName());
  381         }
  382         notifier.addNotificationListener(listener, filter, handback);
  383      }
  384   
  385      /**
  386       */
  387      public void removeAttributeChangeNotificationListener(
  388         NotificationListener listener,
  389         String attributeName) throws MBeanException, ListenerNotFoundException
  390      {
  391         if( attributeName != null )
  392         {
  393            // Check the attribute info
  394            ModelMBeanInfo minfo = (ModelMBeanInfo) info;
  395            ModelMBeanAttributeInfo ainfo = minfo.getAttribute(attributeName);
  396            if( ainfo == null )
  397            {
  398               throw new RuntimeOperationsException(
  399                  new IllegalArgumentException("Attribute does not exist: "+attributeName));         
  400            }
  401         }
  402         notifier.removeNotificationListener(listener);
  403      }
  404   
  405      // PersistentMBean implementation --------------------------------
  406      public void load() throws MBeanException, InstanceNotFoundException
  407      {
  408         if (info == null)
  409            return;
  410   
  411         persistence.load(this, info);
  412      }
  413   
  414      public void store() throws MBeanException, InstanceNotFoundException
  415      {
  416         persistence.store(info);
  417      }
  418   
  419   
  420      // MBeanRegistration implementation ------------------------------
  421   
  422      /**
  423       * The default implementation of <tt>preRegister</tt> invokes the
  424       * {@link #configureInterceptorStack} method which sets up the interceptors
  425       * for this Model MBean instance. Subclasses may override the
  426       * <tt>configureInterceptorStack()</tt> method to implement their own
  427       * interceptor stack configurations. See the JavaDoc for
  428       * <tt>configureInterceptorStack()</tt> for more information.    <p>
  429       *
  430       * After the interceptor configuration, this implementation invokes the
  431       * {@link #load} method on this Model MBean instance. This will attempt
  432       * to load a pre-existing management attribute state for this Model MBean
  433       * instance. See the Javadoc for <tt>load()</tt> for more information.
  434       */
  435      public ObjectName invokePreRegister(MBeanServer server, ObjectName name)
  436         throws Exception
  437      {
  438         // Check for null metadata and prevent registration if metadata
  439         // has not been set
  440         if (info == null)
  441         {
  442            throw new RuntimeErrorException(
  443               new Error("MBeanInfo has not been set."));
  444         }
  445   
  446         // Set the mbean descriptor on the info context for use by interceptor config
  447         final ModelMBeanInfo minfo = (ModelMBeanInfo) info;
  448         Descriptor mbeanDescriptor = minfo.getMBeanDescriptor();
  449         getMBeanInfoCtx = new InvocationContext();
  450         getMBeanInfoCtx.setInvoker(this);
  451         getMBeanInfoCtx.setDescriptor(mbeanDescriptor);
  452         getMBeanInfoCtx.setDispatcher(new AbstractInterceptor("MBeanInfo Dispatcher")
  453         {
  454            public Object invoke(Invocation invocation) throws Throwable
  455            {
  456               return minfo;
  457            }
  458         });
  459         // JBAS-33 - No need to register the "getMBeanInfo" context to the operationsContextMap,
  460         // this is only accessible through AbstractMBeanInvoker.getMBeanInfo().
  461         // Registering it will result in duplicate interceptor construction.
  462   
  463         // Need to install the setManagedResource op
  464         // TODO, this is probably uneccessary now so revisit this
  465         String[] signature = new String[]{"java.lang.Object", "java.lang.String"};
  466         OperationKey opKey = new OperationKey("setManagedResource", signature);
  467         InvocationContext ctx = new InvocationContext();
  468         ctx.setInvoker(this);
  469         ctx.setDispatcher(new AbstractInterceptor("SetMangedResource Dispatcher")
  470         {
  471            public Object invoke(Invocation invocation) throws Throwable
  472            {
  473               Object[] args = invocation.getArgs();
  474               setManagedResource(args[0], (String) args[1]);
  475               return null;
  476            }
  477         });
  478         operationContextMap.put(opKey, ctx);
  479   
  480         if (getResource() == null )
  481         {
  482            return name;
  483         }
  484         else
  485         {
  486            init(server, name);
  487         }
  488   
  489         return super.invokePreRegister(server, name);
  490      }
  491   
  492      // Protected ---------------------------------------------------
  493   
  494      /**
  495       * 
  496       * @param server
  497       * @param name
  498       * @throws Exception
  499       */ 
  500      protected void init(MBeanServer server, ObjectName name)
  501         throws Exception
  502      {
  503         ModelMBeanInfo minfo = (ModelMBeanInfo) info;
  504         configureInterceptorStack(minfo, server, name);
  505         initDispatchers();
  506   
  507         // add the resource classname to the MBean info
  508         Object resource = getResource();
  509         if (resource != null)
  510         {
  511            Descriptor mbeanDescriptor = minfo.getMBeanDescriptor();         
  512            String resClassName = getResource().getClass().getName();
  513            mbeanDescriptor.setField(ModelMBeanConstants.RESOURCE_CLASS, resClassName);
  514            minfo.setMBeanDescriptor(mbeanDescriptor);
  515         }
  516   
  517         //Set initial values provided in descriptors
  518         setValuesFromMBeanInfo();
  519   
  520         initPersistence(server, name);
  521   
  522         //Set (and override) values from mbean persistence store.
  523         load();
  524      }
  525   
  526      /**
  527       * initializes the persistence manager based on the info for this bean.
  528       * If this is successful, loads the bean from the persistence store.
  529       */
  530      protected void initPersistence(MBeanServer server, ObjectName name)
  531         throws MBeanException, InstanceNotFoundException
  532      {
  533         Descriptor[] descriptors;
  534         ModelMBeanInfo minfo = (ModelMBeanInfo) getMetaData();
  535         
  536         try
  537         {
  538            descriptors = minfo.getDescriptors(MBEAN_DESCRIPTOR);
  539         }
  540         catch (MBeanException e)
  541         {
  542            log.error("Failed to obtain MBEAN_DESCRIPTORs", e);
  543            return;
  544         }
  545   
  546         if (descriptors == null)
  547         {
  548            return;
  549         }
  550         String persistMgrName = null;
  551         for (int i = 0; ((i < descriptors.length) && (persistMgrName == null)); i++)
  552         {
  553            persistMgrName = (String) descriptors[i].getFieldValue(PERSISTENCE_MANAGER);
  554         }
  555         if (persistMgrName == null)
  556         {
  557            log.trace("No " + PERSISTENCE_MANAGER
  558               + " descriptor found, null persistence will be used");
  559            return;
  560         }
  561   
  562         try
  563         {
  564            persistence = (PersistenceManager) server.instantiate(persistMgrName);
  565            log.debug("Loaded persistence mgr: " + persistMgrName);
  566            
  567            // Add the ObjectName to the ModelMBean Descriptor
  568            // so that it can be used by the PersistentManager (if needed)
  569            Descriptor descriptor = minfo.getMBeanDescriptor();
  570            descriptor.setField(ModelMBeanConstants.OBJECT_NAME, name);
  571            minfo.setMBeanDescriptor(descriptor);
  572         }
  573         catch (Exception cause)
  574         {
  575            log.error("Unable to instantiate the persistence manager:"
  576               + persistMgrName, cause);
  577         }
  578      }
  579   
  580      protected void initOperationContexts(MBeanOperationInfo[] operations)
  581      {
  582         // make sure we invoke the super class initialization sequence first
  583         super.initOperationContexts(operations);
  584   
  585         for (int i = 0; i < operations.length; ++i)
  586         {
  587            OperationKey key = new OperationKey(operations[i]);
  588   
  589            InvocationContext ctx = (InvocationContext) operationContextMap.get(key);
  590            ModelMBeanOperationInfo info = (ModelMBeanOperationInfo) operations[i];
  591            ctx.setDescriptor(info.getDescriptor());
  592         }
  593      }
  594   
  595      protected void initAttributeContexts(MBeanAttributeInfo[] attributes)
  596      {
  597         super.initAttributeContexts(attributes);
  598   
  599         for (int i = 0; i < attributes.length; ++i)
  600         {
  601            ModelMBeanAttributeInfo info = (ModelMBeanAttributeInfo) attributes[i];
  602            String name = info.getName();
  603            InvocationContext ctx = (InvocationContext) attributeContextMap.get(name);
  604            ctx.setDescriptor(info.getDescriptor());
  605            ctx.setReadable(info.isReadable());
  606            ctx.setWritable(info.isWritable());
  607         }
  608      }
  609   
  610      /** 
  611       * Build the getMBeanInfo, operation, and attribute interceptor stacks
  612       * and associated these with the corresponding InvocationContexts.
  613       * 
  614       * @param info - the ModelMBean metadata
  615       * @param server - the MBeanServer the ModelMBean is registering with
  616       * @param name - the ModelMBean name
  617       * @throws Exception
  618       */
  619      protected void configureInterceptorStack(ModelMBeanInfo info, MBeanServer server, ObjectName name)
  620         throws Exception
  621      {
  622         // Get the MBeanInfo accessor interceptor stack. This is the interceptor
  623         // stack declared at the model mbean level. In 3.2.3 and earlier this was
  624         // the interceptor stack for all operation and attribute access so we
  625         // use this as the default interceptor stack, for all attributes/operations.
  626         
  627         List defaultInterceptors = getInterceptors(getMBeanInfoCtx.getDescriptor());
  628         
  629         List interceptors = null;
  630         if (defaultInterceptors != null)
  631         {
  632            interceptors = new ArrayList(defaultInterceptors);
  633         }
  634         if (interceptors == null)
  635         {
  636            // Set the default interceptor stack
  637            interceptors = getMBeanInfoCtx.getInterceptors();
  638         }
  639         // We always add the ModelMBeanInfoInterceptor as we expect that
  640         // users are specifying additional interceptors, not overriding the
  641         // source of the ModelMBeanInfo.
  642   
  643         String mbeanName = name != null ? name.toString() : info.getClassName();
  644         interceptors.add(new ModelMBeanInfoInterceptor(mbeanName));
  645         getMBeanInfoCtx.setInterceptors(interceptors);
  646   
  647         // Get any custom interceptors specified at the attribute level
  648         for (Iterator it = attributeContextMap.entrySet().iterator(); it.hasNext();)
  649         {
  650            Map.Entry entry = (Map.Entry) it.next();
  651   
  652            InvocationContext ctx = (InvocationContext) entry.getValue();
  653            List list = getInterceptors(ctx.getDescriptor());
  654            if (list == null)
  655            {
  656               // Use the mbean inteceptors if sepecified
  657               if (defaultInterceptors != null)
  658               {
  659                  list = new ArrayList(defaultInterceptors);
  660               }
  661               else
  662               {
  663                  list = new ArrayList();
  664               }
  665            }
  666            // Add the attribute accessor semantic interceptors
  667            list.add(new PersistenceInterceptor());
  668            list.add(new ModelMBeanAttributeInterceptor());
  669            ctx.setInterceptors(list);
  670         }
  671   
  672         // Get any custom interceptors specified at the operation level
  673         for (Iterator it = operationContextMap.entrySet().iterator(); it.hasNext();)
  674         {
  675            Map.Entry entry = (Map.Entry) it.next();
  676   
  677            InvocationContext ctx = (InvocationContext) entry.getValue();
  678            List list = getInterceptors(ctx.getDescriptor());
  679            if (list == null && defaultInterceptors != null)
  680               list = new ArrayList(defaultInterceptors);
  681            
  682            // Add operation caching (not for standard mbeans)
  683            if (dynamicResource)
  684            {
  685               if (list == null)
  686               {
  687                  list = new ArrayList();
  688               }
  689               list.add(new ModelMBeanOperationInterceptor());
  690            }
  691               
  692            if (list != null)
  693            {
  694               // Add a noop interceptor since the 3.2.3- interceptors always had
  695               // to delegate to the next in order to dispatch the operation. Now
  696               // there is no interceptor for this so this prevents NPEs.
  697               
  698               list.add(new NullInterceptor());
  699               ctx.setInterceptors(list);
  700            }
  701         }
  702      }
  703   
  704      /**
  705       * 
  706       * @param d
  707       * @return
  708       * @throws Exception
  709       */
  710      protected List getInterceptors(Descriptor d) throws Exception
  711      {
  712         if (d == null)
  713            return null;
  714         Descriptor[] interceptorDescriptors = (Descriptor[]) d.getFieldValue(INTERCEPTORS);
  715         if (interceptorDescriptors == null)
  716            return null;
  717   
  718         ArrayList interceptors = new ArrayList();
  719         ClassLoader loader = Thread.currentThread().getContextClassLoader();
  720         for (int i = 0; i < interceptorDescriptors.length; i++)
  721         {
  722            Descriptor desc = interceptorDescriptors[i];
  723            String code = (String) desc.getFieldValue("code");
  724            // Ignore the legacy required interceptors
  725            if (code.equals(ModelMBeanInterceptor.class.getName()) ||
  726               code.equals(ObjectReferenceInterceptor.class.getName()) ||
  727               code.equals(PersistenceInterceptor2.class.getName()))
  728            {
  729               log.debug("Ignoring obsolete legacy interceptor: " + code);
  730               continue;
  731            }
  732   
  733            Class interceptorClass = loader.loadClass(code);
  734            Interceptor interceptor = null;
  735            // Check for a ctor(MBeanInvoker)
  736            Class[] ctorSig = {MBeanInvoker.class};
  737            try
  738            {
  739               Constructor ctor = interceptorClass.getConstructor(ctorSig);
  740               Object[] ctorArgs = {this};
  741               interceptor = (Interceptor) ctor.newInstance(ctorArgs);
  742            }
  743            catch (Throwable t)
  744            {
  745               log.debug("Could not invoke CTOR(MBeanInvoker) for '"
  746                     + interceptorClass + "', trying default CTOR: " + t.getMessage()); 
  747               
  748               // Try the default ctor
  749               interceptor = (Interceptor) interceptorClass.newInstance();
  750            }
  751            interceptors.add(interceptor);
  752   
  753            // Apply any interceptor attributes
  754            String[] names = desc.getFieldNames();
  755            HashMap propertyMap = new HashMap();
  756            if (names.length > 1)
  757            {
  758               BeanInfo beanInfo = Introspector.getBeanInfo(interceptorClass);
  759               PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
  760               for (int p = 0; p < props.length; p++)
  761               {
  762                  String fieldName = props[p].getName();
  763                  propertyMap.put(fieldName, props[p]);
  764               }
  765               // Map each attribute to the corresponding interceptor property
  766               for (int n = 0; n < names.length; n++)
  767               {
  768                  String name = names[n];
  769                  if (name.equals("code"))
  770                     continue;
  771                  String text = (String) desc.getFieldValue(name);
  772                  PropertyDescriptor pd = (PropertyDescriptor) propertyMap.get(name);
  773                  if (pd == null)
  774                     throw new IntrospectionException("No PropertyDescriptor for attribute:" + name);
  775                  Method setter = pd.getWriteMethod();
  776                  if (setter != null)
  777                  {
  778                     Class ptype = pd.getPropertyType();
  779                     PropertyEditor editor = PropertyEditorManager.findEditor(ptype);
  780                     if (editor == null)
  781                        throw new IntrospectionException("Cannot convert string to interceptor attribute:" + name);
  782                     editor.setAsText(text);
  783                     Object args[] = {editor.getValue()};
  784                     setter.invoke(interceptor, args);
  785                  }
  786               }
  787            }
  788         }
  789   
  790         if (interceptors.size() == 0)
  791            interceptors = null;
  792         return interceptors;
  793      }
  794   
  795      protected void setValuesFromMBeanInfo() throws JMException
  796      {
  797         for (Iterator it = attributeContextMap.entrySet().iterator(); it.hasNext();)
  798         {
  799            Map.Entry entry = (Map.Entry) it.next();
  800            String key = (String) entry.getKey();
  801   
  802            InvocationContext ctx = (InvocationContext) entry.getValue();
  803            //Initialize value from descriptor.
  804            Object value = ctx.getDescriptor().getFieldValue(XMBeanConstants.CACHED_VALUE);
  805            if (value != null)
  806            {
  807               setAttribute(new Attribute(key, value));
  808            } // end of if ()
  809         }
  810   
  811      }
  812   
  813      protected boolean isSupportedResourceType(Object resource, String resourceType)
  814      {
  815         if (resourceType.equalsIgnoreCase(OBJECT_REF))
  816            return true;
  817   
  818         return false;
  819      }
  820   
  821      protected void override(Invocation invocation) throws MBeanException
  822      {
  823         // Do we allow for dynamic descriptor changes
  824         if (dynamicResource && info != null)
  825         {
  826            Descriptor current = invocation.getDescriptor();
  827            if (current != null)
  828            {
  829               ModelMBeanInfo mminfo = (ModelMBeanInfo) info;
  830               Descriptor descriptor = mminfo.getDescriptor((String) current.getFieldValue(NAME), (String) current.getFieldValue(DESCRIPTOR_TYPE));
  831               if (descriptor != null)
  832                  invocation.setDescriptor(descriptor);
  833            }
  834         }
  835      }
  836      
  837   }
  838   

Save This Page
Home » JBoss-5.1.0 » org.jboss.mx » modelmbean » [javadoc | source]