diff options
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java')
-rw-r--r-- | src/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java new file mode 100644 index 0000000..778e5a2 --- /dev/null +++ b/src/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java @@ -0,0 +1,340 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +// CatalogResolver.java - A SAX EntityResolver/JAXP URI Resolver + +/* + * Copyright 2001-2004 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.xml.internal.resolver.tools; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.MalformedURLException; + +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.InputSource; +import org.xml.sax.EntityResolver; + +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.Source; +import javax.xml.transform.URIResolver; +import javax.xml.transform.TransformerException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import com.sun.org.apache.xml.internal.resolver.Catalog; +import com.sun.org.apache.xml.internal.resolver.CatalogManager; +import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; + +/** + * A SAX EntityResolver/JAXP URIResolver that uses catalogs. + * + * <p>This class implements both a SAX EntityResolver and a JAXP URIResolver. + * </p> + * + * <p>This resolver understands OASIS TR9401 catalogs, XCatalogs, and the + * current working draft of the OASIS Entity Resolution Technical + * Committee specification.</p> + * + * @see Catalog + * @see org.xml.sax.EntityResolver + * @see javax.xml.transform.URIResolver + * + * @author Norman Walsh + * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a> + * + */ +public class CatalogResolver implements EntityResolver, URIResolver { + /** Make the parser Namespace aware? */ + public boolean namespaceAware = true; + + /** Make the parser validating? */ + public boolean validating = false; + + /** The underlying catalog */ + private Catalog catalog = null; + + /** The catalog manager */ + private CatalogManager catalogManager = CatalogManager.getStaticManager(); + + /** Constructor */ + public CatalogResolver() { + initializeCatalogs(false); + } + + /** Constructor */ + public CatalogResolver(boolean privateCatalog) { + initializeCatalogs(privateCatalog); + } + + /** Constructor */ + public CatalogResolver(CatalogManager manager) { + catalogManager = manager; + initializeCatalogs(!catalogManager.getUseStaticCatalog()); + } + + /** Initialize catalog */ + private void initializeCatalogs(boolean privateCatalog) { + catalog = catalogManager.getCatalog(); + } + + /** Return the underlying catalog */ + public Catalog getCatalog() { + return catalog; + } + + /** + * Implements the guts of the <code>resolveEntity</code> method + * for the SAX interface. + * + * <p>Presented with an optional public identifier and a system + * identifier, this function attempts to locate a mapping in the + * catalogs.</p> + * + * <p>If such a mapping is found, it is returned. If no mapping is + * found, null is returned.</p> + * + * @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). + */ + public String getResolvedEntity (String publicId, String systemId) { + 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; + } + + /** + * Implements the <code>resolveEntity</code> method + * for the SAX interface. + * + * <p>Presented with an optional public identifier and a system + * identifier, this function attempts to locate a mapping in the + * catalogs.</p> + * + * <p>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.</p> + * + * <p>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.</p> + * + * @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. + */ + public InputSource resolveEntity (String publicId, String systemId) { + 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; + } + + /** JAXP URIResolver API */ + public Source resolve(String href, String base) + throws TransformerException { + + 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; + } + + /** + * <p>Establish an entityResolver for newly resolved URIs.</p> + * + * <p>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:</p> + * + * <tt>"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"</tt> + * + * <p>...quoted from page 118 of the Java API for XML + * Processing 1.1 specification</p> + * + */ + private void setEntityResolver(SAXSource source) throws TransformerException { + 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); + } + + /** Attempt to construct an absolute URI */ + private String makeAbsolute(String 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; + } + } + } +} |