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;
|
package org.apache.xml.resolver;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.util.MissingResourceException;
|
||||||
import java.util.*;
|
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.Debug;
|
||||||
|
import org.apache.xml.resolver.helpers.BootstrapResolver;
|
||||||
import org.apache.xml.resolver.Catalog;
|
import org.apache.xml.resolver.Catalog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,6 +173,9 @@ public class CatalogManager {
|
|||||||
/** A static CatalogManager instance for sharing */
|
/** A static CatalogManager instance for sharing */
|
||||||
private static CatalogManager staticManager = new CatalogManager();
|
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 */
|
/** Flag to ignore missing property files and/or properties */
|
||||||
private boolean ignoreMissingProperties
|
private boolean ignoreMissingProperties
|
||||||
= (System.getProperty(pIgnoreMissing) != null
|
= (System.getProperty(pIgnoreMissing) != null
|
||||||
@ -255,6 +264,16 @@ public class CatalogManager {
|
|||||||
// to avoid it.
|
// 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
|
* Load the properties from the propertyFile and build the
|
||||||
* resources from it.
|
* 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.URLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.UnknownHostException;
|
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.Catalog;
|
||||||
import org.apache.xml.resolver.CatalogManager;
|
import org.apache.xml.resolver.CatalogManager;
|
||||||
import org.apache.xml.resolver.CatalogException;
|
import org.apache.xml.resolver.CatalogException;
|
||||||
import org.apache.xml.resolver.readers.CatalogReader;
|
import org.apache.xml.resolver.readers.CatalogReader;
|
||||||
import org.apache.xml.resolver.helpers.Debug;
|
import org.apache.xml.resolver.helpers.Debug;
|
||||||
|
|
||||||
import org.xml.sax.*;
|
|
||||||
|
|
||||||
import javax.xml.parsers.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SAX-based CatalogReader.
|
* A SAX-based CatalogReader.
|
||||||
*
|
*
|
||||||
@ -258,6 +269,7 @@ public class SAXCatalogReader implements CatalogReader, ContentHandler, Document
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug = catalog.getCatalogManager().debug;
|
debug = catalog.getCatalogManager().debug;
|
||||||
|
EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
|
||||||
|
|
||||||
this.catalog = catalog;
|
this.catalog = catalog;
|
||||||
|
|
||||||
@ -266,10 +278,16 @@ public class SAXCatalogReader implements CatalogReader, ContentHandler, Document
|
|||||||
SAXParser parser = parserFactory.newSAXParser();
|
SAXParser parser = parserFactory.newSAXParser();
|
||||||
SAXParserHandler spHandler = new SAXParserHandler();
|
SAXParserHandler spHandler = new SAXParserHandler();
|
||||||
spHandler.setContentHandler(this);
|
spHandler.setContentHandler(this);
|
||||||
|
if (bResolver != null) {
|
||||||
|
spHandler.setEntityResolver(bResolver);
|
||||||
|
}
|
||||||
parser.parse(new InputSource(is), spHandler);
|
parser.parse(new InputSource(is), spHandler);
|
||||||
} else {
|
} else {
|
||||||
Parser parser = (Parser) Class.forName(parserClass).newInstance();
|
Parser parser = (Parser) Class.forName(parserClass).newInstance();
|
||||||
parser.setDocumentHandler(this);
|
parser.setDocumentHandler(this);
|
||||||
|
if (bResolver != null) {
|
||||||
|
parser.setEntityResolver(bResolver);
|
||||||
|
}
|
||||||
parser.parse(new InputSource(is));
|
parser.parse(new InputSource(is));
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException cnfe) {
|
} catch (ClassNotFoundException cnfe) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user