View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.config;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  import java.util.Set;
28  
29  import net.sf.ehcache.Cache;
30  import net.sf.ehcache.CacheException;
31  import net.sf.ehcache.CacheManager;
32  import net.sf.ehcache.Ehcache;
33  import net.sf.ehcache.config.CacheConfiguration.CacheDecoratorFactoryConfiguration;
34  import net.sf.ehcache.constructs.CacheDecoratorFactory;
35  import net.sf.ehcache.distribution.CacheManagerPeerListener;
36  import net.sf.ehcache.distribution.CacheManagerPeerListenerFactory;
37  import net.sf.ehcache.distribution.CacheManagerPeerProvider;
38  import net.sf.ehcache.distribution.CacheManagerPeerProviderFactory;
39  import net.sf.ehcache.event.CacheManagerEventListener;
40  import net.sf.ehcache.event.CacheManagerEventListenerFactory;
41  import net.sf.ehcache.exceptionhandler.CacheExceptionHandler;
42  import net.sf.ehcache.exceptionhandler.CacheExceptionHandlerFactory;
43  import net.sf.ehcache.exceptionhandler.ExceptionHandlingDynamicCacheProxy;
44  import net.sf.ehcache.util.ClassLoaderUtil;
45  import net.sf.ehcache.util.PropertyUtil;
46  import org.slf4j.Logger;
47  import org.slf4j.LoggerFactory;
48  
49  /***
50   * The configuration for ehcache.
51   * <p/>
52   * This class can be populated through:
53   * <ul>
54   * <li>introspection by {@link ConfigurationFactory} or
55   * <li>programmatically
56   * </ul>
57   *
58   * @author Greg Luck
59   * @version $Id: ConfigurationHelper.html 13146 2011-08-01 17:12:39Z oletizi $
60   */
61  public final class ConfigurationHelper {
62  
63      private static final Logger LOG = LoggerFactory.getLogger(ConfigurationHelper.class.getName());
64  
65      private final Configuration configuration;
66      private final CacheManager cacheManager;
67  
68      /***
69       * Only Constructor
70       *
71       * @param cacheManager
72       * @param configuration
73       */
74      public ConfigurationHelper(CacheManager cacheManager, Configuration configuration) {
75          if (cacheManager == null || configuration == null) {
76              throw new IllegalArgumentException("Cannot have null parameters");
77          }
78          this.cacheManager = cacheManager;
79          this.configuration = configuration;
80      }
81  
82      /***
83       * Tries to create a CacheLoader from the configuration using the factory
84       * specified.
85       *
86       * @return The CacheExceptionHandler, or null if it could not be found.
87       */
88      public static CacheExceptionHandler createCacheExceptionHandler(
89              CacheConfiguration.CacheExceptionHandlerFactoryConfiguration factoryConfiguration) throws CacheException {
90          String className = null;
91          CacheExceptionHandler cacheExceptionHandler = null;
92          if (factoryConfiguration != null) {
93              className = factoryConfiguration.getFullyQualifiedClassPath();
94          }
95          if (className == null || className.length() == 0) {
96              LOG.debug("No CacheExceptionHandlerFactory class specified. Skipping...");
97          } else {
98              CacheExceptionHandlerFactory factory = (CacheExceptionHandlerFactory)
99                      ClassLoaderUtil.createNewInstance(className);
100             Properties properties = PropertyUtil.parseProperties(factoryConfiguration.getProperties(),
101                     factoryConfiguration.getPropertySeparator());
102             return factory.createExceptionHandler(properties);
103         }
104         return cacheExceptionHandler;
105     }
106 
107 
108     /***
109      * Tries to load the class specified otherwise defaults to null
110      *
111      * @return a map of CacheManagerPeerProviders
112      */
113     public Map<String, CacheManagerPeerProvider> createCachePeerProviders() {
114         String className = null;
115         Map<String, CacheManagerPeerProvider> cacheManagerPeerProviders = new HashMap<String, CacheManagerPeerProvider>();
116         List<FactoryConfiguration> cachePeerProviderFactoryConfiguration =
117                 configuration.getCacheManagerPeerProviderFactoryConfiguration();
118         for (FactoryConfiguration factoryConfiguration : cachePeerProviderFactoryConfiguration) {
119 
120             if (factoryConfiguration != null) {
121                 className = factoryConfiguration.getFullyQualifiedClassPath();
122             }
123             if (className == null) {
124                 LOG.debug("No CachePeerProviderFactoryConfiguration specified. Not configuring a CacheManagerPeerProvider.");
125                 return null;
126             } else {
127                 CacheManagerPeerProviderFactory cacheManagerPeerProviderFactory =
128                         (CacheManagerPeerProviderFactory)
129                                 ClassLoaderUtil.createNewInstance(className);
130                 Properties properties = PropertyUtil.parseProperties(factoryConfiguration.getProperties(),
131                         factoryConfiguration.getPropertySeparator());
132                 CacheManagerPeerProvider cacheManagerPeerProvider =
133                         cacheManagerPeerProviderFactory.createCachePeerProvider(cacheManager, properties);
134                 cacheManagerPeerProviders.put(cacheManagerPeerProvider.getScheme(), cacheManagerPeerProvider);
135 
136             }
137         }
138         return cacheManagerPeerProviders;
139     }
140 
141     /***
142      * Tries to load the class specified otherwise defaults to null
143      */
144     public Map<String, CacheManagerPeerListener> createCachePeerListeners() {
145         String className = null;
146         Map<String, CacheManagerPeerListener> cacheManagerPeerListeners = new HashMap<String, CacheManagerPeerListener>();
147         List<FactoryConfiguration> cacheManagerPeerListenerFactoryConfigurations =
148                 configuration.getCacheManagerPeerListenerFactoryConfigurations();
149         boolean first = true;
150         for (FactoryConfiguration factoryConfiguration : cacheManagerPeerListenerFactoryConfigurations) {
151 
152             if (factoryConfiguration != null) {
153                 className = factoryConfiguration.getFullyQualifiedClassPath();
154             }
155             if (className == null) {
156                 LOG.debug("No CachePeerListenerFactoryConfiguration specified. Not configuring a CacheManagerPeerListener.");
157                 return null;
158             } else {
159                 CacheManagerPeerListenerFactory cacheManagerPeerListenerFactory = (CacheManagerPeerListenerFactory)
160                         ClassLoaderUtil.createNewInstance(className);
161                 Properties properties = PropertyUtil.parseProperties(factoryConfiguration.getProperties(),
162                         factoryConfiguration.getPropertySeparator());
163                 CacheManagerPeerListener cacheManagerPeerListener =
164                         cacheManagerPeerListenerFactory.createCachePeerListener(cacheManager, properties);
165                 cacheManagerPeerListeners.put(cacheManagerPeerListener.getScheme(), cacheManagerPeerListener);
166             }
167         }
168         return cacheManagerPeerListeners;
169     }
170 
171     /***
172      * Tries to load the class specified.
173      *
174      * @return If there is none returns null.
175      * @param cacheManager
176      */
177     public final CacheManagerEventListener createCacheManagerEventListener(CacheManager cacheManager) throws CacheException {
178         String className = null;
179         FactoryConfiguration cacheManagerEventListenerFactoryConfiguration =
180                 configuration.getCacheManagerEventListenerFactoryConfiguration();
181         if (cacheManagerEventListenerFactoryConfiguration != null) {
182             className = cacheManagerEventListenerFactoryConfiguration.getFullyQualifiedClassPath();
183         }
184         if (className == null || className.length() == 0) {
185             LOG.debug("No CacheManagerEventListenerFactory class specified. Skipping...");
186             return null;
187         } else {
188             CacheManagerEventListenerFactory factory = (CacheManagerEventListenerFactory)
189                     ClassLoaderUtil.createNewInstance(className);
190             Properties properties = PropertyUtil.parseProperties(cacheManagerEventListenerFactoryConfiguration.properties,
191                     cacheManagerEventListenerFactoryConfiguration.getPropertySeparator());
192             return factory.createCacheManagerEventListener(cacheManager, properties);
193         }
194     }
195 
196 
197     /***
198      * @return the disk store path, or null if not set.
199      */
200     public final String getDiskStorePath() {
201         DiskStoreConfiguration diskStoreConfiguration = configuration.getDiskStoreConfiguration();
202         if (diskStoreConfiguration == null) {
203             return null;
204         } else {
205             return diskStoreConfiguration.getPath();
206         }
207     }
208 
209     /***
210      * @return the Default Cache
211      * @throws net.sf.ehcache.CacheException if there is no default cache
212      */
213     public final Ehcache createDefaultCache() throws CacheException {
214         CacheConfiguration cacheConfiguration = configuration.getDefaultCacheConfiguration();
215         if (cacheConfiguration == null) {
216             return null;
217         } else {
218             cacheConfiguration.name = Cache.DEFAULT_CACHE_NAME;
219             return createCache(cacheConfiguration);
220         }
221     }
222 
223     /***
224      * Creates unitialised caches for each cache configuration found
225      *
226      * @return an empty set if there are none,
227      */
228     public final Set createCaches() {
229         Set caches = new HashSet();
230         Set cacheConfigurations = configuration.getCacheConfigurations().entrySet();
231         for (Iterator iterator = cacheConfigurations.iterator(); iterator.hasNext();) {
232             Map.Entry entry = (Map.Entry) iterator.next();
233             CacheConfiguration cacheConfiguration = (CacheConfiguration) entry.getValue();
234             Ehcache cache = createCache(cacheConfiguration);
235             caches.add(cache);
236         }
237         return caches;
238     }
239 
240 
241     /***
242      * Calculates the number of caches in the configuration that overflow to disk
243      */
244     public final Integer numberOfCachesThatOverflowToDisk() {
245         int count = 0;
246         Set cacheConfigurations = configuration.getCacheConfigurations().entrySet();
247         for (Iterator iterator = cacheConfigurations.iterator(); iterator.hasNext();) {
248             Map.Entry entry = (Map.Entry) iterator.next();
249             CacheConfiguration cacheConfiguration = (CacheConfiguration) entry.getValue();
250             if (cacheConfiguration.overflowToDisk) {
251                 count++;
252             }
253         }
254         return Integer.valueOf(count);
255     }
256 
257 
258     /***
259      * Calculates the number of caches in the configuration that are diskPersistent
260      */
261     public final Integer numberOfCachesThatAreDiskPersistent() {
262         int count = 0;
263         Set cacheConfigurations = configuration.getCacheConfigurations().entrySet();
264         for (Iterator iterator = cacheConfigurations.iterator(); iterator.hasNext();) {
265             Map.Entry entry = (Map.Entry) iterator.next();
266             CacheConfiguration cacheConfiguration = (CacheConfiguration) entry.getValue();
267             if (cacheConfiguration.isDiskPersistent()) {
268                 count++;
269             }
270         }
271         return Integer.valueOf(count);
272     }
273 
274     /***
275      * Creates a cache from configuration where the configuration cache name matches the given name
276      *
277      * @return the cache, or null if there is no match
278      */
279     final Ehcache createCacheFromName(String name) {
280         CacheConfiguration cacheConfiguration = null;
281         Set cacheConfigurations = configuration.getCacheConfigurations().entrySet();
282         for (Iterator iterator = cacheConfigurations.iterator(); iterator.hasNext();) {
283             Map.Entry entry = (Map.Entry) iterator.next();
284             CacheConfiguration cacheConfigurationCandidate = (CacheConfiguration) entry.getValue();
285             if (cacheConfigurationCandidate.name.equals(name)) {
286                 cacheConfiguration = cacheConfigurationCandidate;
287                 break;
288             }
289         }
290         if (cacheConfiguration == null) {
291             return null;
292         } else {
293             return createCache(cacheConfiguration);
294         }
295     }
296 
297     /***
298      * Create a cache given a cache configuration
299      *
300      * @param cacheConfiguration
301      */
302     final Ehcache createCache(CacheConfiguration cacheConfiguration) {
303         Ehcache cache = new Cache(cacheConfiguration.clone(), null, null);
304         cache = applyCacheExceptionHandler(cacheConfiguration, cache);
305         return cache;
306     }
307 
308     private Ehcache applyCacheExceptionHandler(CacheConfiguration cacheConfiguration, Ehcache cache) {
309         CacheExceptionHandler cacheExceptionHandler =
310                 createCacheExceptionHandler(cacheConfiguration.getCacheExceptionHandlerFactoryConfiguration());
311         cache.setCacheExceptionHandler(cacheExceptionHandler);
312 
313         if (cache.getCacheExceptionHandler() != null) {
314             return ExceptionHandlingDynamicCacheProxy.createProxy(cache);
315         }
316         return cache;
317     }
318 
319     /***
320      * Creates decorated ehcaches for the cache, if any configured in ehcache.xml
321      *
322      * @param cache the cache
323      * @return List of the decorated ehcaches, if any configured in ehcache.xml otherwise returns empty list
324      */
325     public List<Ehcache> createCacheDecorators(Ehcache cache) {
326         CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
327         if (cacheConfiguration == null) {
328             return createDefaultCacheDecorators(cache, configuration.getDefaultCacheConfiguration());
329         }
330         List<CacheDecoratorFactoryConfiguration> cacheDecoratorConfigurations = cacheConfiguration.getCacheDecoratorConfigurations();
331         if (cacheDecoratorConfigurations == null || cacheDecoratorConfigurations.size() == 0) {
332             LOG.debug("CacheDecoratorFactory not configured. Skipping for '" + cache.getName() + "'.");
333             return createDefaultCacheDecorators(cache, configuration.getDefaultCacheConfiguration());
334         }
335         List<Ehcache> result = new ArrayList<Ehcache>();
336         for (CacheDecoratorFactoryConfiguration factoryConfiguration : cacheDecoratorConfigurations) {
337             Ehcache decoratedCache = createDecoratedCache(cache, factoryConfiguration, false);
338             if (decoratedCache != null) {
339                 result.add(decoratedCache);
340             }
341         }
342         for (Ehcache defaultDecoratedCache : createDefaultCacheDecorators(cache, configuration.getDefaultCacheConfiguration())) {
343             result.add(defaultDecoratedCache);
344         }
345         return result;
346     }
347 
348     /***
349      * Creates default cache decorators specified in the default cache configuration if any
350      * @param cache the underlying cache that will be decorated
351      * @param defaultCacheConfiguration default cache configuration
352      * @return list of decorated caches
353      */
354     public static List<Ehcache> createDefaultCacheDecorators(Ehcache cache, CacheConfiguration defaultCacheConfiguration) {
355         if (cache == null) {
356             throw new CacheException("Underlying cache cannot be null when creating decorated caches.");
357         }
358         List<CacheDecoratorFactoryConfiguration> defaultCacheDecoratorConfigurations = defaultCacheConfiguration == null ?
359             null : defaultCacheConfiguration.getCacheDecoratorConfigurations();
360         if (defaultCacheDecoratorConfigurations == null || defaultCacheDecoratorConfigurations.size() == 0) {
361             LOG.debug("CacheDecoratorFactory not configured for defaultCache. Skipping for '" + cache.getName() + "'.");
362             return Collections.emptyList();
363         }
364         List<Ehcache> result = new ArrayList<Ehcache>();
365         Set<String> newCacheNames = new HashSet<String>();
366         for (CacheDecoratorFactoryConfiguration factoryConfiguration : defaultCacheDecoratorConfigurations) {
367             Ehcache decoratedCache = createDecoratedCache(cache, factoryConfiguration, true);
368             if (decoratedCache != null) {
369                 if (newCacheNames.contains(decoratedCache.getName())) {
370                     throw new InvalidConfigurationException(
371                             "Looks like the defaultCache is configured with multiple CacheDecoratorFactory's "
372                                     + "that does not set unique names for newly created caches. Please fix the "
373                                     + "CacheDecoratorFactory and/or the config to set unique names for newly created caches.");
374                 }
375                 newCacheNames.add(decoratedCache.getName());
376                 result.add(decoratedCache);
377             }
378         }
379         return result;
380     }
381 
382     /***
383      * Creates the decorated cache from the decorator config specified. Returns null if the name of the factory class is not specified
384      */
385     private static Ehcache createDecoratedCache(Ehcache cache,
386             CacheConfiguration.CacheDecoratorFactoryConfiguration factoryConfiguration, boolean forDefaultCache) {
387         if (factoryConfiguration == null) {
388             return null;
389         }
390         String className = factoryConfiguration.getFullyQualifiedClassPath();
391         if (className == null) {
392             LOG.debug("CacheDecoratorFactory was specified without the name of the factory. Skipping...");
393             return null;
394         } else {
395             CacheDecoratorFactory factory = (CacheDecoratorFactory) ClassLoaderUtil.createNewInstance(className);
396             Properties properties = PropertyUtil.parseProperties(factoryConfiguration.getProperties(),
397                     factoryConfiguration.getPropertySeparator());
398             if (forDefaultCache) {
399                 return factory.createDefaultDecoratedEhcache(cache, properties);
400             } else {
401                 return factory.createDecoratedEhcache(cache, properties);
402             }
403         }
404     }
405 
406     /***
407      * @return the Configuration used
408      */
409     public final Configuration getConfigurationBean() {
410         return configuration;
411     }
412 }