[jboss-cvs] JBossCache/src/org/jboss/cache/jmx ...

Brian Stansberry brian.stansberry at jboss.com
Thu May 10 00:00:23 EDT 2007


  User: bstansberry
  Date: 07/05/10 00:00:23

  Modified:    src/org/jboss/cache/jmx    CacheJmxWrapper.java
  Added:       src/org/jboss/cache/jmx    CacheNotificationBroadcaster.java
                        CacheNotificationListener.java
  Log:
  [JBCACHE-855] CacheMgmtInterceptor no longer handles JMX notifications; CacheJmxWrapper does
  
  Revision  Changes    Path
  1.16      +162 -101  JBossCache/src/org/jboss/cache/jmx/CacheJmxWrapper.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CacheJmxWrapper.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/jmx/CacheJmxWrapper.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -b -r1.15 -r1.16
  --- CacheJmxWrapper.java	9 May 2007 18:31:19 -0000	1.15
  +++ CacheJmxWrapper.java	10 May 2007 04:00:23 -0000	1.16
  @@ -22,12 +22,14 @@
   package org.jboss.cache.jmx;
   
   import java.util.List;
  +import java.util.concurrent.atomic.AtomicInteger;
   
   import javax.management.ListenerNotFoundException;
   import javax.management.MBeanNotificationInfo;
   import javax.management.MBeanRegistration;
   import javax.management.MBeanServer;
   import javax.management.MalformedObjectNameException;
  +import javax.management.NotificationBroadcasterSupport;
   import javax.management.NotificationFilter;
   import javax.management.NotificationListener;
   import javax.management.ObjectName;
  @@ -39,10 +41,11 @@
   import org.jboss.cache.DefaultCacheFactory;
   import org.jboss.cache.config.Configuration;
   import org.jboss.cache.config.ConfigurationException;
  -import org.jboss.cache.interceptors.CacheMgmtInterceptor;
   import org.jboss.cache.interceptors.Interceptor;
   
  -public class CacheJmxWrapper implements CacheJmxWrapperMBean, MBeanRegistration
  +public class CacheJmxWrapper 
  +   extends NotificationBroadcasterSupport
  +   implements CacheJmxWrapperMBean, MBeanRegistration, CacheNotificationBroadcaster
   {
      private Log log = LogFactory.getLog(getClass().getName());
   
  @@ -55,16 +58,24 @@
      private boolean created;
      private Boolean manageCacheLifecycle;
      private boolean registerInterceptors = true;
  +   private final AtomicInteger listenerCount = new AtomicInteger(0);
  +   private final CacheNotificationListener cacheNotificationListener;
  +   
  +   // ----------------------------------------------------------- Constructors
   
      public CacheJmxWrapper()
      {
  +      cacheNotificationListener = new CacheNotificationListener(this);
      }
   
      public CacheJmxWrapper(Cache cache)
      {
  +      this();
         setCache(cache);
      }
   
  +   // --------------------------------------------------- CacheJmxWrapperMBean
  +   
      public org.jboss.cache.Cache getCache()
      {
         return cache;
  @@ -117,50 +128,27 @@
         return cache == null ? "Cache is null" : formatHtml(cache.printLockInfo());
      }
   
  -   public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object object) throws IllegalArgumentException
  +   public boolean getRegisterInterceptors()
      {
  -      getCacheMgmtInterceptor().addNotificationListener(notificationListener, notificationFilter, object);
  +      return registerInterceptors;
      }
   
  -   public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException
  +   public void setRegisterInterceptors(boolean register)
      {
  -      getCacheMgmtInterceptor().removeNotificationListener(notificationListener);
  +      this.registerInterceptors = register;
      }
   
  -   public MBeanNotificationInfo[] getNotificationInfo()
  +   public boolean getManageCacheLifecycle()
      {
  -      return getCacheMgmtInterceptor().getNotificationInfo();
  +      return manageCacheLifecycle == null ? selfConstructed : manageCacheLifecycle.booleanValue();
      }
   
  -   private CacheMgmtInterceptor getCacheMgmtInterceptor()
  -   {
  -      List<Interceptor> interc = cache.getInterceptorChain();
  -      if (interc != null)
  -      {
  -         for (Interceptor i : interc)
  +   public void setManageCacheLifecycle(boolean manageCacheLifecycle)
            {
  -            if (i instanceof CacheMgmtInterceptor) 
  -               return (CacheMgmtInterceptor) i;
  -         }
  -      }
  -      throw new RuntimeException("Cache management interceptor not found");
  +      this.manageCacheLifecycle = manageCacheLifecycle ? Boolean.TRUE : Boolean.FALSE;
      }
   
  -   /**
  -    * Formats a given String for display as an HTML snippet.
  -    *
  -    * @param s string to format
  -    * @return formatted string
  -    */
  -   public static String formatHtml(String s)
  -   {
  -      s = s.replaceAll("\r\n", "<br />");
  -      s = s.replaceAll("\r", "<br />");
  -      s = s.replaceAll("\n", "<br />");
  -      s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
  -      s = s.replaceAll(" ", "&nbsp;");
  -      return s;
  -   }
  +   // --------------------------------------------------------------  Lifecycle
   
      public void create() throws Exception
      {
  @@ -214,67 +202,7 @@
         created = false;
      }
   
  -   public boolean getRegisterInterceptors()
  -   {
  -      return registerInterceptors;
  -   }
  -
  -   public void setRegisterInterceptors(boolean register)
  -   {
  -      this.registerInterceptors = register;
  -   }
  -
  -   public boolean getManageCacheLifecycle()
  -   {
  -      return manageCacheLifecycle == null ? selfConstructed : manageCacheLifecycle.booleanValue();
  -   }
  -
  -   public void setManageCacheLifecycle(boolean manageCacheLifecycle)
  -   {
  -      this.manageCacheLifecycle = manageCacheLifecycle ? Boolean.TRUE : Boolean.FALSE;
  -   }
  -
  -   protected void constructCache() throws Exception
  -   {
  -      log.debug("Constructing Cache");
  -      setCache(DefaultCacheFactory.getInstance().createCache(config, false));
  -      selfConstructed = true;
  -   }
  -
  -   protected boolean registerInterceptors() throws Exception
  -   {
  -      if (registerInterceptors && !interceptorsRegistered && server != null)
  -      {
  -         log.debug("Registering interceptors");
  -         List<Interceptor> interc = cache.getInterceptorChain();
  -         if (interc != null && interc.size() > 0)
  -         {
  -            JmxUtil.registerInterceptors(server, interc, cacheObjectName);
  -            interceptorsRegistered = true;
  -            return true;
  -         }
  -      }
  -      return false;
  -   }
  -
  -   protected void unregisterInterceptors()
  -   {
  -      if (registerInterceptors && interceptorsRegistered && server != null)
  -      {
  -         try
  -         {
  -            log.debug("Unreqistering interceptors");
  -            JmxUtil.unregisterInterceptors(server, cache.getInterceptorChain(), getCacheObjectName());
  -            interceptorsRegistered = false;
  -         }
  -         catch (Exception e)
  -         {
  -            log.error("Exception unregistering interceptors from JMX", e);
  -         }
  -      }
  -   }
  -
  -   // --------------------------------------------------------------  MBeanRegistration
  +   // ------------------------------------------------------  MBeanRegistration
   
      /**
       * Caches the provided <code>server</code> and <code>objName</code>.
  @@ -342,7 +270,7 @@
         server = null;
      }
   
  -   // ---------------------------------------------------------------  Public methods
  +   // ---------------------------------------------------------  Public methods
   
      /**
       * Sets the configuration that the underlying cache should use.
  @@ -370,6 +298,13 @@
         // FIXME -- having to cast is ugly!!
         this.cache = (CacheImpl) cache;
         this.config = (cache == null ? null : cache.getConfiguration());
  +      synchronized (listenerCount)
  +      {
  +         if (listenerCount.get() > 0)
  +         {
  +            cache.addCacheListener(cacheNotificationListener);
  +         }
  +      }
      }
   
      public String getCacheObjectName()
  @@ -391,13 +326,139 @@
         this.cacheObjectName = name;
      }
   
  -   // ------------------------------------------------------  Protected Methods
  -
      public MBeanServer getMBeanServer()
      {
         return server;
      }
   
  +   /**
  +    * Formats a given String for display as an HTML snippet.
  +    *
  +    * @param s string to format
  +    * @return formatted string
  +    */
  +   public static String formatHtml(String s)
  +   {
  +      s = s.replaceAll("\r\n", "<br />");
  +      s = s.replaceAll("\r", "<br />");
  +      s = s.replaceAll("\n", "<br />");
  +      s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
  +      s = s.replaceAll(" ", "&nbsp;");
  +      return s;
  +   }
  +
  +   // ----------------------------------------------------  Superclass Overrides
  +
  +   @Override
  +   public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object object) throws IllegalArgumentException
  +   {
  +      super.addNotificationListener(notificationListener, notificationFilter, object);
  +      notificationRegistration(true);
  +   }
  +
  +   @Override
  +   public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException
  +   {
  +      super.removeNotificationListener(notificationListener);
  +      notificationRegistration(false);
  +   }
  +
  +   @Override
  +   public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
  +   {
  +      super.removeNotificationListener(listener, filter, handback);
  +      notificationRegistration(false);
  +   }
  +
  +   @Override
  +   public MBeanNotificationInfo[] getNotificationInfo()
  +   {
  +      return cacheNotificationListener.getNotificationInfo();
  +   }
  +
  +   // ------------------------------------------------------  Protected Methods
  +
  +   protected void constructCache() throws Exception
  +   {
  +      log.debug("Constructing Cache");
  +      setCache(DefaultCacheFactory.getInstance().createCache(config, false));
  +      selfConstructed = true;
  +   }
  +
  +   protected boolean registerInterceptors() throws Exception
  +   {
  +      if (registerInterceptors && !interceptorsRegistered && server != null)
  +      {
  +         log.debug("Registering interceptors");
  +         List<Interceptor> interc = cache.getInterceptorChain();
  +         if (interc != null && interc.size() > 0)
  +         {
  +            JmxUtil.registerInterceptors(server, interc, cacheObjectName);
  +            interceptorsRegistered = true;
  +            return true;
  +         }
  +      }
  +      return false;
  +   }
  +
  +   protected void unregisterInterceptors()
  +   {
  +      if (registerInterceptors && interceptorsRegistered && server != null)
  +      {
  +         try
  +         {
  +            log.debug("Unreqistering interceptors");
  +            JmxUtil.unregisterInterceptors(server, cache.getInterceptorChain(), getCacheObjectName());
  +            interceptorsRegistered = false;
  +         }
  +         catch (Exception e)
  +         {
  +            log.error("Exception unregistering interceptors from JMX", e);
  +         }
  +      }
  +   }
  +
      // --------------------------------------------------------  Private methods
   
  +
  +   /**
  +    * Adds and removes the CacheListener.
  +    * A counter is used to determine whether we have any clients who are 
  +    * registered for notifications from this mbean.  When the count is zero, 
  +    * we don't need to listen to cache events, so we remove the CacheListener.  
  +    * Note that a client who terminates without unregistering for notifications 
  +    * will leave the count greater than zero so we'll still listen in that case.
  +    * 
  +    * @param add <code>true</code> if the event was a listerner addition,
  +    *            <code>false</code> if it was a removal
  +    */
  +   private void notificationRegistration(boolean add)
  +   {
  +      // This method adds and removes the CacheImpl listener.
  +      // The m_listeners counter is used to determine whether
  +      // we have any clients who are registered for notifications
  +      // from this mbean.  When the count is zero, we don't need to 
  +      // listen to cache events.  Note that a client who terminates
  +      // without unregistering for notifications will leave the count
  +      // greater than zero so we'll still listen in that case.
  +      synchronized (listenerCount)
  +      {
  +         if (add)
  +         {
  +            listenerCount.incrementAndGet();
  +            if (cache != null)
  +               cache.addCacheListener(cacheNotificationListener);
  +         }
  +         else
  +         {
  +            if (listenerCount.decrementAndGet() <= 0)
  +            {
  +               if (cache != null)
  +                  cache.removeCacheListener(cacheNotificationListener);
  +               
  +               listenerCount.set(0);
  +            }
  +         }
  +      }
  +   }
   }
  
  
  
  1.1      date: 2007/05/10 04:00:23;  author: bstansberry;  state: Exp;JBossCache/src/org/jboss/cache/jmx/CacheNotificationBroadcaster.java
  
  Index: CacheNotificationBroadcaster.java
  ===================================================================
  package org.jboss.cache.jmx;
  
  import javax.management.Notification;
  import javax.management.NotificationEmitter;
  
  public interface CacheNotificationBroadcaster extends NotificationEmitter
  {
     // Notification Types
     public static final String
           NOTIF_CACHE_STARTED = "org.jboss.cache.CacheStarted",
           NOTIF_CACHE_STOPPED = "org.jboss.cache.CacheStopped",
           NOTIF_NODE_CREATED = "org.jboss.cache.NodeCreated",
           NOTIF_NODE_MODIFIED = "org.jboss.cache.NodeModified",
           NOTIF_NODE_REMOVED = "org.jboss.cache.NodeRemoved",
           NOTIF_NODE_MOVED = "org.jboss.cache.NodeMoved",
           NOTIF_NODE_VISITED = "org.jboss.cache.NodeVisited",
           NOTIF_NODE_EVICTED = "org.jboss.cache.NodeEvicted",
           NOTIF_NODE_LOADED = "org.jboss.cache.NodeLoaded",
           NOTIF_NODE_ACTIVATED = "org.jboss.cache.NodeActivated",
           NOTIF_NODE_PASSIVATED = "org.jboss.cache.NodePassivated",
           NOTIF_VIEW_CHANGED = "org.jboss.cache.ViewChanged";
     
     /**
      * Sends a notification to any interested NotificationListener.
      * 
      * @param notification the notification to send
      */
     void sendNotification(Notification notification);
     
  }
  
  
  
  1.1      date: 2007/05/10 04:00:23;  author: bstansberry;  state: Exp;JBossCache/src/org/jboss/cache/jmx/CacheNotificationListener.java
  
  Index: CacheNotificationListener.java
  ===================================================================
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2006, 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.cache.jmx;
  
  import java.util.Map;
  import java.util.concurrent.atomic.AtomicLong;
  
  import javax.management.MBeanNotificationInfo;
  import javax.management.Notification;
  
  import org.jboss.cache.CacheListener;
  import org.jboss.cache.CacheSPI;
  import org.jboss.cache.Fqn;
  import org.jgroups.View;
  
  /**
   * A {@link CacheListener} that creates JMX notifications from listener
   * events.
   * 
   * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
   * @version $Revision: 1.1 $
   */
  class CacheNotificationListener implements CacheListener
  {
     // Notification Messages
     private static final String MSG_CACHE_STARTED = "Cache has been started.";
     private static final String MSG_CACHE_STOPPED = "Cache has been stopped.";
     private static final String MSG_NODE_CREATED = "Node has been created.";
     private static final String MSG_NODE_MODIFIED = "Node has been modifed.";
     private static final String MSG_NODE_REMOVED = "Node has been removed.";
     private static final String MSG_NODE_MOVED = "Node has been moved.";
     private static final String MSG_NODE_VISITED = "Node has been visited.";
     private static final String MSG_NODE_EVICTED = "Node has been evicted.";
     private static final String MSG_NODE_LOADED = "Node has been loaded.";
     private static final String MSG_NODE_ACTIVATED = "Node has been activated.";
     private static final String MSG_NODE_PASSIVATED = "Node has been passivated.";
     private static final String MSG_VIEW_CHANGED = "Cache cluster view has changed.";
  
     // Notification Info 
     private static final String NOTIFICATION_NAME = Notification.class.getName();
     private static final String NOTIFICATION_DESCR = "JBossCache event notifications";
     
     private final CacheNotificationBroadcaster broadcaster;   
     private final AtomicLong sequence = new AtomicLong(0);
     private String serviceName;
     
     // ------------------------------------------------------------ Constructors
     
     CacheNotificationListener(CacheNotificationBroadcaster support)
     {
        this.broadcaster = support;
     }
     
     // ----------------------------------------------------------- PublicMethods
     
     public String getServiceName()
     {
        return serviceName;
     }
  
     public void setServiceName(String serviceName)
     {
        this.serviceName = serviceName;
     }
  
     public MBeanNotificationInfo[] getNotificationInfo()
     {
        String[] types = new String[]
                {
              CacheNotificationBroadcaster.NOTIF_CACHE_STARTED,
              CacheNotificationBroadcaster.NOTIF_CACHE_STOPPED,
              CacheNotificationBroadcaster.NOTIF_NODE_CREATED,
              CacheNotificationBroadcaster.NOTIF_NODE_EVICTED,
              CacheNotificationBroadcaster.NOTIF_NODE_LOADED,
              CacheNotificationBroadcaster.NOTIF_NODE_MODIFIED,
              CacheNotificationBroadcaster.NOTIF_NODE_ACTIVATED,
              CacheNotificationBroadcaster.NOTIF_NODE_PASSIVATED,
              CacheNotificationBroadcaster.NOTIF_NODE_REMOVED,
              CacheNotificationBroadcaster.NOTIF_NODE_VISITED,
              CacheNotificationBroadcaster.NOTIF_VIEW_CHANGED
                };
  
        MBeanNotificationInfo info = new MBeanNotificationInfo(types, NOTIFICATION_NAME, NOTIFICATION_DESCR);
        return new MBeanNotificationInfo[]{info};
     }
     
     // ----------------------------------------------------------- CacheListener
     
     public void cacheStarted(CacheSPI cache)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_CACHE_STARTED, broadcaster, seq(), MSG_CACHE_STARTED);
        n.setUserData(cache.getConfiguration().getServiceName());
        broadcaster.sendNotification(n);
     }
  
     public void cacheStopped(CacheSPI cache)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_CACHE_STOPPED, broadcaster, seq(), MSG_CACHE_STOPPED);
        n.setUserData(cache.getConfiguration().getServiceName());
        broadcaster.sendNotification(n);
     }
  
     public void nodeCreated(Fqn fqn, boolean pre, boolean isLocal)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_CREATED, broadcaster, seq(), MSG_NODE_CREATED);
        n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
        broadcaster.sendNotification(n);
     }
  
     public void nodeEvicted(Fqn fqn, boolean pre, boolean isLocal)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_EVICTED, broadcaster, seq(), MSG_NODE_EVICTED);
        n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
        broadcaster.sendNotification(n);
     }
  
     public void nodeLoaded(Fqn fqn, boolean pre, Map data)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_LOADED, broadcaster, seq(), MSG_NODE_LOADED);
        n.setUserData(new Object[]{fqn.toString(), pre});
        broadcaster.sendNotification(n);
     }
  
     public void nodeModified(Fqn fqn, boolean pre, boolean isLocal, ModificationType modType, Map data)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_MODIFIED, broadcaster, seq(), MSG_NODE_MODIFIED);
        n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
        broadcaster.sendNotification(n);
  
     }
  
     public void nodeRemoved(Fqn fqn, boolean pre, boolean isLocal, Map data)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_REMOVED, broadcaster, seq(), MSG_NODE_REMOVED);
        n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
        broadcaster.sendNotification(n);
     }
  
     public void nodeMoved(Fqn from, Fqn to, boolean pre, boolean isLocal)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_MOVED, broadcaster, seq(), MSG_NODE_MOVED);
        n.setUserData(new Object[]{from.toString(), to.toString(), pre});
        broadcaster.sendNotification(n);
     }
  
     public void nodeVisited(Fqn fqn, boolean pre)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_VISITED, broadcaster, seq(), MSG_NODE_VISITED);
        n.setUserData(new Object[]{fqn.toString(), pre});
        broadcaster.sendNotification(n);
     }
  
     public void viewChange(View view)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_VIEW_CHANGED, broadcaster, seq(), MSG_VIEW_CHANGED);
        n.setUserData(view.toString());
        broadcaster.sendNotification(n);
     }
  
     public void nodeActivated(Fqn fqn, boolean pre)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_ACTIVATED, broadcaster, seq(), MSG_NODE_ACTIVATED);
        n.setUserData(new Object[]{fqn.toString(), pre});
        broadcaster.sendNotification(n);
     }
  
     public void nodePassivated(Fqn fqn, boolean pre)
     {
        Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_PASSIVATED, broadcaster, seq(), MSG_NODE_PASSIVATED);
        n.setUserData(new Object[]{fqn.toString(), pre});
        broadcaster.sendNotification(n);
     }
     
     private long seq()
     {
        return sequence.getAndIncrement();
     }
  }
  
  
  



More information about the jboss-cvs-commits mailing list