OSDN Git Service

Initial revision
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / xml / transform / XSLURIResolver.java
1 /* XSLURIResolver.java -- 
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10
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.
15
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.
20
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.
25
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. */
37
38 package gnu.xml.transform;
39
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.stream.StreamSource;
57 import org.w3c.dom.Node;
58 import org.xml.sax.InputSource;
59 import org.xml.sax.SAXException;
60 import gnu.xml.dom.ls.ReaderInputStream;
61
62 /**
63  * URI resolver for XSLT.
64  * This resolver parses external entities into DOMSources. It
65  * maintains a cache of URIs to DOMSources to avoid expensive re-parsing.
66  *
67  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
68  */
69 class XSLURIResolver
70   implements URIResolver
71 {
72
73   Map lastModifiedCache = new HashMap();
74   Map nodeCache = new HashMap();
75   DocumentBuilder builder;
76   URIResolver userResolver;
77   ErrorListener userListener;
78
79   void setUserResolver(URIResolver userResolver)
80   {
81     this.userResolver = userResolver;
82   }
83
84   void setUserListener(ErrorListener userListener)
85   {
86     this.userListener = userListener;
87   }
88
89   /**
90    * Clear the cache.
91    */
92   void flush()
93   {
94     lastModifiedCache.clear();
95     nodeCache.clear();
96   }
97
98   public Source resolve(String href, String base)
99     throws TransformerException
100   {
101     Source source = null;
102     if (userResolver != null)
103       {
104         source = userResolver.resolve(base, href);
105       }
106     return resolveDOM(source, href, base);
107   }
108
109   DOMSource resolveDOM(Source source, String base, String href)
110     throws TransformerException
111   {
112     if (source != null && source instanceof DOMSource)
113       {
114         return (DOMSource) source;
115       }
116     String systemId = (source == null) ? null : source.getSystemId();
117     long lastModified = 0L, lastLastModified = 0L;
118
119     try
120       {
121         URL url = resolveURL(systemId, base, href);
122         Node node = null;
123         InputStream in = null;
124         if (source instanceof StreamSource)
125           {
126             StreamSource ss = (StreamSource) source;
127             in = ss.getInputStream();
128             if (in == null)
129               {
130                 Reader reader = ss.getReader();
131                 if (reader != null)
132                   {
133                     in = new ReaderInputStream(reader);
134                   }
135               }
136           }
137         if (in == null)
138           {
139             if (url != null)
140               {
141                 systemId = url.toString();
142                 node = (Node) nodeCache.get(systemId);
143                 // Is the resource up to date?
144                 URLConnection conn = url.openConnection();
145                 Long llm = (Long) lastModifiedCache.get(systemId);
146                 if (llm != null)
147                   {
148                     lastLastModified = llm.longValue();
149                     conn.setIfModifiedSince(lastLastModified);
150                   }
151                 conn.connect();
152                 lastModified = conn.getLastModified();
153                 if (node != null && 
154                     lastModified > 0L &&
155                     lastModified <= lastLastModified)
156                   {
157                     // Resource unchanged
158                     return new DOMSource(node, systemId);
159                   }
160                 else
161                   {
162                     // Resource new or modified
163                     in = conn.getInputStream();
164                     nodeCache.put(systemId, node);
165                     lastModifiedCache.put(systemId, new Long(lastModified));
166                   }
167               }
168             else
169               {
170                 throw new TransformerException("can't resolve URL: " +
171                                                systemId);
172               }
173           }
174         InputSource input = new InputSource(in);
175         input.setSystemId(systemId);
176         DocumentBuilder builder = getDocumentBuilder();
177         node = builder.parse(input);
178         return new DOMSource(node, systemId);
179       }
180     catch (IOException e)
181       {
182         throw new TransformerException(e);
183       }
184     catch (SAXException e)
185       {
186         throw new TransformerException(e);
187       }
188   }
189
190   URL resolveURL(String systemId, String base, String href)
191     throws IOException
192   {
193     URL url = null;
194     try
195       {
196         if (systemId != null)
197           {
198             try
199               {
200                 url = new URL(systemId);
201               }
202             catch (MalformedURLException e)
203               {
204                 // Try building from base + href
205               }
206           }
207         if (url == null)
208           {
209             if (base != null)
210               {
211                 URL baseURL = new URL(base);
212                 url = new URL(baseURL, href);
213               }
214             else if (href != null)
215               {
216                 url = new URL(href);
217               }
218             else
219               {
220                 // See below
221                 throw new MalformedURLException(systemId);
222               }
223           }
224         return url;
225       }
226     catch (MalformedURLException e)
227       {
228         // Fall back to local filesystem
229         File file = null;
230         if (href == null)
231           {
232             href = systemId;
233           }
234         if (base != null)
235           {
236             int lsi = base.lastIndexOf(File.separatorChar);
237             if (lsi != -1 && lsi < base.length() - 1)
238               {
239                 base = base.substring(0, lsi);
240               }
241             File baseFile = new File(base);
242             file = new File(baseFile, href);
243           }
244         else if (href != null)
245           {
246             file = new File(href);
247           }
248         return (file == null) ? null : file.toURL();
249       }
250   }
251   
252   DocumentBuilder getDocumentBuilder()
253     throws TransformerException
254   {
255     try
256       {
257         if (builder == null)
258           {
259             DocumentBuilderFactory factory =
260               DocumentBuilderFactory.newInstance();
261             factory.setNamespaceAware(true);
262             factory.setExpandEntityReferences(true);
263             builder = factory.newDocumentBuilder();
264           }
265         if (userResolver != null)
266           {
267             builder.setEntityResolver(new URIResolverEntityResolver(userResolver));
268           }
269         if (userListener != null)
270           {
271             builder.setErrorHandler(new ErrorListenerErrorHandler(userListener));
272           }
273         return builder;
274       }
275     catch (Exception e)
276       {
277         throw new TransformerException(e);
278       }
279   }
280   
281 }
282