Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » system » microcontainer » [javadoc | source]
    1   /*
    2   * JBoss, Home of Professional Open Source
    3   * Copyright 2006, 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.system.microcontainer;
   23   
   24   import java.lang.reflect.InvocationHandler;
   25   import java.lang.reflect.Method;
   26   import java.lang.reflect.Proxy;
   27   import java.util.HashMap;
   28   
   29   import javax.management.MBeanInfo;
   30   import javax.management.MBeanOperationInfo;
   31   import javax.management.MBeanServer;
   32   import javax.management.ObjectName;
   33   
   34   import org.jboss.mx.util.JMXExceptionDecoder;
   35   import org.jboss.system.Service;
   36   import org.jboss.system.ServiceController;
   37   
   38   /**
   39    * An implementation of InvocationHandler used to proxy of the Service
   40    * interface for mbeans. It determines which of the start/stop
   41    * methods of the Service interface an mbean implements by inspecting its
   42    * MBeanOperationInfo values. Each Service interface method that has a
   43    * matching operation is forwarded to the mbean by invoking the method
   44    * through the MBeanServer object.<p>
   45    * 
   46    * This class is based on the old ServiceConfigurator
   47    * 
   48    * @author <a href="mailto:marc@jboss.org">Marc Fleury</a>
   49    * @author <a href="mailto:hiram@jboss.org">Hiram Chirino</a>
   50    * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
   51    * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
   52    * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
   53    * @author <a href="adrian@jboss.com">Adrian Brock</a>
   54    * @version $Revision: 1.1 $
   55    */
   56   public class ServiceProxy implements InvocationHandler
   57   {
   58      /**
   59       * A mapping from the Service interface method names to the corresponding
   60       * index into the ServiceProxy.hasOp array.
   61       */
   62      private static HashMap<String, Integer> serviceOpMap = new HashMap<String, Integer>();
   63   
   64      // A singleton proxy with no callouts
   65      private static Service NO_LIFECYCLE_CALLOUT;
   66      
   67      /**
   68       * Initialize the service operation map.
   69       */
   70      static
   71      {
   72         serviceOpMap.put("create", new Integer(0));
   73         serviceOpMap.put("start", new Integer(1));
   74         serviceOpMap.put("destroy", new Integer(2));
   75         serviceOpMap.put("stop", new Integer(3));
   76         Class<?>[] interfaces = { Service.class };
   77         NO_LIFECYCLE_CALLOUT = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), interfaces, NoLifecycleCallout.INSTANCE);
   78      }
   79   
   80      private boolean[] hasOp = {false, false, false, false};
   81      private ObjectName objectName;
   82      private MBeanServer server;
   83   
   84      /** Whether we have the lifecycle method */
   85      private boolean hasJBossInternalLifecycle;
   86   
   87      /**
   88       * Get the Service interface through which the mbean given by objectName will be managed.
   89       *
   90       * @param objectName the object name
   91       * @param server the mbean server
   92       * @return The Service value
   93       * @throws Exception for any error
   94       */
   95      public static Service getServiceProxy(ObjectName objectName, MBeanServer server) throws Exception
   96      {
   97         return getServiceProxy(objectName, server, true);
   98      }
   99   
  100      /**
  101       * Get the Service interface through which the mbean given by objectName will be managed.
  102       *
  103       * @param objectName the object name
  104       * @param server the mbean server
  105       * @param includeLifecycle include lifecycle
  106       * @return The Service value
  107       * @throws Exception for any error
  108       */
  109      public static Service getServiceProxy(ObjectName objectName, MBeanServer server, boolean includeLifecycle) throws Exception
  110      {
  111         Service service = null;
  112         MBeanInfo info = server.getMBeanInfo(objectName);
  113         MBeanOperationInfo[] opInfo = info.getOperations();
  114         Class<?>[] interfaces = { Service.class };
  115         InvocationHandler handler = new ServiceProxy(objectName, server, opInfo);
  116         if (includeLifecycle == false)
  117            service = NO_LIFECYCLE_CALLOUT; 
  118         else
  119            service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), interfaces, handler);
  120   
  121         return service;
  122      }
  123   
  124      /**
  125       * Go through the opInfo array and for each operation that matches on of
  126       * the Service interface methods set the corresponding hasOp array value
  127       * to true.
  128       *
  129       * @param objectName the object name
  130       * @param server the mbean server
  131       * @param opInfo the MBean operation info
  132       */
  133      public ServiceProxy(ObjectName objectName, MBeanServer server, MBeanOperationInfo[] opInfo)
  134      {
  135         this.server = server;
  136         this.objectName = objectName;
  137   
  138         for (int op = 0; op < opInfo.length; op++)
  139         {
  140            MBeanOperationInfo info = opInfo[op];
  141            String name = info.getName();
  142   
  143            if (name.equals(ServiceController.JBOSS_INTERNAL_LIFECYCLE))
  144            {
  145               hasJBossInternalLifecycle = true;
  146               continue;
  147            }
  148   
  149            Integer opID = serviceOpMap.get(name);
  150            if (opID == null)
  151            {
  152               continue;
  153            }
  154   
  155            // Validate that is a no-arg void return type method
  156            if (info.getReturnType().equals("void") == false)
  157            {
  158               continue;
  159            }
  160            if (info.getSignature().length != 0)
  161            {
  162               continue;
  163            }
  164   
  165            hasOp[opID.intValue()] = true;
  166         }
  167      }
  168   
  169      /**
  170       * Map the method name to a Service interface method index and if the
  171       * corresponding hasOp array element is true, dispatch the method to the
  172       * mbean we are proxying.
  173       *
  174       * @param proxy
  175       * @param method
  176       * @param args
  177       * @return             Always null.
  178       * @throws Throwable
  179       */
  180      public Object invoke(Object proxy, Method method, Object[] args)
  181            throws Throwable
  182      {
  183         String name = method.getName();
  184   
  185         if (hasJBossInternalLifecycle)
  186         {
  187            try
  188            {
  189               server.invoke(objectName, ServiceController.JBOSS_INTERNAL_LIFECYCLE, new Object[] { name }, ServiceController.JBOSS_INTERNAL_LIFECYCLE_SIG);
  190               return null;
  191            }
  192            catch (Exception e)
  193            {
  194               throw JMXExceptionDecoder.decode(e);
  195            }
  196         }
  197   
  198         Integer opID = serviceOpMap.get(name);
  199   
  200         if (opID != null && hasOp[opID.intValue()] == true)
  201         {
  202            // deal with those pesky JMX exceptions
  203            try
  204            {
  205               String[] sig = {};
  206               server.invoke(objectName, name, args, sig);
  207            }
  208            catch (Exception e)
  209            {
  210               throw JMXExceptionDecoder.decode(e);
  211            }
  212         }
  213   
  214         return null;
  215      }
  216      
  217      private static class NoLifecycleCallout implements InvocationHandler
  218      {
  219         private static NoLifecycleCallout INSTANCE = new NoLifecycleCallout();
  220         
  221         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  222         {
  223            return null;
  224         }
  225      }
  226   }

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