Clover icon

Magnolia Module EhCache 5.5.9

  1. Project Clover database Mon Nov 25 2019 16:52:57 CET
  2. Package info.magnolia.module.cache.ehcache

File EhCacheFactory.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart8.png
57% of files have more coverage

Code metrics

24
63
16
2
295
194
28
0.44
3.94
8
1.75
15.6% of code in this file is excluded from these metrics.

Classes

Class Line # Actions
EhCacheFactory 71 60 16.4% 25 17
0.8247422682.5%
EhCacheFactory.DescribingConfigurationSource 278 3 0% 3 4
0.3333333433.3%
 

Contributing tests

This file is covered by 16 tests. .

Source view

1    /**
2    * This file Copyright (c) 2008-2018 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.cache.ehcache;
35   
36    import info.magnolia.cms.core.Path;
37    import info.magnolia.cms.util.DeprecationUtil;
38    import info.magnolia.cms.util.MBeanUtil;
39    import info.magnolia.init.MagnoliaConfigurationProperties;
40    import info.magnolia.init.MagnoliaInitPaths;
41    import info.magnolia.module.cache.Cache;
42    import info.magnolia.module.cache.CacheFactory;
43    import info.magnolia.module.cache.CacheModule;
44    import info.magnolia.module.cache.mbean.CacheMonitor;
45    import info.magnolia.objectfactory.Components;
46   
47    import java.util.Arrays;
48    import java.util.HashMap;
49    import java.util.List;
50    import java.util.Map;
51   
52    import javax.inject.Inject;
53    import javax.management.MBeanServer;
54   
55    import org.apache.commons.lang3.StringUtils;
56   
57    import net.sf.ehcache.CacheManager;
58    import net.sf.ehcache.Ehcache;
59    import net.sf.ehcache.config.Configuration;
60    import net.sf.ehcache.config.DiskStoreConfiguration;
61    import net.sf.ehcache.config.generator.ConfigurationSource;
62    import net.sf.ehcache.constructs.blocking.BlockingCache;
63    import net.sf.ehcache.management.ManagementService;
64   
65    /**
66    * A CacheFactory based on ehcache and which wraps BlockingCache instances.
67    *
68    * @deprecated since 5.4.4. Ehcache2 implementation will be dropped in a next major version in favour of EhCache3. Use {@link info.magnolia.module.cache.ehcache3.EhCache3Factory} instead.
69    */
70    @Deprecated
 
71    public class EhCacheFactory implements CacheFactory {
72    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EhCacheFactory.class);
73   
74    //javax.management.ObjectName invalid characters
75    protected static final String CACHE_MANAGER_ID_INVALID_CHARS = "*?=:,\n\"";
76    protected static final String MAGNOLIA_PROPERTY_CACHE_MANAGER_ID = "magnolia.cache.manager.id";
77   
78    private CacheManager cacheManager;
79    private Map<String, EhCacheConfiguration> caches = new HashMap<String, EhCacheConfiguration>();
80    // 0 == do not timeout ever, set to 10s by default.
81    private int blockingTimeout = 10000;
82    private String diskStorePath;
83   
84    private final CacheMonitor cacheMonitor;
85    private final CacheModule cacheModule;
86    private final MagnoliaInitPaths magnoliaInitPaths;
87    private final String cacheManagerId;
88    private final MagnoliaConfigurationProperties magnoliaConfigurationProperties;
89   
 
90  34 toggle @Inject
91    public EhCacheFactory(CacheMonitor cacheMonitor, CacheModule cacheModule, MagnoliaInitPaths magnoliaInitPaths, MagnoliaConfigurationProperties magnoliaConfigurationProperties) {
92  34 this.cacheMonitor = cacheMonitor;
93  34 this.cacheModule = cacheModule;
94  34 this.magnoliaInitPaths = magnoliaInitPaths;
95  34 this.magnoliaConfigurationProperties = magnoliaConfigurationProperties;
96  34 this.diskStorePath = Path.getCacheDirectoryPath();
97  34 this.cacheManagerId = this.createCacheManagerIdentifier();
98    }
99   
100    /**
101    * @deprecated since 5.4.4. Use {@link #EhCacheFactory(info.magnolia.module.cache.mbean.CacheMonitor, info.magnolia.module.cache.CacheModule, info.magnolia.init.MagnoliaInitPaths, info.magnolia.init.MagnoliaConfigurationProperties)} instead.
102    */
 
