Package org.jboss.varia.deployment

Source Code of org.jboss.varia.deployment.BeanShellScript

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.varia.deployment;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;

import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.jboss.deployment.DeploymentException;
import org.jboss.system.ServiceDynamicMBeanSupport;
import org.jboss.util.Classes;

import bsh.EvalError;
import bsh.Interpreter;

/**
* A wrapper service that exposes a BeanShell script as a JBoss service
* MBean.
*
* @see BeanShellSubDeployer
*
* @author  <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>.
* @version $Revision: 84175 $
*/
public class BeanShellScript extends ServiceDynamicMBeanSupport
{

   protected String name = null;

   protected ScriptService scriptService = null;

   protected ObjectName preferedObjectName = null;
   protected ObjectName[] dependsServices = null;
   protected HashMap supportedInterfaces = new HashMap ();

   protected MBeanInfo mbeanInfo = null;

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   public BeanShellScript(final URL url)
         throws DeploymentException
   {
      init(url);
   }

   BeanShellScript(String name, InputStream stream)
         throws DeploymentException
   {
      try
      {
         this.name = name;
         loadScript (stream);
      }
      catch (Exception e)
      {
         throw new DeploymentException (e);
      }
   }

   protected void init(URL url)
         throws DeploymentException
   {
      try
      {
         String name = url.toString();
         if (name.endsWith("/"))
         {
            name = name.substring(0, name.length() - 1);
         }
         this.name = name;

         loadScript (url);
      }
      catch (Exception e)
      {
         throw new DeploymentException (e);
      }
   }

   // Public --------------------------------------------------------

   // Z implementation ----------------------------------------------

   // ServiceDynamicMBeanSupport overrides --------------------------

   protected Object getInternalAttribute(String attribute)
      throws AttributeNotFoundException, MBeanException, ReflectionException
   {
      try
      {
         String action = "get" + attribute.substring(0, 1).toUpperCase() + attribute.substring(1);

         InvocationCouple invoc = retrieveCompatibleInvocation
            (action, new Class[0]);
         if (invoc == null)
            throw new AttributeNotFoundException (attribute + " getter not implemented on target script");

         return invoc.method.invoke(invoc.proxy, null);

      }
      catch (ClassNotFoundException cnfe)
      {
         throw new javax.management.ReflectionException (cnfe, "A signature class couldn't be loaded");
      }
      catch (IllegalAccessException iae)
      {
         throw new javax.management.ReflectionException (iae, "Problem while invoking gettter for field " + attribute);
      }
      catch (InvocationTargetException ite)
      {
         throw new MBeanException (ite, "Problem while invoking gettter for field " + attribute);
      }
  }

   protected void setInternalAttribute(Attribute attribute)
      throws
         AttributeNotFoundException,
         InvalidAttributeValueException,
         MBeanException,
         ReflectionException
   {
      String field = attribute.getName();
      try
      {
         String action = "set" + field.substring(0, 1).toUpperCase() + field.substring(1);
         Object value = attribute.getValue();
         Class clazz = value.getClass();
         Class tmp = Classes.getPrimitive(clazz);
         if (tmp != null)
            clazz = tmp;

         InvocationCouple invoc = retrieveCompatibleInvocation
            (action, new Class[] {clazz});
         if (invoc == null)
            throw new AttributeNotFoundException (field + " setter not implemented on target script");

         invoc.method.invoke(invoc.proxy, new Object[] {value});

      }
      catch (ClassNotFoundException cnfe)
      {
         throw new javax.management.ReflectionException (cnfe, "A signature class couldn't be loaded");
      }
      catch (IllegalAccessException iae)
      {
         throw new javax.management.ReflectionException (iae, "Problem while invoking setter for field " + field);
      }
      catch (InvocationTargetException ite)
      {
         throw new MBeanException (ite, "Problem while invoking setter for field " + field);
      }
   }

