FileDocCategorySizeDatePackage
SAXCatalogReader.javaAPI DocJava SE 6 API15032Tue Jun 10 00:23:00 BST 2008com.sun.org.apache.xml.internal.resolver.readers

SAXCatalogReader

public class SAXCatalogReader extends Object implements com.sun.org.apache.xml.internal.resolver.readers.CatalogReader, DocumentHandler, ContentHandler
A SAX-based CatalogReader.

This class is used to read XML Catalogs using the SAX. This reader has an advantage over the DOM-based reader in that it functions on the stream of SAX events. It has the disadvantage that it cannot look around in the tree.

Since the choice of CatalogReaders (in the InputStream case) can only be made on the basis of MIME type, the following problem occurs: only one CatalogReader can exist for all XML mime types. In order to get around this problem, the SAXCatalogReader relies on a set of external CatalogParsers to actually build the catalog.

The selection of CatalogParsers is made on the basis of the QName of the root element of the document.

see
Catalog
see
CatalogReader
see
SAXCatalogReader
see
TextCatalogReader
see
DOMCatalogParser
author
Norman Walsh Norman.Walsh@Sun.COM
version
1.0

Fields Summary
protected SAXParserFactory
parserFactory
The SAX Parser Factory
protected String
parserClass
The SAX Parser Class
protected Hashtable
namespaceMap
Mapping table from QNames to CatalogParser classes.

Each key in this hash table has the form "elementname" or "{namespaceuri}elementname". The former is used if the namespace URI is null.

private SAXCatalogParser
saxParser
The parser in use for the current catalog.
private boolean
abandonHope
Set if something goes horribly wrong. It allows the class to ignore the rest of the events that are received.
private com.sun.org.apache.xml.internal.resolver.Catalog
catalog
The Catalog that we're working for.
protected com.sun.org.apache.xml.internal.resolver.helpers.Debug
debug
The debug class to use for this reader. This is a bit of a hack. Anyway, whenever we read for a catalog, we extract the debug object from the catalog's manager so that we can use it to print messages. In production, we don't really expect any messages so it doesn't really matter. But it's still a bit of a hack.
Constructors Summary
public SAXCatalogReader()
The constructor


     
    
    parserFactory = null;
    parserClass = null;
  
public SAXCatalogReader(SAXParserFactory parserFactory)
The constructor

    this.parserFactory = parserFactory;
  
public SAXCatalogReader(String parserClass)
The constructor

    this.parserClass = parserClass;
  
Methods Summary
public voidcharacters(char[] ch, int start, int length)
The SAX characters method. Does nothing.

    if (saxParser != null) {
      saxParser.characters(ch, start, length);
    }
  
public voidendDocument()
The SAX endDocument method. Does nothing.

    if (saxParser != null) {
      saxParser.endDocument();
    }
  
public voidendElement(java.lang.String name)
The SAX endElement method. Does nothing.

    if (saxParser != null) {
      saxParser.endElement(name);
    }
  
public voidendElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName)
The SAX2 endElement method. Does nothing.

    if (saxParser != null) {
      saxParser.endElement(namespaceURI, localName, qName);
    }
  
public voidendPrefixMapping(java.lang.String prefix)
The SAX endPrefixMapping method. Does nothing.

    if (saxParser != null) {
      saxParser.endPrefixMapping (prefix);
    }
  
public java.lang.StringgetCatalogParser(java.lang.String namespaceURI, java.lang.String rootElement)
Get the SAXCatalogParser class for the given namespace/root element type.

    if (namespaceURI == null) {
      return (String) namespaceMap.get(rootElement);
    } else {
      return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
    }
  
public java.lang.StringgetParserClass()
Get the parser class currently in use.

    return parserClass;
  
public javax.xml.parsers.SAXParserFactorygetParserFactory()
Get the parser factory currently in use.

    return parserFactory;
  
public voidignorableWhitespace(char[] ch, int start, int length)
The SAX ignorableWhitespace method. Does nothing.

    if (saxParser != null) {
      saxParser.ignorableWhitespace(ch, start, length);
    }
  
public voidprocessingInstruction(java.lang.String target, java.lang.String data)
The SAX processingInstruction method. Does nothing.

    if (saxParser != null) {
      saxParser.processingInstruction(target, data);
    }
  
public voidreadCatalog(com.sun.org.apache.xml.internal.resolver.Catalog catalog, java.lang.String fileUrl)
Parse an XML Catalog file.

param
catalog The catalog to which this catalog file belongs
param
fileUrl The URL or filename of the catalog file to process
throws
MalformedURLException Improper fileUrl
throws
IOException Error reading catalog file


    URL url = null;

    try {
      url = new URL(fileUrl);
    } catch (MalformedURLException e) {
      url = new URL("file:///" + fileUrl);
    }

    debug = catalog.getCatalogManager().debug;

    try {
      URLConnection urlCon = url.openConnection();
      readCatalog(catalog, urlCon.getInputStream());
    } catch (FileNotFoundException e) {
      catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
		    url.toString());
    }
  
public voidreadCatalog(com.sun.org.apache.xml.internal.resolver.Catalog catalog, java.io.InputStream is)
Parse an XML Catalog stream.

