FileDocCategorySizeDatePackage
CatalogResolver.javaAPI DocJava SE 6 API10334Tue Jun 10 00:23:00 BST 2008com.sun.org.apache.xml.internal.resolver.tools

CatalogResolver

public class CatalogResolver extends Object implements URIResolver, EntityResolver
A SAX EntityResolver/JAXP URIResolver that uses catalogs.

This class implements both a SAX EntityResolver and a JAXP URIResolver.

This resolver understands OASIS TR9401 catalogs, XCatalogs, and the current working draft of the OASIS Entity Resolution Technical Committee specification.

see
Catalog
see
org.xml.sax.EntityResolver
see
javax.xml.transform.URIResolver
author
Norman Walsh Norman.Walsh@Sun.COM
version
1.0

Fields Summary
public boolean
namespaceAware
Make the parser Namespace aware?
public boolean
validating
Make the parser validating?
private com.sun.org.apache.xml.internal.resolver.Catalog
catalog
The underlying catalog
private com.sun.org.apache.xml.internal.resolver.CatalogManager
catalogManager
The catalog manager
Constructors Summary
public CatalogResolver()
Constructor


    
    
    initializeCatalogs(false);
  
public CatalogResolver(boolean privateCatalog)
Constructor

    initializeCatalogs(privateCatalog);
  
public CatalogResolver(com.sun.org.apache.xml.internal.resolver.CatalogManager manager)
Constructor

    catalogManager = manager;
    initializeCatalogs(!catalogManager.getUseStaticCatalog());
  
Methods Summary
public com.sun.org.apache.xml.internal.resolver.CataloggetCatalog()
Return the underlying catalog

    return catalog;
  
public java.lang.StringgetResolvedEntity(java.lang.String publicId, java.lang.String systemId)
Implements the guts of the resolveEntity method for the SAX interface.

Presented with an optional public identifier and a system identifier, this function attempts to locate a mapping in the catalogs.

If such a mapping is found, it is returned. If no mapping is found, null is returned.

param
publicId The public identifier for the entity in question. This may be null.
param
systemId The system identifier for the entity in question. XML requires a system identifier on all external entities, so this value is always specified.
return
The resolved identifier (a URI reference).

    String resolved = null;

    if (catalog == null) {
      catalogManager.debug.message(1, "Catalog resolution attempted with null catalog; ignored");
      return null;
    }

    if (systemId != null) {
      try {
	resolved = catalog.resolveSystem(systemId);
      } catch (MalformedURLException me) {
	catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
		      publicId);
	resolved = null;
      } catch (IOException ie) {
	catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
	resolved = null;
      }
    }

    if (resolved == null) {
      if (publicId != null) {
	try {
	  resolved = catalog.resolvePublic(publicId, systemId);
	} catch (MalformedURLException me) {
	  catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
			publicId);
	} catch (IOException ie) {
	  catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
	}
      }

      if (resolved != null) {
	catalogManager.debug.message(2, "Resolved public", publicId, resolved);
      }
    } else {
      catalogManager.debug.message(2, "Resolved system", systemId, resolved);
    }

    return resolved;
  
private voidinitializeCatalogs(boolean privateCatalog)
Initialize catalog

    catalog = catalogManager.getCatalog();
  
private java.lang.StringmakeAbsolute(java.lang.String uri)
Attempt to construct an absolute URI

    if (uri == null) {
      uri = "";
    }

    try {
      URL url = new URL(uri);
      return url.toString();
    } catch (MalformedURLException mue) {
      try {
	URL fileURL = FileURL.makeURL(uri);
	return fileURL.toString();
      } catch (MalformedURLException mue2) {
	// bail
	return uri;
      }
    }
  
