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.ehcache;
016    
017    import com.liferay.portal.cache.AbstractPortalCacheManager;
018    import com.liferay.portal.kernel.cache.PortalCache;
019    import com.liferay.portal.kernel.cache.PortalCacheWrapper;
020    import com.liferay.portal.kernel.cache.configuration.PortalCacheManagerConfiguration;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.ObjectValuePair;
024    import com.liferay.portal.kernel.util.ReflectionUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.util.PropsUtil;
027    import com.liferay.portal.util.PropsValues;
028    
029    import java.io.Serializable;
030    
031    import java.lang.reflect.Field;
032    
033    import java.net.URL;
034    
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.config.CacheConfiguration;
042    import net.sf.ehcache.config.Configuration;
043    import net.sf.ehcache.event.CacheManagerEventListenerRegistry;
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<K extends Serializable, V>
055            extends AbstractPortalCacheManager<K, V> {
056    
057            public CacheManager getEhcacheManager() {
058                    return _cacheManager;
059            }
060    
061            @Override
062            public String getName() {
063                    return _name;
064            }
065    
066            @Override
067            public void reconfigureCaches(URL configurationURL) {
068                    _configurationPair = EhcacheConfigurationHelperUtil.getConfiguration(
069                            configurationURL, clusterAware, _usingDefault);
070    
071                    Configuration ehcacheConfiguration = _configurationPair.getKey();
072    
073                    if (!_name.equals(ehcacheConfiguration.getName())) {
074                            return;
075                    }
076    
077                    reconfigEhcache(ehcacheConfiguration);
078    
079                    reconfigPortalCache(_configurationPair.getValue());
080            }
081    
082            public void setConfigPropertyKey(String configPropertyKey) {
083                    _configPropertyKey = configPropertyKey;
084            }
085    
086            public void setMBeanServer(MBeanServer mBeanServer) {
087                    _mBeanServer = mBeanServer;
088            }
089    
090            public void setRegisterCacheConfigurations(
091                    boolean registerCacheConfigurations) {
092    
093                    _registerCacheConfigurations = registerCacheConfigurations;
094            }
095    
096            public void setRegisterCacheManager(boolean registerCacheManager) {
097                    _registerCacheManager = registerCacheManager;
098            }
099    
100            public void setRegisterCaches(boolean registerCaches) {
101                    _registerCaches = registerCaches;
102            }
103    
104            public void setRegisterCacheStatistics(boolean registerCacheStatistics) {
105                    _registerCacheStatistics = registerCacheStatistics;
106            }
107    
108            @Override
109            protected PortalCache<K, V> createPortalCache(String cacheName) {
110                    synchronized (_cacheManager) {
111                            if (!_cacheManager.cacheExists(cacheName)) {
112                                    _cacheManager.addCache(cacheName);
113                            }
114                    }
115    
116                    Cache cache = _cacheManager.getCache(cacheName);
117    
118                    return new EhcachePortalCache<K, V>(this, cache);
119            }
120    
121            @Override
122            protected void doClearAll() {
123                    _cacheManager.clearAll();
124            }
125    
126            @Override
127            protected void doDestroy() {
128                    try {
129                            _cacheManager.shutdown();
130                    }
131                    finally {
132                            if (_managementService != null) {
133                                    _managementService.dispose();
134                            }
135                    }
136            }
137    
138            @Override
139            protected void doRemoveCache(String cacheName) {
140                    _cacheManager.removeCache(cacheName);
141            }
142    
143            @Override
144            protected PortalCacheManagerConfiguration
145                    getPortalCacheManagerConfiguration() {
146    
147                    return _configurationPair.getValue();
148            }
149    
150            @Override
151            protected void initPortalCacheManager() {
152                    String configurationPath = PropsUtil.get(_configPropertyKey);
153    
154                    if (Validator.isNull(configurationPath)) {
155                            configurationPath = _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE;
156                    }
157    
158                    _usingDefault = configurationPath.equals(
159                            _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE);
160    
161                    _configurationPair = EhcacheConfigurationHelperUtil.getConfiguration(
162                            configurationPath, clusterAware, _usingDefault);
163    
164                    _cacheManager = CacheManagerUtil.createCacheManager(
165                            _configurationPair.getKey());
166    
167                    _name = _cacheManager.getName();
168    
169                    FailSafeTimer failSafeTimer = _cacheManager.getTimer();
170    
171                    failSafeTimer.cancel();
172    
173                    try {
174                            Field cacheManagerTimerField = ReflectionUtil.getDeclaredField(
175                                    CacheManager.class, "cacheManagerTimer");
176    
177                            cacheManagerTimerField.set(_cacheManager, null);
178                    }
179                    catch (Exception e) {
180                            throw new RuntimeException(e);
181                    }
182    
183                    if (PropsValues.EHCACHE_PORTAL_CACHE_MANAGER_JMX_ENABLED) {
184                            _managementService = new ManagementService(
185                                    _cacheManager, _mBeanServer, _registerCacheManager,
186                                    _registerCaches, _registerCacheConfigurations,
187                                    _registerCacheStatistics);
188    
189                            _managementService.init();
190                    }
191    
192                    CacheManagerEventListenerRegistry cacheManagerEventListenerRegistry =
193                            _cacheManager.getCacheManagerEventListenerRegistry();
194    
195                    cacheManagerEventListenerRegistry.registerListener(
196                            new PortalCacheManagerEventListener(
197                                    aggregatedCacheManagerListener));
198            }
199    
200            protected void reconfigEhcache(Configuration configuration) {
201                    Map<String, CacheConfiguration> cacheConfigurations =
202                            configuration.getCacheConfigurations();
203    
204                    for (CacheConfiguration cacheConfiguration :
205                                    cacheConfigurations.values()) {
206    
207                            String portalCacheName = cacheConfiguration.getName();
208    
209                            synchronized (_cacheManager) {
210                                    if (_cacheManager.cacheExists(portalCacheName)) {
211                                            if (_log.isInfoEnabled()) {
212                                                    _log.info(
213                                                            "Overriding existing cache " + portalCacheName);
214                                            }
215    
216                                            _cacheManager.removeCache(portalCacheName);
217                                    }
218    
219                                    Cache cache = new Cache(cacheConfiguration);
220    
221                                    _cacheManager.addCache(cache);
222    
223                                    PortalCache<K, V> portalCache = portalCaches.get(
224                                            portalCacheName);
225    
226                                    if (portalCache != null) {
227                                            EhcachePortalCache<K, V> ehcachePortalCache =
228                                                    _getEhcachePortalCache(portalCache);
229    
230                                            if (ehcachePortalCache != null) {
231                                                    ehcachePortalCache.reconfigEhcache(cache);
232                                            }
233                                            else {
234                                                    _log.error(
235                                                            "Unable to reconfigure cache with name " +
236                                                                    portalCacheName);
237                                            }
238                                    }
239                            }
240                    }
241            }
242    
243            private EhcachePortalCache<K, V> _getEhcachePortalCache(
244                    PortalCache<K, V> portalCache) {
245    
246                    while (portalCache instanceof PortalCacheWrapper) {
247                            PortalCacheWrapper<K, V> portalCacheWrapper =
248                                    (PortalCacheWrapper<K, V>)portalCache;
249    
250                            portalCache = portalCacheWrapper.getWrappedPortalCache();
251                    }
252    
253                    if (portalCache instanceof EhcachePortalCache) {
254                            return (EhcachePortalCache<K, V>)portalCache;
255                    }
256    
257                    return null;
258            }
259    
260            private static final String _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE =
261                    "/ehcache/liferay-multi-vm-clustered.xml";
262    
263            private static final Log _log = LogFactoryUtil.getLog(
264                    EhcachePortalCacheManager.class);
265    
266            private CacheManager _cacheManager;
267            private String _configPropertyKey;
268            private ObjectValuePair<Configuration, PortalCacheManagerConfiguration>
269                    _configurationPair;
270            private ManagementService _managementService;
271            private MBeanServer _mBeanServer;
272            private String _name;
273            private boolean _registerCacheConfigurations = true;
274            private boolean _registerCacheManager = true;
275            private boolean _registerCaches = true;
276            private boolean _registerCacheStatistics = true;
277            private boolean _usingDefault;
278    
279    }