View Javadoc

1   /**
2    *  Copyright 2003-2006 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.event;
18  
19  import net.sf.ehcache.Cache;
20  import net.sf.ehcache.Element;
21  import net.sf.ehcache.CacheException;
22  import net.sf.ehcache.distribution.CacheReplicator;
23  
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.Set;
27  
28  /**
29   * Registered listeners for registering and unregistering CacheEventListeners and multicasting notifications to registrants.
30   * <p/>
31   * There is one of these per Cache
32   *
33   * @author Greg Luck
34   * @version $Id: RegisteredEventListeners.java 51 2006-04-24 09:21:10Z gregluck $
35   */
36  public final class RegisteredEventListeners {
37  
38      /**
39       * A Map of CacheEventListeners keyed by listener class.
40       * CacheEventListener implementations that will be notified of this cache's events.
41       *
42       * @see CacheEventListener
43       */
44      private final Set cacheEventListeners = new HashSet();
45      private final Cache cache;
46  
47      /**
48       * Constructs a new notification service
49       *
50       * @param cache
51       */
52      public RegisteredEventListeners(Cache cache) {
53          this.cache = cache;
54      }
55  
56  
57      /**
58       * Notifies all registered listeners, in no guaranteed order, that an element was removed
59       *
60       * @param element
61       * @param remoteEvent whether the event came from a remote cache peer
62       * @see CacheEventListener#notifyElementRemoved
63       */
64      public final void notifyElementRemoved(Element element, boolean remoteEvent) throws CacheException {
65          Iterator iterator = cacheEventListeners.iterator();
66          while (iterator.hasNext()) {
67              CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
68              if (!isCircularNotification(remoteEvent, cacheEventListener)) {
69                  cacheEventListener.notifyElementRemoved(cache, element);
70              }
71          }
72      }
73  
74      /**
75       * Notifies all registered listeners, in no guaranteed order, that an element was put into the cache
76       *
77       * @param element
78       * @param remoteEvent whether the event came from a remote cache peer
79       * @see CacheEventListener#notifyElementPut(net.sf.ehcache.Cache,net.sf.ehcache.Element)
80       */
81      public final void notifyElementPut(Element element, boolean remoteEvent) throws CacheException {
82          Iterator iterator = cacheEventListeners.iterator();
83          while (iterator.hasNext()) {
84              CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
85              if (!isCircularNotification(remoteEvent, cacheEventListener)) {
86                  cacheEventListener.notifyElementPut(cache, element);
87              }
88          }
89      }
90  
91      /**
92       * Notifies all registered listeners, in no guaranteed order, that an element in the cache was updated
93       *
94       * @param element
95       * @param remoteEvent whether the event came from a remote cache peer
96       * @see CacheEventListener#notifyElementPut(net.sf.ehcache.Cache,net.sf.ehcache.Element)
97       */
98      public final void notifyElementUpdated(Element element, boolean remoteEvent) {
99          Iterator iterator = cacheEventListeners.iterator();
100         while (iterator.hasNext()) {
101             CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
102             if (!isCircularNotification(remoteEvent, cacheEventListener)) {
103                 cacheEventListener.notifyElementUpdated(cache, element);
104             }
105         }
106     }
107 
108     /**
109      * Notifies all registered listeners, in no guaranteed order, that an element has expired
110      *
111      * @param element
112      * @param remoteEvent whether the event came from a remote cache peer
113      * @see CacheEventListener#notifyElementExpired
114      */
115     public final void notifyElementExpiry(Element element, boolean remoteEvent) {
116         Iterator iterator = cacheEventListeners.iterator();
117         while (iterator.hasNext()) {
118             CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
119             if (!isCircularNotification(remoteEvent, cacheEventListener)) {
120                 cacheEventListener.notifyElementExpired(cache, element);
121             }
122         }
123     }
124 
125 
126     /**
127      * CacheReplicators should not be notified of events received remotely, as this would cause
128      * a circular notification
129      *
130      * @param remoteEvent
131      * @param cacheEventListener
132      * @return true is notifiying the listener would cause a circular notification
133      */
134     private static boolean isCircularNotification(boolean remoteEvent, CacheEventListener cacheEventListener) {
135         return remoteEvent && cacheEventListener instanceof CacheReplicator;
136     }
137 
138 
139     /**
140      * Adds a listener to the notification service. No guarantee is made that listeners will be
141      * notified in the order they were added.
142      *
143      * @param cacheEventListener
144      * @return true if the listener is being added and was not already added
145      */
146     public final boolean registerListener(CacheEventListener cacheEventListener) {
147         if (cacheEventListener == null) {
148             return false;
149         }
150         return cacheEventListeners.add(cacheEventListener);
151     }
152 
153     /**
154      * Removes a listener from the notification service.
155      *
156      * @param cacheEventListener
157      * @return true if the listener was present
158      */
159     public final boolean unregisterListener(CacheEventListener cacheEventListener) {
160         return cacheEventListeners.remove(cacheEventListener);
161     }
162 
163     /**
164      * Gets a list of the listeners registered to this class
165      *
166      * @return a list of type <code>CacheEventListener</code>
167      */
168     public final Set getCacheEventListeners() {
169         return cacheEventListeners;
170     }
171 
172     /**
173      * Tell listeners to dispose themselves.
174      * Because this method is only ever called from a synchronized cache method, it does not itself need to be
175      * synchronized.
176      */
177     public final void dispose() {
178         Iterator iterator = cacheEventListeners.iterator();
179         while (iterator.hasNext()) {
180             CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
181             cacheEventListener.dispose();
182         }
183 
184         cacheEventListeners.clear();
185     }
186 
187     /**
188      * Returns a string representation of the object. In general, the
189      * <code>toString</code> method returns a string that
190      * "textually represents" this object. The result should
191      * be a concise but informative representation that is easy for a
192      * person to read.
193      *
194      * @return a string representation of the object.
195      */
196     public final String toString() {
197         StringBuffer stringBuffer = new StringBuffer(" cacheEventListeners: ");
198         for (Iterator iterator = cacheEventListeners.iterator(); iterator.hasNext();) {
199             CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
200             stringBuffer.append(cacheEventListener.getClass().getName()).append(" ");
201         }
202         return stringBuffer.toString();
203     }
204 }