Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.mx » capability » [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.capability;
   23   
   24   import org.jboss.mx.metadata.AttributeOperationResolver;
   25   
   26   import javax.management.Attribute;
   27   import javax.management.AttributeList;
   28   import javax.management.AttributeNotFoundException;
   29   import javax.management.DynamicMBean;
   30   import javax.management.InvalidAttributeValueException;
   31   import javax.management.MBeanAttributeInfo;
   32   import javax.management.MBeanConstructorInfo;
   33   import javax.management.MBeanException;
   34   import javax.management.MBeanInfo;
   35   import javax.management.MBeanNotificationInfo;
   36   import javax.management.MBeanOperationInfo;
   37   import javax.management.NotificationBroadcaster;
   38   import javax.management.ReflectionException;
   39   import javax.management.RuntimeErrorException;
   40   import javax.management.RuntimeMBeanException;
   41   import javax.management.RuntimeOperationsException;
   42   import java.lang.reflect.InvocationTargetException;
   43   import java.lang.reflect.Method;
   44   import java.util.Iterator;
   45   
   46   /**
   47    * Directs DynamicMBean calls to underlying resource via reflection. It's suitable
   48    * for use as a StandardMBean or as the resource for a ModelMBean.
   49    *
   50    * @author  <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
   51    * @author  <a href="mailto:juha@jboss.org">Juha Lindfors</a>
   52    */
   53   public class ReflectedMBeanDispatcher implements DynamicMBean
   54   {
   55      private Object resource = null;
   56   
   57      private AttributeOperationResolver resolver = null;
   58      private MBeanConstructorInfo[] constructorInfo = null;
   59      private MBeanAttributeInfo[] attributeInfo = null;
   60      private MBeanOperationInfo[] operationInfo = null;
   61   
   62      private Method[] operations = null;
   63      private MethodPair[] attributes = null;
   64   
   65      private boolean isBroadcaster = false;
   66   
   67      private String resourceClassName = null;
   68      private String resourceDescription = null;
   69   
   70      public ReflectedMBeanDispatcher(MBeanInfo mbinfo, AttributeOperationResolver resolver, Object resource)
   71      {
   72         if (null == resource)
   73         {
   74            throw new IllegalArgumentException("resource cannot be null");
   75         }
   76   
   77         if (null == mbinfo)
   78         {
   79            throw new IllegalArgumentException("MBeanInfo cannot be null");
   80         }
   81   
   82         if (null == resolver)
   83         {
   84            throw new IllegalArgumentException("AOresolver cannot be null");
   85         }
   86   
   87   
   88         if (resource instanceof NotificationBroadcaster)
   89         {
   90            this.isBroadcaster = true;
   91         }
   92   
   93         this.resource = resource;
   94         this.resolver = resolver;
   95         this.resourceClassName = mbinfo.getClassName();
   96         this.resourceDescription = mbinfo.getDescription();
   97         this.constructorInfo = mbinfo.getConstructors();
   98         this.attributeInfo = mbinfo.getAttributes();
   99         this.operationInfo = mbinfo.getOperations();
  100   
  101         this.operations = new Method[operationInfo.length];
  102         this.attributes = new MethodPair[attributeInfo.length];
  103      }
  104   
  105      public void bindOperationAt(int position, Method method)
  106      {
  107         try
  108         {
  109            operations[position] = method;
  110         }
  111         catch (ArrayIndexOutOfBoundsException e)
  112         {
  113            throw new IllegalArgumentException("position out of bounds: " + position);
  114         }
  115      }
  116   
  117      public void bindAttributeAt(int position, Method getter, Method setter)
  118      {
  119         try
  120         {
  121            attributes[position] = new MethodPair(getter, setter);
  122         }
  123         catch (ArrayIndexOutOfBoundsException e)
  124         {
  125            throw new IllegalArgumentException("position out of bounds: " + position);
  126         }
  127      }
  128   
  129      public String getResourceClassName()
  130      {
  131         return resourceClassName;
  132      }
  133   
  134      public Object getAttribute(String attribute)
  135         throws AttributeNotFoundException, MBeanException, ReflectionException
  136      {
  137         if (null == attribute)
  138         {
  139            throw new RuntimeOperationsException(new IllegalArgumentException("attribute cannot be null"));
  140         }
  141   
  142         Method m = null;
  143         try
  144         {
  145            m = attributes[resolver.lookup(attribute).intValue()].getter;
  146            return m.invoke(resource, new Object[0]);
  147         }
  148         catch (NullPointerException e)
  149         {
  150            throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found");
  151         }
  152         catch (ArrayIndexOutOfBoundsException e)
  153         {
  154            throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found");
  155         }
  156         catch (InvocationTargetException e)
  157         {
  158            Throwable t = e.getTargetException();
  159            if (t instanceof RuntimeException)
  160            {
  161               throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean when getting attribute '" + attribute + "'");
  162            }
  163            else if (t instanceof Exception)
  164            {
  165               throw new MBeanException((Exception) t, "Exception in MBean when getting attribute '" + attribute + "'");
  166            }
  167            else // it's an error
  168            {
  169               throw new RuntimeErrorException((Error) t, "Error in MBean when getting attribute '" + attribute + "'");
  170            }
  171         }
  172         catch (IllegalArgumentException e)
  173         {
  174            throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found");
  175         }
  176         catch (Exception e) // assume all other exceptions are reflection related
  177         {
  178            throw new ReflectionException(e, "Exception in AttributeProvider for getting '" + attribute + "'");
  179         }
  180         catch (Error e)
  181         {
  182            throw new RuntimeErrorException(e, "Error in AttributeProvider for getting '" + attribute + "'");
  183         }
  184      }
  185   
  186   
  187      public void setAttribute(Attribute attribute)
  188         throws AttributeNotFoundException, InvalidAttributeValueException,
  189         MBeanException, ReflectionException
  190      {
  191         if (null == attribute)
  192         {
  193            throw new RuntimeOperationsException(new IllegalArgumentException("attribute cannot be null"));
  194         }
  195   
  196         Method m = null;
  197         try
  198         {
  199            m = attributes[resolver.lookup(attribute.getName()).intValue()].setter;
  200            m.invoke(resource, new Object[]{attribute.getValue()});
  201         }
  202         catch (NullPointerException e)
  203         {
  204            throw new AttributeNotFoundException("Writable attribute '" + attribute.getName() + "' not found");
  205         }
  206         catch (ArrayIndexOutOfBoundsException e)
  207         {
  208            throw new AttributeNotFoundException("Writable attribute '" + attribute.getName() + "' not found");
  209         }
  210         catch (InvocationTargetException e)
  211         {
  212            Throwable t = e.getTargetException();
  213            if (t instanceof RuntimeException)
  214            {
  215               throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean when setting attribute '" + attribute.getName() + "'");
  216            }
  217            else if (t instanceof Exception)
  218            {
  219               throw new MBeanException((Exception) t, "Exception in MBean when setting attribute '" + attribute.getName() + "'");
  220            }
  221            else // it's an error
  222            {
  223               throw new RuntimeErrorException((Error) t, "Error in MBean when setting attribute '" + attribute.getName() + "'");
  224            }
  225         }
  226         catch (IllegalArgumentException e)
  227         {
  228            String valueType = (null == attribute.getValue()) ? "<null value>" : attribute.getValue().getClass().getName();
  229            throw new InvalidAttributeValueException("Attribute value mismatch while setting '" + attribute.getName() + "': " + valueType);
  230         }
  231         catch (Exception e) // assume all other exceptions are reflection related
  232         {
  233            throw new ReflectionException(e, "Exception in AttributeProvider for setting '" + attribute.getName() + "'");
  234         }
  235         catch (Error e)
  236         {
  237            throw new RuntimeErrorException(e, "Error in AttributeProvider for setting '" + attribute.getName() + "'");
  238         }
  239      }
  240   
  241   
  242      public AttributeList getAttributes(String[] attributes)
  243      {
  244         if (null == attributes)
  245         {
  246            throw new RuntimeOperationsException(new IllegalArgumentException("attributes array cannot be null"));
  247         }
  248   
  249         AttributeList list = new AttributeList();
  250         for (int i = 0; i < attributes.length; i++)
  251         {
  252            try
  253            {
  254               list.add(new Attribute(attributes[i], getAttribute(attributes[i])));
  255            }
  256            catch (Throwable e)
  257            {
  258               // QUERY - do we *really* just ignore all problems?
  259            }
  260         }
  261   
  262         return list;
  263      }
  264   
  265      public AttributeList setAttributes(AttributeList attributes)
  266      {
  267         if (null == attributes)
  268         {
  269            throw new RuntimeOperationsException(new IllegalArgumentException("attribute list cannot be null"));
  270         }
  271   
  272         AttributeList list = new AttributeList();
  273         for (Iterator iterator = attributes.iterator(); iterator.hasNext();)
  274         {
  275            Attribute toSet = (Attribute) iterator.next();
  276            try
  277            {
  278               setAttribute(toSet);
  279               list.add(toSet);
  280            }
  281            catch (Throwable e)
  282            {
  283               // QUERY - do we *really* just ignore all problems?
  284            }
  285         }
  286         return list;
  287      }
  288   
  289      public Object invoke(String actionName,
  290                           Object[] params,
  291                           String[] signature)
  292         throws MBeanException, ReflectionException
  293      {
  294         Method m = null;
  295         try
  296         {
  297            m = operations[resolver.lookup(actionName, signature).intValue()];
  298            return m.invoke(resource, params);
  299         }
  300         catch (NullPointerException e)
  301         {
  302            throw new ReflectionException(new NoSuchMethodException("Unable to locate MBean operation for: " + opKeyString(actionName, signature)));
  303         }
  304         catch (ArrayIndexOutOfBoundsException e)
  305         {
  306            throw new ReflectionException(new NoSuchMethodException("Unable to locate MBean operation for: " + opKeyString(actionName, signature)));
  307         }
  308         catch (InvocationTargetException e)
  309         {
  310            Throwable t = e.getTargetException();
  311            if (t instanceof RuntimeException)
  312            {
  313               throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean operation '" + opKeyString(actionName, signature) + "'");
  314            }
  315            else if (t instanceof Exception)
  316            {
  317               throw new MBeanException((Exception) t, "Exception in MBean operation '" + opKeyString(actionName, signature) + "'");
  318            }
  319            else // it's an error
  320            {
  321               throw new RuntimeErrorException((Error) t, "Error in MBean operation '" + opKeyString(actionName, signature) + "'");
  322            }
  323         }
  324         catch (Exception e) // assume all other exceptions are reflection related
  325         {
  326            throw new ReflectionException(e, "Exception when calling method for '" + opKeyString(actionName, signature) + "'");
  327         }
  328         catch (Error e)
  329         {
  330            throw new RuntimeErrorException(e, "Error when calling method for '" + opKeyString(actionName, signature) + "'");
  331         }
  332   
  333      }
  334   
  335      public MBeanInfo getMBeanInfo()
  336      {
  337         return new MBeanInfo(resourceClassName, resourceDescription,
  338                              attributeInfo, constructorInfo,
  339                              operationInfo, (isBroadcaster) ? this.getNotificationInfo() : new MBeanNotificationInfo[0]);
  340   
  341      }
  342   
  343      // Protected -----------------------------------------------------
  344      protected MBeanNotificationInfo[] getNotificationInfo()
  345      {
  346         if (isBroadcaster)
  347         {
  348            return ((NotificationBroadcaster) resource).getNotificationInfo();
  349         }
  350         else
  351         {
  352            throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster"));
  353         }
  354      }
  355   
  356      protected Object getResourceObject()
  357      {
  358         return resource;
  359      }
  360   
  361      // ONLY used for friendly exceptions!
  362      protected final String opKeyString(String name, String[] signature)
  363      {
  364         StringBuffer buf = new StringBuffer(name).append('(');
  365         if (null != signature)
  366         {
  367            for (int i = 0; i < signature.length-1; i++)
  368               buf.append(signature[i]).append(',');
  369            if (signature.length > 0)
  370               buf.append(signature[signature.length-1]);
  371         }
  372         return buf.append(')').toString();
  373      }
  374   
  375      public static class MethodPair
  376      {
  377         public Method getter = null;
  378         public Method setter = null;
  379   
  380         public MethodPair(Method getter, Method setter)
  381         {
  382            this.getter = getter;
  383            this.setter = setter;
  384         }
  385      }
  386   }

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