   protected Object internalInvoke(String actionName, Object[] params, String[] signature)
      throws MBeanException, ReflectionException
   {
      try
      {
         InvocationCouple invoc = retrieveCompatibleInvocation (actionName, signature);
         if (invoc == null)
            throw new javax.management.ReflectionException (new Exception(), actionName + " not implemented on target script");

         Object value = invoc.method.invoke(invoc.proxy, params);
         return value;

      }
      catch (ClassNotFoundException cnfe)
      {
         throw new javax.management.ReflectionException (cnfe, "A signature class couldn't be loaded");
      }
      catch (IllegalAccessException iae)
      {
         throw new javax.management.ReflectionException (iae, "Problem while invoking " + actionName);
      }
      catch (InvocationTargetException ite)
      {
         throw new MBeanException (ite, "Problem while invoking " + actionName);
      }
   }

   public MBeanInfo getMBeanInfo()
   {
      return this.mbeanInfo;
   }

   // ServiceMBeanSupport overrides ---------------------------------------------------

   protected void createService() throws Exception
   {
      try
      {
         this.scriptService.setCtx(this);
      }
      catch (Exception e)
      {
         log.trace("setCtx", e);
      }

      try
      {
         this.scriptService.create();
      }
      catch (EvalError e)
      {
         log.trace("start", e);
      }
   }

   protected void startService() throws Exception
   {
      try
      {
         this.scriptService.start();
      }
      catch (EvalError e)
      {
         log.trace("start", e);
      }
   }

   protected void stopService() throws Exception
   {
      try
      {
         this.scriptService.stop();
      }
      catch (Exception e)
      {
         log.trace("stop", e);
      }
   }

