1 /**
2 * Copyright Terracotta, Inc.
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 java.util.Iterator;
20 import java.util.Set;
21 import java.util.concurrent.CopyOnWriteArraySet;
22
23 import net.sf.ehcache.Status;
24
25 /**
26 * Registered listeners for registering and unregistering CacheManagerEventListeners and sending notifications to registrants.
27 * <p/>
28 * There is one of these per CacheManager. It is a composite listener.
29 *
30 * @author Greg Luck
31 * @version $Id: CacheManagerEventListenerRegistry.java 5631 2012-05-10 08:31:33Z teck $
32 * @since 1.3
33 */
34 public class CacheManagerEventListenerRegistry implements CacheManagerEventListener {
35
36 private volatile Status status;
37
38 /**
39 * A Set of CacheEventListeners keyed by listener instance.
40 * CacheEventListener implementations that will be notified of this cache's events.
41 *
42 * @see CacheManagerEventListener
43 */
44 private Set listeners;
45
46 /**
47 * Construct a new registry
48 */
49 public CacheManagerEventListenerRegistry() {
50 status = Status.STATUS_UNINITIALISED;
51 listeners = new CopyOnWriteArraySet();
52 }
53
54 /**
55 * Adds a listener to the notification service. No guarantee is made that listeners will be
56 * notified in the order they were added.
57 *
58 * @param cacheManagerEventListener the listener to add. Can be null, in which case nothing happens
59 * @return true if the listener is being added and was not already added
60 */
61 public final boolean registerListener(CacheManagerEventListener cacheManagerEventListener) {
62 if (cacheManagerEventListener == null) {
63 return false;
64 }
65 return listeners.add(cacheManagerEventListener);
66 }
67
68 /**
69 * Removes a listener from the notification service.
70 *
71 * @param cacheManagerEventListener the listener to remove
72 * @return true if the listener was present
73 */
74 public final boolean unregisterListener(CacheManagerEventListener cacheManagerEventListener) {
75 return listeners.remove(cacheManagerEventListener);
76 }
77
78 /**
79 * Returns whether or not at least one cache manager event listeners has been registered.
80 *
81 * @return true if a one or more listeners have registered, otherwise false
82 */
83 public boolean hasRegisteredListeners() {
84 return listeners.size() > 0;
85 }
86
87 /**
88 * Gets a Set of the listeners registered to this class
89 *
90 * @return a set of type <code>CacheManagerEventListener</code>
91 */
92 public Set getRegisteredListeners() {
93 return listeners;
94 }
95
96 /**
97 * Initialises the listeners, ready to receive events.
98 */
99 public void init() {
100 //init once
101 Iterator iterator = listeners.iterator();
102 while (iterator.hasNext()) {
103 CacheManagerEventListener cacheManagerEventListener = (CacheManagerEventListener) iterator.next();
104 cacheManagerEventListener.init();
105 }
106 status = Status.STATUS_ALIVE;
107 }
108
109 /**
110 * Returns the listener status.
111 *
112 * @return the status at the point in time the method is called
113 */
114 public Status getStatus() {
115 return status;
116 }
117
118 /**
119 * Tell listeners to dispose themselves.
120 * Because this method is only ever called from a synchronized cache method, it does not itself need to be
121 * synchronized.
122 */
123 public void dispose() {
124 Iterator iterator = listeners.iterator();
125 while (iterator.hasNext()) {
126 CacheManagerEventListener cacheManagerEventListener = (CacheManagerEventListener) iterator.next();
127 cacheManagerEventListener.dispose();
128 }
129 listeners.clear();
130 status = Status.STATUS_SHUTDOWN;
131 }
132
133 /**
134 * Called immediately after a cache has been added and activated.
135 * <p/>
136 * Note that the CacheManager calls this method from a synchronized method. Any attempt to
137 * call a synchronized method on CacheManager from this method will cause a deadlock.
138 * <p/>
139 * Note that activation will also cause a CacheEventListener status change notification
140 * from {@link net.sf.ehcache.Status#STATUS_UNINITIALISED} to
141 * {@link net.sf.ehcache.Status#STATUS_ALIVE}. Care should be taken on processing that
142 * notification because:
143 * <ul>
144 * <li>the cache will not yet be accessible from the CacheManager.
145 * <li>the addCaches methods which cause this notification are synchronized on the
146 * CacheManager. An attempt to call {@link net.sf.ehcache.CacheManager#getEhcache(String)}
147 * will cause a deadlock.
148 * </ul>
149 * The calling method will block until this method returns.
150 * <p/>
151 *
152 * @param cacheName the name of the <code>Cache</code> the operation relates to
153 * @see CacheEventListener
154 */
155 public void notifyCacheAdded(String cacheName) {
156 Iterator iterator = listeners.iterator();
157 while (iterator.hasNext()) {
158 CacheManagerEventListener cacheManagerEventListener = (CacheManagerEventListener) iterator.next();
159 cacheManagerEventListener.notifyCacheAdded(cacheName);
160 }
161 }
162
163 /**
164 * Called immediately after a cache has been disposed and removed. The calling method will
165 * block until this method returns.
166 * <p/>
167 * Note that the CacheManager calls this method from a synchronized method. Any attempt to
168 * call a synchronized method on CacheManager from this method will cause a deadlock.
169 * <p/>
170 * Note that a {@link CacheEventListener} status changed will also be triggered. Any
171 * attempt from that notification to access CacheManager will also result in a deadlock.
172 *
173 * @param cacheName the name of the <code>Cache</code> the operation relates to
174 */
175 public void notifyCacheRemoved(String cacheName) {
176 Iterator iterator = listeners.iterator();
177 while (iterator.hasNext()) {
178 CacheManagerEventListener cacheManagerEventListener = (CacheManagerEventListener) iterator.next();
179 cacheManagerEventListener.notifyCacheRemoved(cacheName);
180 }
181 }
182
183 /**
184 * Returns a string representation of the object. In general, the
185 * <code>toString</code> method returns a string that
186 * "textually represents" this object. The result should
187 * be a concise but informative representation that is easy for a
188 * person to read.
189 *
190 * @return a string representation of the object.
191 */
192 @Override
193 public String toString() {
194 StringBuilder sb = new StringBuilder(" cacheManagerEventListeners: ");
195 for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
196 CacheManagerEventListener cacheManagerEventListener = (CacheManagerEventListener) iterator.next();
197 sb.append(cacheManagerEventListener.getClass().getName()).append(" ");
198 }
199 return sb.toString();
200 }
201 }
202