KickJava   Java API By Example, From Geeks To Geeks.

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


1 // ResolvingXMLFilter.java - An XMLFilter that performs catalog resolution
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.MalformedURLException JavaDoc;
25 import java.net.URL JavaDoc;
26
27 import org.xml.sax.InputSource JavaDoc;
28 import org.xml.sax.SAXException JavaDoc;
29 import org.xml.sax.XMLReader JavaDoc;
30 import org.xml.sax.Attributes JavaDoc;
31 import org.xml.sax.helpers.XMLFilterImpl JavaDoc;
32
33 import com.sun.org.apache.xml.internal.resolver.Catalog;
34 import com.sun.org.apache.xml.internal.resolver.CatalogManager;
35
36 import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
37
38 /**
39  * A SAX XMLFilter that performs catalog-based entity resolution.
40  *
41  * <p>This class implements a SAX XMLFilter that performs entity resolution
42  * using the CatalogResolver. The actual, underlying parser is obtained
43  * from a SAXParserFactory.</p>
44  * </p>
45  *
46  * @see CatalogResolver
47  * @see org.xml.sax.XMLFilter
48  *
49  * @author Norman Walsh
50  * <a HREF="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
51  *
52  * @version 1.0
53  */

54 public class ResolvingXMLFilter extends XMLFilterImpl JavaDoc {
55   /**
56    * Suppress explanatory message?
57    *
58    * @see #parse(InputSource)
59    */

60   public static boolean suppressExplanation = false;
61
62   /** The manager for the underlying resolver. */
63   private CatalogManager catalogManager = CatalogManager.getStaticManager();
64
65   /** The underlying catalog resolver. */
66   private CatalogResolver catalogResolver = null;
67
68   /** A separate resolver for oasis-xml-pi catalogs. */
69   private CatalogResolver piCatalogResolver = null;
70
71   /** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */
72   private boolean allowXMLCatalogPI = false;
73
74   /** Has an oasis-xml-catalog PI been seen? */
75   private boolean oasisXMLCatalogPI = false;
76
77   /** The base URI of the input document, if known. */
78   private URL JavaDoc baseURL = null;
79
80   /** Construct an empty XML Filter with no parent. */
81   public ResolvingXMLFilter() {
82     super();
83     catalogResolver = new CatalogResolver(catalogManager);
84   }
85
86   /** Construct an XML filter with the specified parent. */
87   public ResolvingXMLFilter(XMLReader JavaDoc parent) {
88     super(parent);
89     catalogResolver = new CatalogResolver(catalogManager);
90   }
91
92   /** Construct an XML filter with the specified parent. */
93   public ResolvingXMLFilter(CatalogManager manager) {
94     super();
95     catalogManager = manager;
96     catalogResolver = new CatalogResolver(catalogManager);
97   }
98
99   /** Construct an XML filter with the specified parent. */
100   public ResolvingXMLFilter(XMLReader JavaDoc parent, CatalogManager manager) {
101     super(parent);
102     catalogManager = manager;
103     catalogResolver = new CatalogResolver(catalogManager);
104   }
105
106   /**
107    * Provide accessto the underlying Catalog.
108    */

109   public Catalog getCatalog() {
110     return catalogResolver.getCatalog();
111   }
112
113   /**
114    * SAX XMLReader API.
115    *
116    * <p>Note that the JAXP 1.1ea2 parser crashes with an InternalError if
117    * it encounters a system identifier that appears to be a relative URI
118    * that begins with a slash. For example, the declaration:</p>
119    *
120    * <pre>
121    * &lt;!DOCTYPE book SYSTEM "/path/to/dtd/on/my/system/docbookx.dtd">
122    * </pre>
123    *
124    * <p>would cause such an error. As a convenience, this method catches
125    * that error and prints an explanation. (Unfortunately, it's not possible
126    * to identify the particular system identifier that causes the problem.)
127    * </p>
128    *
129    * <p>The underlying error is forwarded after printing the explanatory
130    * message. The message is only every printed once and if
131    * <code>suppressExplanation</code> is set to <code>false</code> before
132    * parsing, it will never be printed.</p>
133    */

134   public void parse(InputSource JavaDoc input)
135     throws IOException JavaDoc, SAXException JavaDoc {
136     allowXMLCatalogPI = true;
137
138     setupBaseURI(input.getSystemId());
139
140     try {
141       super.parse(input);
142     } catch (InternalError JavaDoc ie) {
143       explain(input.getSystemId());
144       throw ie;
145     }
146   }
147
148   /** SAX XMLReader API.
149    *
150    * @see #parse(InputSource)
151    */

152   public void parse(String JavaDoc systemId)
153     throws IOException JavaDoc, SAXException JavaDoc {
154     allowXMLCatalogPI = true;
155
156     setupBaseURI(systemId);
157
158     try {
159       super.parse(systemId);
160     } catch (InternalError JavaDoc ie) {
161       explain(systemId);
162       throw ie;
163     }
164   }
165
166   /**
167    * Implements the <code>resolveEntity</code> method
168    * for the SAX interface, using an underlying CatalogResolver
169    * to do the real work.
170    */

171   public InputSource JavaDoc resolveEntity (String JavaDoc publicId, String JavaDoc systemId) {
172     allowXMLCatalogPI = false;
173     String JavaDoc resolved = catalogResolver.getResolvedEntity(publicId, systemId);
174
175     if (resolved == null && piCatalogResolver != null) {
176       resolved = piCatalogResolver.getResolvedEntity(publicId, systemId);
177     }
178
179     if (resolved != null) {
180       try {
181     InputSource JavaDoc iSource = new InputSource JavaDoc(resolved);
182     iSource.setPublicId(publicId);
183
184     // Ideally this method would not attempt to open the
185
// InputStream, but there is a bug (in Xerces, at least)
186
// that causes the parser to mistakenly open the wrong
187
// system identifier if the returned InputSource does
188
// not have a byteStream.
189
//
190
// It could be argued that we still shouldn't do this here,
191
// but since the purpose of calling the entityResolver is
192
// almost certainly to open the input stream, it seems to
193
// do little harm.
194
//
195
URL JavaDoc url = new URL JavaDoc(resolved);
196     InputStream JavaDoc iStream = url.openStream();
197     iSource.setByteStream(iStream);
198
199     return iSource;
200       } catch (Exception JavaDoc e) {
201     catalogManager.debug.message(1, "Failed to create InputSource", resolved);
202     return null;
203       }
204     } else {
205       return null;
206     }
207   }
208
209   /** SAX DTDHandler API.
210    *
211    * <p>Captured here only to detect the end of the prolog so that
212    * we can ignore subsequent oasis-xml-catalog PIs. Otherwise
213    * the events are just passed through.</p>
214    */

215   public void notationDecl (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
216     throws SAXException JavaDoc {
217     allowXMLCatalogPI = false;
218     super.notationDecl(name,publicId,systemId);
219   }
220
221   /** SAX DTDHandler API.
222    *
223    * <p>Captured here only to detect the end of the prolog so that
224    * we can ignore subsequent oasis-xml-catalog PIs. Otherwise
225    * the events are just passed through.</p>
226    */

227   public void unparsedEntityDecl (String JavaDoc name,
228                   String JavaDoc publicId,
229                   String JavaDoc systemId,
230                   String JavaDoc notationName)
231     throws SAXException JavaDoc {
232     allowXMLCatalogPI = false;
233     super.unparsedEntityDecl (name, publicId, systemId, notationName);
234   }
235
236   /** SAX ContentHandler API.
237    *
238    * <p>Captured here only to detect the end of the prolog so that
239    * we can ignore subsequent oasis-xml-catalog PIs. Otherwise
240    * the events are just passed through.</p>
241    */

242   public void startElement (String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
243                 Attributes JavaDoc atts)
244     throws SAXException JavaDoc {
245     allowXMLCatalogPI = false;
246     super.startElement(uri,localName,qName,atts);
247   }
248
249   /** SAX ContentHandler API.
250    *
251    * <p>Detect and use the oasis-xml-catalog PI if it occurs.</p>
252    */

253   public void processingInstruction(String JavaDoc target, String JavaDoc pidata)
254     throws SAXException JavaDoc {
255     if (target.equals("oasis-xml-catalog")) {
256       URL JavaDoc catalog = null;
257       String JavaDoc data = pidata;
258
259       int pos = data.indexOf("catalog=");
260       if (pos >= 0) {
261     data = data.substring(pos+8);
262     if (data.length() > 1) {
263       String JavaDoc quote = data.substring(0,1);
264       data = data.substring(1);
265       pos = data.indexOf(quote);
266       if (pos >= 0) {
267         data = data.substring(0, pos);
268         try {
269           if (baseURL != null) {
270         catalog = new URL JavaDoc(baseURL, data);
271           } else {
272         catalog = new URL JavaDoc(data);
273           }
274         } catch (MalformedURLException JavaDoc mue) {
275           // nevermind
276
}
277       }
278     }
279       }
280
281       if (allowXMLCatalogPI) {
282     if (catalogManager.getAllowOasisXMLCatalogPI()) {
283       catalogManager.debug.message(4,"oasis-xml-catalog PI", pidata);
284
285       if (catalog != null) {
286         try {
287           catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString());
288           oasisXMLCatalogPI = true;
289
290           if (piCatalogResolver == null) {
291         piCatalogResolver = new CatalogResolver(true);
292           }
293
294           piCatalogResolver.getCatalog().parseCatalog(catalog.toString());
295         } catch (Exception JavaDoc e) {
296           catalogManager.debug.message(3, "Exception parsing oasis-xml-catalog: "
297                 + catalog.toString());
298         }
299       } else {
300         catalogManager.debug.message(3, "PI oasis-xml-catalog unparseable: " + pidata);
301       }
302     } else {
303       catalogManager.debug.message(4,"PI oasis-xml-catalog ignored: " + pidata);
304     }
305       } else {
306     catalogManager.debug.message(3, "PI oasis-xml-catalog occurred in an invalid place: "
307               + pidata);
308       }
309     } else {
310       super.processingInstruction(target, pidata);
311     }
312   }
313
314   /** Save the base URI of the document being parsed. */
315   private void setupBaseURI(String JavaDoc systemId) {
316     URL JavaDoc cwd = null;
317
318     try {
319       cwd = FileURL.makeURL("basename");
320     } catch (MalformedURLException JavaDoc mue) {
321       cwd = null;
322     }
323
324     try {
325       baseURL = new URL JavaDoc(systemId);
326     } catch (MalformedURLException JavaDoc mue) {
327       if (cwd != null) {
328     try {
329       baseURL = new URL JavaDoc(cwd, systemId);
330     } catch (MalformedURLException JavaDoc mue2) {
331       // give up
332
baseURL = null;
333     }
334       } else {
335     // give up
336
baseURL = null;
337       }
338     }
339   }
340
341   /** Provide one possible explanation for an InternalError. */
342   private void explain(String JavaDoc systemId) {
343     if (!suppressExplanation) {
344       System.out.println("XMLReader probably encountered bad URI in " + systemId);
345       System.out.println("For example, replace '/some/uri' with 'file:/some/uri'.");
346     }
347     suppressExplanation = true;
348   }
349 }
350
351
Popular Tags