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.cache;
016    
017    import com.liferay.portal.cache.transactional.TransactionalPortalCache;
018    import com.liferay.portal.kernel.cache.AggregatedCacheManagerListener;
019    import com.liferay.portal.kernel.cache.BlockingPortalCache;
020    import com.liferay.portal.kernel.cache.BootstrapLoader;
021    import com.liferay.portal.kernel.cache.CacheListener;
022    import com.liferay.portal.kernel.cache.CacheListenerScope;
023    import com.liferay.portal.kernel.cache.CacheManagerListener;
024    import com.liferay.portal.kernel.cache.CallbackFactory;
025    import com.liferay.portal.kernel.cache.PortalCache;
026    import com.liferay.portal.kernel.cache.PortalCacheException;
027    import com.liferay.portal.kernel.cache.PortalCacheManager;
028    import com.liferay.portal.kernel.cache.PortalCacheProvider;
029    import com.liferay.portal.kernel.cache.configuration.CallbackConfiguration;
030    import com.liferay.portal.kernel.cache.configuration.PortalCacheConfiguration;
031    import com.liferay.portal.kernel.cache.configuration.PortalCacheManagerConfiguration;
032    import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
033    import com.liferay.portal.kernel.util.CharPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.util.PropsValues;
036    
037    import java.io.Serializable;
038    
039    import java.util.Map;
040    import java.util.Set;
041    import java.util.concurrent.ConcurrentHashMap;
042    import java.util.concurrent.ConcurrentMap;
043    
044    /**
045     * @author Tina Tian
046     */
047    public abstract class AbstractPortalCacheManager<K extends Serializable, V>
048            implements PortalCacheManager<K, V> {
049    
050            public void afterPropertiesSet() {
051                    if ((_portalCacheManagerConfiguration != null) ||
052                            (_mpiOnly && SPIUtil.isSPI())) {
053    
054                            return;
055                    }
056    
057                    initPortalCacheManager();
058    
059                    _portalCacheManagerConfiguration = getPortalCacheManagerConfiguration();
060    
061                    for (CallbackConfiguration callbackConfiguration :
062                                    _portalCacheManagerConfiguration.
063                                            getCacheManagerListenerConfigurations()) {
064    
065                            CallbackFactory callbackFactory =
066                                    callbackConfiguration.getCallbackFactory();
067    
068                            CacheManagerListener cacheManagerListener =
069                                    callbackFactory.createCacheManagerListener(
070                                            callbackConfiguration.getProperties());
071    
072                            if (cacheManagerListener != null) {
073                                    registerCacheManagerListener(cacheManagerListener);
074                            }
075                    }
076    
077                    PortalCacheProvider.registerPortalCacheManager(this);
078            }
079    
080            @Override
081            public void clearAll() throws PortalCacheException {
082                    _portalCaches.clear();
083    
084                    doClearAll();
085            }
086    
087            @Override
088            public void destroy() {
089                    PortalCacheProvider.unregisterPortalCacheManager(getName());
090    
091                    _portalCaches.clear();
092    
093                    doDestroy();
094            }
095    
096            @Override
097            public PortalCache<K, V> getCache(String name) throws PortalCacheException {
098                    return getCache(name, false);
099            }
100    
101            @Override
102            public PortalCache<K, V> getCache(String name, boolean blocking)
103                    throws PortalCacheException {
104    
105                    PortalCache<K, V> portalCache = _portalCaches.get(name);
106    
107                    if (portalCache != null) {
108                            return portalCache;
109                    }
110    
111                    portalCache = createPortalCache(name);
112    
113                    PortalCacheConfiguration portalCacheConfiguration =
114                            _portalCacheManagerConfiguration.getPortalCacheConfiguration(
115                                    portalCache.getName());
116    
117                    if (portalCacheConfiguration == null) {
118                            portalCacheConfiguration =
119                                    _portalCacheManagerConfiguration.
120                                            getDefaultPortalCacheConfiguration();
121                    }
122    
123                    _initPortalCacheListeners(portalCache, portalCacheConfiguration);
124    
125                    if (PropsValues.TRANSACTIONAL_CACHE_ENABLED &&
126                            isTransactionalPortalCache(name)) {
127    
128                            portalCache = new TransactionalPortalCache<K, V>(portalCache);
129                    }
130    
131                    if (PropsValues.EHCACHE_BLOCKING_CACHE_ALLOWED && blocking) {
132                            portalCache = new BlockingPortalCache<K, V>(portalCache);
133                    }
134    
135                    PortalCache<K, V> previousPortalCache = _portalCaches.putIfAbsent(
136                            name, portalCache);
137    
138                    if (previousPortalCache != null) {
139                            portalCache = previousPortalCache;
140                    }
141                    else if (PropsValues.EHCACHE_BOOTSTRAP_CACHE_LOADER_ENABLED &&
142                                     (portalCacheConfiguration != null)) {
143    
144                            CallbackConfiguration bootstrapLoaderConfiguration =
145                                    portalCacheConfiguration.getBootstrapLoaderConfiguration();
146    
147                            if (bootstrapLoaderConfiguration != null) {
148                                    CallbackFactory callbackFactory =
149                                            bootstrapLoaderConfiguration.getCallbackFactory();
150    
151                                    BootstrapLoader bootstrapLoader =
152                                            callbackFactory.createBootstrapLoader(
153                                                    bootstrapLoaderConfiguration.getProperties());
154    
155                                    if (bootstrapLoader != null) {
156                                            bootstrapLoader.load(getName(), name);
157                                    }
158                            }
159                    }
160    
161                    return portalCache;
162            }
163    
164            @Override
165            public Set<CacheManagerListener> getCacheManagerListeners() {
166                    return aggregatedCacheManagerListener.getCacheManagerListeners();
167            }
168    
169            @Override
170            public boolean isClusterAware() {
171                    return clusterAware;
172            }
173    
174            @Override
175            public boolean registerCacheManagerListener(
176                    CacheManagerListener cacheManagerListener) {
177    
178                    return aggregatedCacheManagerListener.addCacheListener(
179                            cacheManagerListener);
180            }
181    
182            @Override
183            public void removeCache(String name) {
184                    _portalCaches.remove(name);
185    
186                    doRemoveCache(name);
187            }
188    
189            public void setClusterAware(boolean clusterAware) {
190                    this.clusterAware = clusterAware;
191            }
192    
193            public void setMpiOnly(boolean mpiOnly) {
194                    _mpiOnly = mpiOnly;
195            }
196    
197            @Override
198            public boolean unregisterCacheManagerListener(
199                    CacheManagerListener cacheManagerListener) {
200    
201                    return aggregatedCacheManagerListener.removeCacheListener(
202                            cacheManagerListener);
203            }
204    
205            @Override
206            public void unregisterCacheManagerListeners() {
207                    aggregatedCacheManagerListener.clearAll();
208            }
209    
210            protected abstract PortalCache<K, V> createPortalCache(String cacheName);
211    
212            protected abstract void doClearAll();
213    
214            protected abstract void doDestroy();
215    
216            protected abstract void doRemoveCache(String cacheName);
217    
218            protected abstract PortalCacheManagerConfiguration
219                    getPortalCacheManagerConfiguration();
220    
221            protected abstract void initPortalCacheManager();
222    
223            protected boolean isTransactionalPortalCache(String name) {
224                    for (String namePattern : PropsValues.TRANSACTIONAL_CACHE_NAMES) {
225                            if (StringUtil.wildcardMatches(
226                                            name, namePattern, CharPool.QUESTION, CharPool.STAR,
227                                            CharPool.PERCENT, true)) {
228    
229                                    return true;
230                            }
231                    }
232    
233                    return false;
234            }
235    
236            protected void reconfigPortalCache(
237                    PortalCacheManagerConfiguration portalCacheManagerConfiguration) {
238    
239                    for (String portalCacheName :
240                                    portalCacheManagerConfiguration.getPortalCacheNames()) {
241    
242                            PortalCache<K, V> portalCache = _portalCaches.get(portalCacheName);
243    
244                            if (portalCache == null) {
245                                    continue;
246                            }
247    
248                            portalCache.unregisterCacheListeners();
249    
250                            _initPortalCacheListeners(
251                                    portalCache,
252                                    portalCacheManagerConfiguration.getPortalCacheConfiguration(
253                                            portalCacheName));
254                    }
255            }
256    
257            protected final AggregatedCacheManagerListener
258                    aggregatedCacheManagerListener = new AggregatedCacheManagerListener();
259            protected boolean clusterAware;
260    
261            private void _initPortalCacheListeners(
262                    PortalCache<K, V> portalCache,
263                    PortalCacheConfiguration portalCacheConfiguration) {
264    
265                    if (portalCacheConfiguration == null) {
266                            return;
267                    }
268    
269                    Map<CallbackConfiguration, CacheListenerScope>
270                            cacheListenerConfigurations =
271                                    portalCacheConfiguration.getCacheListenerConfigurations();
272    
273                    for (Map.Entry<CallbackConfiguration, CacheListenerScope> entry :
274                                    cacheListenerConfigurations.entrySet()) {
275    
276                            CallbackConfiguration callbackConfiguration = entry.getKey();
277    
278                            CallbackFactory callbackFactory =
279                                    callbackConfiguration.getCallbackFactory();
280    
281                            CacheListener<K, V> cacheListener =
282                                    (CacheListener<K, V>)callbackFactory.createCacheListener(
283                                            callbackConfiguration.getProperties());
284    
285                            portalCache.registerCacheListener(cacheListener, entry.getValue());
286                    }
287            }
288    
289            private boolean _mpiOnly;
290            private PortalCacheManagerConfiguration _portalCacheManagerConfiguration;
291            private final ConcurrentMap<String, PortalCache<K, V>> _portalCaches =
292                    new ConcurrentHashMap<String, PortalCache<K, V>>();
293    
294    }