param
catalog The catalog to which this catalog file belongs
param
is The input stream from which the catalog will be read
throws
MalformedURLException Improper fileUrl
throws
IOException Error reading catalog file
throws
CatalogException A Catalog exception


    // Create an instance of the parser
    if (parserFactory == null && parserClass == null) {
      debug.message(1, "Cannot read SAX catalog without a parser");
      throw new CatalogException(CatalogException.UNPARSEABLE);
    }

    debug = catalog.getCatalogManager().debug;
    EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();

    this.catalog = catalog;

    try {
      if (parserFactory != null) {
	SAXParser parser = parserFactory.newSAXParser();
	SAXParserHandler spHandler = new SAXParserHandler();
	spHandler.setContentHandler(this);
	if (bResolver != null) {
	  spHandler.setEntityResolver(bResolver);
	}
	parser.parse(new InputSource(is), spHandler);
      } else {
	Parser parser = (Parser) Class.forName(parserClass).newInstance();
	parser.setDocumentHandler(this);
	if (bResolver != null) {
	  parser.setEntityResolver(bResolver);
	}
	parser.parse(new InputSource(is));
      }
    } catch (ClassNotFoundException cnfe) {
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (IllegalAccessException iae) {
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (InstantiationException ie) {
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (ParserConfigurationException pce) {
      throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
    } catch (SAXException se) {
      Exception e = se.getException();
      // FIXME: there must be a better way
      UnknownHostException uhe = new UnknownHostException();
      FileNotFoundException fnfe = new FileNotFoundException();
      if (e != null) {
	if (e.getClass() == uhe.getClass()) {
	  throw new CatalogException(CatalogException.PARSE_FAILED,
				     e.toString());
	} else if (e.getClass() == fnfe.getClass()) {
	  throw new CatalogException(CatalogException.PARSE_FAILED,
				     e.toString());
	}
      }
      throw new CatalogException(se);
    }
  
public voidsetCatalogParser(java.lang.String namespaceURI, java.lang.String rootElement, java.lang.String parserClass)
Set the SAXCatalogParser class for the given namespace/root element type.

    if (namespaceURI == null) {
      namespaceMap.put(rootElement, parserClass);
    } else {
      namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
    }
  
public voidsetDocumentLocator(org.xml.sax.Locator locator)
The SAX setDocumentLocator method. Does nothing.

    if (saxParser != null) {
      saxParser.setDocumentLocator(locator);
    }
  
public voidsetParserClass(java.lang.String parserClass)
Set the XML SAX Parser Class

    this.parserClass = parserClass;
  
public voidsetParserFactory(javax.xml.parsers.SAXParserFactory parserFactory)
Set the XML SAX Parser Factory.


           
      
    this.parserFactory = parserFactory;
  
public voidskippedEntity(java.lang.String name)
The SAX skippedentity method. Does nothing.

    if (saxParser != null) {
      saxParser.skippedEntity(name);
    }
  
public voidstartDocument()
The SAX startDocument method. Does nothing.

    saxParser = null;
    abandonHope = false;
    return;
  
public voidstartElement(java.lang.String name, org.xml.sax.AttributeList atts)
The SAX startElement method.

The catalog parser is selected based on the namespace of the first element encountered in the catalog.


    if (abandonHope) {
      return;
    }

    if (saxParser == null) {
      String prefix = "";
      if (name.indexOf(':") > 0) {
	prefix = name.substring(0, name.indexOf(':"));
      }

      String localName = name;
      if (localName.indexOf(':") > 0) {
	localName = localName.substring(localName.indexOf(':")+1);
      }

      String namespaceURI = null;
      if (prefix.equals("")) {
	namespaceURI = atts.getValue("xmlns");
      } else {
	namespaceURI = atts.getValue("xmlns:" + prefix);
      }

      String saxParserClass = getCatalogParser(namespaceURI,
					       localName);

      if (saxParserClass == null) {
	abandonHope = true;
	if (namespaceURI == null) {
	  debug.message(2, "No Catalog parser for " + name);
	} else {
	  debug.message(2, "No Catalog parser for "
			+ "{" + namespaceURI + "}"
			+ name);
	}
	return;
      }

      try {
	saxParser = (SAXCatalogParser)
	  Class.forName(saxParserClass).newInstance();

	saxParser.setCatalog(catalog);
	saxParser.startDocument();
	saxParser.startElement(name, atts);
      } catch (ClassNotFoundException cnfe) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, cnfe.toString());
      } catch (InstantiationException ie) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, ie.toString());
      } catch (IllegalAccessException iae) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, iae.toString());
      } catch (ClassCastException cce ) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, cce.toString());
      }
    } else {
      saxParser.startElement(name, atts);
    }
  
public voidstartElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes atts)
The SAX2 startElement method.

The catalog parser is selected based on the namespace of the first element encountered in the catalog.


    if (abandonHope) {
      return;
    }

    if (saxParser == null) {
      String saxParserClass = getCatalogParser(namespaceURI,
					       localName);

      if (saxParserClass == null) {
	abandonHope = true;
	if (namespaceURI == null) {
	  debug.message(2, "No Catalog parser for " + localName);
	} else {
	  debug.message(2, "No Catalog parser for "
			+ "{" + namespaceURI + "}"
			+ localName);
	}
	return;
      }

      try {
	saxParser = (SAXCatalogParser)
	  Class.forName(saxParserClass).newInstance();

	saxParser.setCatalog(catalog);
	saxParser.startDocument();
	saxParser.startElement(namespaceURI, localName, qName, atts);
      } catch (ClassNotFoundException cnfe) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, cnfe.toString());
      } catch (InstantiationException ie) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, ie.toString());
      } catch (IllegalAccessException iae) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, iae.toString());
      } catch (ClassCastException cce ) {
	saxParser = null;
	abandonHope = true;
	debug.message(2, cce.toString());
      }
    } else {
      saxParser.startElement(namespaceURI, localName, qName, atts);
    }
  
public voidstartPrefixMapping(java.lang.String prefix, java.lang.String uri)
The SAX startPrefixMapping method. Does nothing.

    if (saxParser != null) {
      saxParser.startPrefixMapping (prefix, uri);
    }