Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » resolver » readers » [javadoc | source]
    1   /*
    2    * reserved comment block
    3    * DO NOT REMOVE OR ALTER!
    4    */
    5   // SAXCatalogReader.java - Read XML Catalog files
    6   
    7   /*
    8    * Copyright 2001-2004 The Apache Software Foundation or its licensors,
    9    * as applicable.
   10    *
   11    * Licensed under the Apache License, Version 2.0 (the "License");
   12    * you may not use this file except in compliance with the License.
   13    * You may obtain a copy of the License at
   14    *
   15    *      http://www.apache.org/licenses/LICENSE-2.0
   16    *
   17    * Unless required by applicable law or agreed to in writing, software
   18    * distributed under the License is distributed on an "AS IS" BASIS,
   19    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   20    * See the License for the specific language governing permissions and
   21    * limitations under the License.
   22    */
   23   
   24   package com.sun.org.apache.xml.internal.resolver.readers;
   25   
   26   import java.util.Hashtable;
   27   import java.io.IOException;
   28   import java.io.FileNotFoundException;
   29   import java.io.InputStream;
   30   import java.net.URL;
   31   import java.net.URLConnection;
   32   import java.net.MalformedURLException;
   33   import java.net.UnknownHostException;
   34   
   35   import javax.xml.parsers.ParserConfigurationException;
   36   import javax.xml.parsers.SAXParserFactory;
   37   import javax.xml.parsers.SAXParser;
   38   
   39   import org.xml.sax.AttributeList;
   40   import org.xml.sax.Attributes;
   41   import org.xml.sax.ContentHandler;
   42   import org.xml.sax.DocumentHandler;
   43   import org.xml.sax.EntityResolver;
   44   import org.xml.sax.InputSource;
   45   import org.xml.sax.Locator;
   46   import org.xml.sax.Parser;
   47   import org.xml.sax.SAXException;
   48   
   49   import com.sun.org.apache.xml.internal.resolver.Catalog;
   50   import com.sun.org.apache.xml.internal.resolver.CatalogManager;
   51   import com.sun.org.apache.xml.internal.resolver.CatalogException;
   52   import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
   53   import com.sun.org.apache.xml.internal.resolver.helpers.Debug;
   54   
   55   /**
   56    * A SAX-based CatalogReader.
   57    *
   58    * <p>This class is used to read XML Catalogs using the SAX. This reader
   59    * has an advantage over the DOM-based reader in that it functions on
   60    * the stream of SAX events. It has the disadvantage
   61    * that it cannot look around in the tree.</p>
   62    *
   63    * <p>Since the choice of CatalogReaders (in the InputStream case) can only
   64    * be made on the basis of MIME type, the following problem occurs: only
   65    * one CatalogReader can exist for all XML mime types. In order to get
   66    * around this problem, the SAXCatalogReader relies on a set of external
   67    * CatalogParsers to actually build the catalog.</p>
   68    *
   69    * <p>The selection of CatalogParsers is made on the basis of the QName
   70    * of the root element of the document.</p>
   71    *
   72    * @see Catalog
   73    * @see CatalogReader
   74    * @see SAXCatalogReader
   75    * @see TextCatalogReader
   76    * @see DOMCatalogParser
   77    *
   78    * @author Norman Walsh
   79    * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
   80    *
   81    */
   82   public class SAXCatalogReader implements CatalogReader, ContentHandler, DocumentHandler {
   83     /** The SAX Parser Factory */
   84     protected SAXParserFactory parserFactory = null;
   85   
   86     /** The SAX Parser Class */
   87     protected String parserClass = null;
   88   
   89     /**
   90        * Mapping table from QNames to CatalogParser classes.
   91        *
   92        * <p>Each key in this hash table has the form "elementname"
   93        * or "{namespaceuri}elementname". The former is used if the
   94        * namespace URI is null.</p>
   95        */
   96     protected Hashtable namespaceMap = new Hashtable();
   97   
   98     /** The parser in use for the current catalog. */
   99     private SAXCatalogParser saxParser = null;
  100   
  101     /** Set if something goes horribly wrong. It allows the class to
  102        * ignore the rest of the events that are received.
  103        */
  104     private boolean abandonHope = false;
  105   
  106     /** The Catalog that we're working for. */
  107     private Catalog catalog;
  108   
  109     /** Set the XML SAX Parser Factory.
  110      */
  111     public void setParserFactory(SAXParserFactory parserFactory) {
  112       this.parserFactory = parserFactory;
  113     }
  114   
  115     /** Set the XML SAX Parser Class
  116      */
  117     public void setParserClass(String parserClass) {
  118       this.parserClass = parserClass;
  119     }
  120   
  121     /** Get the parser factory currently in use. */
  122     public SAXParserFactory getParserFactory() {
  123       return parserFactory;
  124     }
  125   
  126     /** Get the parser class currently in use. */
  127     public String getParserClass() {
  128       return parserClass;
  129     }
  130   
  131     /** The debug class to use for this reader.
  132      *
  133      * This is a bit of a hack. Anyway, whenever we read for a catalog,
  134      * we extract the debug object
  135      * from the catalog's manager so that we can use it to print messages.
  136      *
  137      * In production, we don't really expect any messages so it doesn't
  138      * really matter. But it's still a bit of a hack.
  139      */
  140     protected Debug debug = CatalogManager.getStaticManager().debug;
  141   
  142     /** The constructor */
  143     public SAXCatalogReader() {
  144       parserFactory = null;
  145       parserClass = null;
  146     }
  147   
  148     /** The constructor */
  149     public SAXCatalogReader(SAXParserFactory parserFactory) {
  150       this.parserFactory = parserFactory;
  151     }
  152   
  153     /** The constructor */
  154     public SAXCatalogReader(String parserClass) {
  155       this.parserClass = parserClass;
  156     }
  157   
  158     /** Set the SAXCatalogParser class for the given namespace/root
  159        * element type.
  160        */
  161     public void setCatalogParser(String namespaceURI,
  162                                  String rootElement,
  163                                  String parserClass) {
  164       if (namespaceURI == null) {
  165         namespaceMap.put(rootElement, parserClass);
  166       } else {
  167         namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
  168       }
  169     }
  170   
  171     /** Get the SAXCatalogParser class for the given namespace/root
  172        * element type.
  173        */
  174     public String getCatalogParser(String namespaceURI,
  175                                    String rootElement) {
  176       if (namespaceURI == null) {
  177         return (String) namespaceMap.get(rootElement);
  178       } else {
  179         return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
  180       }
  181     }
  182   
  183     /**
  184      * Parse an XML Catalog file.
  185      *
  186      * @param catalog The catalog to which this catalog file belongs
  187      * @param fileUrl The URL or filename of the catalog file to process
  188      *
  189      * @throws MalformedURLException Improper fileUrl
  190      * @throws IOException Error reading catalog file
  191      */
  192     public void readCatalog(Catalog catalog, String fileUrl)
  193       throws MalformedURLException, IOException,
  194              CatalogException {
  195   
  196       URL url = null;
  197   
  198       try {
  199         url = new URL(fileUrl);
  200       } catch (MalformedURLException e) {
  201         url = new URL("file:///" + fileUrl);
  202       }
  203   
  204       debug = catalog.getCatalogManager().debug;
  205   
  206       try {
  207         URLConnection urlCon = url.openConnection();
  208         readCatalog(catalog, urlCon.getInputStream());
  209       } catch (FileNotFoundException e) {
  210         catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
  211                       url.toString());
  212       }
  213     }
  214   
  215     /**
  216      * Parse an XML Catalog stream.
  217      *
  218      * @param catalog The catalog to which this catalog file belongs
  219      * @param is The input stream from which the catalog will be read
  220      *
  221      * @throws MalformedURLException Improper fileUrl
  222      * @throws IOException Error reading catalog file
  223      * @throws CatalogException A Catalog exception
  224      */
  225     public void readCatalog(Catalog catalog, InputStream is)
  226       throws IOException, CatalogException {
  227   
  228       // Create an instance of the parser
  229       if (parserFactory == null && parserClass == null) {
  230         debug.message(1, "Cannot read SAX catalog without a parser");
  231         throw new CatalogException(CatalogException.UNPARSEABLE);
  232       }
  233   
  234       debug = catalog.getCatalogManager().debug;
  235       EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
  236   
  237       this.catalog = catalog;
  238   
  239       try {
  240         if (parserFactory != null) {
  241           SAXParser parser = parserFactory.newSAXParser();
  242           SAXParserHandler spHandler = new SAXParserHandler();
  243           spHandler.setContentHandler(this);
  244           if (bResolver != null) {
  245             spHandler.setEntityResolver(bResolver);
  246           }
  247           parser.parse(new InputSource(is), spHandler);
  248         } else {
  249           Parser parser = (Parser) Class.forName(parserClass).newInstance();
  250           parser.setDocumentHandler(this);
  251           if (bResolver != null) {
  252             parser.setEntityResolver(bResolver);
  253           }
  254           parser.parse(new InputSource(is));
  255         }
  256       } catch (ClassNotFoundException cnfe) {
  257         throw new CatalogException(CatalogException.UNPARSEABLE);
  258       } catch (IllegalAccessException iae) {
  259         throw new CatalogException(CatalogException.UNPARSEABLE);
  260       } catch (InstantiationException ie) {
  261         throw new CatalogException(CatalogException.UNPARSEABLE);
  262       } catch (ParserConfigurationException pce) {
  263         throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
  264       } catch (SAXException se) {
  265         Exception e = se.getException();
  266         // FIXME: there must be a better way
  267         UnknownHostException uhe = new UnknownHostException();
  268         FileNotFoundException fnfe = new FileNotFoundException();
  269         if (e != null) {
  270           if (e.getClass() == uhe.getClass()) {
  271             throw new CatalogException(CatalogException.PARSE_FAILED,
  272                                        e.toString());
  273           } else if (e.getClass() == fnfe.getClass()) {
  274             throw new CatalogException(CatalogException.PARSE_FAILED,
  275                                        e.toString());
  276           }
  277         }
  278         throw new CatalogException(se);
  279       }
  280     }
  281   
  282     // ----------------------------------------------------------------------
  283     // Implement the SAX ContentHandler interface
  284   
  285     /** The SAX <code>setDocumentLocator</code> method. Does nothing. */
  286     public void setDocumentLocator (Locator locator) {
  287       if (saxParser != null) {
  288         saxParser.setDocumentLocator(locator);
  289       }
  290     }
  291   
  292     /** The SAX <code>startDocument</code> method. Does nothing. */
  293     public void startDocument () throws SAXException {
  294       saxParser = null;
  295       abandonHope = false;
  296       return;
  297     }
  298   
  299     /** The SAX <code>endDocument</code> method. Does nothing. */
  300     public void endDocument ()throws SAXException {
  301       if (saxParser != null) {
  302         saxParser.endDocument();
  303       }
  304     }
  305   
  306     /**
  307      * The SAX <code>startElement</code> method.
  308      *
  309      * <p>The catalog parser is selected based on the namespace of the
  310      * first element encountered in the catalog.</p>
  311      */
  312     public void startElement (String name,
  313                               AttributeList atts)
  314       throws SAXException {
  315   
  316       if (abandonHope) {
  317         return;
  318       }
  319   
  320       if (saxParser == null) {
  321         String prefix = "";
  322         if (name.indexOf(':') > 0) {
  323           prefix = name.substring(0, name.indexOf(':'));
  324         }
  325   
  326         String localName = name;
  327         if (localName.indexOf(':') > 0) {
  328           localName = localName.substring(localName.indexOf(':')+1);
  329         }
  330   
  331         String namespaceURI = null;
  332         if (prefix.equals("")) {
  333           namespaceURI = atts.getValue("xmlns");
  334         } else {
  335           namespaceURI = atts.getValue("xmlns:" + prefix);
  336         }
  337   
  338         String saxParserClass = getCatalogParser(namespaceURI,
  339                                                  localName);
  340   
  341         if (saxParserClass == null) {
  342           abandonHope = true;
  343           if (namespaceURI == null) {
  344             debug.message(2, "No Catalog parser for " + name);
  345           } else {
  346             debug.message(2, "No Catalog parser for "
  347                           + "{" + namespaceURI + "}"
  348                           + name);
  349           }
  350           return;
  351         }
  352   
  353         try {
  354           saxParser = (SAXCatalogParser)
  355             Class.forName(saxParserClass).newInstance();
  356   
  357           saxParser.setCatalog(catalog);
  358           saxParser.startDocument();
  359           saxParser.startElement(name, atts);
  360         } catch (ClassNotFoundException cnfe) {
  361           saxParser = null;
  362           abandonHope = true;
  363           debug.message(2, cnfe.toString());
  364         } catch (InstantiationException ie) {
  365           saxParser = null;
  366           abandonHope = true;
  367           debug.message(2, ie.toString());
  368         } catch (IllegalAccessException iae) {
  369           saxParser = null;
  370           abandonHope = true;
  371           debug.message(2, iae.toString());
  372         } catch (ClassCastException cce ) {
  373           saxParser = null;
  374           abandonHope = true;
  375           debug.message(2, cce.toString());
  376         }
  377       } else {
  378         saxParser.startElement(name, atts);
  379       }
  380     }
  381   
  382     /**
  383      * The SAX2 <code>startElement</code> method.
  384      *
  385      * <p>The catalog parser is selected based on the namespace of the
  386      * first element encountered in the catalog.</p>
  387      */
  388     public void startElement (String namespaceURI,
  389                               String localName,
  390                               String qName,
  391                               Attributes atts)
  392       throws SAXException {
  393   
  394       if (abandonHope) {
  395         return;
  396       }
  397   
  398       if (saxParser == null) {
  399         String saxParserClass = getCatalogParser(namespaceURI,
  400                                                  localName);
  401   
  402         if (saxParserClass == null) {
  403           abandonHope = true;
  404           if (namespaceURI == null) {
  405             debug.message(2, "No Catalog parser for " + localName);
  406           } else {
  407             debug.message(2, "No Catalog parser for "
  408                           + "{" + namespaceURI + "}"
  409                           + localName);
  410           }
  411           return;
  412         }
  413   
  414         try {
  415           saxParser = (SAXCatalogParser)
  416             Class.forName(saxParserClass).newInstance();
  417   
  418           saxParser.setCatalog(catalog);
  419           saxParser.startDocument();
  420           saxParser.startElement(namespaceURI, localName, qName, atts);
  421         } catch (ClassNotFoundException cnfe) {
  422           saxParser = null;
  423           abandonHope = true;
  424           debug.message(2, cnfe.toString());
  425         } catch (InstantiationException ie) {
  426           saxParser = null;
  427           abandonHope = true;
  428           debug.message(2, ie.toString());
  429         } catch (IllegalAccessException iae) {
  430           saxParser = null;
  431           abandonHope = true;
  432           debug.message(2, iae.toString());
  433         } catch (ClassCastException cce ) {
  434           saxParser = null;
  435           abandonHope = true;
  436           debug.message(2, cce.toString());
  437         }
  438       } else {
  439         saxParser.startElement(namespaceURI, localName, qName, atts);
  440       }
  441     }
  442   
  443     /** The SAX <code>endElement</code> method. Does nothing. */
  444     public void endElement (String name) throws SAXException {
  445       if (saxParser != null) {
  446         saxParser.endElement(name);
  447       }
  448     }
  449   
  450     /** The SAX2 <code>endElement</code> method. Does nothing. */
  451     public void endElement (String namespaceURI,
  452                             String localName,
  453                             String qName) throws SAXException {
  454       if (saxParser != null) {
  455         saxParser.endElement(namespaceURI, localName, qName);
  456       }
  457     }
  458   
  459     /** The SAX <code>characters</code> method. Does nothing. */
  460     public void characters (char ch[], int start, int length)
  461       throws SAXException {
  462       if (saxParser != null) {
  463         saxParser.characters(ch, start, length);
  464       }
  465     }
  466   
  467     /** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
  468     public void ignorableWhitespace (char ch[], int start, int length)
  469       throws SAXException {
  470       if (saxParser != null) {
  471         saxParser.ignorableWhitespace(ch, start, length);
  472       }
  473     }
  474   
  475     /** The SAX <code>processingInstruction</code> method. Does nothing. */
  476     public void processingInstruction (String target, String data)
  477       throws SAXException {
  478       if (saxParser != null) {
  479         saxParser.processingInstruction(target, data);
  480       }
  481     }
  482   
  483     /** The SAX <code>startPrefixMapping</code> method. Does nothing. */
  484     public void startPrefixMapping (String prefix, String uri)
  485       throws SAXException {
  486       if (saxParser != null) {
  487         saxParser.startPrefixMapping (prefix, uri);
  488       }
  489     }
  490   
  491     /** The SAX <code>endPrefixMapping</code> method. Does nothing. */
  492     public void endPrefixMapping (String prefix)
  493       throws SAXException {
  494       if (saxParser != null) {
  495         saxParser.endPrefixMapping (prefix);
  496       }
  497     }
  498   
  499     /** The SAX <code>skippedentity</code> method. Does nothing. */
  500     public void skippedEntity (String name)
  501       throws SAXException {
  502       if (saxParser != null) {
  503         saxParser.skippedEntity(name);
  504       }
  505     }
  506   }

Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » resolver » readers » [javadoc | source]