001    /**
002     * Copyright (c) 2000-2013 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.ehcache;
016    
017    import com.liferay.portal.cache.transactional.TransactionalPortalCache;
018    import com.liferay.portal.dao.orm.common.EntityCacheImpl;
019    import com.liferay.portal.dao.orm.common.FinderCacheImpl;
020    import com.liferay.portal.kernel.cache.BlockingPortalCache;
021    import com.liferay.portal.kernel.cache.PortalCache;
022    import com.liferay.portal.kernel.cache.PortalCacheManager;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
026    import com.liferay.portal.kernel.util.ReflectionUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.util.PropsUtil;
029    import com.liferay.portal.util.PropsValues;
030    
031    import java.io.Serializable;
032    
033    import java.lang.reflect.Field;
034    
035    import java.net.URL;
036    
037    import java.util.HashMap;
038    import java.util.Map;
039    
040    import javax.management.MBeanServer;
041    
042    import net.sf.ehcache.Cache;
043    import net.sf.ehcache.CacheManager;
044    import net.sf.ehcache.Ehcache;
045    import net.sf.ehcache.config.CacheConfiguration;
046    import net.sf.ehcache.config.Configuration;
047    import net.sf.ehcache.management.ManagementService;
048    import net.sf.ehcache.util.FailSafeTimer;
049    
050    /**
051     * @author Joseph Shum
052     * @author Raymond Aug??
053     * @author Michael C. Han
054     * @author Shuyang Zhou
055     * @author Edward Han
056     */
057    public class EhcachePortalCacheManager<K extends Serializable, V>
058            implements PortalCacheManager<K, V> {
059    
060            public void afterPropertiesSet() {
061                    if ((_cacheManager != null) || (_mpiOnly && SPIUtil.isSPI())) {
062                            return;
063                    }
064    
065                    String configurationPath = PropsUtil.get(_configPropertyKey);
066    
067                    if (Validator.isNull(configurationPath)) {
068                            configurationPath = _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE;
069                    }
070    
071                    _usingDefault = configurationPath.equals(
072                            _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE);
073    
074                    Configuration configuration = EhcacheConfigurationUtil.getConfiguration(
075                            configurationPath, _clusterAware, _usingDefault);
076    
077                    _cacheManager = CacheManagerUtil.createCacheManager(configuration);
078    
079                    FailSafeTimer failSafeTimer = _cacheManager.getTimer();
080    
081                    failSafeTimer.cancel();
082    
083                    try {
084                            Field cacheManagerTimerField = ReflectionUtil.getDeclaredField(
085                                    CacheManager.class, "cacheManagerTimer");
086    
087                            cacheManagerTimerField.set(_cacheManager, null);
088                    }
089                    catch (Exception e) {
090                            throw new RuntimeException(e);
091                    }
092    
093                    if (PropsValues.EHCACHE_PORTAL_CACHE_MANAGER_JMX_ENABLED) {
094                            _managementService = new ManagementService(
095                                    _cacheManager, _mBeanServer, _registerCacheManager,
096                                    _registerCaches, _registerCacheConfigurations,
097                                    _registerCacheStatistics);
098    
099                            _managementService.init();
100                    }
101            }
102    
103            @Override
104            public void clearAll() {
105                    _cacheManager.clearAll();
106            }
107    
108            public void destroy() throws Exception {
109                    try {
110                            _cacheManager.shutdown();
111                    }
112                    finally {
113                            if (_managementService != null) {
114                                    _managementService.dispose();
115                            }
116                    }
117            }
118    
119            @Override
120            public PortalCache<K, V> getCache(String name) {
121                    return getCache(name, false);
122            }
123    
124            @Override
125            public PortalCache<K, V> getCache(String name, boolean blocking) {
126                    PortalCache<K, V> portalCache = _ehcachePortalCaches.get(name);
127    
128                    if (portalCache == null) {
129                            synchronized (_cacheManager) {
130                                    portalCache = _ehcachePortalCaches.get(name);
131    
132                                    if (portalCache == null) {
133                                            portalCache = addCache(name, null);
134                                    }
135                            }
136                    }
137    
138                    if (PropsValues.TRANSACTIONAL_CACHE_ENABLED &&
139                            (name.startsWith(EntityCacheImpl.CACHE_NAME) ||
140                             name.startsWith(FinderCacheImpl.CACHE_NAME))) {
141    
142                            portalCache = new TransactionalPortalCache<K, V>(portalCache);
143                    }
144    
145                    if (PropsValues.EHCACHE_BLOCKING_CACHE_ALLOWED && blocking) {
146                            portalCache = new BlockingPortalCache<K, V>(portalCache);
147                    }
148    
149                    return portalCache;
150            }
151    
152            public CacheManager getEhcacheManager() {
153                    return _cacheManager;
154            }
155    
156            @Override
157            public void reconfigureCaches(URL configurationURL) {
158                    Configuration configuration = EhcacheConfigurationUtil.getConfiguration(
159                            configurationURL, _clusterAware, _usingDefault);
160    
161                    Map<String, CacheConfiguration> cacheConfigurations =
162                            configuration.getCacheConfigurations();
163    
164                    for (CacheConfiguration cacheConfiguration :
165                                    cacheConfigurations.values()) {
166    
167                            Cache cache = new Cache(cacheConfiguration);
168    
169                            PortalCache<K, V> portalCache = addCache(cache.getName(), cache);
170    
171                            if (portalCache == null) {
172                                    _log.error(
173                                            "Failed to override cache " + cacheConfiguration.getName());
174                            }
175                    }
176            }
177    
178            @Override
179            public void removeCache(String name) {
180                    _ehcachePortalCaches.remove(name);
181    
182                    _cacheManager.removeCache(name);
183            }
184    
185            public void setClusterAware(boolean clusterAware) {
186                    _clusterAware = clusterAware;
187            }
188    
189            public void setConfigPropertyKey(String configPropertyKey) {
190                    _configPropertyKey = configPropertyKey;
191            }
192    
193            public void setMBeanServer(MBeanServer mBeanServer) {
194                    _mBeanServer = mBeanServer;
195            }
196    
197            public void setMpiOnly(boolean mpiOnly) {
198                    _mpiOnly = mpiOnly;
199            }
200    
201            public void setRegisterCacheConfigurations(
202                    boolean registerCacheConfigurations) {
203    
204                    _registerCacheConfigurations = registerCacheConfigurations;
205            }
206    
207            public void setRegisterCacheManager(boolean registerCacheManager) {
208                    _registerCacheManager = registerCacheManager;
209            }
210    
211            public void setRegisterCaches(boolean registerCaches) {
212                    _registerCaches = registerCaches;
213            }
214    
215            public void setRegisterCacheStatistics(boolean registerCacheStatistics) {
216                    _registerCacheStatistics = registerCacheStatistics;
217            }
218    
219            protected PortalCache<K, V> addCache(String name, Cache cache) {
220                    EhcachePortalCache<K, V> ehcachePortalCache = null;
221    
222                    synchronized (_cacheManager) {
223                            if ((cache != null) && _cacheManager.cacheExists(name)) {
224                                    if (_log.isInfoEnabled()) {
225                                            _log.info("Overriding existing cache " + name);
226                                    }
227    
228                                    _cacheManager.removeCache(name);
229                            }
230    
231                            if (cache == null) {
232                                    if (!_cacheManager.cacheExists(name)) {
233                                            _cacheManager.addCache(name);
234                                    }
235                            }
236                            else {
237                                    _cacheManager.addCache(cache);
238                            }
239    
240                            Ehcache ehcache = _cacheManager.getEhcache(name);
241    
242                            if (ehcache == null) {
243                                    return null;
244                            }
245    
246                            ehcachePortalCache = _ehcachePortalCaches.get(name);
247    
248                            if (ehcachePortalCache == null) {
249                                    ehcachePortalCache = new EhcachePortalCache<K, V>(ehcache);
250    
251                                    _ehcachePortalCaches.put(name, ehcachePortalCache);
252                            }
253                            else {
254                                    ehcachePortalCache.setEhcache(ehcache);
255                            }
256                    }
257    
258                    return ehcachePortalCache;
259            }
260    
261            private static final String _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE =
262                    "/ehcache/liferay-multi-vm-clustered.xml";
263    
264            private static Log _log = LogFactoryUtil.getLog(
265                    EhcachePortalCacheManager.class);
266    
267            private CacheManager _cacheManager;
268            private boolean _clusterAware;
269            private String _configPropertyKey;
270            private Map<String, EhcachePortalCache<K, V>> _ehcachePortalCaches =
271                    new HashMap<String, EhcachePortalCache<K, V>>();
272            private ManagementService _managementService;
273            private MBeanServer _mBeanServer;
274            private boolean _mpiOnly;
275            private boolean _registerCacheConfigurations = true;
276            private boolean _registerCacheManager = true;
277            private boolean _registerCaches = true;
278            private boolean _registerCacheStatistics = true;
279            private boolean _usingDefault;
280    
281    }