public javax.xml.transform.Sourceresolve(java.lang.String href, java.lang.String base)
JAXP URIResolver API


    String uri = href;
    String fragment = null;
    int hashPos = href.indexOf("#");
    if (hashPos >= 0) {
      uri = href.substring(0, hashPos);
      fragment = href.substring(hashPos+1);
    }

    String result = null;

    try {
      result = catalog.resolveURI(href);
    } catch (Exception e) {
      // nop;
    }

    if (result == null) {
      try {
	URL url = null;

	if (base==null) {
	  url = new URL(uri);
	  result = url.toString();
	} else {
	  URL baseURL = new URL(base);
	  url = (href.length()==0 ? baseURL : new URL(baseURL, uri));
	  result = url.toString();
	}
      } catch (java.net.MalformedURLException mue) {
	// try to make an absolute URI from the current base
	String absBase = makeAbsolute(base);
	if (!absBase.equals(base)) {
	  // don't bother if the absBase isn't different!
	  return resolve(href, absBase);
	} else {
	  throw new TransformerException("Malformed URL "
					 + href + "(base " + base + ")",
					 mue);
	}
      }
    }

    catalogManager.debug.message(2, "Resolved URI", href, result);

    SAXSource source = new SAXSource();
    source.setInputSource(new InputSource(result));
    setEntityResolver(source);
    return source;
  
public org.xml.sax.InputSourceresolveEntity(java.lang.String publicId, java.lang.String systemId)
Implements the resolveEntity method for the SAX interface.

Presented with an optional public identifier and a system identifier, this function attempts to locate a mapping in the catalogs.

If such a mapping is found, the resolver attempts to open the mapped value as an InputSource and return it. Exceptions are ignored and null is returned if the mapped value cannot be opened as an input source.

If no mapping is found (or an error occurs attempting to open the mapped value as an input source), null is returned and the system will use the specified system identifier as if no entityResolver was specified.

param
publicId The public identifier for the entity in question. This may be null.
param
systemId The system identifier for the entity in question. XML requires a system identifier on all external entities, so this value is always specified.
return
An InputSource for the mapped identifier, or null.

    String resolved = getResolvedEntity(publicId, systemId);

    if (resolved != null) {
      try {
	InputSource iSource = new InputSource(resolved);
	iSource.setPublicId(publicId);

	// Ideally this method would not attempt to open the
	// InputStream, but there is a bug (in Xerces, at least)
	// that causes the parser to mistakenly open the wrong
	// system identifier if the returned InputSource does
	// not have a byteStream.
	//
	// It could be argued that we still shouldn't do this here,
	// but since the purpose of calling the entityResolver is
	// almost certainly to open the input stream, it seems to
	// do little harm.
	//
	URL url = new URL(resolved);
	InputStream iStream = url.openStream();
	iSource.setByteStream(iStream);

	return iSource;
      } catch (Exception e) {
	catalogManager.debug.message(1, "Failed to create InputSource", resolved);
	return null;
      }
    }

    return null;
  
private voidsetEntityResolver(javax.xml.transform.sax.SAXSource source)

Establish an entityResolver for newly resolved URIs.

This is called from the URIResolver to set an EntityResolver on the SAX parser to be used for new XML documents that are encountered as a result of the document() function, xsl:import, or xsl:include. This is done because the XSLT processor calls out to the SAXParserFactory itself to create a new SAXParser to parse the new document. The new parser does not automatically inherit the EntityResolver of the original (although arguably it should). See below:

"If an application wants to set the ErrorHandler or EntityResolver for an XMLReader used during a transformation, it should use a URIResolver to return the SAXSource which provides (with getXMLReader) a reference to the XMLReader"

...quoted from page 118 of the Java API for XML Processing 1.1 specification

    XMLReader reader = source.getXMLReader();
    if (reader == null) {
      SAXParserFactory spFactory = SAXParserFactory.newInstance();
      spFactory.setNamespaceAware(true);
      try {
	reader = spFactory.newSAXParser().getXMLReader();
      }
      catch (ParserConfigurationException ex) {
	throw new TransformerException(ex);
      }
      catch (SAXException ex) {
	throw new TransformerException(ex);
      }
    }
    reader.setEntityResolver(this);
    source.setXMLReader(reader);