User: juhalindfors
  Date: 01/12/05 06:24:55

  Modified:    src/main/org/jboss/mx/server MBeanServerImpl.java
  Added:       src/main/org/jboss/mx/server
                        ObjectInputStreamWithClassLoader.java
                        StandardMBean.java
  Log:
  more server stuff
  
  Revision  Changes    Path
  1.2       +293 -55   jmx/src/main/org/jboss/mx/server/MBeanServerImpl.java
  
  Index: MBeanServerImpl.java
  ===================================================================
  RCS file: /cvsroot/jboss/jmx/src/main/org/jboss/mx/server/MBeanServerImpl.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MBeanServerImpl.java      2001/12/03 02:20:55     1.1
  +++ MBeanServerImpl.java      2001/12/05 14:24:55     1.2
  @@ -12,8 +12,14 @@
   import javax.management.Attribute;
   import javax.management.AttributeList;
   import javax.management.MBeanServer;
  +import javax.management.MBeanServerDelegate;
  +import javax.management.MBeanRegistration;
  +import javax.management.MBeanServerNotification;
  +import javax.management.NotificationBroadcaster;
   import javax.management.NotificationListener;
   import javax.management.NotificationFilter;
  +import javax.management.MalformedObjectNameException;
  +import javax.management.NotCompliantMBeanException;
   import javax.management.InstanceAlreadyExistsException;
   import javax.management.NotCompliantMBeanException;
   import javax.management.MBeanRegistrationException;
  @@ -23,6 +29,7 @@
   import javax.management.InvalidAttributeValueException;
   import javax.management.ListenerNotFoundException;
   import javax.management.RuntimeErrorException;
  +import javax.management.RuntimeOperationsException;
   import javax.management.QueryExp;
   import javax.management.MBeanInfo;
   import javax.management.DynamicMBean;
  @@ -30,7 +37,10 @@
   
   import java.lang.reflect.Constructor;
   import java.lang.reflect.InvocationTargetException;
  +
   import java.io.ObjectInputStream;
  +import java.io.ByteArrayInputStream;
  +import java.io.IOException;
   
   import org.jboss.mx.server.registry.BasicMBeanRegistry;
   import org.jboss.mx.server.registry.MBeanRegistry;
  @@ -38,12 +48,37 @@
   
   public class MBeanServerImpl implements MBeanServer {
   
  +   
  +   public final static String MBEAN_SERVER_DELEGATE = 
"JMImplementation:type=MBeanServerDelegate";
  +   
  +   protected static long registrationNotificationSequence = 1;
  +   protected static long unregistrationNotificationSequence = 1;
  +   
      protected String defaultDomain = "DefaultDomain";
      protected MBeanRegistry registry    = null;
  +   protected MBeanServerDelegate delegate = null;
      
      public MBeanServerImpl(String defaultDomain) {
  +      
         this.defaultDomain = defaultDomain;
         this.registry = new BasicMBeanRegistry();
  +      this.delegate = new MBeanServerDelegate();
  +      
  +      try {
  +         registerMBean(delegate, new ObjectName(MBEAN_SERVER_DELEGATE));
  +      }
  +      catch (MalformedObjectNameException e) {
  +         throw new Error("Cannot create MBean Server Delegate.");
  +      }
  +      catch (InstanceAlreadyExistsException e) {
  +         throw new Error("Cannot register the MBean Server Delegate.");
  +      }
  +      catch (MBeanRegistrationException e) {
  +         throw new Error("Exception registering the the MBean Server Delegate: " + 
e.getTargetException().toString());
  +      }
  +      catch (NotCompliantMBeanException e) {
  +         throw new Error("MBean Server Delegate is not a compliant MBean");
  +      }
      }
   
   
  @@ -51,8 +86,7 @@
         try {
            Class clazz = DefaultLoaderRepository.loadClass(className);
            return clazz.newInstance();
  -      }
  -      catch (ClassNotFoundException e) {
  +      } catch (ClassNotFoundException e) {
            throw new ReflectionException(e, "Class not found: " + className);
         }
         catch (InstantiationException e) {
  @@ -63,30 +97,47 @@
         }
      }
   
  -   public Object instantiate(String className, ObjectName loaderName) 
  +   public Object instantiate(String className, ObjectName loaderName)
      throws ReflectionException, MBeanException, InstanceNotFoundException {
  -      return null;
  +      try {
  +         ClassLoader loader = (ClassLoader)registry.get(loaderName).getInstance();
  +
  +         if (loader == null)
  +            loader = this.getClass().getClassLoader();
  +
  +         Class clazz = loader.loadClass(className);
  +         return clazz.newInstance();
  +      } catch (ClassCastException e) {
  +         throw new ReflectionException(e, loaderName + " is not a class loader.");
  +      }
  +      catch (ClassNotFoundException e) {
  +         throw new ReflectionException(e, "Class not found: " + className);
  +      }
  +      catch (InstantiationException e) {
  +         throw new ReflectionException(e, "Caanot instantiate with not-args 
constructor: " + className);
  +      }
  +      catch (IllegalAccessException e) {
  +         throw new ReflectionException(e, "Illegal access to default constructor: " 
+ className);
  +      }
      }
   
  -   public Object instantiate(String className, Object[] params, String[] signature) 
  +   public Object instantiate(String className, Object[] params, String[] signature)
      throws ReflectionException, MBeanException {
         try {
            Class clazz = DefaultLoaderRepository.loadClass(className);
  -         
  +
            Class[] sign = new Class[signature.length];
  -         for (int i = 0; i < signature.length; ++i) { 
  +         for (int i = 0; i < signature.length; ++i) {
               try {
                  sign[i] = DefaultLoaderRepository.loadClass(signature[i]);
  -            }
  -            catch (ClassNotFoundException e) {
  +            } catch (ClassNotFoundException e) {
                  throw new ReflectionException(e, "Constructor parameter class not 
found: " + signature[i]);
               }
            }
  -         
  +
            Constructor constructor = clazz.getConstructor(sign);
            return constructor.newInstance(params);
  -      }
  -      catch (ClassNotFoundException e) {
  +      } catch (ClassNotFoundException e) {
            throw new ReflectionException(e, "Class not found: " + className);
         }
         catch (InstantiationException e) {
  @@ -102,18 +153,55 @@
            Throwable t = e.getTargetException();
            if (t instanceof Exception)
               throw new MBeanException((Exception)t, "Constructor has thrown an 
exception: " + t.getMessage());
  -         else 
  -            throw new RuntimeErrorException((Error)t, "Error thrown from the 
specified constructor: " + t.getMessage()); 
  +         else
  +            throw new RuntimeErrorException((Error)t, "Error thrown from the 
specified constructor: " + t.getMessage());
         }
      }
   
   
  -   public java.lang.Object instantiate(String className, ObjectName loaderName, 
Object[] params, String[] signature)
  +   public Object instantiate(String className, ObjectName loaderName, Object[] 
params, String[] signature)
      throws ReflectionException, MBeanException, InstanceNotFoundException {
  -      return null;
  +      try {
  +         ClassLoader cl = (ClassLoader)registry.get(loaderName).getInstance();
  +
  +         if (cl == null)
  +            cl = this.getClass().getClassLoader();
  +
  +         Class clazz = cl.loadClass(className);
  +
  +         Class[] sign = new Class[signature.length];
  +         for (int i = 0; i < signature.length; ++i) {
  +            try {
  +               sign[i] = cl.loadClass(signature[i]);
  +            } catch (ClassNotFoundException e) {
  +               // FIXME: should we delegate to DLR before throwing the exception?
  +               throw new ReflectionException(e, "Constructor parameter class not 
found: " + signature[i]);
  +            }
  +         }
  +         Constructor constructor = clazz.getConstructor(sign);
  +         return constructor.newInstance(params);
  +      } catch (ClassNotFoundException e) {
  +         throw new ReflectionException(e, "Class not found: " + className);
  +      }
  +      catch (InstantiationException e) {
  +         throw new ReflectionException(e, "Cannot instantiate with specified 
constructor: " + className);
  +      }
  +      catch (IllegalAccessException e) {
  +         throw new ReflectionException(e, "Illegal access to specified constructor: 
" + className);
  +      }
  +      catch (NoSuchMethodException e) {
  +         throw new ReflectionException(e, "Specified constructor not found for 
class " + className);
  +      }
  +      catch (InvocationTargetException e) {
  +         Throwable t = e.getTargetException();
  +         if (t instanceof Exception)
  +            throw new MBeanException((Exception)t, "Constructor has thrown an 
exception: " + t.getMessage());
  +         else
  +            throw new RuntimeErrorException((Error)t, "Error thrown from the 
specified constructor: " + t.getMessage());
  +      }
      }
   
  -   public ObjectInstance createMBean(String className, ObjectName name) 
  +   public ObjectInstance createMBean(String className, ObjectName name)
      throws ReflectionException, InstanceAlreadyExistsException, 
MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
         Object mbean = instantiate(className);
         registerMBean(mbean, name);
  @@ -136,39 +224,111 @@
   
      public ObjectInstance createMBean(String className, ObjectName name, ObjectName 
loaderName, Object[] params, String[] signature)
      throws ReflectionException, InstanceAlreadyExistsException, 
MBeanRegistrationException, MBeanException, NotCompliantMBeanException, 
InstanceNotFoundException {
  -      return null;
  +      Object mbean = instantiate(className, loaderName, params, signature);
  +      registerMBean(mbean, name);
  +      return new ObjectInstance(name, className);
      }
   
   
      public ObjectInstance registerMBean(Object object, ObjectName name)
      throws InstanceAlreadyExistsException, MBeanRegistrationException, 
NotCompliantMBeanException {
  +      
         if (isRegistered(name))
            throw new InstanceAlreadyExistsException("MBean " + name + " already 
registered.");
  -         
  +
  +      MBeanRegistration registrationInterface = null;
         MBeanEntry entry = null;
  +      boolean registrationDone = true;
         
  -      if (isStandardMBean(object))
  -         throw new Error("StandardMBean NYI");
  -         
  -      else if (DynamicMBean.class.isAssignableFrom(object.getClass())) {
  -         entry = new MBeanEntry(name, object);
  +      if (object instanceof MBeanRegistration) {
  +         MBeanRegistration reg = (MBeanRegistration)object;
  +         try {
  +            ObjectName mbeanName = reg.preRegister(this, name);
  +            if (name == null)
  +               name = mbeanName;
  +         }
  +         catch (Throwable t) {
  +            registrationDone = false;      
  +         }
  +      }
  +            
  +      if (name == null)
  +         throw new RuntimeOperationsException(new NullPointerException("null object 
name"));
  +   
  +      if (registrationDone) {
  +         if (getMBeanType(object) == STANDARD_MBEAN) {
  +            try {
  +               entry = new MBeanEntry(name, new StandardMBean(object));
  +            }
  +            catch (ReflectionException e) {
  +               throw new MBeanRegistrationException(e.getTargetException(), 
"Registration of MBean '" + name + "' failed: " + e.getTargetException().toString());
  +            }
  +         }
  +         else if (object instanceof DynamicMBean) 
  +            entry = new MBeanEntry(name, object);
  +         else
  +            throw new NotCompliantMBeanException(object + " is not compliant MBean 
(does not implement Standard or Dynamic MBean interface).");
  +
            registry.add(entry);
  +            
  +         delegate.sendNotification(
  +            new MBeanServerNotification(
  +                  MBeanServerNotification.REGISTRATION_NOTIFICATION,
  +                  delegate,
  +                  registrationNotificationSequence++,
  +                  name
  +            )
  +         );
         }
  -      else
  -         throw new NotCompliantMBeanException(object + " is not compliant MBean.");
  +      
  +      
  +      if (registrationInterface != null)
  +         registrationInterface.postRegister(new Boolean(registrationDone));
  +         
            
  -      return new ObjectInstance(name, entry.getClassName());
  +      return (registrationDone) ? new ObjectInstance(name, entry.getClassName())
  +                                : null;
      }
   
      public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, 
MBeanRegistrationException {
  +      Object mbean = registry.get(name).getInstance();
  +      MBeanRegistration registrationInterface = null;
  +      boolean unregisterSuccessful = true;
  +      
  +      // FIXME: need to fix this for standard mbean
  +      if (mbean instanceof MBeanRegistration) {
  +         registrationInterface = (MBeanRegistration)mbean;
  +         try {
  +            registrationInterface.preDeregister();
  +         }
  +         catch (Throwable t) {
  +            return;
  +         }
  +      }
  +            
         registry.remove(name);
  -   }
  +      
  +      // FIXME: if CL, remove from class loader repository
  +      
  +      delegate.sendNotification(
  +         new MBeanServerNotification(
  +               MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
  +               delegate,
  +               unregistrationNotificationSequence++,
  +               name
  +         )
  +      );
  +      
  +      if (registrationInterface != null)
  +         registrationInterface.postDeregister();
  +   }  
   
      public ObjectInstance getObjectInstance(ObjectName name) throws 
InstanceNotFoundException {
         if (!isRegistered(name))
            throw new InstanceNotFoundException(name + " not registered.");
  -         
  -      return null;//new ObjectInstance(name, registry.get(name).getClassName());
  +
  +      // FIXME: check for std
  +      return new ObjectInstance(name, registry.get(name).getClassName());
      }
   
      public java.util.Set queryMBeans(ObjectName name, QueryExp query) {
  @@ -180,7 +340,7 @@
      }
   
      public boolean isRegistered(ObjectName name) {
  -      return registry.contains(name);  
  +      return registry.contains(name);
      }
   
      public java.lang.Integer getMBeanCount() {
  @@ -189,26 +349,26 @@
   
      public Object getAttribute(ObjectName name, String attribute)
      throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, 
ReflectionException {
  -      //DynamicMBean mbean = registry.get(name).getInvocationInterface();
  -      return null;//mbean.getAttribute(attribute);
  +      DynamicMBean mbean = registry.get(name).getInvocationInterface();
  +      return mbean.getAttribute(attribute);
      }
   
      public AttributeList getAttributes(ObjectName name, String[] attributes)
      throws InstanceNotFoundException, ReflectionException {
  -      //DynamicMBean mbean = registry.get(name).getInvocationInterface();
  -      return null;//mbean.getAttributes(attributes);
  +      DynamicMBean mbean = registry.get(name).getInvocationInterface();
  +      return mbean.getAttributes(attributes);
      }
   
      public void setAttribute(ObjectName name, Attribute attribute)
      throws InstanceNotFoundException, AttributeNotFoundException, 
InvalidAttributeValueException, MBeanException, ReflectionException {
  -      //DynamicMBean mbean = registry.get(name).getInvocationInterface();
  -      //mbean.setAttribute(attribute);
  +      DynamicMBean mbean = registry.get(name).getInvocationInterface();
  +      mbean.setAttribute(attribute);
      }
   
      public AttributeList setAttributes(ObjectName name, AttributeList attributes)
      throws InstanceNotFoundException, ReflectionException {
  -      //DynamicMBean mbean = registry.get(name).getInvocationInterface();
  -      return null;//mbean.setAttributes(attributes);
  +      DynamicMBean mbean = registry.get(name).getInvocationInterface();
  +      return mbean.setAttributes(attributes);
      }
   
      public Object invoke(ObjectName name, String operationName, Object[] params, 
String[] signature)
  @@ -221,26 +381,55 @@
         return defaultDomain;
      }
   
  -   public void addNotificationListener(ObjectName name, NotificationListener 
listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException 
{
  -      throw new Error("NYI");
  +   public void addNotificationListener(ObjectName name, NotificationListener 
listener, NotificationFilter filter, Object handback)
  +   throws InstanceNotFoundException {
  +      
  +      // FIXME: need to set source on outgoing notifications
  +      // FIXME: standard's instance
  +      try {
  +         NotificationBroadcaster broadcaster = 
(NotificationBroadcaster)registry.get(name).getInstance();
  +         broadcaster.addNotificationListener(listener, filter, handback);
  +      }
  +      catch (ClassCastException e) {
  +         throw new RuntimeOperationsException(e, "MBean " + name + " does not 
implement the NotificationBroadcaster interface.");
  +      }
      }
   
  -   public void addNotificationListener(ObjectName name, ObjectName listener, 
NotificationFilter filter, Object handback) throws InstanceNotFoundException {
  -      throw new Error("NYI");
  +   public void addNotificationListener(ObjectName name, ObjectName listener, 
NotificationFilter filter, Object handback)
  +   throws InstanceNotFoundException {
  +      try {
  +         NotificationBroadcaster broadcaster = 
(NotificationBroadcaster)registry.get(name).getInstance();
  +         
broadcaster.addNotificationListener((NotificationListener)registry.get(listener).getInstance(),
 filter, handback);
  +      }
  +      catch (ClassCastException e) {
  +         throw new RuntimeOperationsException(e, "MBean " + listener + " is not a 
notification listener or " + name + " does not implement notification broadcaster 
interface.");
  +      }
      }
   
      public void removeNotificationListener(ObjectName name, NotificationListener 
listener)
      throws InstanceNotFoundException, ListenerNotFoundException {
  -      throw new Error("NYI");
  +      try {
  +         NotificationBroadcaster broadcaster = 
(NotificationBroadcaster)registry.get(name).getInstance();
  +         broadcaster.removeNotificationListener(listener);
  +      }
  +      catch (ClassCastException e) {
  +         throw new RuntimeOperationsException(e, "MBean " + name + " does not 
implement the NotificationBroadcaster interface.");
  +      }
      }
   
      public void removeNotificationListener(ObjectName name, ObjectName listener)
      throws InstanceNotFoundException, ListenerNotFoundException {
  -      throw new Error("NYI");
  +      try {
  +         NotificationBroadcaster broadcaster = 
(NotificationBroadcaster)registry.get(name).getInstance();
  +         
broadcaster.removeNotificationListener((NotificationListener)registry.get(listener).getInstance());
  +      }
  +      catch (ClassCastException e) {
  +         throw new RuntimeOperationsException(e, e.getMessage());
  +      }
      }
   
      public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, 
IntrospectionException, ReflectionException {
  -      return null;//registry.get(name).getInvocationInterface().getMBeanInfo();
  +      return registry.get(name).getInvocationInterface().getMBeanInfo();
      }
   
      public boolean isInstanceOf(ObjectName name, java.lang.String className) throws 
InstanceNotFoundException {
  @@ -248,27 +437,76 @@
      }
   
      public ObjectInputStream deserialize(ObjectName name, byte[] data) throws 
InstanceNotFoundException, OperationsException {
  -      
  -      return null;
  +      try {
  +         ClassLoader cl = 
registry.get(name).getInstance().getClass().getClassLoader();
  +         return new ObjectInputStreamWithClassLoader(new 
ByteArrayInputStream(data), cl);
  +      }
  +      catch (IOException e) {
  +         throw new OperationsException("I/O exception deserializing: " + 
e.getMessage());
  +      }
      }
   
      public ObjectInputStream deserialize(String className, byte[] data) throws 
OperationsException, ReflectionException {
  -      return null;
  -
  +      try {
  +         Class c = DefaultLoaderRepository.loadClass(className);
  +         ClassLoader cl = c.getClassLoader();
  +         return new ObjectInputStreamWithClassLoader(new 
ByteArrayInputStream(data), cl);
  +      }
  +      catch (IOException e) {
  +         throw new OperationsException("I/O exception deserializing: " + 
e.getMessage());
  +      }
  +      catch (ClassNotFoundException e) {
  +         throw new ReflectionException(e, "Class not found from default repository: 
" + className);
  +      }
      }
   
  -
      public ObjectInputStream deserialize(String className, ObjectName loaderName, 
byte[] data)
      throws InstanceNotFoundException, OperationsException, ReflectionException {
  -      return null;
  +      try {
  +         ClassLoader cl = (ClassLoader)registry.get(loaderName).getInstance();
  +         return new ObjectInputStreamWithClassLoader(new 
ByteArrayInputStream(data), cl);
  +      }
  +      catch (IOException e) {
  +         throw new OperationsException("I/O exception deserializing: " + 
e.getMessage());
  +      }
      }
   
   
  -   
  -   protected boolean isStandardMBean(Object object) {
  +   protected int getMBeanType(Object object) {
  +
  +      Class clazz = object.getClass();
  +      int type = NOT_AN_MBEAN;
         
  -      return false;
  +      while (clazz != null) {
  +         Class[] interfaces = clazz.getInterfaces();
  +         
  +         for (int i = 0; i < interfaces.length; ++i) {
  +            type = getMBeanInterface(clazz.getName(), interfaces[i]);
  +            if (type != NOT_AN_MBEAN) return type;
  +            
  +            Class[] superInterfaces = interfaces[i].getInterfaces();
  +            for (int j = 0; j < interfaces.length; ++j) {
  +               type = getMBeanInterface(clazz.getName(), superInterfaces[j]);
  +               if (type != NOT_AN_MBEAN) return type;
  +            }
  +         }
  +         clazz = clazz.getSuperclass();  
  +      }
  +      
  +      return type;
      }
      
  +   private static int DYNAMIC_MBEAN  = 0x321;
  +   private static int STANDARD_MBEAN = 0x123;
  +   private static int NOT_AN_MBEAN   = 0xc0de;
  +   
  +   private int getMBeanInterface(String className, Class c) {
  +      if (c.getName().equals("javax.management.DynamicMBean"))
  +         return DYNAMIC_MBEAN;
  +      if (c.getName().equals(className + "MBean"))
  +         return STANDARD_MBEAN;
  +      return NOT_AN_MBEAN;
  +   }
  +
   }
   
  
  
  
  1.1                  
jmx/src/main/org/jboss/mx/server/ObjectInputStreamWithClassLoader.java
  
  Index: ObjectInputStreamWithClassLoader.java
  ===================================================================
  /*
   * LGPL
   */
  package org.jboss.mx.server;
  
  
  import java.io.InputStream;
  import java.io.ObjectInputStream;
  import java.io.ObjectStreamClass;
  import java.io.IOException;
  
  import java.lang.reflect.Proxy;
  
  /**
   * This replaces the EjbossInputStream in the storage package.
   * The input stream will take a class loader in its constructor and look
   * into it to retrieve the class definitions.
   * It is used throughout the server to deserialize parameters and objects
   * whose definition are in a jar and not the global classpath
   * It also has better comments than the previous version.
   *
   * @author  <a href="[EMAIL PROTECTED]">Rickard Oberg</a>
   * @since   Ejboss 0.9
   */
  
  
  public class ObjectInputStreamWithClassLoader
      extends ObjectInputStream {
  
      /**
      * The classloader to use when the default classloader cannot find
      * the classes in the stream.
      */
      ClassLoader cl;
  
      
  /******************************************************************************/
  /******************************************************************************/
  /*
  /*   CONSTRUCTORS
  /*
  /******************************************************************************/
  /******************************************************************************/
  
      /**
      * Construct a new instance with the given classloader and input stream.
      *
      * @param  ClassLoader      classloader to use
      * @param  InputStream      stream to read objects from
      */
      public ObjectInputStreamWithClassLoader(InputStream in, ClassLoader cl)
           throws IOException {
  
           super(in);
  
           this.cl = cl;
      }
  
  
  /******************************************************************************/
  /******************************************************************************/
  /*
  /*   OVERWRITING  <ObjectInputStream>
  /*
  /******************************************************************************/
  /******************************************************************************/
  
      /**
      * Resolve the class described in the osc parameter. First, try the
      * default classloader (implemented by the super class). If it cannot
      * load the class, try the classloader given to this instance.
      *
      * @param  ObjectStreamClass     class description object
      * @return      the Class corresponding to class description
      * @exception   IOException     if an I/O error occurs
      * @exception   ClassNotFoundException  if the class cannot be found by the 
classloader
      */
      protected Class resolveClass(ObjectStreamClass osc)
          throws IOException, ClassNotFoundException {
  
          return cl.loadClass(osc.getName());
      }
      
      protected Class resolveProxyClass( String[] interfaces )
                throws IOException, ClassNotFoundException {
                
                Class[] interfacesClass = new Class[interfaces.length];
                for( int i=0; i< interfaces.length; i++ )
                {
                        interfacesClass[i] = Class.forName(interfaces[i], false, cl);
                }
                
        return Proxy.getProxyClass(cl, interfacesClass);
      }
  }
  
  
  
  
  
  
  
  1.1                  jmx/src/main/org/jboss/mx/server/StandardMBean.java
  
  Index: StandardMBean.java
  ===================================================================
  /*
   * LGPL
   */
  package org.jboss.mx.server;
  
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Iterator;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationTargetException;
  
  import javax.management.DynamicMBean;
  import javax.management.Attribute;
  import javax.management.AttributeList;
  import javax.management.MBeanInfo;
  import javax.management.MBeanOperationInfo;
  import javax.management.MBeanParameterInfo;
  import javax.management.JMException;
  import javax.management.NotCompliantMBeanException;
  import javax.management.ReflectionException;
  import javax.management.RuntimeErrorException;
  import javax.management.MBeanException;
  import javax.management.AttributeNotFoundException;
  import javax.management.InvalidAttributeValueException;
  import javax.management.loading.DefaultLoaderRepository;
  
  import org.jboss.mx.metadata.StandardMetaData;
  
  public class StandardMBean implements DynamicMBean {
     
     public static Class getMBeanInterface(Object resource) {
  
        Class clazz = resource.getClass();
        
        while (clazz != null) {
           Class[] interfaces = clazz.getInterfaces();
           
           for (int i = 0; i < interfaces.length; ++i) {
              
              if (interfaces[i].getName().equals(clazz.getName() + "MBean"))
                 return interfaces[i];
              
              Class[] superInterfaces = interfaces[i].getInterfaces();
              for (int j = 0; j < superInterfaces.length; ++j) {
                 if (superInterfaces[j].getName().equals(clazz.getName() + "MBean"))
                    return superInterfaces[j];
              }
           }
           clazz = clazz.getSuperclass();  
        }
        
        return null;
     }
  
     public static Class[] getSignatureAsClassArray(MBeanParameterInfo[] signature, 
ClassLoader cl) throws ClassNotFoundException {
     
        Class[] sign = new Class[signature.length];
        for (int i = 0; i < signature.length; ++i) {
           try {
              String type = signature[i].getType();
              if (isPrimitive(type))
                 sign[i] = getPrimitive(type);
              else 
                 sign[i] = cl.loadClass(signature[i].getName());
           }
           catch (ClassNotFoundException e) {
              // if the explicit CL fails, go to the repository... allow CNFE to be 
thrown
              DefaultLoaderRepository.loadClass(signature[i].getName());
           }
        }
  
        return sign;            
     }
     
     public static boolean isPrimitive(String type) {
        if (int.class.getName().equals(type))           return true;
        else if (float.class.getName().equals(type))    return true;
        else if (double.class.getName().equals(type))   return true;
        else if (long.class.getName().equals(type))     return true;
        else if (byte.class.getName().equals(type))     return true;
        else if (boolean.class.getName().equals(type))  return true;
        else if (char.class.getName().equals(type))     return true;      
        else if (void.class.getName().equals(type))     return true; 
        else if (short.class.getName().equals(type))    return true;
        return false;
     }
     
     public static Class getPrimitive(String type) {
        if (int.class.getName().equals(type))           return Integer.TYPE;
        else if (float.class.getName().equals(type))    return Float.TYPE;
        else if (double.class.getName().equals(type))   return Double.TYPE;
        else if (long.class.getName().equals(type))     return Long.TYPE;
        else if (byte.class.getName().equals(type))     return Byte.TYPE;
        else if (boolean.class.getName().equals(type))  return Boolean.TYPE;
        else if (char.class.getName().equals(type))     return Character.TYPE;      
        else if (void.class.getName().equals(type))     return Void.TYPE; 
        else if (short.class.getName().equals(type))    return Short.TYPE;
        return null;
     }
        
     
     
     private MBeanInfo info = null;
     private Object resource = null;
     private Class invocationInterface = null;
     private Map operationMap = new HashMap();
     private Map attributeMap = new HashMap();
     
     public StandardMBean(Object resource) throws NotCompliantMBeanException, 
ReflectionException {
        
        this.resource = resource;
        this.info = new StandardMetaData(resource).build();
        this.invocationInterface = StandardMBean.getMBeanInterface(resource);   
  
        MBeanOperationInfo[] operations = info.getOperations();
        for (int i = 0; i < operations.length; ++i) {
           try {
              // FIXME: name is not enough for overloaded operations!
              operationMap.put(operations[i].getName(), invocationInterface.getMethod(
                    operations[i].getName(),
                    getSignatureAsClassArray(operations[i].getSignature(), 
resource.getClass().getClassLoader())
              ));
           }
           catch (ClassNotFoundException e) {
              throw new ReflectionException(e, "Unable to load operation " + 
operations[i].getName() + " parameter types: " + e.getMessage());
           }
           catch (NoSuchMethodException e) {
              throw new ReflectionException(e);
           }
        }      
     }
  
     
     public Object invoke(String operationName, Object[] args, String[] signature) 
throws MBeanException, ReflectionException {
        
        // FIXME: Interceptors
        
        try {
           Method m = (Method)operationMap.get(operationName);
           return m.invoke(resource, args);
        }
        catch (IllegalAccessException e) {
           throw new ReflectionException(e, "Illegal access to method " + 
operationName);
        }
        catch (IllegalArgumentException e) {
           throw new ReflectionException(e, "Illegal operation arguments in " + 
operationName + ": " + e.getMessage());
        }
        catch (InvocationTargetException e) {
           if (e.getTargetException() instanceof Exception) {
              Exception e2 = (Exception)e.getTargetException();
              throw new MBeanException(e2, "Operation " + operationName + " on MBean " 
+ info.getClassName() + " has thrown an exception: " + e2.toString());
           }
           else  {
              Error err = (Error)e.getTargetException();
              throw new RuntimeErrorException(err, "Operation " + operationName + " on 
MBean " + info.getClassName() + " has thrown an errpr: " + err.toString());
           }
        }
        catch (NullPointerException e) {
           throw new ReflectionException(e, "Operation " + operationName + " is not a 
declared management operation in " + invocationInterface + " interface.");
        }
     }
     
     public Object getAttribute(java.lang.String attribute) 
     throws AttributeNotFoundException, MBeanException, ReflectionException {
        throw new Error("NYI");
        // FIXME: deal with runtime exceptions and errors from the resource
     }
  
     public void setAttribute(Attribute attribute)
     throws AttributeNotFoundException, InvalidAttributeValueException, 
MBeanException, ReflectionException {
        throw new Error("NYI");
        // FIXME: deal with runtime exceptions and errors from the resource
     }
  
     public AttributeList getAttributes(java.lang.String[] attributes) {
      
        if (attributes == null)
           throw new IllegalArgumentException("null array");
        
        AttributeList list = new AttributeList();
      
        for (int i = 0; i < attributes.length; ++i) {
           try {
             list.add(new Attribute(attributes[i], getAttribute(attributes[i])));
           }
           catch (JMException ignored) {
              // if the attribute could not be retrieved, skip it            
           }
         }
      
        return list;
     }
     
     public AttributeList setAttributes(AttributeList attributes) {
        
        if (attributes == null)
           throw new IllegalArgumentException("null list");
        
        AttributeList results = new AttributeList();
        Iterator it           = attributes.iterator();
      
        while (it.hasNext()) {
           try {
              Attribute attr = (Attribute)it.next();
              setAttribute(attr);
              results.add(attr);
           }
           catch (JMException ignored) {
              // if unable to set the attribute, skip it
           }
        }    
      
        return results;
     }
     
     public MBeanInfo getMBeanInfo() {
        return info;
     }
  
  }
  
  
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to