KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > resolver > readers > SAXCatalogReader


1 // SAXCatalogReader.java - Read XML Catalog files
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.readers;
21
22 import java.util.Hashtable JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.FileNotFoundException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLConnection JavaDoc;
28 import java.net.MalformedURLException JavaDoc;
29 import java.net.UnknownHostException JavaDoc;
30
31 import javax.xml.parsers.ParserConfigurationException JavaDoc;
32 import javax.xml.parsers.SAXParserFactory JavaDoc;
33 import javax.xml.parsers.SAXParser JavaDoc;
34
35 import org.xml.sax.AttributeList JavaDoc;
36 import org.xml.sax.Attributes JavaDoc;
37 import org.xml.sax.ContentHandler JavaDoc;
38 import org.xml.sax.DocumentHandler JavaDoc;
39 import org.xml.sax.EntityResolver JavaDoc;
40 import org.xml.sax.InputSource JavaDoc;
41 import org.xml.sax.Locator JavaDoc;
42 import org.xml.sax.Parser JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44
45 import com.sun.org.apache.xml.internal.resolver.Catalog;
46 import com.sun.org.apache.xml.internal.resolver.CatalogManager;
47 import com.sun.org.apache.xml.internal.resolver.CatalogException;
48 import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
49 import com.sun.org.apache.xml.internal.resolver.helpers.Debug;
50
51 /**
52  * A SAX-based CatalogReader.
53  *
54  * <p>This class is used to read XML Catalogs using the SAX. This reader
55  * has an advantage over the DOM-based reader in that it functions on
56  * the stream of SAX events. It has the disadvantage
57  * that it cannot look around in the tree.</p>
58  *
59  * <p>Since the choice of CatalogReaders (in the InputStream case) can only
60  * be made on the basis of MIME type, the following problem occurs: only
61  * one CatalogReader can exist for all XML mime types. In order to get
62  * around this problem, the SAXCatalogReader relies on a set of external
63  * CatalogParsers to actually build the catalog.</p>
64  *
65  * <p>The selection of CatalogParsers is made on the basis of the QName
66  * of the root element of the document.</p>
67  *
68  * @see Catalog
69  * @see CatalogReader
70  * @see SAXCatalogReader
71  * @see TextCatalogReader
72  * @see DOMCatalogParser
73  *
74  * @author Norman Walsh
75  * <a HREF="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
76  *
77  * @version 1.0
78  */

