001
014
015 package com.liferay.portal.kernel.cache;
016
017 import com.liferay.portal.kernel.util.InitialThreadLocal;
018
019 import java.io.Serializable;
020
021 import java.util.Collections;
022 import java.util.Map;
023 import java.util.concurrent.ConcurrentHashMap;
024 import java.util.concurrent.ConcurrentMap;
025
026
029 public class AggregatedCacheListener<K extends Serializable, V>
030 implements CacheListener<K, V> {
031
032 public static boolean isRemoteInvoke() {
033 return _remoteInvokeThreadLocal.get();
034 }
035
036 public static void setRemoteInvoke(boolean remoteInvoke) {
037 _remoteInvokeThreadLocal.set(remoteInvoke);
038 }
039
040 public void addCacheListener(CacheListener<K, V> cacheListener) {
041 addCacheListener(cacheListener, CacheListenerScope.ALL);
042 }
043
044 public void addCacheListener(
045 CacheListener<K, V> cacheListener,
046 CacheListenerScope cacheListenerScope) {
047
048 _cacheListeners.putIfAbsent(cacheListener, cacheListenerScope);
049 }
050
051 public void clearAll() {
052 _cacheListeners.clear();
053 }
054
055 public Map<CacheListener<K, V>, CacheListenerScope> getCacheListeners() {
056 return Collections.unmodifiableMap(_cacheListeners);
057 }
058
059 @Override
060 public void notifyEntryEvicted(
061 PortalCache<K, V> portalCache, K key, V value, int timeToLive)
062 throws PortalCacheException {
063
064 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
065 _cacheListeners.entrySet()) {
066
067 CacheListener<K, V> cacheListener = entry.getKey();
068
069 if (_shouldDeliver(cacheListener, entry.getValue())) {
070 cacheListener.notifyEntryEvicted(
071 portalCache, key, value, timeToLive);
072 }
073 }
074 }
075
076 @Override
077 public void notifyEntryExpired(
078 PortalCache<K, V> portalCache, K key, V value, int timeToLive)
079 throws PortalCacheException {
080
081 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
082 _cacheListeners.entrySet()) {
083
084 CacheListener<K, V> cacheListener = entry.getKey();
085
086 if (_shouldDeliver(cacheListener, entry.getValue())) {
087 cacheListener.notifyEntryExpired(
088 portalCache, key, value, timeToLive);
089 }
090 }
091 }
092
093 @Override
094 public void notifyEntryPut(
095 PortalCache<K, V> portalCache, K key, V value, int timeToLive)
096 throws PortalCacheException {
097
098 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
099 _cacheListeners.entrySet()) {
100
101 CacheListener<K, V> cacheListener = entry.getKey();
102
103 if (_shouldDeliver(cacheListener, entry.getValue())) {
104 cacheListener.notifyEntryPut(
105 portalCache, key, value, timeToLive);
106 }
107 }
108 }
109
110 @Override
111 public void notifyEntryRemoved(
112 PortalCache<K, V> portalCache, K key, V value, int timeToLive)
113 throws PortalCacheException {
114
115 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
116 _cacheListeners.entrySet()) {
117
118 CacheListener<K, V> cacheListener = entry.getKey();
119
120 if (_shouldDeliver(cacheListener, entry.getValue())) {
121 cacheListener.notifyEntryRemoved(
122 portalCache, key, value, timeToLive);
123 }
124 }
125 }
126
127 @Override
128 public void notifyEntryUpdated(
129 PortalCache<K, V> portalCache, K key, V value, int timeToLive)
130 throws PortalCacheException {
131
132 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
133 _cacheListeners.entrySet()) {
134
135 CacheListener<K, V> cacheListener = entry.getKey();
136
137 if (_shouldDeliver(cacheListener, entry.getValue())) {
138 cacheListener.notifyEntryUpdated(
139 portalCache, key, value, timeToLive);
140 }
141 }
142 }
143
144 @Override
145 public void notifyRemoveAll(PortalCache<K, V> portalCache)
146 throws PortalCacheException {
147
148 for (Map.Entry<CacheListener<K, V>, CacheListenerScope> entry :
149 _cacheListeners.entrySet()) {
150
151 CacheListener<K, V> cacheListener = entry.getKey();
152
153 if (_shouldDeliver(cacheListener, entry.getValue())) {
154 cacheListener.notifyRemoveAll(portalCache);
155 }
156 }
157 }
158
159 public void removeCacheListener(CacheListener<K, V> cacheListener) {
160 _cacheListeners.remove(cacheListener);
161 }
162
163 private boolean _shouldDeliver(
164 CacheListener<K, V> cacheListener,
165 CacheListenerScope cacheListenerScope) {
166
167 if (_remoteInvokeThreadLocal.get()) {
168 if (cacheListener instanceof CacheReplicator) {
169 return false;
170 }
171
172 if (cacheListenerScope.equals(CacheListenerScope.ALL) ||
173 cacheListenerScope.equals(CacheListenerScope.REMOTE)) {
174
175 return true;
176 }
177
178 return false;
179 }
180
181 if (cacheListenerScope.equals(CacheListenerScope.ALL) ||
182 cacheListenerScope.equals(CacheListenerScope.LOCAL)) {
183
184 return true;
185 }
186
187 return false;
188 }
189
190 private static final ThreadLocal<Boolean> _remoteInvokeThreadLocal =
191 new InitialThreadLocal<Boolean>(
192 AggregatedCacheListener.class + "._remoteInvokeThreadLocal", false);
193
194 private final ConcurrentMap<CacheListener<K, V>, CacheListenerScope>
195 _cacheListeners =
196 new ConcurrentHashMap<CacheListener<K, V>, CacheListenerScope>();
197
198 }