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                    doClearAll();
083            }
084    
085            @Override
086            public void destroy() {
087                    PortalCacheProvider.unregisterPortalCacheManager(getName());
088    
089                    portalCaches.clear();
090    
091                    doDestroy();
092            }
093    
094            @Override
095            public PortalCache<K, V> getCache(String name) throws PortalCacheException {
096                    return getCache(name, false);
097            }
098    
099            @Override
100            public PortalCache<K, V> getCache(String name, boolean blocking)
101                    throws PortalCacheException {
102    
103                    PortalCache<K, V> portalCache = portalCaches.get(name);
104    
105                    if (portalCache != null) {
106                            return portalCache;
107                    }
108    
109                    portalCache = createPortalCache(name);
110    
111                    PortalCacheConfiguration portalCacheConfiguration =
112                            _portalCacheManagerConfiguration.getPortalCacheConfiguration(
113                                    portalCache.getName());
114    
115                    if (portalCacheConfiguration == null) {
116                            portalCacheConfiguration =
117                                    _portalCacheManagerConfiguration.
118                                            getDefaultPortalCacheConfiguration();
119                    }
120    
121                    _initPortalCacheListeners(portalCache, portalCacheConfiguration);
122    
123                    if (PropsValues.TRANSACTIONAL_CACHE_ENABLED &&
124                            isTransactionalPortalCache(name)) {
125    
126                            portalCache = new TransactionalPortalCache<K, V>(portalCache);
127                    }
128    
129                    if (PropsValues.EHCACHE_BLOCKING_CACHE_ALLOWED && blocking) {
130                            portalCache = new BlockingPortalCache<K, V>(portalCache);
131                    }
132    
133                    PortalCache<K, V> previousPortalCache = portalCaches.putIfAbsent(
134                            name, portalCache);
135    
136                    if (previousPortalCache != null) {
137                            portalCache = previousPortalCache;
138                    }
139                    else if (PropsValues.EHCACHE_BOOTSTRAP_CACHE_LOADER_ENABLED &&
140                                     (portalCacheConfiguration != null)) {
141    
142                            CallbackConfiguration bootstrapLoaderConfiguration =
143                                    portalCacheConfiguration.getBootstrapLoaderConfiguration();
144    
145                            if (bootstrapLoaderConfiguration != null) {
146                                    CallbackFactory callbackFactory =
147                                            bootstrapLoaderConfiguration.getCallbackFactory();
148    
149                                    BootstrapLoader bootstrapLoader =
150                                            callbackFactory.createBootstrapLoader(
151                                                    bootstrapLoaderConfiguration.getProperties());
152    
153                                    if (bootstrapLoader != null) {
154                                            bootstrapLoader.load(getName(), name);
155                                    }
156                            }
157                    }
158    
159                    return portalCache;
160            }
161    
162            @Override
163            public Set<CacheManagerListener> getCacheManagerListeners() {
164                    return aggregatedCacheManagerListener.getCacheManagerListeners();
165            }
166    
167            @Override
168            public boolean isClusterAware() {
169                    return clusterAware;
170            }
171    
172            @Override
173            public boolean registerCacheManagerListener(
174                    CacheManagerListener cacheManagerListener) {
175    
176                    return aggregatedCacheManagerListener.addCacheListener(
177                            cacheManagerListener);
178            }
179    
180            @Override
181            public void removeCache(String name) {
182                    portalCaches.remove(name);
183    
184                    doRemoveCache(name);
185            }
186    
187            public void setClusterAware(boolean clusterAware) {
188                    this.clusterAware = clusterAware;
189            }
190    
191            public void setMpiOnly(boolean mpiOnly) {
192                    _mpiOnly = mpiOnly;
193            }
194    
195            @Override
196            public boolean unregisterCacheManagerListener(
197                    CacheManagerListener cacheManagerListener) {
198    
199                    return aggregatedCacheManagerListener.removeCacheListener(
200                            cacheManagerListener);
201            }
202    
203            @Override
204            public void unregisterCacheManagerListeners() {
205                    aggregatedCacheManagerListener.clearAll();
206            }
207    
208            protected abstract PortalCache<K, V> createPortalCache(String cacheName);
209    
210            protected abstract void doClearAll();
211    
212            protected abstract void doDestroy();
213    
214            protected abstract void doRemoveCache(String cacheName);
215    
216            protected abstract PortalCacheManagerConfiguration
217                    getPortalCacheManagerConfiguration();
218    
219            protected abstract void initPortalCacheManager();
220    
221            protected boolean isTransactionalPortalCache(String name) {
222                    for (String namePattern : PropsValues.TRANSACTIONAL_CACHE_NAMES) {
223                            if (StringUtil.wildcardMatches(
224                                            name, namePattern, CharPool.QUESTION, CharPool.STAR,
225                                            CharPool.PERCENT, true)) {
226    
227                                    return true;
228                            }
229                    }
230    
231                    return false;
232            }
233    
234            protected void reconfigPortalCache(
235                    PortalCacheManagerConfiguration portalCacheManagerConfiguration) {
236    
237                    for (String portalCacheName :
238                                    portalCacheManagerConfiguration.getPortalCacheNames()) {
239    
240                            PortalCacheConfiguration portalCacheConfiguration =
241                                    portalCacheManagerConfiguration.getPortalCacheConfiguration(
242                                            portalCacheName);
243    
244                            _portalCacheManagerConfiguration.putPortalCacheConfiguration(
245                                    portalCacheName, portalCacheConfiguration);
246    
247                            PortalCache<K, V> portalCache = portalCaches.get(portalCacheName);
248    
249                            if (portalCache == null) {
250                                    continue;
251                            }
252    
253                            portalCache.unregisterCacheListeners();
254    
255                            _initPortalCacheListeners(portalCache, portalCacheConfiguration);
256                    }
257            }
258    
259            protected final AggregatedCacheManagerListener
260                    aggregatedCacheManagerListener = new AggregatedCacheManagerListener();
261            protected boolean clusterAware;
262            protected final ConcurrentMap<String, PortalCache<K, V>> portalCaches =
263                    new ConcurrentHashMap<String, PortalCache<K, V>>();
264    
265            private void _initPortalCacheListeners(
266                    PortalCache<K, V> portalCache,
267                    PortalCacheConfiguration portalCacheConfiguration) {
268    
269                    if (portalCacheConfiguration == null) {
270                            return;
271                    }
272    
273                    Map<CallbackConfiguration, CacheListenerScope>
274                            cacheListenerConfigurations =
275                                    portalCacheConfiguration.getCacheListenerConfigurations();
276    
277                    for (Map.Entry<CallbackConfiguration, CacheListenerScope> entry :
278                                    cacheListenerConfigurations.entrySet()) {
279    
280                            CallbackConfiguration callbackConfiguration = entry.getKey();
281    
282                            CallbackFactory callbackFactory =
283                                    callbackConfiguration.getCallbackFactory();
284    
285                            CacheListener<K, V> cacheListener =
286                                    (CacheListener<K, V>)callbackFactory.createCacheListener(
287                                            callbackConfiguration.getProperties());
288    
289                            portalCache.registerCacheListener(cacheListener, entry.getValue());
290                    }
291            }
292    
293            private boolean _mpiOnly;
294            private PortalCacheManagerConfiguration _portalCacheManagerConfiguration;
295    
296    }