Added a bootstrap resolver for use when reading XML Catalog files (so the DTD for catalogs can be resolved to the DTD stored in the Jar file, for example).
git-svn-id: https://svn.apache.org/repos/asf/xml/commons/trunk@226059 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
46f117aae8
commit
21fc7e9d1a
@ -59,13 +59,19 @@
|
||||
|
||||
package org.apache.xml.resolver;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.PropertyResourceBundle;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.xml.resolver.helpers.Debug;
|
||||
import org.apache.xml.resolver.helpers.BootstrapResolver;
|
||||
import org.apache.xml.resolver.Catalog;
|
||||
|
||||
/**
|
||||
@ -167,6 +173,9 @@ public class CatalogManager {
|
||||
/** A static CatalogManager instance for sharing */
|
||||
private static CatalogManager staticManager = new CatalogManager();
|
||||
|
||||
/** The bootstrap resolver to use when loading XML Catalogs. */
|
||||
private BootstrapResolver bResolver = new BootstrapResolver();
|
||||
|
||||
/** Flag to ignore missing property files and/or properties */
|
||||
private boolean ignoreMissingProperties
|
||||
= (System.getProperty(pIgnoreMissing) != null
|
||||
@ -255,6 +264,16 @@ public class CatalogManager {
|
||||
// to avoid it.
|
||||
}
|
||||
|
||||
/** Set the bootstrap resolver.*/
|
||||
public void setBootstrapResolver(BootstrapResolver resolver) {
|
||||
bResolver = resolver;
|
||||
}
|
||||
|
||||
/** Get the bootstrap resolver.*/
|
||||
public BootstrapResolver getBootstrapResolver() {
|
||||
return bResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the properties from the propertyFile and build the
|
||||
* resources from it.
|
||||
|
||||
249
java/src/org/apache/xml/resolver/helpers/BootstrapResolver.java
Normal file
249
java/src/org/apache/xml/resolver/helpers/BootstrapResolver.java
Normal file
@ -0,0 +1,249 @@
|
||||
// BootstrapResolver.java - Resolve entities and URIs internally
|
||||
|
||||
/*
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2001 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Xalan" and "Apache Software Foundation" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* nor may "Apache" appear in their name, without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation and was
|
||||
* originally based on software copyright (c) 2001, International
|
||||
* Business Machines Corporation., http://www.ibm.com. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
package org.apache.xml.resolver.helpers;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* A simple bootstrapping resolver.
|
||||
*
|
||||
* <p>This class is used as the entity resolver when reading XML Catalogs.
|
||||
* It searches for the OASIS XML Catalog DTD, Relax NG Grammar and W3C XML Schema
|
||||
* as resources (e.g., in the resolver jar file).</p>
|
||||
*
|
||||
* <p>If you have your own DTDs or schemas, you can extend this class and
|
||||
* set the BootstrapResolver in your CatalogManager.</p>
|
||||
*
|
||||
* @see CatalogManager
|
||||
*
|
||||
* @author Norman Walsh
|
||||
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class BootstrapResolver implements EntityResolver, URIResolver {
|
||||
/** URI of the W3C XML Schema for OASIS XML Catalog files. */
|
||||
public static final String xmlCatalogXSD = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.xsd";
|
||||
|
||||
/** URI of the RELAX NG Grammar for OASIS XML Catalog files. */
|
||||
public static final String xmlCatalogRNG = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.rng";
|
||||
|
||||
/** Public identifier for OASIS XML Catalog files. */
|
||||
public static final String xmlCatalogPubId = "-//OASIS//DTD XML Catalogs V1.0//EN";
|
||||
|
||||
/** System identifier for OASIS XML Catalog files. */
|
||||
public static final String xmlCatalogSysId = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd";
|
||||
|
||||
/** Private hash used for public identifiers. */
|
||||
private Hashtable publicMap = new Hashtable();
|
||||
|
||||
/** Private hash used for system identifiers. */
|
||||
private Hashtable systemMap = new Hashtable();
|
||||
|
||||
/** Private hash used for URIs. */
|
||||
private Hashtable uriMap = new Hashtable();
|
||||
|
||||
/** Constructor. */
|
||||
public BootstrapResolver() {
|
||||
URL url = this.getClass().getResource("/org/apache/xml/resolver/etc/catalog.dtd");
|
||||
if (url != null) {
|
||||
publicMap.put(xmlCatalogPubId, url.toString());
|
||||
systemMap.put(xmlCatalogSysId, url.toString());
|
||||
}
|
||||
|
||||
url = this.getClass().getResource("/org/apache/xml/resolver/etc/catalog.rng");
|
||||
if (url != null) {
|
||||
uriMap.put(xmlCatalogRNG, url.toString());
|
||||
}
|
||||
|
||||
url = this.getClass().getResource("/org/apache/xml/resolver/etc/catalog.xsd");
|
||||
if (url != null) {
|
||||
uriMap.put(xmlCatalogXSD, url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/** SAX resolveEntity API. */
|
||||
public InputSource resolveEntity (String publicId, String systemId) {
|
||||
String resolved = null;
|
||||
|
||||
if (systemId != null && systemMap.containsKey(systemId)) {
|
||||
resolved = (String) systemMap.get(systemId);
|
||||
} else if (publicId != null && publicMap.containsKey(publicId)) {
|
||||
resolved = (String) publicMap.get(publicId);
|
||||
}
|
||||
|
||||
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) {
|
||||
// FIXME: silently fail?
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Transformer resolve 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;
|
||||
if (href != null && uriMap.containsKey(href)) {
|
||||
result = (String) uriMap.get(href);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAXSource source = new SAXSource();
|
||||
source.setInputSource(new InputSource(result));
|
||||
return source;
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
String dir = System.getProperty("user.dir");
|
||||
String file = "";
|
||||
|
||||
if (dir.endsWith("/")) {
|
||||
file = "file://" + dir + uri;
|
||||
} else {
|
||||
file = "file://" + dir + "/" + uri;
|
||||
}
|
||||
|
||||
try {
|
||||
URL fileURL = new URL(file);
|
||||
return fileURL.toString();
|
||||
} catch (MalformedURLException mue2) {
|
||||
// bail
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,16 +67,27 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
|
||||
import org.xml.sax.AttributeList;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.DocumentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.Parser;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import org.apache.xml.resolver.Catalog;
|
||||
import org.apache.xml.resolver.CatalogManager;
|
||||
import org.apache.xml.resolver.CatalogException;
|
||||
import org.apache.xml.resolver.readers.CatalogReader;
|
||||
import org.apache.xml.resolver.helpers.Debug;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
/**
|
||||
* A SAX-based CatalogReader.
|
||||
*
|
||||
@ -258,6 +269,7 @@ public class SAXCatalogReader implements CatalogReader, ContentHandler, Document
|
||||
}
|
||||
|
||||
debug = catalog.getCatalogManager().debug;
|
||||
EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
|
||||
|
||||
this.catalog = catalog;
|
||||
|
||||
@ -266,10 +278,16 @@ public class SAXCatalogReader implements CatalogReader, ContentHandler, Document
|
||||
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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user