KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > notification > ListenerRegistry


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.notification;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.NoSuchElementException JavaDoc;
28
29 import javax.management.JMException JavaDoc;
30 import javax.management.ListenerNotFoundException JavaDoc;
31 import javax.management.NotificationFilter JavaDoc;
32 import javax.management.NotificationListener JavaDoc;
33
34 /**
35  * A notification listener registry.<p>
36  *
37  * For addition and removal, the registrations are deeply cloned to
38  * allow the registrations to be iterated externally without
39  * incurring the cost of synchronization.
40  *
41  * @see org.jboss.mx.notification.ListenerRegistration
42  *
43  * @author <a HREF="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
44  * @author <a HREF="mailto:juha@jboss.org">Juha Lindfors</a>.
45  *
46  * @version $Revision: 37459 $
47  *
48  * <p><b>Revisions:</b>
49  *
50  * <p><b>20030806 Juha Lindfors:</b>
51  * <ul>
52  * <li>
53  * Added removeAll()
54  * </ul>
55  *
56  */

57 public class ListenerRegistry
58 {
59    // Attributes ----------------------------------------------------
60

61    /**
62     * A map of listeners to a list of NotificationRegistrations.
63     */

64    private HashMap JavaDoc listeners = new HashMap JavaDoc();
65
66    /**
67     * The factory used to generate the listener registration.
68     */

69    private ListenerRegistrationFactory factory;
70
71
72    // Constructor ---------------------------------------------------
73

74    /**
75     * Create a notification listener registry using the default
76     * listener registration factory.
77     */

78    public ListenerRegistry()
79    {
80       this(null);
81    }
82
83    /**
84     * Create a notification listener registry using the passed
85     * listener registration factory.<p>
86     *
87     * @param factory the factory to create registrations, use
88     * null for the default factory
89     */

90    public ListenerRegistry(ListenerRegistrationFactory factory)
91    {
92       if (factory == null)
93          this.factory = new DefaultListenerRegistrationFactory();
94       else
95          this.factory = factory;
96    }
97
98    // Public --------------------------------------------------------
99

100    /**
101     * Adds a listener to a broadcaster<p>
102     *
103     * @param listener the listener to register
104     * @param filter filters the notifications in the broadcaster, can be null
105     * @param handback the object to include in the notification, can be null
106     * @exception IllegalArgumentException for a null listener
107     * @exception JMException for an error adding to the registry
108     */

109    public void add(NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
110       throws JMException JavaDoc
111    {
112       if (listener == null)
113          throw new IllegalArgumentException JavaDoc("Null listener");
114
115       synchronized(listeners)
116       {
117          HashMap JavaDoc newListeners = (HashMap JavaDoc) listeners.clone();
118
119          ArrayList JavaDoc registrations = (ArrayList JavaDoc) newListeners.get(listener);
120          if (registrations == null)
121          {
122             registrations = new ArrayList JavaDoc();
123             newListeners.put(listener, registrations);
124          }
125          else
126          {
127             registrations = (ArrayList JavaDoc) registrations.clone();
128             newListeners.put(listener, registrations);
129          }
130
131          registrations.add(factory.create(listener, filter, handback));
132
133          listeners = newListeners;
134       }
135    }
136
137    /**
138     * Removes all registrations for a listener.
139     *
140     * @param listener the listener to remove
141     * @exception ListenerNotFoundException when the listener is not registered
142     */

143    public void remove(NotificationListener JavaDoc listener)
144       throws ListenerNotFoundException JavaDoc
145    {
146       ArrayList JavaDoc registrations = null;
147       synchronized(listeners)
148       {
149          if (listeners.containsKey(listener) == false)
150             throw new ListenerNotFoundException JavaDoc("Listener not found " + listener);
151
152          HashMap JavaDoc newListeners = (HashMap JavaDoc) listeners.clone();
153
154          registrations = (ArrayList JavaDoc) newListeners.remove(listener);
155
156          listeners = newListeners;
157       }
158
159       for (Iterator JavaDoc iterator = registrations.iterator(); iterator.hasNext();)
160       {
161           ListenerRegistration registration = (ListenerRegistration) iterator.next();
162           registration.removed();
163       }
164    }
165
166    /**
167     * Removes only the registrations for a listener that match the filter and handback.
168     *
169     * @param listener the listener to remove
170     * @param filter the filter of the registration to remove
171     * @param handback the handback object of the registration to remove
172     * @exception ListenerNotFoundException when the listener is not registered
173     */

174    public void remove(NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
175       throws ListenerNotFoundException JavaDoc
176    {
177       ListenerRegistration registration = null;
178       synchronized(listeners)
179       {
180          ArrayList JavaDoc registrations = (ArrayList JavaDoc) listeners.get(listener);
181          if (registrations == null)
182             throw new ListenerNotFoundException JavaDoc("No registristrations for listener not listener=" + listener +
183                                                 " filter=" + filter + " handback=" + handback);
184
185          registration = new DefaultListenerRegistration(listener, filter, handback);
186          int index = registrations.indexOf(registration);
187          if (index == -1)
188             throw new ListenerNotFoundException JavaDoc("Listener not found listener=" + listener +
189                                                 " filter=" + filter + " handback=" + handback);
190
191          HashMap JavaDoc newListeners = (HashMap JavaDoc) listeners.clone();
192
193          registrations = (ArrayList JavaDoc) registrations.clone();
194          registration = (ListenerRegistration) registrations.remove(index);
195          if (registrations.isEmpty())
196             newListeners.remove(listener);
197          else
198             newListeners.put(listener, registrations);
199
200          listeners = newListeners;
201       }
202
203       registration.removed();
204    }
205
206    /**
207     * Removes all listeners from this listener registry.
208     */

209    public void removeAll()
210    {
211       synchronized (listeners)
212       {
213          listeners.clear();
214       }
215    }
216
217    /**
218     * Retrieve an iterator over the registrations<p>
219     *
220     * The iterator behaves like a snapshot of the registrations
221     * is taken during this operation.
222     *
223     * @return the iterator
224     */

225    public ListenerRegistrationIterator iterator()
226    {
227       return new ListenerRegistrationIterator();
228    }
229
230    /**
231     * Test whether the registry is empty
232     *
233     * @return true when it is empty, false otherwise
234     */

235    public boolean isEmpty()
236    {
237       return listeners.isEmpty();
238    }
239
240    // Inner Classes -------------------------------------------------
241

242    public class ListenerRegistrationIterator
243       implements Iterator JavaDoc
244    {
245       private Iterator JavaDoc listenerIterator;
246       private Iterator JavaDoc registrationIterator;
247
248       /**
249        * Constructs a new ListenerRegistration iterator
250        */

251       public ListenerRegistrationIterator()
252       {
253          listenerIterator = listeners.values().iterator();
254       }
255
256       public boolean hasNext()
257       {
258          if (registrationIterator == null || registrationIterator.hasNext() == false)
259          {
260             do
261             {
262                if (listenerIterator.hasNext() == false)
263                   return false;
264
265                registrationIterator = ((ArrayList JavaDoc) listenerIterator.next()).iterator();
266             }
267             while (registrationIterator.hasNext() == false);
268          }
269          return true;
270       }
271
272       public Object JavaDoc next()
273       {
274          if (hasNext() == false)
275             throw new NoSuchElementException JavaDoc("Use hasNext before next");
276
277          return registrationIterator.next();
278       }
279
280       /**
281        * Convenience method to returned a typed object
282        */

283       public ListenerRegistration nextRegistration()
284       {
285          return (ListenerRegistration) next();
286       }
287
288       /**
289        * @exception UnsupportedOpertionException remove is not supported
290        */

291       public void remove()
292       {
293          throw new UnsupportedOperationException JavaDoc("remove is not supported");
294       }
295    }
296 }
297
Popular Tags