KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > resolver > tools > CatalogResolver


1 // CatalogResolver.java - A SAX EntityResolver/JAXP URI Resolver
2

3 /*
4  * Copyright 2001-2004 The Apache Software Foundation or its licensors,
5  * as applicable.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19
20 package com.sun.org.apache.xml.internal.resolver.tools;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.net.URL JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26
27 import org.xml.sax.SAXException JavaDoc;
28 import org.xml.sax.XMLReader JavaDoc;
29 import org.xml.sax.InputSource JavaDoc;
30 import org.xml.sax.EntityResolver JavaDoc;
31
32 import javax.xml.transform.sax.SAXSource JavaDoc;
33 import javax.xml.transform.Source JavaDoc;
34 import javax.xml.transform.URIResolver JavaDoc;
35 import javax.xml.transform.TransformerException JavaDoc;
36 import javax.xml.parsers.ParserConfigurationException JavaDoc;
37 import javax.xml.parsers.SAXParserFactory JavaDoc;
38
39 import com.sun.org.apache.xml.internal.resolver.Catalog;
40 import com.sun.org.apache.xml.internal.resolver.CatalogManager;
41 import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
42
43 /**
44  * A SAX EntityResolver/JAXP URIResolver that uses catalogs.
45  *
46  * <p>This class implements both a SAX EntityResolver and a JAXP URIResolver.
47  * </p>
48  *
49  * <p>This resolver understands OASIS TR9401 catalogs, XCatalogs, and the
50  * current working draft of the OASIS Entity Resolution Technical
51  * Committee specification.</p>
52  *
53  * @see Catalog
54  * @see org.xml.sax.EntityResolver
55  * @see javax.xml.transform.URIResolver
56  *
57  * @author Norman Walsh
58  * <a HREF="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
59  *
60  * @version 1.0
61  */

62 public class CatalogResolver implements EntityResolver JavaDoc, URIResolver JavaDoc {
63   /** Make the parser Namespace aware? */
64   public boolean namespaceAware = true;
65
66   /** Make the parser validating? */
67   public boolean validating = false;
68
69   /** The underlying catalog */
70   private Catalog catalog = null;
71
72   /** The catalog manager */
73   private CatalogManager catalogManager = CatalogManager.getStaticManager();
74
75   /** Constructor */
76   public CatalogResolver() {
77     initializeCatalogs(false);
78   }
79
80   /** Constructor */
81   public CatalogResolver(boolean privateCatalog) {
82     initializeCatalogs(privateCatalog);
83   }
84
85   /** Constructor */
86   public CatalogResolver(CatalogManager manager) {
87     catalogManager = manager;
88     initializeCatalogs(!catalogManager.getUseStaticCatalog());
89   }
90
91   /** Initialize catalog */
92   private void initializeCatalogs(boolean privateCatalog) {
93     catalog = catalogManager.getCatalog();
94   }
95
96   /** Return the underlying catalog */
97   public Catalog getCatalog() {
98     return catalog;
99   }
100
101   /**
102    * Implements the guts of the <code>resolveEntity</code> method
103    * for the SAX interface.
104    *
105    * <p>Presented with an optional public identifier and a system
106    * identifier, this function attempts to locate a mapping in the
107    * catalogs.</p>
108    *
109    * <p>If such a mapping is found, it is returned. If no mapping is
110    * found, null is returned.</p>
111    *
112    * @param publicId The public identifier for the entity in question.
113    * This may be null.
114    *
115    * @param systemId The system identifier for the entity in question.
116    * XML requires a system identifier on all external entities, so this
117    * value is always specified.
118    *
119    * @return The resolved identifier (a URI reference).
120    */

121   public String JavaDoc getResolvedEntity (String JavaDoc publicId, String JavaDoc systemId) {
122     String JavaDoc resolved = null;
123
124     if (catalog == null) {
125       catalogManager.debug.message(1, "Catalog resolution attempted with null catalog; ignored");
126       return null;
127     }
128
129     if (systemId != null) {
130       try {
131     resolved = catalog.resolveSystem(systemId);
132       } catch (MalformedURLException JavaDoc me) {
133     catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
134               publicId);
135     resolved = null;
136       } catch (IOException JavaDoc ie) {
137     catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
138     resolved = null;
139       }
140     }
141
142     if (resolved == null) {
143       if (publicId != null) {
144     try {
145       resolved = catalog.resolvePublic(publicId, systemId);
146     } catch (MalformedURLException JavaDoc me) {
147       catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
148             publicId);
149     } catch (IOException JavaDoc ie) {
150       catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
151     }
152       }
153
154       if (resolved != null) {
155     catalogManager.debug.message(2, "Resolved public", publicId, resolved);
156       }
157     } else {
158       catalogManager.debug.message(2, "Resolved system", systemId, resolved);
159     }
160
161     return resolved;
162   }
163
164   /**
165    * Implements the <code>resolveEntity</code> method
166    * for the SAX interface.
167    *
168    * <p>Presented with an optional public identifier and a system
169    * identifier, this function attempts to locate a mapping in the
170    * catalogs.</p>
171    *
172    * <p>If such a mapping is found, the resolver attempts to open
173    * the mapped value as an InputSource and return it. Exceptions are
174    * ignored and null is returned if the mapped value cannot be opened
175    * as an input source.</p>
176    *
177    * <p>If no mapping is found (or an error occurs attempting to open
178    * the mapped value as an input source), null is returned and the system
179    * will use the specified system identifier as if no entityResolver
180    * was specified.</p>
181    *
182    * @param publicId The public identifier for the entity in question.
183    * This may be null.
184    *
185    * @param systemId The system identifier for the entity in question.
186    * XML requires a system identifier on all external entities, so this
187    * value is always specified.
188    *
189    * @return An InputSource for the mapped identifier, or null.
190    */

