User: ejort   
  Date: 02/04/14 08:28:07

  Modified:    src/main/org/jboss/mx/server MBeanServerImpl.java
                        ServerConstants.java
  Added:       src/main/org/jboss/mx/server NotificationListenerProxy.java
  Log:
  POJO Registry and correct Notification source from the MBeanServer
  
  Revision  Changes    Path
  1.22      +251 -18   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.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- MBeanServerImpl.java      9 Apr 2002 00:08:32 -0000       1.21
  +++ MBeanServerImpl.java      14 Apr 2002 15:28:07 -0000      1.22
  @@ -51,9 +51,13 @@
   import java.io.ObjectInputStream;
   import java.lang.reflect.Constructor;
   import java.lang.reflect.InvocationTargetException;
  +import java.util.Arrays;
  +import java.util.Collections;
  +import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
   import java.util.List;
  +import java.util.Map;
   import java.util.Set;
   
   /**
  @@ -91,7 +95,7 @@
    * @author  <a href="mailto:[EMAIL PROTECTED]";>Juha Lindfors</a>.
    * @author  <a href="mailto:[EMAIL PROTECTED]";>Trevor Squires</a>.
    * @author  <a href="mailto:[EMAIL PROTECTED]";>Adrian Brock</a>.
  - * @version $Revision: 1.21 $
  + * @version $Revision: 1.22 $
    */
   public class MBeanServerImpl
      implements MBeanServer, ServerConstants
  @@ -116,10 +120,16 @@
      protected MBeanRegistry registry                   = null;
   
      /**
  -    * Registry proxy, used for dynamic invocations on register/unregister
  +    * Registry MBean, used for dynamic invocations on register/unregister
       */
  -   protected MBeanRegistry registryProxy              = null;
  -   
  +   protected ObjectName registryName                  = null;
  +
  +   /**
  +    * The notification listener proxies. It is a map of object names
  +    * to another map of listeners to another map of handback objects to
  +    * proxies. Phew!
  +    */
  +   private Map listenerProxies = Collections.synchronizedMap(new HashMap());
   
      // Static --------------------------------------------------------
   
  @@ -172,16 +182,22 @@
            throw new RuntimeException("Unable to create the MBean registry instance. 
Class " + registryClass + " has raised an exception in constructor: " + 
e.getTargetException().toString());
         }
   
  -      // Get a proxy for dynamic invocation on the proxy
  +      /**
  +       * Check for a mbean version of the registry
  +       */
         try
         {
  -         ObjectName name = new ObjectName(MBEAN_REGISTRY);
  -         registryProxy = (MBeanRegistry) MBeanProxy.get(MBeanRegistry.class,
  -                                                        name, this);
  +          registryName = new ObjectName(MBEAN_REGISTRY);
  +          registry.get(registryName);
  +      }
  +      catch (MalformedObjectNameException e)
  +      {
  +         throw new RuntimeException("The registry name is not valid +: " + 
MBEAN_REGISTRY);
         }
  -      catch (Exception e)
  +      catch (InstanceNotFoundException e)
         {
  -         throw new Error("Error generating registry proxy: " + e.toString());
  +         // POJO Registry
  +         registryName = null;
         }
      }
   
  @@ -264,7 +280,36 @@
      public void unregisterMBean(ObjectName name)
         throws InstanceNotFoundException, MBeanRegistrationException
      {
  -      registryProxy.unregisterMBean(name);
  +      // Get the mbean to remove
  +      Object mbean = registry.get(name).getResourceInstance();
  +
  +      // Dynamic Invocation
  +      if (registryName != null)
  +      {
  +         try
  +         {
  +            invoke(registryName, "unregisterMBean",
  +                   new Object[] { name },
  +                   new String[] { ObjectName.class.getName() }
  +            );
  +         }
  +         catch (Exception e)
  +         {
  +            Exception result = handleInvocationException(registryName, e);
  +            if (result instanceof InstanceNotFoundException)
  +               throw (InstanceNotFoundException) result;
  +            if (result instanceof MBeanRegistrationException)
  +               throw (MBeanRegistrationException) result;
  +            throw new RuntimeException(result.toString());
  +         }
  +      }
  +      else
  +         // POJO Registry
  +         registry.unregisterMBean(name);
  +
  +      // Unregistration worked, remove any proxies for a broadcaster
  +      if (mbean instanceof NotificationBroadcaster)
  +         removeListenerProxies((NotificationBroadcaster) mbean, name);
      }
   
      public ObjectInstance getObjectInstance(ObjectName name)
  @@ -483,8 +528,6 @@
      public void addNotificationListener(ObjectName name, NotificationListener 
listener, NotificationFilter filter, Object handback)
      throws InstanceNotFoundException
      {
  -
  -      // FIXME: need to set source on outgoing notifications
         MBeanEntry entry = registry.get(name);
         ClassLoader newTCL = entry.getClassLoader();
         NotificationBroadcaster broadcaster = null;
  @@ -497,6 +540,9 @@
            throw new RuntimeOperationsException(e, "MBean " + name + " does not 
implement the NotificationBroadcaster interface.");
         }
   
  +      NotificationListener proxy = createListenerProxy(entry.getObjectName(),
  +                                                       listener, handback);
  +
         Thread thread = Thread.currentThread();
         ClassLoader oldTCL = thread.getContextClassLoader();
         try
  @@ -504,7 +550,7 @@
            if (newTCL != oldTCL && newTCL != null)
               thread.setContextClassLoader(newTCL);
   
  -         broadcaster.addNotificationListener(listener, filter, handback);
  +         broadcaster.addNotificationListener(proxy, filter, handback);
         }
         finally
         {
  @@ -528,6 +574,10 @@
            throw new RuntimeOperationsException(e, "MBean " + listener + " is not a 
notification listener or " + name + " does not implement notification broadcaster 
interface.");
         }
   
  +      NotificationListener proxy = createListenerProxy(entry.getObjectName(), 
  +         (NotificationListener)registry.get(listener).getResourceInstance(),
  +          handback);
  +
         Thread thread = Thread.currentThread();
         ClassLoader oldTCL = thread.getContextClassLoader();
         try
  @@ -535,7 +585,7 @@
            if (newTCL != oldTCL && newTCL != null)
               thread.setContextClassLoader(newTCL);
   
  -         
broadcaster.addNotificationListener((NotificationListener)registry.get(listener).getResourceInstance(),
 filter, handback);
  +         broadcaster.addNotificationListener(proxy, filter, handback);
         }
         finally
         {
  @@ -559,6 +609,8 @@
            throw new RuntimeOperationsException(e, "MBean " + name + " does not 
implement the NotificationBroadcaster interface.");
         }
   
  +      Iterator proxies = removeListenerProxies(entry.getObjectName(), listener);
  +
         Thread thread = Thread.currentThread();
         ClassLoader oldTCL = thread.getContextClassLoader();
         try
  @@ -566,7 +618,10 @@
            if (newTCL != oldTCL && newTCL != null)
               thread.setContextClassLoader(newTCL);
   
  -         broadcaster.removeNotificationListener(listener);
  +         // REVIEW: Try to remove all before throwing an exception?
  +         while (proxies.hasNext())
  +            broadcaster.removeNotificationListener(
  +               (NotificationListener) proxies.next());
         }
         finally
         {
  @@ -590,6 +645,9 @@
            throw new RuntimeOperationsException(e, "MBean " + name + " does not 
implement the NotificationBroadcaster interface.");
         }
   
  +      Iterator proxies = removeListenerProxies(entry.getObjectName(),
  +         (NotificationListener)registry.get(listener).getResourceInstance());
  +
         Thread thread = Thread.currentThread();
         ClassLoader oldTCL = thread.getContextClassLoader();
         try
  @@ -597,7 +655,10 @@
            if (newTCL != oldTCL && newTCL != null)
               thread.setContextClassLoader(newTCL);
   
  -         
broadcaster.removeNotificationListener((NotificationListener)registry.get(listener).getResourceInstance());
  +         // REVIEW: Try to remove all before throwing an exception?
  +         while (proxies.hasNext())
  +            broadcaster.removeNotificationListener(
  +               (NotificationListener) proxies.next());
         }
         finally
         {
  @@ -859,10 +920,182 @@
                MBeanRegistrationException, 
                NotCompliantMBeanException
      {
  -       return registryProxy.registerMBean(object, name, cl, null);
  +      // Dynamic Invocation
  +      if (registryName != null)
  +      {
  +         try
  +         {
  +            return (ObjectInstance) invoke(registryName, "registerMBean",
  +                    new Object[] { object, name, cl, null },
  +                    new String[] { Object.class.getName(),
  +                                   ObjectName.class.getName(),
  +                                   ClassLoader.class.getName(),
  +                                   Object.class.getName() }
  +            );
  +         }
  +         catch (Exception e)
  +         {
  +            Exception result = handleInvocationException(registryName, e);
  +            if (result instanceof InstanceAlreadyExistsException)
  +               throw (InstanceAlreadyExistsException) result;
  +            if (result instanceof MBeanRegistrationException)
  +               throw (MBeanRegistrationException) result;
  +            if (result instanceof NotCompliantMBeanException)
  +               throw (NotCompliantMBeanException) result;
  +            throw new RuntimeException(result.toString());
  +         }
  +      }
  +      else
  +         // POJO Registry
  +         return registry.registerMBean(object, name, cl, null);
  +   }
  +
  +   /**
  +    * Add a notification listener proxy
  +    *
  +    * @param name the broadcaster's object name
  +    * @param listener the original listener
  +    * @return a proxy notification listener
  +    * @exception IllegalArgumentException for a null listener
  +    */
  +   protected NotificationListener createListenerProxy(ObjectName name, 
  +                            NotificationListener listener, Object handback)
  +   {
  +      // Sanity check
  +      if (listener == null)
  +         throw new IllegalArgumentException("Null listener");
  +
  +      NotificationListener result = null;
  +
  +      // Retrieve any previous listener or construct the data structure
  +      HashMap listeners = (HashMap) listenerProxies.get(name);
  +      HashMap handbacks = null;
  +      if (listeners == null)
  +      {
  +         listeners = new HashMap();
  +         listenerProxies.put(name, listeners);
  +         handbacks = new HashMap();
  +         listeners.put(listener, handbacks);
  +      }
  +      else
  +      {
  +         handbacks = (HashMap) listeners.get(listener);
  +         if (handbacks == null)
  +         {
  +            handbacks = new HashMap();
  +            listeners.put(listener, handbacks);
  +         }
  +         else
  +         {
  +            result = (NotificationListener) handbacks.get(handback);
  +            if (result != null)
  +               return result;
  +         }
  +      }
  +
  +      // Create a new proxy
  +      result = new NotificationListenerProxy(name, listener);
  +      handbacks.put(handback, result);
  +      return result;
  +   }
  +
  +   /**
  +    * Remove notification listener proxies for a listener
  +    *
  +    * @param name the broadcaster's object name
  +    * @param listener the original listener
  +    * @return an iterator of notification listeners
  +    */
  +   protected Iterator removeListenerProxies(ObjectName name, 
  +                                            NotificationListener listener)
  +   {
  +      // See if we know this listener
  +      HashMap listeners = (HashMap) listenerProxies.get(name);
  +      if (listeners != null)
  +      {
  +         HashMap handbacks = (HashMap) listeners.remove(listener);
  +         if (handbacks != null && handbacks.size() != 0)
  +            return handbacks.values().iterator();
  +      }
  +
  +      // Give the broadcaster chance to remove the original listener
  +      // REVIEW: Is this correct? Or do we just throw a not found?
  +      return Arrays.asList(new Object[]{ listener }).iterator();
  +   }
  +
  +   /**
  +    * Remove notification listener proxies for a broadcaster
  +    *
  +    * @param broadcaster the broadcaster implementation
  +    * @param name the broadcaster's object name
  +    */
  +   protected void removeListenerProxies(NotificationBroadcaster broadcaster,
  +                                        ObjectName name)
  +   {
  +      // See if we know this broadcaster
  +      HashMap listeners = (HashMap) listenerProxies.remove(name);
  +      if (listeners == null)
  +         return;
  +      Iterator listener = listeners.values().iterator();
  +      while (listener.hasNext())
  +      {
  +         Iterator handback = ((HashMap) listener.next()).values().iterator();
  +         while (handback.hasNext())
  +         {
  +            NotificationListener original = (NotificationListener) handback.next();
  +            try
  +            {
  +               broadcaster.removeNotificationListener(original);
  +            }
  +            catch (Exception ignored)
  +            {
  +            }
  +         }
  +      }
      }
   
      // Private -------------------------------------------------------
  +
  +   /**
  +    * Handles exceptions thrown by the implementation MBeans<p>
  +    *
  +    * Either returns a wrapped exception or throws a runtime exception
  +    *
  +    * @param name the ObjectName of the implementation invoked
  +    * @param e the exception thrown by the invocation
  +    * @return any wrapped exception
  +    */
  +   private Exception handleInvocationException(ObjectName name, Exception e)
  +   {
  +       // Return the wrapped exception
  +       if (e instanceof MBeanException)
  +       {
  +          return ((MBeanException) e).getTargetException();
  +       }
  +       // The following are runtime errors, normally caused by the user
  +       if  (e instanceof RuntimeOperationsException)
  +       {
  +          throw ((RuntimeOperationsException) e).getTargetException();
  +       }
  +       if (e instanceof ReflectionException)
  +       {
  +          Exception target = ((ReflectionException) e).getTargetException();
  +          if (target instanceof RuntimeException)
  +             throw (RuntimeException) target;
  +          else
  +             throw new RuntimeException(target.toString());
  +       }
  +       if (e instanceof RuntimeMBeanException)
  +       {
  +          throw ((RuntimeMBeanException) e).getTargetException();
  +       }
  +       if (e instanceof RuntimeErrorException)
  +       {
  +          throw ((RuntimeErrorException) e).getTargetError();
  +       }
  +       // Don't know what to do with this, wrap it in a runtime error
  +       throw new RuntimeException(e.toString());
  +   }
   
      /**
       * Query an MBean against the query
  
  
  
  1.8       +2 -2      jmx/src/main/org/jboss/mx/server/ServerConstants.java
  
  Index: ServerConstants.java
  ===================================================================
  RCS file: /cvsroot/jboss/jmx/src/main/org/jboss/mx/server/ServerConstants.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ServerConstants.java      17 Mar 2002 10:22:50 -0000      1.7
  +++ ServerConstants.java      14 Apr 2002 15:28:07 -0000      1.8
  @@ -18,7 +18,7 @@
    *
    * @author  <a href="mailto:[EMAIL PROTECTED]";>Juha Lindfors</a>.
    * @author  <a href="mailto:[EMAIL PROTECTED]";>Adrian Brock</a>.
  - * @version $Revision: 1.7 $
  + * @version $Revision: 1.8 $
    *   
    */
   public interface ServerConstants
  @@ -73,7 +73,7 @@
      /**
       * The version of the implementation. This value can be retrieved from the MBean 
server delegate.
       */
  -   final static String IMPLEMENTATION_VERSION             =  "1.0 Alpha 2";
  +   final static String IMPLEMENTATION_VERSION             =  "1.1 Development";
      
      /**
       * The vendor of the implementation. This value can be retrieved from the MBean 
server delegate.
  
  
  
  1.1                  jmx/src/main/org/jboss/mx/server/NotificationListenerProxy.java
  
  Index: NotificationListenerProxy.java
  ===================================================================
  /*
   * JBoss, the OpenSource J2EE webOS
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.mx.server;
  
  import java.io.ObjectStreamException;
  
  import javax.management.Notification;
  import javax.management.NotificationListener;
  import javax.management.ObjectName;
  
  /**
   * A notification listener used to forward notifications to listeners
   * added through the mbean server.<p>
   *
   * The original source is replaced with the object name.
   * 
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Adrian Brock</a>.
   * @version $Revision: 1.1 $
   */
  public class NotificationListenerProxy
     implements NotificationListener
  {
     // Constants ---------------------------------------------------
  
     // Attributes --------------------------------------------------
  
     /**
      * The original listener
      */
     private NotificationListener listener;
  
     /**
      * The object name we are proxying
      */
     private ObjectName name;
  
     // Static ------------------------------------------------------
  
     // Constructors ------------------------------------------------
  
     /**
      * Create a new Notification Listener Proxy
      * 
      * @param name the object name
      * @param listener the original listener
      */
     public NotificationListenerProxy(ObjectName name, 
                                      NotificationListener listener)
     {
        this.name = name;
        this.listener = listener;
     }
  
     // Public ------------------------------------------------------
  
     // implementation NotificationListener -------------------------
  
     public void handleNotification(Notification notification, Object handback)
     {
        if (notification == null)
           return;
  
        // Forward the notification with the object name as source
        // FIXME: This overwrites the original source, there is no way
        //        to put it back with the current spec
        notification.setSource(name);
        listener.handleNotification(notification, handback);
     }
  
     // overrides ---------------------------------------------------
  
     // Protected ---------------------------------------------------
  
     // Private -----------------------------------------------------
  
     // Inner classes -----------------------------------------------
  }
  
  
  

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

Reply via email to