KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > dom > DocumentCache


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
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  * $Id: DocumentCache.java,v 1.15 2004/02/16 22:54:59 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.dom;
21
22 import java.io.File JavaDoc;
23 import java.io.PrintWriter JavaDoc;
24 import java.net.URL JavaDoc;
25 import java.net.URLConnection JavaDoc;
26 import java.net.URLDecoder JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.Hashtable JavaDoc;
29
30 import javax.xml.parsers.ParserConfigurationException JavaDoc;
31 import javax.xml.parsers.SAXParser JavaDoc;
32 import javax.xml.parsers.SAXParserFactory JavaDoc;
33 import javax.xml.transform.TransformerException JavaDoc;
34 import javax.xml.transform.sax.SAXSource JavaDoc;
35
36 import org.apache.xalan.xsltc.DOM;
37 import org.apache.xalan.xsltc.DOMCache;
38 import org.apache.xalan.xsltc.DOMEnhancedForDTM;
39 import org.apache.xalan.xsltc.Translet;
40 import org.apache.xalan.xsltc.runtime.AbstractTranslet;
41 import org.apache.xalan.xsltc.runtime.BasisLibrary;
42 import org.apache.xalan.xsltc.runtime.Constants;
43 import org.apache.xml.utils.SystemIDResolver;
44
45 import org.xml.sax.InputSource JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import org.xml.sax.XMLReader JavaDoc;
48
49 /**
50  * @author Morten Jorgensen
51  */

