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