191   public InputSource JavaDoc resolveEntity (String JavaDoc publicId, String JavaDoc systemId) {
192     String JavaDoc resolved = getResolvedEntity(publicId, systemId);
193
194     if (resolved != null) {
195       try {
196     InputSource JavaDoc iSource = new InputSource JavaDoc(resolved);
197     iSource.setPublicId(publicId);
198
199     // Ideally this method would not attempt to open the
200
// InputStream, but there is a bug (in Xerces, at least)
201
// that causes the parser to mistakenly open the wrong
202
// system identifier if the returned InputSource does
203
// not have a byteStream.
204
//
205
// It could be argued that we still shouldn't do this here,
206
// but since the purpose of calling the entityResolver is
207
// almost certainly to open the input stream, it seems to
208
// do little harm.
209
//
210
URL JavaDoc url = new URL JavaDoc(resolved);
211     InputStream JavaDoc iStream = url.openStream();
212     iSource.setByteStream(iStream);
213
214     return iSource;
215       } catch (Exception JavaDoc e) {
216     catalogManager.debug.message(1, "Failed to create InputSource", resolved);
217     return null;
218       }
219     }
220
221     return null;
222   }
223
224   /** JAXP URIResolver API */
225   public Source JavaDoc resolve(String JavaDoc href, String JavaDoc base)
226     throws TransformerException JavaDoc {
227
228     String JavaDoc uri = href;
229     String JavaDoc fragment = null;
230     int hashPos = href.indexOf("#");
231     if (hashPos >= 0) {
232       uri = href.substring(0, hashPos);
233       fragment = href.substring(hashPos+1);
234     }
235
236     String JavaDoc result = null;
237
238     try {
239       result = catalog.resolveURI(href);
240     } catch (Exception JavaDoc e) {
241       // nop;
242
}
243
244     if (result == null) {
245       try {
246     URL JavaDoc url = null;
247
248     if (base==null) {
249       url = new URL JavaDoc(uri);
250       result = url.toString();
251     } else {
252       URL JavaDoc baseURL = new URL JavaDoc(base);
253       url = (href.length()==0 ? baseURL : new URL JavaDoc(baseURL, uri));
254       result = url.toString();
255     }
256       } catch (java.net.MalformedURLException JavaDoc mue) {
257     // try to make an absolute URI from the current base
258
String JavaDoc absBase = makeAbsolute(base);
259     if (!absBase.equals(base)) {
260       // don't bother if the absBase isn't different!
261
return resolve(href, absBase);
262     } else {
263       throw new TransformerException JavaDoc("Malformed URL "
264                      + href + "(base " + base + ")",
265                      mue);
266     }
267       }
268     }
269
270     catalogManager.debug.message(2, "Resolved URI", href, result);
271
272     SAXSource JavaDoc source = new SAXSource JavaDoc();
273     source.setInputSource(new InputSource JavaDoc(result));
274     setEntityResolver(source);
275     return source;
276   }
277
278   /**
279    * <p>Establish an entityResolver for newly resolved URIs.</p>
280    *
281    * <p>This is called from the URIResolver to set an EntityResolver
282    * on the SAX parser to be used for new XML documents that are
283    * encountered as a result of the document() function, xsl:import,
284    * or xsl:include. This is done because the XSLT processor calls
285    * out to the SAXParserFactory itself to create a new SAXParser to
286    * parse the new document. The new parser does not automatically
287    * inherit the EntityResolver of the original (although arguably
288    * it should). See below:</p>
289    *
290    * <tt>"If an application wants to set the ErrorHandler or
291    * EntityResolver for an XMLReader used during a transformation,
292    * it should use a URIResolver to return the SAXSource which
293    * provides (with getXMLReader) a reference to the XMLReader"</tt>
294    *
295    * <p>...quoted from page 118 of the Java API for XML
296    * Processing 1.1 specification</p>
297    *
298    */

299   private void setEntityResolver(SAXSource JavaDoc source) throws TransformerException JavaDoc {
300     XMLReader JavaDoc reader = source.getXMLReader();
301     if (reader == null) {
302       SAXParserFactory JavaDoc spFactory = SAXParserFactory.newInstance();
303       spFactory.setNamespaceAware(true);
304       try {
305     reader = spFactory.newSAXParser().getXMLReader();
306       }
307       catch (ParserConfigurationException JavaDoc ex) {
308     throw new TransformerException JavaDoc(ex);
309       }
310       catch (SAXException JavaDoc ex) {
311     throw new TransformerException JavaDoc(ex);
312       }
313     }
314     reader.setEntityResolver(this);
315     source.setXMLReader(reader);
316   }
317
318   /** Attempt to construct an absolute URI */
319   private String JavaDoc makeAbsolute(String JavaDoc uri) {
320     if (uri == null) {
321       uri = "";
322     }
323
324     try {
325       URL JavaDoc url = new URL JavaDoc(uri);
326       return url.toString();
327     } catch (MalformedURLException JavaDoc mue) {
328       try {
329     URL JavaDoc fileURL = FileURL.makeURL(uri);
330     return fileURL.toString();
331       } catch (MalformedURLException JavaDoc mue2) {
332     // bail
333
return uri;
334       }
335     }
336   }
337 }
338
Popular Tags