KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > util > xml > catalog > readers > SAXCatalogReader


1 // SAXCatalogReader.java - Read XML Catalog files
2

3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" must
29  * not be used to endorse or promote products derived from this
30  * software without prior written permission. For written
31  * permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * nor may "Apache" appear in their name, without prior written
35  * permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 package org.jboss.util.xml.catalog.readers;
58
59 import java.util.Hashtable JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.io.FileNotFoundException JavaDoc;
62 import java.io.InputStream JavaDoc;
63 import java.net.URL JavaDoc;
64 import java.net.URLConnection JavaDoc;
65 import java.net.MalformedURLException JavaDoc;
66 import java.net.UnknownHostException JavaDoc;
67
68 import javax.xml.parsers.ParserConfigurationException JavaDoc;
69 import javax.xml.parsers.SAXParserFactory JavaDoc;
70 import javax.xml.parsers.SAXParser JavaDoc;
71
72 import org.xml.sax.AttributeList JavaDoc;
73 import org.xml.sax.Attributes JavaDoc;
74 import org.xml.sax.ContentHandler JavaDoc;
75 import org.xml.sax.DocumentHandler JavaDoc;
76 import org.xml.sax.EntityResolver JavaDoc;
77 import org.xml.sax.InputSource JavaDoc;
78 import org.xml.sax.Locator JavaDoc;
79 import org.xml.sax.Parser JavaDoc;
80 import org.xml.sax.SAXException JavaDoc;
81
82 import org.jboss.util.xml.catalog.Catalog;
83 import org.jboss.util.xml.catalog.CatalogException;
84 import org.jboss.util.xml.catalog.CatalogManager;
85 import org.jboss.util.xml.catalog.helpers.Debug;
86 import org.jboss.util.xml.catalog.readers.CatalogReader;
87
88 /**
89  * A SAX-based CatalogReader.
90  *
91  * <p>This class is used to read XML Catalogs using the SAX. This reader
92  * has an advantage over the DOM-based reader in that it functions on
93  * the stream of SAX events. It has the disadvantage
94  * that it cannot look around in the tree.</p>
95  *
96  * <p>Since the choice of CatalogReaders (in the InputStream case) can only
97  * be made on the basis of MIME type, the following problem occurs: only
98  * one CatalogReader can exist for all XML mime types. In order to get
99  * around this problem, the SAXCatalogReader relies on a set of external
100  * CatalogParsers to actually build the catalog.</p>
101  *
102  * <p>The selection of CatalogParsers is made on the basis of the QName
103  * of the root element of the document.</p>
104  *
105  * @see Catalog
106  * @see CatalogReader
107  * @see SAXCatalogReader
108  * @see TextCatalogReader
109  * @see DOMCatalogParser
110  *
111  * @author Norman Walsh
112  * <a HREF="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
113  *
114  * @version 1.0
115  */