   protected void destroyService() throws Exception
   {
      try
      {
         this.scriptService.destroy();
      }
      catch (Exception e)
      {
         log.trace("destroy", e);
      }
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   protected InvocationCouple retrieveCompatibleInvocation
      (String name, String[] signature)
      throws ClassNotFoundException
   {
      ClassLoader ucl = Thread.currentThread().getContextClassLoader();
      // first transform signature
      //
      Class[] realSignature = null;
      if (signature != null)
      {
         realSignature = new Class[signature.length];
         for (int i=0; i<signature.length;i++)
            realSignature[i] = ucl.loadClass(signature[i]);
      }

      return retrieveCompatibleInvocation (name, realSignature);
   }

   protected InvocationCouple retrieveCompatibleInvocation
      (String name, Class[] signature)
      throws ClassNotFoundException
   {
      Iterator keys = supportedInterfaces.keySet().iterator();
      while (keys.hasNext())
      {
         Class key = (Class)keys.next();
         try
         {
            Method method = key.getMethod(name, signature);

            Object targetProxy = supportedInterfaces.get(key);
            return new InvocationCouple (targetProxy, method);
         }
         catch (NoSuchMethodException ok) {}
      }

      // if we arrive here it means that this operation does not exist!
      //
      return null;


   }

   protected void loadScript (java.net.URL url) throws Exception
   {
      InputStream stream = url.openStream();
      try
      {
         loadScript(stream);
      }
      finally
      {
         try
         {
            stream.close();
         }
         catch (IOException e)
         {
            log.info(e);
         }
      }
   }

   /**
    * Load script.
    * Stream should/must be closed/handled
    * by the client invoking this method.
    *
    * @param stream the stream
    * @throws Exception for any error
    */
   protected void loadScript (InputStream stream) throws Exception
   {
      Interpreter interpreter = new Interpreter ();
      interpreter.setClassLoader(Thread.currentThread().getContextClassLoader());
      interpreter.eval (new java.io.InputStreamReader (stream));

      scriptService = (ScriptService)interpreter.getInterface(ScriptService.class);

      // We now load the script preferences
      //
      String[] depends = null;
      try
      {
         depends = scriptService.dependsOn();
      }
      catch (Exception e)
      {
         log.trace("dependsOn", e);
      }
      if (depends != null)
      {
         dependsServices = new ObjectName[depends.length];
         for (int i=0; i<depends.length; i++)
            dependsServices[i] = new ObjectName (depends[i]);
      }

      String myName = null;
      try
      {
         myName = scriptService.objectName ();
      }
      catch (Exception e)
      {
         log.trace("objectName", e);
      }
      if (myName != null)
         this.preferedObjectName = new ObjectName (myName);

      Class[] intfs = null;
      try
      {
         intfs = scriptService.getInterfaces ();
         if (intfs != null)
            log.debug("getInterfaces=" + Arrays.asList(intfs));
      }
      catch (Exception e)
      {
         log.trace("getInterfaces", e);
      }
      if (intfs != null)
      {
         for (int i=0; i<intfs.length; i++)
         {
            Object iface = interpreter.getInterface(intfs[i]);
            supportedInterfaces.put (intfs[i], iface);
         }
      }

      this.mbeanInfo = generateMBeanInfo (intfs);
      log.debug("mbeanInfo=" + mbeanInfo);

   }

   protected MBeanInfo generateMBeanInfo (Class[] intfs)
      throws IntrospectionException
   {
      MBeanInfo result = super.getMBeanInfo();

      if (intfs != null && intfs.length > 0)
      {
         ArrayList attrs = new ArrayList (Arrays.asList(result.getAttributes()));
         ArrayList ops = new ArrayList (Arrays.asList(result.getOperations()));

         HashMap readAttr = new HashMap ();
         HashMap writeAttr = new HashMap ();

         //  we now populate the MBeanInfo with information from our script
         //
         for (int i=0; i<intfs.length; i++)
         {
            Class clazz = intfs[i];
            Method[] methods = clazz.getMethods();
            for (int m=0; m<methods.length; m++)
            {
               Method meth = methods[m];
               String name = meth.getName();
               Class[] params = meth.getParameterTypes();

               if (name.startsWith("get") && params.length == 0)
               {
                  readAttr.put (name, meth);
               }
               else if (name.startsWith("set") && params.length == 1)
               {
                  writeAttr.put (name, meth);
               }
               else
               {
                  ops.add(new MBeanOperationInfo
                     (
                     "Method " + name + " from class/interface " + clazz.getName(), meth
                     )
                  );

               }
            }
         }

         // we now combine the getters and setters in single RW attributes
         //
         Iterator readKeys = readAttr.keySet().iterator();
         while (readKeys.hasNext())
         {
            String getter = (String)readKeys.next();
            Method getterMethod = (Method)readAttr.get( getter );

            String attribute = getter.substring(3);
            String setter = "set" + attribute;

            Method setterMethod = (Method)writeAttr.remove(setter);
            attrs.add (new MBeanAttributeInfo (attribute, "", getterMethod, setterMethod));
         }

         // we  add the remaining WO attributes
         //
         Iterator writeKeys = writeAttr.keySet().iterator();
         while (writeKeys.hasNext())
         {
            String setter = (String)writeKeys.next();
            Method setterMethod = (Method)writeAttr.get( setter );
            String attribute = setter.substring(3);

            attrs.add (new MBeanAttributeInfo (attribute, "", null, setterMethod));
         }


         result = new MBeanInfo(this.name,
                           "Dynamic MBean Service around BSH script " + this.name,
                           (MBeanAttributeInfo[])attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
                           result.getConstructors(),
                           (MBeanOperationInfo[])ops.toArray(new MBeanOperationInfo[ops.size()]),
                           result.getNotifications());
      }

      return result;
   }

   public ObjectName getPreferedObjectName ()
   {
      return this.preferedObjectName;
   }

   public ObjectName[] getDependsServices ()
   {
      return this.dependsServices;
   }

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

   public class InvocationCouple
   {
      public Object proxy = null;
      public Method method = null;

      public InvocationCouple (Object proxy, Method m)
      {
         this.proxy = proxy;
         this.method = m;
      }

   }
}
TOP

Related Classes of org.jboss.varia.deployment.BeanShellScript

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.