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 }