001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import java.io.InputStream;
022: import java.io.IOException;
023: import java.util.HashMap;
024:
025: import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
026: import org.apache.batik.dom.svg.SVGDocumentFactory;
027: import org.apache.batik.dom.util.DocumentDescriptor;
028: import org.apache.batik.util.CleanerThread;
029:
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.svg.SVGDocument;
033:
034: /**
035: * This class is responsible on loading an SVG document and
036: * maintaining a cache.
037: *
038: * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
039: * @version $Id: DocumentLoader.java 475685 2006-11-16 11:16:05Z cam $
040: */
041: public class DocumentLoader {
042:
043: /**
044: * The document factory used to create the document according a
045: * DOM implementation.
046: */
047: protected SVGDocumentFactory documentFactory;
048:
049: /**
050: * The map that contains the Document indexed by the URI.
051: *
052: * WARNING: tagged private as no element of this Map should be
053: * referenced outise of this class
054: */
055: protected HashMap cacheMap = new HashMap();
056:
057: /**
058: * The user agent.
059: */
060: protected UserAgent userAgent;
061:
062: /**
063: * Constructs a new <tt>DocumentLoader</tt>.
064: */
065: protected DocumentLoader() {
066: }
067:
068: /**
069: * Constructs a new <tt>DocumentLoader</tt> with the specified XML parser.
070: * @param userAgent the user agent to use
071: */
072: public DocumentLoader(UserAgent userAgent) {
073: this .userAgent = userAgent;
074: documentFactory = new SAXSVGDocumentFactory(userAgent
075: .getXMLParserClassName(), true);
076: documentFactory
077: .setValidating(userAgent.isXMLParserValidating());
078: }
079:
080: public Document checkCache(String uri) {
081: int n = uri.lastIndexOf('/');
082: if (n == -1)
083: n = 0;
084: n = uri.indexOf('#', n);
085: if (n != -1) {
086: uri = uri.substring(0, n);
087: }
088: DocumentState state;
089: synchronized (cacheMap) {
090: state = (DocumentState) cacheMap.get(uri);
091: }
092: if (state != null)
093: return state.getDocument();
094: return null;
095: }
096:
097: /**
098: * Returns a document from the specified uri.
099: * @param uri the uri of the document
100: * @exception IOException if an I/O error occured while loading
101: * the document
102: */
103: public Document loadDocument(String uri) throws IOException {
104: Document ret = checkCache(uri);
105: if (ret != null)
106: return ret;
107:
108: SVGDocument document = documentFactory.createSVGDocument(uri);
109:
110: DocumentDescriptor desc = documentFactory
111: .getDocumentDescriptor();
112: DocumentState state = new DocumentState(uri, document, desc);
113: synchronized (cacheMap) {
114: cacheMap.put(uri, state);
115: }
116:
117: return state.getDocument();
118: }
119:
120: /**
121: * Returns a document from the specified uri.
122: * @param uri the uri of the document
123: * @exception IOException if an I/O error occured while loading
124: * the document
125: */
126: public Document loadDocument(String uri, InputStream is)
127: throws IOException {
128: Document ret = checkCache(uri);
129: if (ret != null)
130: return ret;
131:
132: SVGDocument document = documentFactory.createSVGDocument(uri,
133: is);
134:
135: DocumentDescriptor desc = documentFactory
136: .getDocumentDescriptor();
137: DocumentState state = new DocumentState(uri, document, desc);
138: synchronized (cacheMap) {
139: cacheMap.put(uri, state);
140: }
141:
142: return state.getDocument();
143: }
144:
145: /**
146: * Returns the userAgent used by this DocumentLoader
147: */
148: public UserAgent getUserAgent() {
149: return userAgent;
150: }
151:
152: /**
153: * Disposes and releases all resources allocated by this document loader.
154: */
155: public void dispose() {
156: // new Exception("purge the cache").printStackTrace();
157: synchronized (cacheMap) {
158: cacheMap.clear();
159: }
160: }
161:
162: /**
163: * Returns the line in the source code of the specified element or
164: * -1 if not found.
165: *
166: * @param e the element
167: * @return -1 the document has been removed from the cache or has not
168: * been loaded by this document loader.
169: */
170: public int getLineNumber(Element e) {
171: String uri = ((SVGDocument) e.getOwnerDocument()).getURL();
172: DocumentState state;
173: synchronized (cacheMap) {
174: state = (DocumentState) cacheMap.get(uri);
175: }
176: if (state == null) {
177: return -1;
178: } else {
179: return state.desc.getLocationLine(e);
180: }
181: }
182:
183: /**
184: * A simple class that contains a Document and its number of nodes.
185: */
186: private class DocumentState extends
187: CleanerThread.SoftReferenceCleared {
188:
189: private String uri;
190: private DocumentDescriptor desc;
191:
192: public DocumentState(String uri, Document document,
193: DocumentDescriptor desc) {
194: super (document);
195: this .uri = uri;
196: this .desc = desc;
197: }
198:
199: public void cleared() {
200: synchronized (cacheMap) {
201: cacheMap.remove(uri);
202: }
203: }
204:
205: public DocumentDescriptor getDocumentDescriptor() {
206: return desc;
207: }
208:
209: public String getURI() {
210: return uri;
211: }
212:
213: public Document getDocument() {
214: return (Document) get();
215: }
216: }
217:
218: }
|