103  0 toggle @Deprecated
104    public EhCacheFactory(CacheMonitor cacheMonitor, CacheModule cacheModule, MagnoliaInitPaths magnoliaInitPaths) {
105  0 this(cacheMonitor, cacheModule, magnoliaInitPaths, Components.getComponent(MagnoliaConfigurationProperties.class));
106    }
107   
108    /**
109    * @deprecated since 5.4. Use {@link #EhCacheFactory(info.magnolia.module.cache.mbean.CacheMonitor, info.magnolia.module.cache.CacheModule, info.magnolia.init.MagnoliaInitPaths, info.magnolia.init.MagnoliaConfigurationProperties)} instead.
110    */
 
111  0 toggle public EhCacheFactory(CacheMonitor cacheMonitor) {
112  0 this(cacheMonitor, Components.getComponent(CacheModule.class), Components.getComponent(MagnoliaInitPaths.class), Components.getComponent(MagnoliaConfigurationProperties.class));
113    }
114   
 
115    toggle @Deprecated
116    public EhCacheConfiguration getDefaultCacheConfiguration() {
117    DeprecationUtil.isDeprecated("Code should not be calling info.magnolia.module.cache.ehcache.EhCacheFactory#getDefaultCacheConfiguration");
118    return getCaches().get(DEFAULT_CACHE_NAME);
119    }
120   
121    // There is no absolute guarantee that the caches Map will be populated before Node2Bean calls setDefaultCacheConfiguration(), but we know that's how it behaves (populates subnodes first)
 
122  0 toggle @Deprecated
123    public void setDefaultCacheConfiguration(EhCacheConfiguration defaultCacheConfiguration) {
124  0 if (!isDefaultCacheName(defaultCacheConfiguration.getName())) {
125  0 log.warn("Calling setDefaultCacheConfiguration with a CacheConfiguration of name " + defaultCacheConfiguration.getName() + "; it should be unnamed.");
126    }
127  0 if (!getCaches().containsKey(DEFAULT_CACHE_NAME)) {
128  0 DeprecationUtil.isDeprecated("Configure your default cache settings under modules/cache/configuration/cacheFactory/caches/default rather than modules/cache/configuration/cacheFactory/defaultCacheConfiguration");
129  0 getCaches().put(DEFAULT_CACHE_NAME, defaultCacheConfiguration);
130    } else {
131  0 log.warn("You already have a configuration at modules/cache/configuration/cacheFactory/caches/default, ignoring modules/cache/configuration/cacheFactory/defaultCacheConfiguration");
132    }
133    }
134   
135    /**
136    * These are cache configurations. We call this method getCaches() to make it nicer to configure than if it was called getCacheConfigurations().
137    */
 
138    toggle public Map<String, EhCacheConfiguration> getCaches() {
139    return caches;
140    }
141   
 
142    toggle public void setCaches(Map<String, EhCacheConfiguration> caches) {
143    this.caches = caches;
144    }
145   
 
146    toggle public String getDiskStorePath() {
147    return diskStorePath;
148    }
149   
 
150    toggle public void setDiskStorePath(String diskStorePath) {
151    this.diskStorePath = diskStorePath;
152    }
153   
 
154    toggle public int getBlockingTimeout() {
155    return blockingTimeout;
156    }
157   
 
158    toggle public void setBlockingTimeout(int blockingTimeout) {
159    this.blockingTimeout = blockingTimeout;
160    }
161   
162    /**
163    * Caches currently known by the underlying CacheManager (which includes all configured caches as well as those created on-demand based on the default config).
164    */
 
165    toggle @Override
166    public List getCacheNames() {
167    return Arrays.asList(cacheManager.getCacheNames());
168    }
169   
 
170  46 toggle @Override
171    public Cache getCache(String name) {
172  46 if (isDefaultCacheName(name)) {
173  1 throw new IllegalArgumentException("'" + name + "' is not a valid cache name.");
174    }
175  45 Ehcache ehcache = cacheManager.getEhcache(name);
176   
177    // cacheManager will return null if there is no explicit cache configuration for this name
178  45 if (ehcache == null) {
179    // then we need to explicitly create/register it
180  21 createCache(name);
181  21 return getCache(name);
182    }
183    // cacheManager will return a non-wrapped instance of Ehcache if there is an explicit configuration with this name
184    // Recent versions of EhCache introduced a CacheDecoratorFactory, but that would imply configuring this for every cache, it forces an empty constructor and passes Properties around to the decorate() method. Not very elegant.
185  24 if (!(ehcache instanceof BlockingCache)) {
186  23 ehcache = decorateAndSubstitute(ehcache);
187    }
188  24 return wrap(name, ehcache);
189    }
190   
191    // Adds a cache to the cacheManager, which is somehow able to retrieve items previously stored
 