116 public class SAXCatalogReader implements CatalogReader, ContentHandler JavaDoc, DocumentHandler JavaDoc {
117   /** The SAX Parser Factory */
118   protected SAXParserFactory JavaDoc parserFactory = null;
119
120   /** The SAX Parser Class */
121   protected String JavaDoc parserClass = null;
122
123   /**
124      * Mapping table from QNames to CatalogParser classes.
125      *
126      * <p>Each key in this hash table has the form "elementname"
127      * or "{namespaceuri}elementname". The former is used if the
128      * namespace URI is null.</p>
129      */

130   protected Hashtable JavaDoc namespaceMap = new Hashtable JavaDoc();
131
132   /** The parser in use for the current catalog. */
133   private SAXCatalogParser saxParser = null;
134
135   /** Set if something goes horribly wrong. It allows the class to
136      * ignore the rest of the events that are received.
137      */

138   private boolean abandonHope = false;
139
140   /** The Catalog that we're working for. */
141   private Catalog catalog;
142
143   /** Set the XML SAX Parser Factory.
144    */

145   public void setParserFactory(SAXParserFactory JavaDoc parserFactory) {
146     this.parserFactory = parserFactory;
147   }
148
149   /** Set the XML SAX Parser Class
150    */

151   public void setParserClass(String JavaDoc parserClass) {
152     this.parserClass = parserClass;
153   }
154
155   /** Get the parser factory currently in use. */
156   public SAXParserFactory JavaDoc getParserFactory() {
157     return parserFactory;
158   }
159
160   /** Get the parser class currently in use. */
161   public String JavaDoc getParserClass() {
162     return parserClass;
163   }
164
165   /** The debug class to use for this reader.
166    *
167    * This is a bit of a hack. Anyway, whenever we read for a catalog,
168    * we extract the debug object
169    * from the catalog's manager so that we can use it to print messages.
170    *
171    * In production, we don't really expect any messages so it doesn't
172    * really matter. But it's still a bit of a hack.
173    */

174   protected Debug debug = CatalogManager.getStaticManager().debug;
175
176   /** The constructor */
177   public SAXCatalogReader() {
178     parserFactory = null;
179     parserClass = null;
180   }
181
182   /** The constructor */
183   public SAXCatalogReader(SAXParserFactory JavaDoc parserFactory) {
184     this.parserFactory = parserFactory;
185   }
186
187   /** The constructor */
188   public SAXCatalogReader(String JavaDoc parserClass) {
189     this.parserClass = parserClass;
190   }
191
192   /** Set the SAXCatalogParser class for the given namespace/root
193      * element type.
194      */

195   public void setCatalogParser(String JavaDoc namespaceURI,
196                    String JavaDoc rootElement,
197                    String JavaDoc parserClass) {
198     if (namespaceURI == null) {
199       namespaceMap.put(rootElement, parserClass);
200     } else {
201       namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
202     }
203   }
204
205   /** Get the SAXCatalogParser class for the given namespace/root
206      * element type.
207      */

208   public String JavaDoc getCatalogParser(String JavaDoc namespaceURI,
209                  String JavaDoc rootElement) {
210     if (namespaceURI == null) {
211       return (String JavaDoc) namespaceMap.get(rootElement);
212     } else {
213       return (String JavaDoc) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
214     }
215   }
216
217   /**
218    * Parse an XML Catalog file.
219    *
220    * @param catalog The catalog to which this catalog file belongs
221    * @param fileUrl The URL or filename of the catalog file to process
222    *
223    * @throws MalformedURLException Improper fileUrl
224    * @throws IOException Error reading catalog file
225    */

226   public void readCatalog(Catalog catalog, String JavaDoc fileUrl)
227     throws MalformedURLException JavaDoc, IOException JavaDoc,
228        CatalogException {
229
230     URL JavaDoc url = null;
231
232     try {
233       url = new URL JavaDoc(fileUrl);
234     } catch (MalformedURLException JavaDoc e) {
235       url = new URL JavaDoc("file:///" + fileUrl);
236     }
237
238     debug = catalog.getCatalogManager().debug;
239
240     try {
241       URLConnection JavaDoc urlCon = url.openConnection();
242       readCatalog(catalog, urlCon.getInputStream());
243     } catch (FileNotFoundException JavaDoc e) {
244       catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
245             url.toString());
246     }
247   }
248
249   /**
250    * Parse an XML Catalog stream.
251    *
252    * @param catalog The catalog to which this catalog file belongs
253    * @param is The input stream from which the catalog will be read
254    *
255    * @throws MalformedURLException Improper fileUrl
256    * @throws IOException Error reading catalog file
257    * @throws CatalogException A Catalog exception
258    */