79 public class SAXCatalogReader implements CatalogReader, ContentHandler JavaDoc, DocumentHandler JavaDoc {
80   /** The SAX Parser Factory */
81   protected SAXParserFactory JavaDoc parserFactory = null;
82
83   /** The SAX Parser Class */
84   protected String JavaDoc parserClass = null;
85
86   /**
87      * Mapping table from QNames to CatalogParser classes.
88      *
89      * <p>Each key in this hash table has the form "elementname"
90      * or "{namespaceuri}elementname". The former is used if the
91      * namespace URI is null.</p>
92      */

93   protected Hashtable JavaDoc namespaceMap = new Hashtable JavaDoc();
94
95   /** The parser in use for the current catalog. */
96   private SAXCatalogParser saxParser = null;
97
98   /** Set if something goes horribly wrong. It allows the class to
99      * ignore the rest of the events that are received.
100      */

101   private boolean abandonHope = false;
102
103   /** The Catalog that we're working for. */
104   private Catalog catalog;
105
106   /** Set the XML SAX Parser Factory.
107    */

108   public void setParserFactory(SAXParserFactory JavaDoc parserFactory) {
109     this.parserFactory = parserFactory;
110   }
111
112   /** Set the XML SAX Parser Class
113    */

114   public void setParserClass(String JavaDoc parserClass) {
115     this.parserClass = parserClass;
116   }
117
118   /** Get the parser factory currently in use. */
119   public SAXParserFactory JavaDoc getParserFactory() {
120     return parserFactory;
121   }
122
123   /** Get the parser class currently in use. */
124   public String JavaDoc getParserClass() {
125     return parserClass;
126   }
127
128   /** The debug class to use for this reader.
129    *
130    * This is a bit of a hack. Anyway, whenever we read for a catalog,
131    * we extract the debug object
132    * from the catalog's manager so that we can use it to print messages.
133    *
134    * In production, we don't really expect any messages so it doesn't
135    * really matter. But it's still a bit of a hack.
136    */

137   protected Debug debug = CatalogManager.getStaticManager().debug;
138
139   /** The constructor */
140   public SAXCatalogReader() {
141     parserFactory = null;
142     parserClass = null;
143   }
144
145   /** The constructor */
146   public SAXCatalogReader(SAXParserFactory JavaDoc parserFactory) {
147     this.parserFactory = parserFactory;
148   }
149
150   /** The constructor */
151   public SAXCatalogReader(String JavaDoc parserClass) {
152     this.parserClass = parserClass;
153   }
154
155   /** Set the SAXCatalogParser class for the given namespace/root
156      * element type.
157      */

158   public void setCatalogParser(String JavaDoc namespaceURI,
159                    String JavaDoc rootElement,
160                    String JavaDoc parserClass) {
161     if (namespaceURI == null) {
162       namespaceMap.put(rootElement, parserClass);
163     } else {
164       namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
165     }
166   }
167
168   /** Get the SAXCatalogParser class for the given namespace/root
169      * element type.
170      */

171   public String JavaDoc getCatalogParser(String JavaDoc namespaceURI,
172                  String JavaDoc rootElement) {
173     if (namespaceURI == null) {
174       return (String JavaDoc) namespaceMap.get(rootElement);
175     } else {
176       return (String JavaDoc) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
177     }
178   }
179
180   /**
181    * Parse an XML Catalog file.
182    *
183    * @param catalog The catalog to which this catalog file belongs
184    * @param fileUrl The URL or filename of the catalog file to process
185    *
186    * @throws MalformedURLException Improper fileUrl
187    * @throws IOException Error reading catalog file
188    */

189   public void readCatalog(Catalog catalog, String JavaDoc fileUrl)
190     throws MalformedURLException JavaDoc, IOException JavaDoc,
191        CatalogException {
192
193     URL JavaDoc url = null;
194
195     try {
196       url = new URL JavaDoc(fileUrl);
197     } catch (MalformedURLException JavaDoc e) {
198       url = new URL JavaDoc("file:///" + fileUrl);
199     }
200
201     debug = catalog.getCatalogManager().debug;
202
203     try {
204       URLConnection JavaDoc urlCon = url.openConnection();
205       readCatalog(catalog, urlCon.getInputStream());
206     } catch (FileNotFoundException JavaDoc e) {
207       catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
208             url.toString());
209     }
210   }
211
212   /**
213    * Parse an XML Catalog stream.
214    *
215    * @param catalog The catalog to which this catalog file belongs
216    * @param is The input stream from which the catalog will be read
217    *
218    * @throws MalformedURLException Improper fileUrl
219    * @throws IOException Error reading catalog file
220    * @throws CatalogException A Catalog exception
221    */

222   public void readCatalog(Catalog catalog, InputStream JavaDoc is)
223     throws IOException JavaDoc, CatalogException {
224
225     // Create an instance of the parser
226
if (parserFactory == null && parserClass == null) {
227       debug.message(1, "Cannot read SAX catalog without a parser");
228       throw new CatalogException(CatalogException.UNPARSEABLE);
229     }
230
231     debug = catalog.getCatalogManager().debug;
232     EntityResolver JavaDoc bResolver = catalog.getCatalogManager().getBootstrapResolver();
233
234     this.catalog = catalog;
235
236     try {
237       if (parserFactory != null) {
238     SAXParser JavaDoc parser = parserFactory.newSAXParser();
239     SAXParserHandler spHandler = new SAXParserHandler();
240     spHandler.setContentHandler(this);
241     if (bResolver != null) {
242       spHandler.setEntityResolver(bResolver);
243     }
244     parser.parse(new InputSource JavaDoc(is), spHandler);
245       } else {
246     Parser JavaDoc parser = (Parser JavaDoc) Class.forName(parserClass).newInstance();
247     parser.setDocumentHandler(this);
248     if (bResolver != null) {
249       parser.setEntityResolver(bResolver);
250     }
251     parser.parse(new InputSource JavaDoc(is));
252       }
253     } catch (ClassNotFoundException JavaDoc cnfe) {
254       throw new CatalogException(CatalogException.UNPARSEABLE);
255     } catch (IllegalAccessException JavaDoc iae) {
256       throw new CatalogException(CatalogException.UNPARSEABLE);
257     } catch (InstantiationException JavaDoc ie) {
258       throw new CatalogException(CatalogException.UNPARSEABLE);
259     } catch (ParserConfigurationException JavaDoc pce) {
260       throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
261     } catch (SAXException JavaDoc se) {
262       Exception JavaDoc e = se.getException();
263       // FIXME: there must be a better way
264
UnknownHostException JavaDoc uhe = new UnknownHostException JavaDoc();
265       FileNotFoundException JavaDoc fnfe = new FileNotFoundException JavaDoc();
266       if (e != null) {
267     if (e.getClass() == uhe.getClass()) {
268       throw new CatalogException(CatalogException.PARSE_FAILED,
269                      e.toString());
270     } else if (e.getClass() == fnfe.getClass()) {
271       throw new CatalogException(CatalogException.PARSE_FAILED,
272                      e.toString());
273     }
274       }
275       throw new CatalogException(se);
276     }
277   }
278
279   // ----------------------------------------------------------------------
280
// Implement the SAX ContentHandler interface
281