192  22 toggle protected void createCache(String name) {
193  22 synchronized (this.getClass()) {
194  22 cacheManager.addCache(name);
195    }
196    }
197   
 
198  23 toggle protected BlockingCache decorateAndSubstitute(Ehcache ehcache) {
199  23 synchronized (this.getClass()) {
200  23 BlockingCache newBlockingCache = new BlockingCache(ehcache);
201  23 newBlockingCache.setTimeoutMillis(getBlockingTimeout());
202  23 cacheManager.replaceCacheWithDecoratedCache(ehcache, newBlockingCache);
203  23 return newBlockingCache;
204    }
205    }
206   
 
207  24 toggle protected EhCacheWrapper wrap(String name, Ehcache ehcache) {
208  24 return new EhCacheWrapper(cacheModule, ehcache, cacheMonitor, name);
209    }
210   
 
211  67 toggle private boolean isDefaultCacheName(String name) {
212  67 return DEFAULT_CACHE_NAME.equals(name) || name == null;
213    }
214   
 
215  28 toggle @Override
216    public void start(boolean isRestart) {
217  28 final Configuration cfg = new Configuration();
218   
219    // This methods gets called whenever the module's config changes, so this is fine - TODO we just need to double what happens with existing cache/cacheManager
220  28 for (EhCacheConfiguration cacheConfig : caches.values()) {
221    // skip "default", which is not an actual cache but just a "template" config.
222  21 if (!isDefaultCacheName(cacheConfig.getName())) {
223  2 cfg.addCache(cacheConfig);
224    }
225    }
226   
227  28 EhCacheConfiguration defaultCacheConfiguration = caches.get(DEFAULT_CACHE_NAME);
228  28 if (defaultCacheConfiguration != null) {
229    // The defaultCacheConfiguration should not have a name (it has one here, as a side-effect of node2bean auto-calling the setName method with a node's name)
230  19 defaultCacheConfiguration.resetName();
231    } else {
232  9 log.warn("Default cache configuration is not set.");
233  9 defaultCacheConfiguration = new EhCacheConfiguration();
234  9 defaultCacheConfiguration.setMaxEntriesLocalHeap(10000);
235    }
236  28 cfg.setDefaultCacheConfiguration(defaultCacheConfiguration);
237   
238   
239  28 if (!caches.isEmpty()) {
240  20 cfg.setSource(new DescribingConfigurationSource("Magnolia-based cache configuration"));
241    }
242  28 if (diskStorePath != null) {
243  28 cfg.diskStore(new DiskStoreConfiguration().path(diskStorePath));
244  28 cfg.setSource(new DescribingConfigurationSource("Magnolia-based diskStorePath"));
245    }
246  28 cfg.setName(cacheManagerId);
247  28 cacheManager = CacheManager.getCacheManager(cfg.getName());
248  28 if (shouldRegisterCacheManager()) { //module start
249  26 cacheManager = new CacheManager(cfg);
250  26 final MBeanServer mBeanServer = MBeanUtil.getMBeanServer();
251  26 ManagementService.registerMBeans(cacheManager, mBeanServer, true, true, true, true, false);
252    }
253    }
254   
 
255  24 toggle protected boolean shouldRegisterCacheManager() {
256  24 return cacheManager == null; //module start
257    }
258   
 
259  34 toggle protected String createCacheManagerIdentifier() {
260  34 if (magnoliaConfigurationProperties.hasProperty(MAGNOLIA_PROPERTY_CACHE_MANAGER_ID)) {
261  2 return magnoliaConfigurationProperties.getProperty(MAGNOLIA_PROPERTY_CACHE_MANAGER_ID);
262    } else {
263  32 return StringUtils.replaceChars(magnoliaInitPaths.getRootPath(), CACHE_MANAGER_ID_INVALID_CHARS, "-") + "#" + getClass().getName() + "#cacheManager";
264    }
265    }
266   
 
267  21 toggle @Override
268    public void stop(boolean isRestart) {
269  21 if (!isRestart) {
270  21 cacheManager.shutdown();
271    }
272    }
273   
 
274    toggle public CacheManager getWrappedCacheManager() {
275    return cacheManager;
276    }
277   
 
278    private static final class DescribingConfigurationSource extends ConfigurationSource {
279    private final String description;
280   
 
281  48 toggle private DescribingConfigurationSource(String description) {
282  48 this.description = description;
283    }
284   
 
285  0 toggle @Override
286    public Configuration createConfiguration() {
287  0 throw new IllegalStateException("not implemented - not needed");
288    }
289   
 
290  0 toggle @Override
291    public String toString() {
292  0 return description;
293    }
294    }
295    }