Source code: org/apache/batik/bridge/DocumentLoader.java
1 /*
2
3 Copyright 2000-2004 The Apache Software Foundation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 */
18 package org.apache.batik.bridge;
19
20 import java.io.InputStream;
21 import java.io.IOException;
22 import java.util.HashMap;
23
24 import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
25 import org.apache.batik.dom.svg.SVGDocumentFactory;
26 import org.apache.batik.dom.util.DocumentDescriptor;
27 import org.apache.batik.util.CleanerThread;
28
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.svg.SVGDocument;
32
33 /**
34 * This class is responsible on loading an SVG document and
35 * maintaining a cache.
36 *
37 * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
38 * @version $Id: DocumentLoader.java,v 1.23 2005/01/03 10:48:05 deweese Exp $
39 */
40 public class DocumentLoader {
41
42 /**
43 * The document factory used to create the document according a
44 * DOM implementation.
45 */
46 protected SVGDocumentFactory documentFactory;
47
48 /**
49 * The map that contains the Document indexed by the URI.
50 *
51 * WARNING: tagged private as no element of this Map should be
52 * referenced outise of this class
53 */
54 protected HashMap cacheMap = new HashMap();
55
56 /**
57 * The user agent.
58 */
59 protected UserAgent userAgent;
60
61 /**
62 * Constructs a new <tt>DocumentLoader</tt>.
63 */
64 protected DocumentLoader() { }
65
66 /**
67 * Constructs a new <tt>DocumentLoader</tt> with the specified XML parser.
68 * @param userAgent the user agent to use
69 */
70 public DocumentLoader(UserAgent userAgent) {
71 this.userAgent = userAgent;
72 documentFactory = new SAXSVGDocumentFactory
73 (userAgent.getXMLParserClassName(), true);
74 documentFactory.setValidating(userAgent.isXMLParserValidating());
75 }
76
77 public Document checkCache(String uri) {
78 int n = uri.lastIndexOf('/');
79 if (n == -1)
80 n = 0;
81 n = uri.indexOf('#', n);
82 if (n != -1) {
83 uri = uri.substring(0, n);
84 }
85 DocumentState state;
86 synchronized (cacheMap) {
87 state = (DocumentState)cacheMap.get(uri);
88 }
89 if (state != null)
90 return state.getDocument();
91 return null;
92 }
93
94 /**
95 * Returns a document from the specified uri.
96 * @param uri the uri of the document
97 * @exception IOException if an I/O error occured while loading
98 * the document
99 */
100 public Document loadDocument(String uri) throws IOException {
101 Document ret = checkCache(uri);
102 if (ret != null)
103 return ret;
104
105 SVGDocument document = documentFactory.createSVGDocument(uri);
106
107 DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
108 DocumentState state = new DocumentState(uri, document, desc);
109 synchronized (cacheMap) {
110 cacheMap.put(uri, state);
111 }
112
113 return state.getDocument();
114 }
115
116 /**
117 * Returns a document from the specified uri.
118 * @param uri the uri of the document
119 * @exception IOException if an I/O error occured while loading
120 * the document
121 */
122 public Document loadDocument(String uri, InputStream is)
123 throws IOException {
124 Document ret = checkCache(uri);
125 if (ret != null)
126 return ret;
127
128 SVGDocument document = documentFactory.createSVGDocument(uri, is);
129
130 DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
131 DocumentState state = new DocumentState(uri, document, desc);
132 synchronized (cacheMap) {
133 cacheMap.put(uri, state);
134 }
135
136 return state.getDocument();
137 }
138
139 /**
140 * Returns the userAgent used by this DocumentLoader
141 */
142 public UserAgent getUserAgent(){
143 return userAgent;
144 }
145
146 /**
147 * Disposes and releases all resources allocated by this document loader.
148 */
149 public void dispose() {
150 // new Exception("purge the cache").printStackTrace();
151 synchronized (cacheMap) {
152 cacheMap.clear();
153 }
154 }
155
156 /**
157 * Returns the line in the source code of the specified element or
158 * -1 if not found.
159 *
160 * @param e the element
161 * @return -1 the document has been removed from the cache or has not
162 * been loaded by this document loader.
163 */
164 public int getLineNumber(Element e) {
165 String uri = ((SVGDocument)e.getOwnerDocument()).getURL();
166 DocumentState state;
167 synchronized (cacheMap) {
168 state = (DocumentState)cacheMap.get(uri);
169 }
170 if (state == null) {
171 return -1;
172 } else {
173 return state.desc.getLocationLine(e);
174 }
175 }
176
177 /**
178 * A simple class that contains a Document and its number of nodes.
179 */
180 private class DocumentState extends CleanerThread.SoftReferenceCleared {
181
182 private String uri;
183 private DocumentDescriptor desc;
184
185 public DocumentState(String uri,
186 Document document,
187 DocumentDescriptor desc) {
188 super(document);
189 this.uri = uri;
190 this.desc = desc;
191 }
192
193 public void cleared() {
194 synchronized (cacheMap) {
195 cacheMap.remove(uri);
196 }
197 }
198
199 public DocumentDescriptor getDocumentDescriptor() {
200 return desc;
201 }
202
203 public String getURI() {
204 return uri;
205 }
206
207 public Document getDocument() {
208 return (Document)get();
209 }
210 }
211
212 }