KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > cache > xslt > TemplateCache


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.xslt;
11
12 import org.mmbase.cache.Cache;
13 import javax.xml.transform.Templates JavaDoc;
14 import javax.xml.transform.Source JavaDoc;
15 import javax.xml.transform.stream.StreamSource JavaDoc;
16 import org.mmbase.util.ResourceLoader;
17 import org.mmbase.util.ResourceWatcher;
18
19 import java.util.Map JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import javax.xml.transform.URIResolver JavaDoc;
22
23 import org.mmbase.util.logging.Logger;
24 import org.mmbase.util.logging.Logging;
25
26 /**
27  * A cache for XSL transformation templates. A template can be based
28  * on a file, or on a string. In the first case the cache key is based
29  * on the file name, and the cache entry is invalidated if the file
30  * changes (so, if you uses 'imports' in the XSL template, you have to
31  * touch the file which imports, if the imported files changes). If
32  * the template is based on a string, then the string itself serves as
33  * a key.
34  *
35  * @author Michiel Meeuwissen
36  * @version $Id: TemplateCache.java,v 1.15 2006/02/13 18:02:35 michiel Exp $
37  * @since MMBase-1.6
38  */

39 public class TemplateCache extends Cache {
40
41     private static final Logger log = Logging.getLoggerInstance(TemplateCache.class);
42
43     private static int cacheSize = 50;
44     private static TemplateCache cache;
45
46     /**
47      * The Source-s which are based on a file, are added to this FileWatcher, which wil invalidate
48      * the corresponding cache entry when the file changes.
49      */

50     private static ResourceWatcher templateWatcher = new ResourceWatcher(ResourceLoader.getWebRoot()) {
51             public void onChange(String JavaDoc file) {
52                 // invalidate cache.
53
if (log.isDebugEnabled()) log.debug("Removing " + file.toString() + " from cache");
54                 synchronized(cache) {
55                     int removed = cache.remove(file);
56                     if (removed == 0) {
57                         log.error("Could not remove " + file.toString() + " Template(s) from cache!");
58                     } else {
59                         if (log.isDebugEnabled()) log.debug("Removed " + removed + " entries from cache");
60                     }
61                 }
62                 this.remove(file); // should call remove of FileWatcher, not of TemplateCache again.
63
}
64         };
65
66     /**
67      * Returns the Template cache.
68      */

69     public static TemplateCache getCache() {
70         return cache;
71     }
72
73     static {
74         cache = new TemplateCache(cacheSize);
75         putCache(cache);
76         templateWatcher.setDelay(10 * 1000); // check every 10 secs if one of the stream source templates was change
77
templateWatcher.start();
78
79     }
80
81     public String JavaDoc getName() {
82         return "XSLTemplates";
83     }
84     public String JavaDoc getDescription() {
85         return "XSL Templates";
86     }
87
88     /**
89      * Creates the XSL Template Cache.
90      */

91     private TemplateCache(int size) {
92         super(size);
93     }
94
95     /**
96      * Object to use as a key in the Caches.
97      * Contains the systemid of the XSLT object (if there is one)
98      * and the URIResolver.
99      */

100     private class Key {
101         private String JavaDoc src;
102         private URIResolver JavaDoc uri;
103         Key(Source JavaDoc src, URIResolver JavaDoc uri) {
104             this.src = src.getSystemId();
105             this.uri = uri;
106         }
107         public boolean equals(Object JavaDoc o) {
108             if (o instanceof Key) {
109                 Key k = (Key) o;
110                 return (src == null ? k.src == null : src.equals(k.src)) &&
111                         (uri == null ? k.uri == null : uri.equals(k.uri));
112             }
113             return false;
114         }
115         public int hashCode() {
116             return 32 * (src == null ? 0 : src.hashCode()) + (uri == null ? 0 : uri.hashCode());
117         }
118         /**
119          * Returns File object or null
120          */

121         String JavaDoc getURL() {
122             if (src == null) return null;
123             try {
124                 return src;
125             } catch (Exception JavaDoc e) {
126                 return null;
127             }
128         }
129         public String JavaDoc toString() {
130             return "" + src + "/" + uri;
131         }
132
133     }
134
135     /**
136      * Remove all entries associated wit a certain url (used by FileWatcher).
137      *
138      * @param The file under concern
139      * @return The number of cache entries removed
140      */

141
142     private int remove(String JavaDoc file) {
143         int removed = 0;
144         Iterator JavaDoc i = entrySet().iterator();
145         if (log.isDebugEnabled()) log.debug("trying to remove keys containing " + file);
146         while (i.hasNext()) {
147             Key mapKey = (Key) ((Map.Entry JavaDoc) i.next()).getKey();
148             if (mapKey.getURL().equals(file)) {
149                 if(remove(mapKey) != null) {
150                     removed++;
151                 } else {
152                     log.warn("Could not remove " + mapKey);
153                 }
154             }
155         }
156         return removed;
157     }
158
159
160     public Templates JavaDoc getTemplates(Source JavaDoc src) {
161         return getTemplates(src, null);
162     }
163     public Templates JavaDoc getTemplates(Source JavaDoc src, URIResolver JavaDoc uri) {
164         Key key = new Key(src, uri);
165         if (log.isDebugEnabled()) log.debug("Getting from cache " + key);
166         return (Templates JavaDoc) get(key);
167     }
168
169     /**
170      * When removing an entry (because of LRU e.g), then also the FileWatcher must be removed.
171      */

172
173     public synchronized Object JavaDoc remove(Object JavaDoc key) {
174         if (log.isDebugEnabled()) log.debug("Removing " + key);
175         Object JavaDoc result = super.remove(key);
176         String JavaDoc url = ((Key) key).getURL();
177         remove(url);
178         templateWatcher.remove(url);
179         return result;
180     }
181
182     /**
183      * You can only put Source/Templates values in the cache, so this throws an Exception.
184      *
185      * @throws RuntimeException
186      **/

187
188     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
189         throw new RuntimeException JavaDoc("wrong types in cache");
190     }
191     public Object JavaDoc put(Source JavaDoc src, Templates JavaDoc value) {
192         return put(src, value, null);
193     }
194     public Object JavaDoc put(Source JavaDoc src, Templates JavaDoc value, URIResolver JavaDoc uri) {
195         if (! isActive()) {
196             if (log.isDebugEnabled()) {
197                 log.debug("XSLT Cache is not active");
198             }
199             return null;
200         }
201         Key key = new Key(src, uri);
202         Object JavaDoc res = super.put(key, value);
203         log.service("Put xslt in cache with key " + key);
204         templateWatcher.add(key.getURL());
205         if (log.isDebugEnabled()) {
206             log.debug("have set watch on " + key.getURL());
207             log.trace("currently watching: " + templateWatcher);
208         }
209         return res;
210     }
211
212
213     /**
214      * Invocation of the class from the commandline for testing
215      */

