KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > cache > CacheManager


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.cache;
11
12 import java.util.*;
13
14 import org.mmbase.util.*;
15 import org.mmbase.util.logging.Logger;
16 import org.mmbase.util.logging.Logging;
17 import org.mmbase.util.xml.DocumentReader;
18 import org.w3c.dom.Element JavaDoc;
19
20 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
21
22
23
24 /**
25  * Cache manager manages the static methods of {@link Cache}. If you prefer you can call them on this in stead.
26  *
27  * @since MMBase-1.8
28  * @version $Id: CacheManager.java,v 1.6.2.1 2006/09/04 10:48:30 michiel Exp $
29  */

30 public class CacheManager {
31
32     private static final Logger log = Logging.getLoggerInstance(CacheManager.class);
33
34     /**
35      * All registered caches
36      */

37     private static final Map caches = new ConcurrentHashMap();
38
39     /**
40      * Returns the Cache with a certain name. To be used in combination with getCaches(). If you
41      * need a certain cache, you can just as well call the non-static 'getCache' which is normally
42      * in cache singletons.
43      *
44      * @see #getCaches
45      */

46     public static Cache getCache(String JavaDoc name) {
47         return (Cache) caches.get(name);
48     }
49
50     /**
51      * Returns the names of all caches.
52      *
53      * @return A Set containing the names of all caches.
54      */

55     public static Set getCaches() {
56         return Collections.unmodifiableSet(caches.keySet());
57     }
58
59
60     /**
61      * Puts a cache in the caches repository. This function will be
62      * called in the static of childs, therefore it is protected.
63      *
64      * @param cache A cache.
65      * @return The previous cache of the same type (stored under the same name)
66      */

67     protected static Cache putCache(Cache cache) {
68         Cache old = (Cache) caches.put(cache.getName(), cache);
69         configure(configReader, cache.getName());
70         return old;
71     }
72
73     /**
74      * Configures the caches using a config File. There is only one
75      * config file now so the argument is a little overdone, but it
76      * doesn't harm.
77      */

78
79     private static void configure(DocumentReader file) {
80         configure(file, null);
81     }
82
83     private static DocumentReader configReader = null;
84
85     /**
86      * As configure, but it only changes the configuration of the cache 'only'.
87      * This is called on first use of a cache.
88      */

89     private static void configure(DocumentReader xmlReader, String JavaDoc only) {
90         if (xmlReader == null) {
91             return; // nothing can be done...
92
}
93
94         if (only == null) {
95             log.service("Configuring caches with " + xmlReader.getSystemId());
96         } else {
97             if (log.isDebugEnabled()) log.debug("Configuring cache " + only + " with file " + xmlReader.getSystemId());
98         }
99
100         Iterator e = xmlReader.getChildElements("caches", "cache");
101         while (e.hasNext()) {
102             Element JavaDoc cacheElement = (Element JavaDoc) e.next();
103             String JavaDoc cacheName = cacheElement.getAttribute("name");
104             if (only != null && ! only.equals(cacheName)) {
105                 continue;
106             }
107             Cache cache = getCache(cacheName);
108             if (cache == null) {
109                 log.service("No cache " + cacheName + " is present (perhaps not used yet?)");
110             } else {
111                 String JavaDoc clazz = xmlReader.getElementValue(xmlReader.getElementByPath(cacheElement, "cache.implementation.class"));
112                 if(!"".equals(clazz)) {
113                     Element JavaDoc cacheImpl = xmlReader.getElementByPath(cacheElement, "cache.implementation");
114                     Iterator it = xmlReader.getChildElements(cacheImpl, "param");
115                     Map configValues = new HashMap();
116                     while (it.hasNext()) {
117                         Element JavaDoc attrNode = (Element JavaDoc)it.next();
118                         String JavaDoc paramName = xmlReader.getElementAttributeValue(attrNode, "name");
119                         String JavaDoc paramValue = xmlReader.getElementValue(attrNode);
120                         configValues.put(paramName, paramValue);
121                     }
122                     cache.setImplementation(clazz, configValues);
123                 }
124                 String JavaDoc status = xmlReader.getElementValue(xmlReader.getElementByPath(cacheElement, "cache.status"));
125                 cache.setActive(status.equalsIgnoreCase("active"));
126                 try {
127                     Integer JavaDoc size = new Integer JavaDoc(xmlReader.getElementValue(xmlReader.getElementByPath(cacheElement, "cache.size")));
128                     cache.setMaxSize(size.intValue());
129                     log.service("Setting " + cacheName + " " + status + " with size " + size);
130                 } catch (NumberFormatException JavaDoc nfe) {
131                     log.error("Could not configure cache " + cacheName + " because the size was wrong: " + nfe.toString());
132                 }
133                 String JavaDoc maxSize = xmlReader.getElementValue(xmlReader.getElementByPath(cacheElement, "cache.maxEntrySize"));
134                 if (!"".equals(maxSize)) {
135                     try {
136                         cache.maxEntrySize = Integer.parseInt(maxSize);
137                         log.service("Setting maximum entry size on " + cacheName + ": " + cache.maxEntrySize + " bytes ");
138                     } catch (NumberFormatException JavaDoc nfe2) {
139                         log.error("Could not set max entry size cache of " + cacheName + " because " + nfe2.toString());
140                     }
141                 } else {
142                     if (cache.getDefaultMaxEntrySize() > 0) {
143                         log.service("No max entry size specified for this cache taking default " + cache.getDefaultMaxEntrySize() + " bytes");
144                     }
145                     cache.maxEntrySize = cache.getDefaultMaxEntrySize();
146                     //now see if we have to load cache release strategies for this lovely cache...
147
if(cache instanceof QueryResultCache){
148                         QueryResultCache queryCache = (QueryResultCache) cache;
149                         //first remove all present strategies (this might be a reconfiguration)
150
queryCache.getReleaseStrategy().removeAllStrategies();
151                         log.debug("found a SearchQueryCache: " + cacheName);
152                         //see if there are globally configured release strategies
153
List strategies = findReleaseStrategies(xmlReader, xmlReader.getElementByPath("caches"));
154                         if(strategies != null){
155                             log.debug("found " + strategies.size() + " globally configured strategies");
156                             queryCache.addReleaseStrategies(strategies);
157                         }
158
159                         //see if there are strategies configured for this cache
160
strategies = findReleaseStrategies(xmlReader, cacheElement);
161                         if(strategies != null){
162                             log.debug("found " + strategies.size() + " strategies for cache " + cache.getName());
163                             queryCache.addReleaseStrategies(strategies);
164                         }
165                         if (queryCache.getReleaseStrategy().size() == 0) {
166                             log.warn("No release-strategies configured for cache " + queryCache + " (nor globally configured); falling back to basic release strategy");
167                             queryCache.addReleaseStrategy(new BasicReleaseStrategy());
168                         }
169                     }
170                 }
171             }
172         }
173     }
174
175     /**
176      * @param reader xml document reader instance
177      * @param parentElement the parent of the releaseStrategies element
178      * @return List of ReleaseStrategy instances
179      * @since 1.8
180      */

181     private static List findReleaseStrategies(DocumentReader reader, Element JavaDoc parentElement) {
182         List result = new ArrayList();
183         Iterator strategyParentIterator = reader.getChildElements(parentElement, "releaseStrategies");
184         if(!strategyParentIterator.hasNext()){
185             return null;
186         }else{
187             parentElement = (Element JavaDoc) strategyParentIterator.next();
188
189             //now find the strategies
190
Iterator strategyIterator = reader.getChildElements(parentElement, "strategy");
191             while(strategyIterator.hasNext()){
192                 String JavaDoc strategyClassName =
193                     reader.getElementValue((Element JavaDoc)strategyIterator.next());
194                 log.debug("found strategy in configuration: "+ strategyClassName);
195                 try {
196                     ReleaseStrategy releaseStrategy = getStrategyInstance(strategyClassName);
197                     log.debug("still there after trying to get a strategy instance... Instance is " + releaseStrategy==null ? "null" : "not null");
198
199                     //check if we got something
200
if(releaseStrategy != null){
201
202                         result.add(releaseStrategy);
203                         log.debug("Successfully created and added "+releaseStrategy.getName() + " instance");
204                     }else{
205                         log.error("release strategy instance is null.");
206                     }
207
208                 } catch (CacheConfigurationException e1) {
209                     // here we throw a runtime exception, because there is
210
// no way we can deal with this error.
211
throw new RuntimeException JavaDoc("Cache configuration error: " + e1.toString(), e1);
212                 }
213             }
214         }
215         return result;
216     }
217
218     /**
219      * I moved this code away from <code>configure()</code> just to
220      * clean up a little, and keep the code readable
221      * XXX: Who is I?
222      * @param strategyClassName
223      * @since 1.8
224      */

225     private static ReleaseStrategy getStrategyInstance(String JavaDoc strategyClassName) throws CacheConfigurationException {
226         log.debug("getStrategyInstance()");
227         Class JavaDoc strategyClass;
228         ReleaseStrategy strategy = null;
229         try {
230             strategyClass = Class.forName(strategyClassName);
231             strategy = (ReleaseStrategy) strategyClass.newInstance();
232             log.debug("created strategy instance: "+strategyClassName);
233
234         } catch (ClassCastException JavaDoc e){
235             log.debug(strategyClassName + " can not be cast to strategy");
236             throw new CacheConfigurationException(strategyClassName + " can not be cast to strategy");
237         } catch (ClassNotFoundException JavaDoc e) {
238             log.debug("exception getStrategyInstance()");
239             throw new CacheConfigurationException("Class "+strategyClassName +
240                     "was not found");
241         } catch (InstantiationException JavaDoc e) {
242             log.debug("exception getStrategyInstance()");
243             throw new CacheConfigurationException("A new instance of " + strategyClassName +
244                     "could not be created: " + e.toString());
245         } catch (IllegalAccessException JavaDoc e) {
246             log.debug("exception getStrategyInstance()");
247             throw new CacheConfigurationException("A new instance of " + strategyClassName +
248                     "could not be created: " + e.toString());
249         }
250         log.debug("exit getStrategyInstance()");
251         return strategy;
252     }
253
254     /**
255      * The caches can be configured with an XML file, this file can
256      * be changed which causes the caches to be reconfigured automaticly.
257      */

258     private static ResourceWatcher configWatcher = new ResourceWatcher () {
259             public void onChange(String JavaDoc resource) {
260                 try {
261                     configReader = new DocumentReader(ResourceLoader.getConfigurationRoot().getInputSource(resource), Cache.class);
262                 } catch (Exception JavaDoc e) {
263                     log.error(e);
264                     return;
265                 }
266                 configure(configReader);
267             }
268         };
269
270     static { // configure
271
log.debug("Static init of Caches");
272         configWatcher.add("caches.xml");
273         configWatcher.onChange("caches.xml");
274         configWatcher.setDelay(10 * 1000); // check every 10 secs if config changed
275
configWatcher.start();
276
277     }
278
279
280     public static int getTotalByteSize() {
281         Iterator i = caches.entrySet().iterator();
282         int len = 0;
283         SizeOf sizeof = new SizeOf();
284         while (i.hasNext()) {
285             Map.Entry entry = (Map.Entry) i.next();
286             len += sizeof.sizeof(entry.getKey()) + sizeof.sizeof(entry.getValue());
287         }
288         return len;
289     }
290
291     /**
292      * Clears and dereferences all caches. To be used on shutdown of MMBase.
293      * @since MMBase-1.8.1
294      */

295     public static void shutdown() {
296         log.info("Clearing all caches");
297         Iterator i = caches.values().iterator();
298         while (i.hasNext()) {
299             Cache cache = (Cache) i.next();
300             cache.clear();
301             i.remove();
302         }
303     }
304
305 }
306
Popular Tags