259   public void readCatalog(Catalog catalog, InputStream JavaDoc is)
260     throws IOException JavaDoc, CatalogException {
261
262     // Create an instance of the parser
263
if (parserFactory == null && parserClass == null) {
264       debug.message(1, "Cannot read SAX catalog without a parser");
265       throw new CatalogException(CatalogException.UNPARSEABLE);
266     }
267
268     debug = catalog.getCatalogManager().debug;
269     EntityResolver JavaDoc bResolver = catalog.getCatalogManager().getBootstrapResolver();
270
271     this.catalog = catalog;
272
273     try {
274       if (parserFactory != null) {
275     SAXParser JavaDoc parser = parserFactory.newSAXParser();
276     SAXParserHandler spHandler = new SAXParserHandler();
277     spHandler.setContentHandler(this);
278     if (bResolver != null) {
279       spHandler.setEntityResolver(bResolver);
280     }
281     parser.parse(new InputSource JavaDoc(is), spHandler);
282       } else {
283     Parser JavaDoc parser = (Parser JavaDoc) Class.forName(parserClass).newInstance();
284     parser.setDocumentHandler(this);
285     if (bResolver != null) {
286       parser.setEntityResolver(bResolver);
287     }
288     parser.parse(new InputSource JavaDoc(is));
289       }
290     } catch (ClassNotFoundException JavaDoc cnfe) {
291       throw new CatalogException(CatalogException.UNPARSEABLE);
292     } catch (IllegalAccessException JavaDoc iae) {
293       throw new CatalogException(CatalogException.UNPARSEABLE);
294     } catch (InstantiationException JavaDoc ie) {
295       throw new CatalogException(CatalogException.UNPARSEABLE);
296     } catch (ParserConfigurationException JavaDoc pce) {
297       throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
298     } catch (SAXException JavaDoc se) {
299       Exception JavaDoc e = se.getException();
300       // FIXME: there must be a better way
301
UnknownHostException JavaDoc uhe = new UnknownHostException JavaDoc();
302       FileNotFoundException JavaDoc fnfe = new FileNotFoundException JavaDoc();
303       if (e != null) {
304     if (e.getClass() == uhe.getClass()) {
305       throw new CatalogException(CatalogException.PARSE_FAILED,
306                      e.toString());
307     } else if (e.getClass() == fnfe.getClass()) {
308       throw new CatalogException(CatalogException.PARSE_FAILED,
309                      e.toString());
310     }
311       }
312       throw new CatalogException(se);
313     }
314   }
315
316   // ----------------------------------------------------------------------
317
// Implement the SAX ContentHandler interface
318

319   /** The SAX <code>setDocumentLocator</code> method. Does nothing. */
320   public void setDocumentLocator (Locator JavaDoc locator) {
321     if (saxParser != null) {
322       saxParser.setDocumentLocator(locator);
323     }
324   }
325
326   /** The SAX <code>startDocument</code> method. Does nothing. */
327   public void startDocument () throws SAXException JavaDoc {
328     saxParser = null;
329     abandonHope = false;
330     return;
331   }
332
333   /** The SAX <code>endDocument</code> method. Does nothing. */
334   public void endDocument ()throws SAXException JavaDoc {
335     if (saxParser != null) {
336       saxParser.endDocument();
337     }
338   }
339
340   /**
341    * The SAX <code>startElement</code> method.
342    *
343    * <p>The catalog parser is selected based on the namespace of the
344    * first element encountered in the catalog.</p>
345    */

346   public void startElement (String JavaDoc name,
347                 AttributeList JavaDoc atts)
348     throws SAXException JavaDoc {
349
350     if (abandonHope) {
351       return;
352     }
353
354     if (saxParser == null) {
355       String JavaDoc prefix = "";
356       if (name.indexOf(':') > 0) {
357     prefix = name.substring(0, name.indexOf(':'));
358       }
359
360       String JavaDoc localName = name;
361       if (localName.indexOf(':') > 0) {
362     localName = localName.substring(localName.indexOf(':')+1);
363       }
364
365       String JavaDoc namespaceURI = null;
366       if (prefix.equals("")) {
367     namespaceURI = atts.getValue("xmlns");
368       } else {
369     namespaceURI = atts.getValue("xmlns:" + prefix);
370       }
371
372       String JavaDoc saxParserClass = getCatalogParser(namespaceURI,
373                            localName);
374
375       if (saxParserClass == null) {
376     abandonHope = true;
377     if (namespaceURI == null) {
378       debug.message(2, "No Catalog parser for " + name);
379     } else {
380       debug.message(2, "No Catalog parser for "
381             + "{" + namespaceURI + "}"
382             + name);
383     }
384     return;
385       }
386
387       try {
388     saxParser = (SAXCatalogParser)
389       Class.forName(saxParserClass).newInstance();
390
391     saxParser.setCatalog(catalog);
392     saxParser.startDocument();
393     saxParser.startElement(name, atts);
394       } catch (ClassNotFoundException JavaDoc cnfe) {
395     saxParser = null;
396     abandonHope = true;
397     debug.message(2, cnfe.toString());
398       } catch (InstantiationException JavaDoc ie) {
399     saxParser = null;
400     abandonHope = true;
401     debug.message(2, ie.toString());
402       } catch (IllegalAccessException JavaDoc iae) {
403     saxParser = null;
404     abandonHope = true;
405     debug.message(2, iae.toString());
406       } catch (ClassCastException JavaDoc cce ) {
407     saxParser = null;
408     abandonHope = true;
409     debug.message(2, cce.toString());
410       }
411     } else {
412       saxParser.startElement(name, atts);
413     }
414   }
415
416   /**
417    * The SAX2 <code>startElement</code> method.
418    *
419    * <p>The catalog parser is selected based on the namespace of the
420    * first element encountered in the catalog.</p>
421    */

