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 }