libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / xml / transform / XSLURIResolver.java
blobc1379211ae57994651084b3441fe6ed02d930713
1 /* XSLURIResolver.java --
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.xml.transform;
40 import java.io.File;
41 import java.io.InputStream;
42 import java.io.IOException;
43 import java.io.Reader;
44 import java.net.MalformedURLException;
45 import java.net.URL;
46 import java.net.URLConnection;
47 import java.util.HashMap;
48 import java.util.Map;
49 import javax.xml.parsers.DocumentBuilder;
50 import javax.xml.parsers.DocumentBuilderFactory;
51 import javax.xml.transform.ErrorListener;
52 import javax.xml.transform.Source;
53 import javax.xml.transform.TransformerException;
54 import javax.xml.transform.URIResolver;
55 import javax.xml.transform.dom.DOMSource;
56 import javax.xml.transform.sax.SAXSource;
57 import javax.xml.transform.stream.StreamSource;
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Node;
60 import org.xml.sax.InputSource;
61 import org.xml.sax.SAXException;
62 import org.xml.sax.XMLReader;
63 import gnu.xml.dom.DomDocument;
64 import gnu.xml.dom.ls.SAXEventSink;
65 import gnu.xml.dom.ls.ReaderInputStream;
67 /**
68 * URI resolver for XSLT.
69 * This resolver parses external entities into DOMSources. It
70 * maintains a cache of URIs to DOMSources to avoid expensive re-parsing.
72 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
74 class XSLURIResolver
75 implements URIResolver
78 final Map<String,Long> lastModifiedCache = new HashMap<String,Long>();
79 final Map<String,Node> nodeCache = new HashMap<String,Node>();
80 DocumentBuilder builder;
81 URIResolver userResolver;
82 ErrorListener userListener;
84 void setUserResolver(URIResolver userResolver)
86 this.userResolver = userResolver;
89 void setUserListener(ErrorListener userListener)
91 this.userListener = userListener;
94 /**
95 * Clear the cache.
97 void flush()
99 lastModifiedCache.clear();
100 nodeCache.clear();
103 public Source resolve(String href, String base)
104 throws TransformerException
106 Source source = null;
107 if (userResolver != null)
109 source = userResolver.resolve(base, href);
111 return resolveDOM(source, href, base);
114 DOMSource resolveDOM(Source source, String base, String href)
115 throws TransformerException
117 if (source != null && source instanceof DOMSource)
119 return (DOMSource) source;
121 String systemId = (source == null) ? null : source.getSystemId();
122 long lastModified = 0L, lastLastModified = 0L;
126 Node node = null;
127 InputStream in = null;
128 if (source != null && source instanceof StreamSource)
130 StreamSource ss = (StreamSource) source;
131 in = ss.getInputStream();
132 if (in == null)
134 Reader reader = ss.getReader();
135 if (reader != null)
137 in = new ReaderInputStream(reader);
141 else if (source != null && source instanceof SAXSource)
143 SAXSource ss = (SAXSource) source;
144 InputSource input = ss.getInputSource();
145 if (input != null)
147 if (systemId == null)
148 systemId = input.getSystemId();
149 XMLReader reader = ss.getXMLReader();
150 if (reader != null)
151 return parse(input, reader);
154 if (in == null)
156 URL url = resolveURL(systemId, base, href);
157 if (url != null)
159 systemId = url.toString();
160 node = nodeCache.get(systemId);
161 // Is the resource up to date?
162 URLConnection conn = url.openConnection();
163 Long llm = lastModifiedCache.get(systemId);
164 if (llm != null)
166 lastLastModified = llm.longValue();
167 conn.setIfModifiedSince(lastLastModified);
169 conn.connect();
170 lastModified = conn.getLastModified();
171 if (node != null &&
172 lastModified > 0L &&
173 lastModified <= lastLastModified)
175 // Resource unchanged
176 return new DOMSource(node, systemId);
178 else
180 // Resource new or modified
181 in = conn.getInputStream();
182 nodeCache.put(systemId, node);
183 lastModifiedCache.put(systemId, new Long(lastModified));
186 else
188 throw new TransformerException("can't resolve URL: " +
189 systemId);
192 InputSource input = new InputSource(in);
193 input.setSystemId(systemId);
194 DocumentBuilder builder = getDocumentBuilder();
195 node = builder.parse(input);
196 return new DOMSource(node, systemId);
198 catch (IOException e)
200 throw new TransformerException(e);
202 catch (SAXException e)
204 throw new TransformerException(e);
208 URL resolveURL(String systemId, String base, String href)
209 throws IOException
211 URL url = null;
214 if (systemId != null)
218 url = new URL(systemId);
220 catch (MalformedURLException e)
222 // Try building from base + href
225 if (url == null)
227 if (base != null)
229 URL baseURL = new URL(base);
230 url = new URL(baseURL, href);
232 else if (href != null)
234 url = new URL(href);
236 else
238 // See below
239 throw new MalformedURLException(systemId);
242 return url;
244 catch (MalformedURLException e)
246 // Fall back to local filesystem
247 File file = null;
248 if (href == null)
250 href = systemId;
252 if (base != null)
254 int lsi = base.lastIndexOf(File.separatorChar);
255 if (lsi != -1 && lsi < base.length() - 1)
257 base = base.substring(0, lsi);
259 File baseFile = new File(base);
260 file = new File(baseFile, href);
262 else if (href != null)
264 file = new File(href);
266 return (file == null) ? null : file.toURL();
270 DocumentBuilder getDocumentBuilder()
271 throws TransformerException
275 if (builder == null)
277 DocumentBuilderFactory factory =
278 DocumentBuilderFactory.newInstance();
279 factory.setNamespaceAware(true);
280 factory.setExpandEntityReferences(true);
281 builder = factory.newDocumentBuilder();
283 if (userResolver != null)
285 builder.setEntityResolver(new URIResolverEntityResolver(userResolver));
287 if (userListener != null)
289 builder.setErrorHandler(new ErrorListenerErrorHandler(userListener));
291 return builder;
293 catch (Exception e)
295 throw new TransformerException(e);
299 DOMSource parse(InputSource source, XMLReader reader)
300 throws SAXException, IOException
302 SAXEventSink eventSink = new SAXEventSink();
303 eventSink.setReader(reader);
304 eventSink.setNamespaceAware(true);
305 reader.setContentHandler(eventSink);
306 reader.setDTDHandler(eventSink);
307 reader.setProperty("http://xml.org/sax/properties/lexical-handler",
308 eventSink);
309 reader.setProperty("http://xml.org/sax/properties/declaration-handler",
310 eventSink);
311 // XXX entityResolver
312 // XXX errorHandler
313 reader.parse(source);
314 Document doc = eventSink.getDocument();
315 String systemId = source.getSystemId();
316 if (systemId != null && doc instanceof DomDocument)
317 ((DomDocument) doc).setDocumentURI(systemId);
318 return new DOMSource(doc, systemId);