001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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    /**
027     * @author Tina Tian
028     */
029    public class AggregatedPortalCacheListener<K extends Serializable, V>
030            implements PortalCacheListener<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 addPortalCacheListener(
041                    PortalCacheListener<K, V> portalCacheListener) {
042    
043                    addPortalCacheListener(
044                            portalCacheListener, PortalCacheListenerScope.ALL);
045            }
046    
047            public void addPortalCacheListener(
048                    PortalCacheListener<K, V> portalCacheListener,
049                    PortalCacheListenerScope portalCacheListenerScope) {
050    
051                    _portalCacheListeners.putIfAbsent(
052                            portalCacheListener, portalCacheListenerScope);
053            }
054    
055            public void clearAll() {
056                    dispose();
057    
058                    _portalCacheListeners.clear();
059            }
060    
061            @Override
062            public void dispose() {
063                    for (PortalCacheListener<K, V> portalCacheListener :
064                                    _portalCacheListeners.keySet()) {
065    
066                            portalCacheListener.dispose();
067                    }
068            }
069    
070            public Map<PortalCacheListener<K, V>, PortalCacheListenerScope>
071                    getPortalCacheListeners() {
072    
073                    return Collections.unmodifiableMap(_portalCacheListeners);
074            }
075    
076            public boolean isEmpty() {
077                    return _portalCacheListeners.isEmpty();
078            }
079    
080            @Override
081            public void notifyEntryEvicted(
082                            PortalCache<K, V> portalCache, K key, V value, int timeToLive)
083                    throws PortalCacheException {
084    
085                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
086                            entry : _portalCacheListeners.entrySet()) {
087    
088                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
089    
090                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
091                                    portalCacheListener.notifyEntryEvicted(
092                                            portalCache, key, value, timeToLive);
093                            }
094                    }
095            }
096    
097            @Override
098            public void notifyEntryExpired(
099                            PortalCache<K, V> portalCache, K key, V value, int timeToLive)
100                    throws PortalCacheException {
101    
102                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
103                            entry : _portalCacheListeners.entrySet()) {
104    
105                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
106    
107                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
108                                    portalCacheListener.notifyEntryExpired(
109                                            portalCache, key, value, timeToLive);
110                            }
111                    }
112            }
113    
114            @Override
115            public void notifyEntryPut(
116                            PortalCache<K, V> portalCache, K key, V value, int timeToLive)
117                    throws PortalCacheException {
118    
119                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
120                                    entry : _portalCacheListeners.entrySet()) {
121    
122                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
123    
124                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
125                                    portalCacheListener.notifyEntryPut(
126                                            portalCache, key, value, timeToLive);
127                            }
128                    }
129            }
130    
131            @Override
132            public void notifyEntryRemoved(
133                            PortalCache<K, V> portalCache, K key, V value, int timeToLive)
134                    throws PortalCacheException {
135    
136                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
137                                    entry : _portalCacheListeners.entrySet()) {
138    
139                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
140    
141                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
142                                    portalCacheListener.notifyEntryRemoved(
143                                            portalCache, key, value, timeToLive);
144                            }
145                    }
146            }
147    
148            @Override
149            public void notifyEntryUpdated(
150                            PortalCache<K, V> portalCache, K key, V value, int timeToLive)
151                    throws PortalCacheException {
152    
153                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
154                                    entry : _portalCacheListeners.entrySet()) {
155    
156                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
157    
158                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
159                                    portalCacheListener.notifyEntryUpdated(
160                                            portalCache, key, value, timeToLive);
161                            }
162                    }
163            }
164    
165            @Override
166            public void notifyRemoveAll(PortalCache<K, V> portalCache)
167                    throws PortalCacheException {
168    
169                    for (Map.Entry<PortalCacheListener<K, V>, PortalCacheListenerScope>
170                                    entry : _portalCacheListeners.entrySet()) {
171    
172                            PortalCacheListener<K, V> portalCacheListener = entry.getKey();
173    
174                            if (_shouldDeliver(portalCacheListener, entry.getValue())) {
175                                    portalCacheListener.notifyRemoveAll(portalCache);
176                            }
177                    }
178            }
179    
180            public void removePortalCacheListener(
181                    PortalCacheListener<K, V> portalCacheListener) {
182    
183                    portalCacheListener.dispose();
184    
185                    _portalCacheListeners.remove(portalCacheListener);
186            }
187    
188            private boolean _shouldDeliver(
189                    PortalCacheListener<K, V> portalCacheListener,
190                    PortalCacheListenerScope portalCacheListenerScope) {
191    
192                    if (_remoteInvokeThreadLocal.get()) {
193                            if (portalCacheListener instanceof PortalCacheReplicator) {
194                                    return false;
195                            }
196    
197                            if (portalCacheListenerScope.equals(PortalCacheListenerScope.ALL) ||
198                                    portalCacheListenerScope.equals(
199                                            PortalCacheListenerScope.REMOTE)) {
200    
201                                    return true;
202                            }
203    
204                            return false;
205                    }
206    
207                    if (portalCacheListenerScope.equals(PortalCacheListenerScope.ALL) ||
208                            portalCacheListenerScope.equals(PortalCacheListenerScope.LOCAL)) {
209    
210                            return true;
211                    }
212    
213                    return false;
214            }
215    
216            private static final ThreadLocal<Boolean> _remoteInvokeThreadLocal =
217                    new InitialThreadLocal<>(
218                            AggregatedPortalCacheListener.class + "._remoteInvokeThreadLocal",
219                            false);
220    
221            private final ConcurrentMap
222                    <PortalCacheListener<K, V>, PortalCacheListenerScope>
223                            _portalCacheListeners = new ConcurrentHashMap<>();
224    
225    }