52 public final class DocumentCache implements DOMCache {
53
54     private int _size;
55     private Hashtable JavaDoc _references;
56     private String JavaDoc[] _URIs;
57     private int _count;
58     private int _current;
59     private SAXParser JavaDoc _parser;
60     private XMLReader JavaDoc _reader;
61     private XSLTCDTMManager _dtmManager;
62
63     private static final int REFRESH_INTERVAL = 1000;
64
65     /*
66      * Inner class containing a DOMImpl object and DTD handler
67      */

68     public final class CachedDocument {
69     
70     // Statistics data
71
private long _firstReferenced;
72     private long _lastReferenced;
73     private long _accessCount;
74     private long _lastModified;
75     private long _lastChecked;
76     private long _buildTime;
77
78     // DOM and DTD handler references
79
private DOMEnhancedForDTM _dom = null;
80     
81     /**
82      * Constructor - load document and initialise statistics
83      */

84     public CachedDocument(String JavaDoc uri) {
85         // Initialise statistics variables
86
final long stamp = System.currentTimeMillis();
87         _firstReferenced = stamp;
88         _lastReferenced = stamp;
89         _accessCount = 0;
90         loadDocument(uri);
91
92         _buildTime = System.currentTimeMillis() - stamp;
93     }
94
95     /**
96      * Loads the document and updates build-time (latency) statistics
97      */

98     public void loadDocument(String JavaDoc uri) {
99
100         try {
101         final long stamp = System.currentTimeMillis();
102                 _dom = (DOMEnhancedForDTM)_dtmManager.getDTM(
103                                  new SAXSource JavaDoc(_reader, new InputSource JavaDoc(uri)),
104                                  false, null, true, false);
105         _dom.setDocumentURI(uri);
106
107         // The build time can be used for statistics for a better
108
// priority algorithm (currently round robin).
109
final long thisTime = System.currentTimeMillis() - stamp;
110         if (_buildTime > 0)
111             _buildTime = (_buildTime + thisTime) >>> 1;
112         else
113             _buildTime = thisTime;
114         }
115         catch (Exception JavaDoc e) {
116         _dom = null;
117         }
118     }
119
120     public DOM getDocument() { return(_dom); }
121
122     public long getFirstReferenced() { return(_firstReferenced); }
123
124     public long getLastReferenced() { return(_lastReferenced); }
125
126     public long getAccessCount() { return(_accessCount); }
127
128     public void incAccessCount() { _accessCount++; }
129
130     public long getLastModified() { return(_lastModified); }
131
132     public void setLastModified(long t){ _lastModified = t; }
133
134     public long getLatency() { return(_buildTime); }
135
136     public long getLastChecked() { return(_lastChecked); }
137     
138     public void setLastChecked(long t) { _lastChecked = t; }
139
140     public long getEstimatedSize() {
141         if (_dom != null)
142         return(_dom.getSize() << 5); // ???
143
else
144         return(0);
145     }
146
147     }
148
149     /**
150      * DocumentCache constructor
151      */

152     public DocumentCache(int size) throws SAXException JavaDoc {
153         this(size, null);
154         try {
155             _dtmManager = (XSLTCDTMManager)XSLTCDTMManager.getDTMManagerClass()
156                                                           .newInstance();
157         } catch (Exception JavaDoc e) {
158             throw new SAXException JavaDoc(e);
159         }
160     }
161
162     /**
163      * DocumentCache constructor
164      */

165     public DocumentCache(int size, XSLTCDTMManager dtmManager) throws SAXException JavaDoc {
166     _dtmManager = dtmManager;
167     _count = 0;
168     _current = 0;
169     _size = size;
170     _references = new Hashtable JavaDoc(_size+2);
171     _URIs = new String JavaDoc[_size];
172
173     try {
174         // Create a SAX parser and get the XMLReader object it uses
175
final SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
176         try {
177         factory.setFeature(Constants.NAMESPACE_FEATURE,true);
178         }
179         catch (Exception JavaDoc e) {
180         factory.setNamespaceAware(true);
181         }
182         _parser = factory.newSAXParser();
183         _reader = _parser.getXMLReader();
184     }
185     catch (ParserConfigurationException JavaDoc e) {
186         BasisLibrary.runTimeError(BasisLibrary.NAMESPACES_SUPPORT_ERR);
187         System.exit(-1);
188     }
189     }
190
191     /**
192      * Returns the time-stamp for a document's last update
193      */

194     private final long getLastModified(String JavaDoc uri) {
195     try {
196         URL JavaDoc url = new URL JavaDoc(uri);
197         URLConnection JavaDoc connection = url.openConnection();
198         long timestamp = connection.getLastModified();
199         // Check for a "file:" URI (courtesy of Brian Ewins)
200
if (timestamp == 0){ // get 0 for local URI
201
if ("file".equals(url.getProtocol())){
202                 File JavaDoc localfile = new File JavaDoc(URLDecoder.decode(url.getFile()));
203                 timestamp = localfile.lastModified();
204             }
205         }
206         return(timestamp);
207     }
208     // Brutal handling of all exceptions
209
catch (Exception JavaDoc e) {
210         return(System.currentTimeMillis());
211     }
212     }
213
214     /**
215      *
216      */

217     private CachedDocument lookupDocument(String JavaDoc uri) {
218     return((CachedDocument)_references.get(uri));
219     }
220
221     /**
222      *
223      */

224     private synchronized void insertDocument(String JavaDoc uri, CachedDocument doc) {
225     if (_count < _size) {
226         // Insert out URI in circular buffer
227
_URIs[_count++] = uri;
228         _current = 0;
229     }
230     else {
231         // Remove oldest URI from reference Hashtable
232
_references.remove(_URIs[_current]);
233         // Insert our URI in circular buffer
234
_URIs[_current] = uri;
235         if (++_current >= _size) _current = 0;
236     }
237     _references.put(uri, doc);
238     }
239
240     /**
241      *
242      */

243     private synchronized void replaceDocument(String JavaDoc uri, CachedDocument doc) {
244     CachedDocument old = (CachedDocument)_references.get(uri);
245     if (doc == null)
246         insertDocument(uri, doc);
247     else
248         _references.put(uri, doc);
249     }
250
251     /**
252      * Returns a document either by finding it in the cache or
253      * downloading it and putting it in the cache.
254      */

255     public DOM retrieveDocument(String JavaDoc baseURI, String JavaDoc href, Translet trs) {
256     CachedDocument doc;
257
258     String JavaDoc uri = href;
259     if (baseURI != null && !baseURI.equals("")) {
260         try {
261             uri = SystemIDResolver.getAbsoluteURI(uri, baseURI);
262         } catch (TransformerException JavaDoc te) {
263             // ignore
264
}
265     }
266     
267     // Try to get the document from the cache first
268
if ((doc = lookupDocument(uri)) == null) {
269         doc = new CachedDocument(uri);
270         if (doc == null) return null; // better error handling needed!!!
271
doc.setLastModified(getLastModified(uri));
272         insertDocument(uri, doc);
273     }
274     // If the document is in the cache we must check if it is still valid
275
else {
276         long now = System.currentTimeMillis();
277         long chk = doc.getLastChecked();
278         doc.setLastChecked(now);
279         // Has the modification time for this file been checked lately?
280
if (now > (chk + REFRESH_INTERVAL)) {
281         doc.setLastChecked(now);
282         long last = getLastModified(uri);
283         // Reload document if it has been modified since last download
284
if (last > doc.getLastModified()) {
285             doc = new CachedDocument(uri);
286             if (doc == null) return null;
287             doc.setLastModified(getLastModified(uri));
288             replaceDocument(uri, doc);
289         }
290         }
291         
292     }
293
294     // Get the references to the actual DOM and DTD handler
295
final DOM dom = doc.getDocument();
296
297     // The dom reference may be null if the URL pointed to a
298
// non-existing document
299
if (dom == null) return null;
300
301     doc.incAccessCount(); // For statistics
302

303     final AbstractTranslet translet = (AbstractTranslet)trs;
304
305     // Give the translet an early opportunity to extract any
306
// information from the DOM object that it would like.
307
translet.prepassDocument(dom);
308
309     return(doc.getDocument());
310     }
311
312     /**
313      * Outputs the cache statistics
314      */

315     public void getStatistics(PrintWriter JavaDoc out) {
316     out.println("<h2>DOM cache statistics</h2><center><table border=\"2\">"+
317             "<tr><td><b>Document URI</b></td>"+
318             "<td><center><b>Build time</b></center></td>"+
319             "<td><center><b>Access count</b></center></td>"+
320             "<td><center><b>Last accessed</b></center></td>"+
321             "<td><center><b>Last modified</b></center></td></tr>");
322
323     for (int i=0; i<_count; i++) {
324         CachedDocument doc = (CachedDocument)_references.get(_URIs[i]);
325         out.print("<tr><td><a HREF=\""+_URIs[i]+"\">"+
326               "<font size=-1>"+_URIs[i]+"</font></a></td>");
327         out.print("<td><center>"+doc.getLatency()+"ms</center></td>");
328         out.print("<td><center>"+doc.getAccessCount()+"</center></td>");
329         out.print("<td><center>"+(new Date JavaDoc(doc.getLastReferenced()))+
330               "</center></td>");
331         out.print("<td><center>"+(new Date JavaDoc(doc.getLastModified()))+
332               "</center></td>");
333         out.println("</tr>");
334     }
335
336     out.println("</table></center>");
337     }
338 }
339
Popular Tags