282   /** The SAX <code>setDocumentLocator</code> method. Does nothing. */
283   public void setDocumentLocator (Locator JavaDoc locator) {
284     if (saxParser != null) {
285       saxParser.setDocumentLocator(locator);
286     }
287   }
288
289   /** The SAX <code>startDocument</code> method. Does nothing. */
290   public void startDocument () throws SAXException JavaDoc {
291     saxParser = null;
292     abandonHope = false;
293     return;
294   }
295
296   /** The SAX <code>endDocument</code> method. Does nothing. */
297   public void endDocument ()throws SAXException JavaDoc {
298     if (saxParser != null) {
299       saxParser.endDocument();
300     }
301   }
302
303   /**
304    * The SAX <code>startElement</code> method.
305    *
306    * <p>The catalog parser is selected based on the namespace of the
307    * first element encountered in the catalog.</p>
308    */

309   public void startElement (String JavaDoc name,
310                 AttributeList JavaDoc atts)
311     throws SAXException JavaDoc {
312
313     if (abandonHope) {
314       return;
315     }
316
317     if (saxParser == null) {
318       String JavaDoc prefix = "";
319       if (name.indexOf(':') > 0) {
320     prefix = name.substring(0, name.indexOf(':'));
321       }
322
323       String JavaDoc localName = name;
324       if (localName.indexOf(':') > 0) {
325     localName = localName.substring(localName.indexOf(':')+1);
326       }
327
328       String JavaDoc namespaceURI = null;
329       if (prefix.equals("")) {
330     namespaceURI = atts.getValue("xmlns");
331       } else {
332     namespaceURI = atts.getValue("xmlns:" + prefix);
333       }
334
335       String JavaDoc saxParserClass = getCatalogParser(namespaceURI,
336                            localName);
337
338       if (saxParserClass == null) {
339     abandonHope = true;
340     if (namespaceURI == null) {
341       debug.message(2, "No Catalog parser for " + name);
342     } else {
343       debug.message(2, "No Catalog parser for "
344             + "{" + namespaceURI + "}"
345             + name);
346     }
347     return;
348       }
349
350       try {
351     saxParser = (SAXCatalogParser)
352       Class.forName(saxParserClass).newInstance();
353
354     saxParser.setCatalog(catalog);
355     saxParser.startDocument();
356     saxParser.startElement(name, atts);
357       } catch (ClassNotFoundException JavaDoc cnfe) {
358     saxParser = null;
359     abandonHope = true;
360     debug.message(2, cnfe.toString());
361       } catch (InstantiationException JavaDoc ie) {
362     saxParser = null;
363     abandonHope = true;
364     debug.message(2, ie.toString());
365       } catch (IllegalAccessException JavaDoc iae) {
366     saxParser = null;
367     abandonHope = true;
368     debug.message(2, iae.toString());
369       } catch (ClassCastException JavaDoc cce ) {
370     saxParser = null;
371     abandonHope = true;
372     debug.message(2, cce.toString());
373       }
374     } else {
375       saxParser.startElement(name, atts);
376     }
377   }
378
379   /**
380    * The SAX2 <code>startElement</code> method.
381    *
382    * <p>The catalog parser is selected based on the namespace of the
383    * first element encountered in the catalog.</p>
384    */

