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.cache.configuration.CallbackConfiguration;
018    import com.liferay.portal.kernel.cache.configuration.PortalCacheConfiguration;
019    import com.liferay.portal.kernel.cache.configuration.PortalCacheManagerConfiguration;
020    import com.liferay.portal.kernel.cache.transactional.TransactionalPortalCache;
021    import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
022    import com.liferay.portal.kernel.util.CharPool;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    
027    import java.io.Serializable;
028    
029    import java.util.Map;
030    import java.util.Set;
031    import java.util.concurrent.ConcurrentHashMap;
032    import java.util.concurrent.ConcurrentMap;
033    
034    /**
035     * @author Tina Tian
036     */
037    public abstract class AbstractPortalCacheManager<K extends Serializable, V>
038            implements PortalCacheManager<K, V> {
039    
040            @Override
041            public void clearAll() throws PortalCacheException {
042                    doClearAll();
043            }
044    
045            @Override
046            public void destroy() {
047                    portalCaches.clear();
048    
049                    doDestroy();
050            }
051    
052            @Override
053            public PortalCache<K, V> getCache(String portalCacheName)
054                    throws PortalCacheException {
055    
056                    return getCache(portalCacheName, false);
057            }
058    
059            @Override
060            public PortalCache<K, V> getCache(String portalCacheName, boolean blocking)
061                    throws PortalCacheException {
062    
063                    PortalCache<K, V> portalCache = portalCaches.get(portalCacheName);
064    
065                    if (portalCache != null) {
066                            return portalCache;
067                    }
068    
069                    PortalCacheConfiguration portalCacheConfiguration =
070                            _portalCacheManagerConfiguration.getPortalCacheConfiguration(
071                                    portalCacheName);
072    
073                    if (portalCacheConfiguration == null) {
074                            portalCacheConfiguration =
075                                    _defaultPortalCacheConfiguration.newPortalCacheConfiguration(
076                                            portalCacheName);
077    
078                            _portalCacheManagerConfiguration.putPortalCacheConfiguration(
079                                    portalCacheName, portalCacheConfiguration);
080                    }
081    
082                    portalCache = createPortalCache(portalCacheConfiguration);
083    
084                    _initPortalCacheListeners(portalCache, portalCacheConfiguration);
085    
086                    if (isTransactionalCacheEnabled() &&
087                            isTransactionalPortalCache(portalCacheName)) {
088    
089                            portalCache = new TransactionalPortalCache<>(portalCache);
090                    }
091    
092                    if (isBlockingCacheAllowed() && blocking) {
093                            portalCache = new BlockingPortalCache<>(portalCache);
094                    }
095    
096                    PortalCache<K, V> previousPortalCache = portalCaches.putIfAbsent(
097                            portalCacheName, portalCache);
098    
099                    if (previousPortalCache != null) {
100                            portalCache = previousPortalCache;
101                    }
102                    else if (isBootstrapCacheLoaderEnabled() &&
103                                     (portalCacheConfiguration != null)) {
104    
105                            CallbackConfiguration bootstrapLoaderConfiguration =
106                                    portalCacheConfiguration.getBootstrapLoaderConfiguration();
107    
108                            if (bootstrapLoaderConfiguration != null) {
109                                    CallbackFactory callbackFactory =
110                                            bootstrapLoaderConfiguration.getCallbackFactory();
111    
112                                    BootstrapLoader bootstrapLoader =
113                                            callbackFactory.createBootstrapLoader(
114                                                    bootstrapLoaderConfiguration.getProperties());
115    
116                                    if (bootstrapLoader != null) {
117                                            bootstrapLoader.load(getName(), portalCacheName);
118                                    }
119                            }
120                    }
121    
122                    return portalCache;
123            }
124    
125            @Override
126            public Set<CacheManagerListener> getCacheManagerListeners() {
127                    return aggregatedCacheManagerListener.getCacheManagerListeners();
128            }
129    
130            @Override
131            public String getName() {
132                    return _portalCacheManagerName;
133            }
134    
135            public String[] getTransactionalCacheNames() {
136                    return _transactionalCacheNames;
137            }
138    
139            public boolean isBlockingCacheAllowed() {
140                    return _blockingCacheAllowed;
141            }
142    
143            public boolean isBootstrapCacheLoaderEnabled() {
144                    return _bootstrapCacheLoaderEnabled;
145            }
146    
147            @Override
148            public boolean isClusterAware() {
149                    return _clusterAware;
150            }
151    
152            public boolean isTransactionalCacheEnabled() {
153                    return _transactionalCacheEnabled;
154            }
155    
156            @Override
157            public boolean registerCacheManagerListener(
158                    CacheManagerListener cacheManagerListener) {
159    
160                    return aggregatedCacheManagerListener.addCacheListener(
161                            cacheManagerListener);
162            }
163    
164            @Override
165            public void removeCache(String portalCacheName) {
166                    portalCaches.remove(portalCacheName);
167    
168                    doRemoveCache(portalCacheName);
169            }
170    
171            public void setBlockingCacheAllowed(boolean blockingCacheAllowed) {
172                    _blockingCacheAllowed = blockingCacheAllowed;
173            }
174    
175            public void setBootstrapCacheLoaderEnabled(
176                    boolean bootstrapCacheLoaderEnabled) {
177    
178                    _bootstrapCacheLoaderEnabled = bootstrapCacheLoaderEnabled;
179            }
180    
181            public void setClusterAware(boolean clusterAware) {
182                    this._clusterAware = clusterAware;
183            }
184    
185            public void setMpiOnly(boolean mpiOnly) {
186                    _mpiOnly = mpiOnly;
187            }
188    
189            public void setName(String portalCacheManagerName) {
190                    _portalCacheManagerName = portalCacheManagerName;
191            }
192    
193            public void setTransactionalCacheEnabled(
194                    boolean transactionalCacheEnabled) {
195    
196                    _transactionalCacheEnabled = transactionalCacheEnabled;
197            }
198    
199            public void setTransactionalCacheNames(String[] transactionalCacheNames) {
200                    _transactionalCacheNames = transactionalCacheNames;
201            }
202    
203            @Override
204            public boolean unregisterCacheManagerListener(
205                    CacheManagerListener cacheManagerListener) {
206    
207                    return aggregatedCacheManagerListener.removeCacheListener(
208                            cacheManagerListener);
209            }
210    
211            @Override
212            public void unregisterCacheManagerListeners() {
213                    aggregatedCacheManagerListener.clearAll();
214            }
215    
216            protected abstract PortalCache<K, V> createPortalCache(
217                    PortalCacheConfiguration portalCacheConfiguration);
218    
219            protected abstract void doClearAll();
220    
221            protected abstract void doDestroy();
222    
223            protected abstract void doRemoveCache(String portalCacheName);
224    
225            protected abstract PortalCacheManagerConfiguration
226                    getPortalCacheManagerConfiguration();
227    
228            protected abstract String getType();
229    
230            protected void initialize() {
231                    if ((_portalCacheManagerConfiguration != null) ||
232                            (_mpiOnly && SPIUtil.isSPI())) {
233    
234                            return;
235                    }
236    
237                    if (Validator.isNull(_portalCacheManagerName)) {
238                            throw new IllegalArgumentException(
239                                    "Portal cache manager name is not specified");
240                    }
241    
242                    initPortalCacheManager();
243    
244                    _portalCacheManagerConfiguration = getPortalCacheManagerConfiguration();
245    
246                    _defaultPortalCacheConfiguration =
247                            _portalCacheManagerConfiguration.
248                                    getDefaultPortalCacheConfiguration();
249    
250                    for (CallbackConfiguration callbackConfiguration :
251                                    _portalCacheManagerConfiguration.
252                                            getCacheManagerListenerConfigurations()) {
253    
254                            CallbackFactory callbackFactory =
255                                    callbackConfiguration.getCallbackFactory();
256    
257                            CacheManagerListener cacheManagerListener =
258                                    callbackFactory.createCacheManagerListener(
259                                            callbackConfiguration.getProperties());
260    
261                            if (cacheManagerListener != null) {
262                                    registerCacheManagerListener(cacheManagerListener);
263                            }
264                    }
265            }
266    
267            protected abstract void initPortalCacheManager();
268    
269            protected boolean isTransactionalPortalCache(String portalCacheName) {
270                    for (String namePattern : getTransactionalCacheNames()) {
271                            if (StringUtil.wildcardMatches(
272                                            portalCacheName, namePattern, CharPool.QUESTION,
273                                            CharPool.STAR, CharPool.PERCENT, true)) {
274    
275                                    return true;
276                            }
277                    }
278    
279                    return false;
280            }
281    
282            protected void reconfigPortalCache(
283                    PortalCacheManagerConfiguration portalCacheManagerConfiguration) {
284    
285                    for (String portalCacheName :
286                                    portalCacheManagerConfiguration.getPortalCacheNames()) {
287    
288                            PortalCacheConfiguration portalCacheConfiguration =
289                                    portalCacheManagerConfiguration.getPortalCacheConfiguration(
290                                            portalCacheName);
291    
292                            _portalCacheManagerConfiguration.putPortalCacheConfiguration(
293                                    portalCacheName, portalCacheConfiguration);
294    
295                            PortalCache<K, V> portalCache = portalCaches.get(portalCacheName);
296    
297                            if (portalCache == null) {
298                                    continue;
299                            }
300    
301                            portalCache.unregisterCacheListeners();
302    
303                            _initPortalCacheListeners(portalCache, portalCacheConfiguration);
304                    }
305            }
306    
307            protected final AggregatedCacheManagerListener
308                    aggregatedCacheManagerListener = new AggregatedCacheManagerListener();
309            protected final ConcurrentMap<String, PortalCache<K, V>> portalCaches =
310                    new ConcurrentHashMap<>();
311    
312            private void _initPortalCacheListeners(
313                    PortalCache<K, V> portalCache,
314                    PortalCacheConfiguration portalCacheConfiguration) {
315    
316                    if (portalCacheConfiguration == null) {
317                            return;
318                    }
319    
320                    Map<CallbackConfiguration, CacheListenerScope>
321                            cacheListenerConfigurations =
322                                    portalCacheConfiguration.getCacheListenerConfigurations();
323    
324                    for (Map.Entry<CallbackConfiguration, CacheListenerScope> entry :
325                                    cacheListenerConfigurations.entrySet()) {
326    
327                            CallbackConfiguration callbackConfiguration = entry.getKey();
328    
329                            CallbackFactory callbackFactory =
330                                    callbackConfiguration.getCallbackFactory();
331    
332                            CacheListener<K, V> cacheListener =
333                                    callbackFactory.createCacheListener(
334                                            callbackConfiguration.getProperties());
335    
336                            portalCache.registerCacheListener(cacheListener, entry.getValue());
337                    }
338            }
339    
340            private boolean _blockingCacheAllowed;
341            private boolean _bootstrapCacheLoaderEnabled;
342            private boolean _clusterAware;
343            private PortalCacheConfiguration _defaultPortalCacheConfiguration;
344            private boolean _mpiOnly;
345            private PortalCacheManagerConfiguration _portalCacheManagerConfiguration;
346            private String _portalCacheManagerName;
347            private boolean _transactionalCacheEnabled;
348            private String[] _transactionalCacheNames = StringPool.EMPTY_ARRAY;
349    
350    }