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.dao.orm.hibernate.region;
016    
017    import com.liferay.portal.cache.ehcache.CacheManagerUtil;
018    import com.liferay.portal.cache.ehcache.EhcacheConfigurationUtil;
019    import com.liferay.portal.cache.ehcache.EhcachePortalCache;
020    import com.liferay.portal.cache.ehcache.ModifiableEhcacheWrapper;
021    import com.liferay.portal.kernel.cache.CacheManagerListener;
022    import com.liferay.portal.kernel.cache.PortalCache;
023    import com.liferay.portal.kernel.cache.PortalCacheManager;
024    import com.liferay.portal.kernel.cache.PortalCacheProvider;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.GetterUtil;
028    import com.liferay.portal.kernel.util.PortalLifecycle;
029    import com.liferay.portal.kernel.util.ReflectionUtil;
030    import com.liferay.portal.kernel.util.SystemProperties;
031    import com.liferay.portal.kernel.util.Validator;
032    
033    import java.io.Serializable;
034    
035    import java.lang.reflect.Field;
036    
037    import java.net.URL;
038    
039    import java.util.HashMap;
040    import java.util.Map;
041    import java.util.Properties;
042    import java.util.Set;
043    
044    import net.sf.ehcache.Cache;
045    import net.sf.ehcache.CacheManager;
046    import net.sf.ehcache.Ehcache;
047    import net.sf.ehcache.config.CacheConfiguration;
048    import net.sf.ehcache.config.Configuration;
049    import net.sf.ehcache.config.ConfigurationFactory;
050    import net.sf.ehcache.hibernate.EhCacheRegionFactory;
051    import net.sf.ehcache.hibernate.regions.EhcacheCollectionRegion;
052    import net.sf.ehcache.hibernate.regions.EhcacheEntityRegion;
053    import net.sf.ehcache.hibernate.regions.EhcacheQueryResultsRegion;
054    import net.sf.ehcache.hibernate.regions.EhcacheTimestampsRegion;
055    import net.sf.ehcache.util.FailSafeTimer;
056    
057    import org.hibernate.cache.CacheDataDescription;
058    import org.hibernate.cache.CacheException;
059    import org.hibernate.cache.CollectionRegion;
060    import org.hibernate.cache.EntityRegion;
061    import org.hibernate.cache.QueryResultsRegion;
062    import org.hibernate.cache.TimestampsRegion;
063    import org.hibernate.cfg.Settings;
064    
065    /**
066     * @author Edward Han
067     */
068    public class LiferayEhcacheRegionFactory extends EhCacheRegionFactory {
069    
070            public LiferayEhcacheRegionFactory(Properties properties) {
071                    super(properties);
072            }
073    
074            @Override
075            public CollectionRegion buildCollectionRegion(
076                            String regionName, Properties properties,
077                            CacheDataDescription cacheDataDescription)
078                    throws CacheException {
079    
080                    configureCache(regionName);
081    
082                    EhcacheCollectionRegion ehcacheCollectionRegion =
083                            (EhcacheCollectionRegion)super.buildCollectionRegion(
084                                    regionName, properties, cacheDataDescription);
085    
086                    return new CollectionRegionWrapper(ehcacheCollectionRegion);
087            }
088    
089            @Override
090            public EntityRegion buildEntityRegion(
091                            String regionName, Properties properties,
092                            CacheDataDescription cacheDataDescription)
093                    throws CacheException {
094    
095                    configureCache(regionName);
096    
097                    EhcacheEntityRegion ehcacheEntityRegion =
098                            (EhcacheEntityRegion)super.buildEntityRegion(
099                                    regionName, properties, cacheDataDescription);
100    
101                    return new EntityRegionWrapper(ehcacheEntityRegion);
102            }
103    
104            @Override
105            public QueryResultsRegion buildQueryResultsRegion(
106                            String regionName, Properties properties)
107                    throws CacheException {
108    
109                    configureCache(regionName);
110    
111                    EhcacheQueryResultsRegion ehcacheQueryResultsRegion =
112                            (EhcacheQueryResultsRegion)super.buildQueryResultsRegion(
113                                    regionName, properties);
114    
115                    return new QueryResultsRegionWrapper(ehcacheQueryResultsRegion);
116            }
117    
118            @Override
119            public TimestampsRegion buildTimestampsRegion(
120                            String regionName, Properties properties)
121                    throws CacheException {
122    
123                    configureCache(regionName);
124    
125                    EhcacheTimestampsRegion ehcacheTimestampsRegion =
126                            (EhcacheTimestampsRegion)super.buildTimestampsRegion(
127                                    regionName, properties);
128    
129                    TimestampsRegion timestampsRegion = new TimestampsRegionWrapper(
130                            ehcacheTimestampsRegion);
131    
132                    return timestampsRegion;
133            }
134    
135            public void reconfigureCaches(URL cacheConfigFile) {
136                    if (manager == null) {
137                            return;
138                    }
139    
140                    synchronized (manager) {
141                            Configuration configuration =
142                                    EhcacheConfigurationUtil.getConfiguration(
143                                            cacheConfigFile, true, _usingDefault);
144    
145                            Map<String, CacheConfiguration> cacheConfigurations =
146                                    configuration.getCacheConfigurations();
147    
148                            for (CacheConfiguration cacheConfiguration :
149                                            cacheConfigurations.values()) {
150    
151                                    Ehcache ehcache = new Cache(cacheConfiguration);
152    
153                                    reconfigureCache(ehcache);
154                            }
155                    }
156            }
157    
158            @Override
159            public void start(Settings settings, Properties properties)
160                    throws CacheException {
161    
162                    try {
163                            String configurationPath = null;
164    
165                            if (properties != null) {
166                                    configurationPath = (String)properties.get(
167                                            NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME);
168                            }
169    
170                            if (Validator.isNull(configurationPath)) {
171                                    configurationPath = _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE;
172                            }
173    
174                            Configuration configuration = null;
175    
176                            if (Validator.isNull(configurationPath)) {
177                                    configuration = ConfigurationFactory.parseConfiguration();
178                            }
179                            else {
180                                    _usingDefault = configurationPath.equals(
181                                            _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE);
182    
183                                    configuration = EhcacheConfigurationUtil.getConfiguration(
184                                            configurationPath, true, _usingDefault);
185                            }
186    
187                            /*Object transactionManager =
188                                    getOnePhaseCommitSyncTransactionManager(settings, properties);
189    
190                            configuration.setDefaultTransactionManager(transactionManager);*/
191    
192                            manager = CacheManagerUtil.createCacheManager(configuration);
193    
194                            boolean skipUpdateCheck = GetterUtil.getBoolean(
195                                    SystemProperties.get("net.sf.ehcache.skipUpdateCheck"));
196                            boolean tcActive = GetterUtil.getBoolean(
197                                    SystemProperties.get("tc.active"));
198    
199                            if (skipUpdateCheck && !tcActive) {
200                                    FailSafeTimer failSafeTimer = manager.getTimer();
201    
202                                    failSafeTimer.cancel();
203    
204                                    try {
205                                            Field cacheManagerTimerField =
206                                                    ReflectionUtil.getDeclaredField(
207                                                            CacheManager.class, "cacheManagerTimer");
208    
209                                            cacheManagerTimerField.set(manager, null);
210                                    }
211                                    catch (Exception e) {
212                                            throw new RuntimeException(e);
213                                    }
214                            }
215    
216                            mbeanRegistrationHelper.registerMBean(manager, properties);
217    
218                            _mBeanRegisteringPortalLifecycle =
219                                    new MBeanRegisteringPortalLifecycle(manager);
220    
221                            _mBeanRegisteringPortalLifecycle.registerPortalLifecycle(
222                                    PortalLifecycle.METHOD_INIT);
223    
224                            PortalCacheProvider.registerPortalCacheManager(
225                                    new HibernatePortalCacheManager(manager));
226                    }
227                    catch (net.sf.ehcache.CacheException ce) {
228                            throw new CacheException(ce);
229                    }
230            }
231    
232            @Override
233            public void stop() {
234                    PortalCacheProvider.unregisterPortalCacheManager(manager.getName());
235    
236                    super.stop();
237            }
238    
239            protected void configureCache(String regionName) {
240                    synchronized (manager) {
241                            Ehcache ehcache = manager.getEhcache(regionName);
242    
243                            if (ehcache == null) {
244                                    manager.addCache(regionName);
245    
246                                    ehcache = manager.getEhcache(regionName);
247                            }
248    
249                            if (!(ehcache instanceof ModifiableEhcacheWrapper)) {
250                                    Ehcache modifiableEhcacheWrapper = new ModifiableEhcacheWrapper(
251                                            ehcache);
252    
253                                    manager.replaceCacheWithDecoratedCache(
254                                            ehcache, modifiableEhcacheWrapper);
255                            }
256                    }
257            }
258    
259            protected void reconfigureCache(Ehcache replacementCache) {
260                    String cacheName = replacementCache.getName();
261    
262                    Ehcache ehcache = manager.getEhcache(cacheName);
263    
264                    if ((ehcache != null) &&
265                            (ehcache instanceof ModifiableEhcacheWrapper)) {
266    
267                            if (_log.isInfoEnabled()) {
268                                    _log.info("Reconfiguring Hibernate cache " + cacheName);
269                            }
270    
271                            ModifiableEhcacheWrapper modifiableEhcacheWrapper =
272                                    (ModifiableEhcacheWrapper)ehcache;
273    
274                            manager.replaceCacheWithDecoratedCache(
275                                    ehcache, modifiableEhcacheWrapper.getWrappedCache());
276    
277                            manager.removeCache(cacheName);
278    
279                            manager.addCache(replacementCache);
280    
281                            modifiableEhcacheWrapper.setWrappedCache(replacementCache);
282    
283                            manager.replaceCacheWithDecoratedCache(
284                                    replacementCache, modifiableEhcacheWrapper);
285                    }
286                    else {
287                            if (_log.isInfoEnabled()) {
288                                    _log.info("Configuring Hibernate cache " + cacheName);
289                            }
290    
291                            if (ehcache != null) {
292                                    manager.removeCache(cacheName);
293                            }
294    
295                            ehcache = new ModifiableEhcacheWrapper(replacementCache);
296    
297                            manager.addCache(replacementCache);
298    
299                            manager.replaceCacheWithDecoratedCache(replacementCache, ehcache);
300                    }
301            }
302    
303            private static final String _DEFAULT_CLUSTERED_EHCACHE_CONFIG_FILE =
304                    "/ehcache/hibernate-clustered.xml";
305    
306            private static final Log _log = LogFactoryUtil.getLog(
307                    LiferayEhcacheRegionFactory.class);
308    
309            private MBeanRegisteringPortalLifecycle _mBeanRegisteringPortalLifecycle;
310            private boolean _usingDefault;
311    
312            private class HibernatePortalCacheManager
313                    implements PortalCacheManager<Serializable, Serializable> {
314    
315                    public HibernatePortalCacheManager(CacheManager cacheManager) {
316                            _cacheManager = cacheManager;
317                    }
318    
319                    @Override
320                    public void clearAll() {
321                            throw new UnsupportedOperationException();
322                    }
323    
324                    @Override
325                    public void destroy() {
326                            throw new UnsupportedOperationException();
327                    }
328    
329                    @Override
330                    public PortalCache<Serializable, Serializable> getCache(String name) {
331                            PortalCache<Serializable, Serializable> portalCache =
332                                    _portalCaches.get(name);
333    
334                            if (portalCache != null) {
335                                    return portalCache;
336                            }
337    
338                            synchronized (_cacheManager) {
339                                    portalCache = _portalCaches.get(name);
340    
341                                    if (portalCache == null) {
342                                            if (!_cacheManager.cacheExists(name)) {
343                                                    return null;
344                                            }
345    
346                                            Cache cache = _cacheManager.getCache(name);
347    
348                                            portalCache =
349                                                    new EhcachePortalCache<Serializable, Serializable>(
350                                                            this, cache);
351    
352                                            _portalCaches.put(name, portalCache);
353                                    }
354                            }
355    
356                            return portalCache;
357                    }
358    
359                    @Override
360                    public PortalCache<Serializable, Serializable> getCache(
361                            String name, boolean blocking) {
362    
363                            throw new UnsupportedOperationException();
364                    }
365    
366                    @Override
367                    public Set<CacheManagerListener> getCacheManagerListeners() {
368                            throw new UnsupportedOperationException();
369                    }
370    
371                    @Override
372                    public String getName() {
373                            return _cacheManager.getName();
374                    }
375    
376                    @Override
377                    public boolean isClusterAware() {
378                            return true;
379                    }
380    
381                    @Override
382                    public void reconfigureCaches(URL configurationURL) {
383                            throw new UnsupportedOperationException();
384                    }
385    
386                    @Override
387                    public boolean registerCacheManagerListener(
388                            CacheManagerListener cacheManagerListener) {
389    
390                            throw new UnsupportedOperationException();
391                    }
392    
393                    @Override
394                    public void removeCache(String name) {
395                            throw new UnsupportedOperationException();
396                    }
397    
398                    @Override
399                    public boolean unregisterCacheManagerListener(
400                            CacheManagerListener cacheManagerListener) {
401    
402                            throw new UnsupportedOperationException();
403                    }
404    
405                    @Override
406                    public void unregisterCacheManagerListeners() {
407                            throw new UnsupportedOperationException();
408                    }
409    
410                    private final CacheManager _cacheManager;
411                    private final Map<String, PortalCache<Serializable, Serializable>>
412                            _portalCaches =
413                                    new HashMap<String, PortalCache<Serializable, Serializable>>();
414    
415            }
416    
417    }