422   public void startElement (String JavaDoc namespaceURI,
423                 String JavaDoc localName,
424                 String JavaDoc qName,
425                 Attributes JavaDoc atts)
426     throws SAXException JavaDoc {
427
428     if (abandonHope) {
429       return;
430     }
431
432     if (saxParser == null) {
433       String JavaDoc saxParserClass = getCatalogParser(namespaceURI,
434                            localName);
435
436       if (saxParserClass == null) {
437     abandonHope = true;
438     if (namespaceURI == null) {
439       debug.message(2, "No Catalog parser for " + localName);
440     } else {
441       debug.message(2, "No Catalog parser for "
442             + "{" + namespaceURI + "}"
443             + localName);
444     }
445     return;
446       }
447
448       try {
449     saxParser = (SAXCatalogParser)
450       Class.forName(saxParserClass).newInstance();
451
452     saxParser.setCatalog(catalog);
453     saxParser.startDocument();
454     saxParser.startElement(namespaceURI, localName, qName, atts);
455       } catch (ClassNotFoundException JavaDoc cnfe) {
456     saxParser = null;
457     abandonHope = true;
458     debug.message(2, cnfe.toString());
459       } catch (InstantiationException JavaDoc ie) {
460     saxParser = null;
461     abandonHope = true;
462     debug.message(2, ie.toString());
463       } catch (IllegalAccessException JavaDoc iae) {
464     saxParser = null;
465     abandonHope = true;
466     debug.message(2, iae.toString());
467       } catch (ClassCastException JavaDoc cce ) {
468     saxParser = null;
469     abandonHope = true;
470     debug.message(2, cce.toString());
471       }
472     } else {
473       saxParser.startElement(namespaceURI, localName, qName, atts);
474     }
475   }
476
477   /** The SAX <code>endElement</code> method. Does nothing. */
478   public void endElement (String JavaDoc name) throws SAXException JavaDoc {
479     if (saxParser != null) {
480       saxParser.endElement(name);
481     }
482   }
483
484   /** The SAX2 <code>endElement</code> method. Does nothing. */
485   public void endElement (String JavaDoc namespaceURI,
486               String JavaDoc localName,
487               String JavaDoc qName) throws SAXException JavaDoc {
488     if (saxParser != null) {
489       saxParser.endElement(namespaceURI, localName, qName);
490     }
491   }
492
493   /** The SAX <code>characters</code> method. Does nothing. */
494   public void characters (char ch[], int start, int length)
495     throws SAXException JavaDoc {
496     if (saxParser != null) {
497       saxParser.characters(ch, start, length);
498     }
499   }
500
501   /** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
502   public void ignorableWhitespace (char ch[], int start, int length)
503     throws SAXException JavaDoc {
504     if (saxParser != null) {
505       saxParser.ignorableWhitespace(ch, start, length);
506     }
507   }
508
509   /** The SAX <code>processingInstruction</code> method. Does nothing. */
510   public void processingInstruction (String JavaDoc target, String JavaDoc data)
511     throws SAXException JavaDoc {
512     if (saxParser != null) {
513       saxParser.processingInstruction(target, data);
514     }
515   }
516
517   /** The SAX <code>startPrefixMapping</code> method. Does nothing. */
518   public void startPrefixMapping (String JavaDoc prefix, String JavaDoc uri)
519     throws SAXException JavaDoc {
520     if (saxParser != null) {
521       saxParser.startPrefixMapping (prefix, uri);
522     }
523   }
524
525   /** The SAX <code>endPrefixMapping</code> method. Does nothing. */
526   public void endPrefixMapping (String JavaDoc prefix)
527     throws SAXException JavaDoc {
528     if (saxParser != null) {
529       saxParser.endPrefixMapping (prefix);
530     }
531   }
532
533   /** The SAX <code>skippedentity</code> method. Does nothing. */
534   public void skippedEntity (String JavaDoc name)
535     throws SAXException JavaDoc {
536     if (saxParser != null) {
537       saxParser.skippedEntity(name);
538     }
539   }
540 }
541
Popular Tags