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