Package org.jboss.mx.notification

Source Code of org.jboss.mx.notification.ListenerRegistry

/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.mx.notification;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;

import javax.management.JMException;
import javax.management.ListenerNotFoundException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;

/**
* A notification listener registry.<p>
*
* For addition and removal, the registrations are deeply cloned to
* allow the registrations to be iterated externally without
* incurring the cost of synchronization.
*
* @see org.jboss.mx.notification.ListenerRegistration
*
* @author  <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
* @version $Revision: 1.1 $
*/
public class ListenerRegistry
{
   // Attributes ----------------------------------------------------

   /**
    * A map of listeners to a list of NotificationRegistrations.
    */
   private HashMap listeners = new HashMap();

   /**
    * The factory used to generate the listener registration.
    */
   private ListenerRegistrationFactory factory;

   // Constructor ---------------------------------------------------

   /**
    * Create a notification listener registry using the default
    * listener registration factory.
    */
   public ListenerRegistry()
   {
      this(null);
   }

   /**
    * Create a notification listener registry using the passed
    * listener registration factory.<p>
    *
    * @param factory the factory to create registrations, use
    *        null for the default factory
    */
   public ListenerRegistry(ListenerRegistrationFactory factory)
   {
      if (factory == null)
         this.factory = new DefaultListenerRegistrationFactory();
      else
         this.factory = factory;
   }

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

   /**
    * Adds a listener to a broadcaster<p>
    *
    * @param listener the listener to register
    * @param filter filters the notifications in the broadcaster, can be null
    * @param handback the object to include in the notification, can be null
    * @exception IllegalArgumentException for a null listener
    * @exception JMException for an error adding to the registry
    */
   public void add(NotificationListener listener, NotificationFilter filter, Object handback)
      throws JMException
   {
      if (listener == null)
         throw new IllegalArgumentException("Null listener");

      synchronized(listeners)
      {
         HashMap newListeners = (HashMap) listeners.clone();

         ArrayList registrations = (ArrayList) newListeners.get(listener);
         if (registrations == null)
         {
            registrations = new ArrayList();
            newListeners.put(listener, registrations);
         }
         else
         {
            registrations = (ArrayList) registrations.clone();
            newListeners.put(listener, registrations);
         }

         registrations.add(factory.create(listener, filter, handback));

         listeners = newListeners;
      }

   }

   /**
    * Removes all registrations for a listener.
    *
    * @param listener the listener to remove
    * @exception ListenerNotFoundException when the listener is not registered
    */
   public void remove(NotificationListener listener)
      throws ListenerNotFoundException
   {
      ArrayList registrations = null;
      synchronized(listeners)
      {
         if (listeners.containsKey(listener) == false)
            throw new ListenerNotFoundException("Listener not found " + listener);

         HashMap newListeners = (HashMap) listeners.clone();

         registrations = (ArrayList) newListeners.remove(listener);

         listeners = newListeners;
      }

      for (Iterator iterator = registrations.iterator(); iterator.hasNext();)
      {
          ListenerRegistration registration = (ListenerRegistration) iterator.next();
          registration.removed();
      }
   }

   /**
    * Removes only the registrations for a listener that match the filter and handback.
    *
    * @param listener the listener to remove
    * @param filter the filter of the registration to remove
    * @param handback the handback object of the registration to remove
    * @exception ListenerNotFoundException when the listener is not registered
    */
   public void remove(NotificationListener listener, NotificationFilter filter, Object handback)
      throws ListenerNotFoundException
   {
      ListenerRegistration registration = null;
      synchronized(listeners)
      {
         ArrayList registrations = (ArrayList) listeners.get(listener);
         if (registrations == null)
            throw new ListenerNotFoundException("No registristrations for listener not listener=" + listener +
                                                " filter=" + filter + " handback=" + handback);

         registration = new DefaultListenerRegistration(listener, filter, handback);
         int index = registrations.indexOf(registration);
         if (index == -1)
            throw new ListenerNotFoundException("Listener not found listener=" + listener +
                                                " filter=" + filter + " handback=" + handback);

         HashMap newListeners = (HashMap) listeners.clone();

         registrations = (ArrayList) registrations.clone();
         registration = (ListenerRegistration) registrations.remove(index);
         if (registrations.isEmpty())
            newListeners.remove(listener);
         else
            newListeners.put(listener, registrations);

         listeners = newListeners;
      }

      registration.removed();
   }

   /**
    * Retrieve an iterator over the registrations<p>
    *
    * The iterator behaves like a snapshot of the registrations
    * is taken during this operation.
    *
    * @return the iterator
    */
   public ListenerRegistrationIterator iterator()
   {
      return new ListenerRegistrationIterator();
   }

   /**
    * Test whether the registry is empty
    *
    * @return true when it is empty, false otherwise
    */
   public boolean isEmpty()
   {
      return listeners.isEmpty();
   }

   // Inner Classes -------------------------------------------------

   public class ListenerRegistrationIterator
      implements Iterator
   {
      private Iterator listenerIterator;
      private Iterator registrationIterator;

      /**
       * Constructs a new ListenerRegistration iterator
       */
      public ListenerRegistrationIterator()
      {
         listenerIterator = listeners.values().iterator();
      }

      public boolean hasNext()
      {
         if (registrationIterator == null || registrationIterator.hasNext() == false)
         {
            do
            {
               if (listenerIterator.hasNext() == false)
                  return false;

               registrationIterator = ((ArrayList) listenerIterator.next()).iterator();
            }
            while (registrationIterator.hasNext() == false);
         }
         return true;
      }

      public Object next()
      {
         if (hasNext() == false)
            throw new NoSuchElementException("Use hasNext before next");

         return registrationIterator.next();
      }

      /**
       * Convenience method to returned a typed object
       */
      public ListenerRegistration nextRegistration()
      {
         return (ListenerRegistration) next();
      }

      /**
       * @exception UnsupportedOpertionException remove is not supported
       */
      public void remove()
      {
         throw new UnsupportedOperationException("remove is not supported");
      }
   }
}
TOP

Related Classes of org.jboss.mx.notification.ListenerRegistry

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.