385   public void startElement (String JavaDoc namespaceURI,
386                 String JavaDoc localName,
387                 String JavaDoc qName,
388                 Attributes JavaDoc atts)
389     throws SAXException JavaDoc {
390
391     if (abandonHope) {
392       return;
393     }
394
395     if (saxParser == null) {
396       String JavaDoc saxParserClass = getCatalogParser(namespaceURI,
397                            localName);
398
399       if (saxParserClass == null) {
400     abandonHope = true;
401     if (namespaceURI == null) {
402       debug.message(2, "No Catalog parser for " + localName);
403     } else {
404       debug.message(2, "No Catalog parser for "
405             + "{" + namespaceURI + "}"
406             + localName);
407     }
408     return;
409       }
410
411       try {
412     saxParser = (SAXCatalogParser)
413       Class.forName(saxParserClass).newInstance();
414
415     saxParser.setCatalog(catalog);
416     saxParser.startDocument();
417     saxParser.startElement(namespaceURI, localName, qName, atts);
418       } catch (ClassNotFoundException JavaDoc cnfe) {
419     saxParser = null;
420     abandonHope = true;
421     debug.message(2, cnfe.toString());
422       } catch (InstantiationException JavaDoc ie) {
423     saxParser = null;
424     abandonHope = true;
425     debug.message(2, ie.toString());
426       } catch (IllegalAccessException JavaDoc iae) {
427     saxParser = null;
428     abandonHope = true;
429     debug.message(2, iae.toString());
430       } catch (ClassCastException JavaDoc cce ) {
431     saxParser = null;
432     abandonHope = true;
433     debug.message(2, cce.toString());
434       }
435     } else {
436       saxParser.startElement(namespaceURI, localName, qName, atts);
437     }
438   }
439
440   /** The SAX <code>endElement</code> method. Does nothing. */
441   public void endElement (String JavaDoc name) throws SAXException JavaDoc {
442     if (saxParser != null) {
443       saxParser.endElement(name);
444     }
445   }
446
447   /** The SAX2 <code>endElement</code> method. Does nothing. */
448   public void endElement (String JavaDoc namespaceURI,
449               String JavaDoc localName,
450               String JavaDoc qName) throws SAXException JavaDoc {
451     if (saxParser != null) {
452       saxParser.endElement(namespaceURI, localName, qName);
453     }
454   }
455
456   /** The SAX <code>characters</code> method. Does nothing. */
457   public void characters (char ch[], int start, int length)
458     throws SAXException JavaDoc {
459     if (saxParser != null) {
460       saxParser.characters(ch, start, length);
461     }
462   }
463
464   /** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
465   public void ignorableWhitespace (char ch[], int start, int length)
466     throws SAXException JavaDoc {
467     if (saxParser != null) {
468       saxParser.ignorableWhitespace(ch, start, length);
469     }
470   }
471
472   /** The SAX <code>processingInstruction</code> method. Does nothing. */
473   public void processingInstruction (String JavaDoc target, String JavaDoc data)
474     throws SAXException JavaDoc {
475     if (saxParser != null) {
476       saxParser.processingInstruction(target, data);
477     }
478   }
479
480   /** The SAX <code>startPrefixMapping</code> method. Does nothing. */
481   public void startPrefixMapping (String JavaDoc prefix, String JavaDoc uri)
482     throws SAXException JavaDoc {
483     if (saxParser != null) {
484       saxParser.startPrefixMapping (prefix, uri);
485     }
486   }
487
488   /** The SAX <code>endPrefixMapping</code> method. Does nothing. */
489   public void endPrefixMapping (String JavaDoc prefix)
490     throws SAXException JavaDoc {
491     if (saxParser != null) {
492       saxParser.endPrefixMapping (prefix);
493     }
494   }
495
496   /** The SAX <code>skippedentity</code> method. Does nothing. */
497   public void skippedEntity (String JavaDoc name)
498     throws SAXException JavaDoc {
499     if (saxParser != null) {
500       saxParser.skippedEntity(name);
501     }
502   }
503 }
504
Popular Tags