216     public static void main(String JavaDoc[] argv) {
217         log.setLevel(org.mmbase.util.logging.Level.DEBUG);
218         try {
219             java.io.File JavaDoc xslFile = java.io.File.createTempFile("templatecachetest", ".xsl");
220             log.info("using file " + xslFile);
221             java.io.FileWriter JavaDoc fw = new java.io.FileWriter JavaDoc(xslFile);
222             fw.write("<xsl:stylesheet version = \"1.1\" xmlns:xsl =\"http://www.w3.org/1999/XSL/Transform\"></xsl:stylesheet>");
223             fw.close();
224             for (int i =0; i<10; i++) {
225                 TemplateCache cache = TemplateCache.getCache();
226                 Source JavaDoc xsl = new StreamSource JavaDoc(xslFile);
227                 org.mmbase.util.xml.URIResolver uri = new org.mmbase.util.xml.URIResolver(xslFile.getParentFile());
228                 Templates JavaDoc cachedXslt = cache.getTemplates(xsl, uri);
229                 log.info("template cache size " + cache.size() + " entries: " + cache.entrySet());
230                 if (cachedXslt == null) {
231                     cachedXslt = FactoryCache.getCache().getFactory(uri).newTemplates(xsl);
232                     cache.put(xsl, cachedXslt, uri);
233                 } else {
234                     if (log.isDebugEnabled()) log.debug("Used xslt from cache with " + xsl.getSystemId());
235                 }
236             }
237             xslFile.delete();
238         } catch (Exception JavaDoc e) {
239             System.err.println("hmm?" + e);
240         }
241
242
243     }
244
245 }
246
Popular Tags