Initial checkin of Sun Resolver 1.1 sources

git-svn-id: https://svn.apache.org/repos/asf/xml/commons/trunk@225950 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
ndw committed 2002-01-30 12:25:00 +00:00
1 parent 32b041f81d
commit 92f652862f
35 files changed
+9761

No files matched your search

@@ -0,0 +1,118 @@
// CatalogReader.java - An interface for reading catalog files
/*
* 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.readers;
import java.io.IOException;
import java.net.MalformedURLException;
import org.apache.xml.resolver.CatalogException;
import java.io.InputStream;
import org.apache.xml.resolver.Catalog;
/**
* <p>The CatalogReader interface.</p>
*
* <p>The Catalog class requires that classes implement this interface
* in order to be used to read catalogs. Examples of CatalogReaders
* include the TextCatalogReader, the SAXCatalogReader, and the
* DOMCatalogReader.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public interface CatalogReader {
/**
* <p>Read a catalog from a file</p>
*
* <p>This class reads a catalog from a URL.</p>
*
* @param catalog The catalog for which this reader is called.
* @param fileUrl The URL of a document to be read.
* @throws MalformedURLException if the specified URL cannot be
* turned into a URL object.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException, CatalogException;
/**
* <p>Read a catalog from an input stream</p>
*
* <p>This class reads a catalog from an input stream.</p>
*
* @param catalog The catalog for which this reader is called.
* @param is The input stream that is to be read.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException;
}
@@ -0,0 +1,90 @@
// DOMCatalogParser.java - An interface for reading catalog files
/*
* 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.readers;
import org.apache.xml.resolver.Catalog;
import org.w3c.dom.Node;
/**
* <p>The DOMCatalogParser interface.</p>
*
* <p>This interface must be implemented in order for a class to
* participate as a parser for the DOMCatalogReader.
*
* @see Catalog
* @see DOMCatalogReader
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public interface DOMCatalogParser {
/**
* <p>Parse a DOM node as a catalog entry</p>
*
* <p>This method is expected to analyze the specified node and
* construct appropriate catalog entry(ies) from it.</p>
*
* @param catalog The catalog for which this node is being considered.
* @param node The DOM Node from the catalog.
*/
public void parseCatalogEntry(Catalog catalog, Node node);
}
@@ -0,0 +1,288 @@
// DOMCatalogReader.java - Read XML Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.Debug;
import org.apache.xml.resolver.helpers.PublicId;
import org.apache.xml.resolver.helpers.Namespaces;
import org.xml.sax.SAXException;
import org.w3c.dom.*;
/**
* <p>A DOM-based CatalogReader</p>
*
* <p>This class is used to read XML Catalogs using the DOM. This reader
* has an advantage over the SAX-based reader that it can analyze the
* DOM tree rather than simply a series of SAX events. It has the disadvantage
* that it requires all of the code necessary to build and walk a DOM
* tree.</p>
*
* <p>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 DOMCatalogReader relies on a set of external
* CatalogParsers to actually build the catalog.</p>
*
* <p>The selection of CatalogParsers is made on the basis of the QName
* of the root element of the document.</p>
*
* <p>This class requires the <a href="http://java.sun.com/aboutJava/communityprocess/final/jsr005/index.html">Java API for XML Parsing</a>.</p>
*
* @see Catalog
* @see CatalogReader
* @see SAXCatalogReader
* @see TextCatalogReader
* @see DOMCatalogParser
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class DOMCatalogReader implements CatalogReader {
/**
* <p>Mapping table from QNames to CatalogParser classes.</p>
*
* <p>Each key in this hash table has the form "elementname"
* or "{namespaceuri}elementname". The former is used if the
* namespace URI is null.</p>
*/
protected Hashtable namespaceMap = new Hashtable();
/**
* <p>Add a new parser to the reader.</p>
*
* <p>This method associates the specified parserClass with the
* namespaceURI/rootElement names specified.</p>
*
* @param namespaceURI The namespace URI. <em>Not</em> the prefix.
* @param rootElement The name of the root element.
* @param parserClass The name of the parserClass to instantiate
* for this kind of catalog.
*/
public void setCatalogParser(String namespaceURI,
String rootElement,
String parserClass) {
if (namespaceURI == null) {
namespaceMap.put(rootElement, parserClass);
} else {
namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
}
}
/**
* <p>Get the name of the parser class for a given catalog type.</p>
*
* <p>This method returns the parserClass associated with the
* namespaceURI/rootElement names specified.</p>
*
* @param namespaceURI The namespace URI. <em>Not</em> the prefix.
* @param rootElement The name of the root element.
* @return The parser class.
*/
public String getCatalogParser(String namespaceURI,
String rootElement) {
if (namespaceURI == null) {
return (String) namespaceMap.get(rootElement);
} else {
return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
}
}
/**
* <p>Null constructor; something for subclasses to call.</p>
*/
public DOMCatalogReader() { }
/**
* <p>Read a catalog from an input stream</p>
*
* <p>This class reads a catalog from an input stream:</p>
*
* <ul>
* <li>Based on the QName of the root element, it determines which
* parser to instantiate for this catalog.</li>
* <li>It constructs a DOM Document from the catalog and</li>
* <li>For each child of the root node, it calls the parser's
* parseCatalogEntry method. This method is expected to make
* appropriate calls back into the catalog to add entries for the
* entries in the catalog. It is free to do this in whatever manner
* is appropriate (perhaps using just the node passed in, perhaps
* wandering arbitrarily throughout the tree).</li>
* </ul>
*
* @param catalog The catalog for which this reader is called.
* @param is The input stream that is to be read.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed or
* if the parser class cannot be instantiated.)
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException {
DocumentBuilderFactory factory = null;
DocumentBuilder builder = null;
factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
throw new CatalogException(CatalogException.UNPARSEABLE);
}
Document doc = null;
try {
doc = builder.parse(is);
} catch (SAXException se) {
throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
}
Element root = doc.getDocumentElement();
String namespaceURI = Namespaces.getNamespaceURI(root);
String localName = Namespaces.getLocalName(root);
String domParserClass = getCatalogParser(namespaceURI,
localName);
if (domParserClass == null) {
if (namespaceURI == null) {
Debug.message(1, "No Catalog parser for " + localName);
} else {
Debug.message(1, "No Catalog parser for "
+ "{" + namespaceURI + "}"
+ localName);
}
return;
}
DOMCatalogParser domParser = null;
try {
domParser = (DOMCatalogParser) Class.forName(domParserClass).newInstance();
} catch (ClassNotFoundException cnfe) {
Debug.message(1, "Cannot load XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (InstantiationException ie) {
Debug.message(1, "Cannot instantiate XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (IllegalAccessException iae) {
Debug.message(1, "Cannot access XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (ClassCastException cce ) {
Debug.message(1, "Cannot cast XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
}
Node node = root.getFirstChild();
while (node != null) {
domParser.parseCatalogEntry(catalog, node);
node = node.getNextSibling();
}
}
/**
* <p>Read the catalog behind the specified URL.</p>
*
* @see #readCatalog(Catalog, InputStream)
*
* @param catalog The catalog for which we are reading.
* @param fileUrl The URL of the document that should be read.
*
* @throws MalformedURLException if the specified URL cannot be
* turned into a URL object.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException, CatalogException {
URL url = new URL(fileUrl);
URLConnection urlCon = url.openConnection();
readCatalog(catalog, urlCon.getInputStream());
}
}
@@ -0,0 +1,235 @@
// ExtendedXMLCatalogReader.java - Read XML Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.util.Stack;
import java.util.Vector;
import java.util.Enumeration;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.Resolver;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.PublicId;
import org.apache.xml.resolver.helpers.Debug;
import org.xml.sax.*;
import org.w3c.dom.*;
/**
* <p>Parse Extended OASIS Entity Resolution Technical Committee
* XML Catalog files.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class ExtendedXMLCatalogReader extends OASISXMLCatalogReader {
/** The namespace name of extended catalog elements */
public static final String extendedNamespaceName = "http://nwalsh.com/xcatalog/1.0";
/**
* <p>The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.</p>
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
// Check before calling the super because super will report our
// namespace as an extension namespace, but that doesn't count
// for this element.
boolean inExtension = inExtensionNamespace();
super.startElement(namespaceURI, localName, qName, atts);
int entryType = -1;
Vector entryArgs = new Vector();
if (namespaceURI != null && extendedNamespaceName.equals(namespaceURI)
&& !inExtension) {
// This is an Extended XML Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
Debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if (localName.equals("uriSuffix")) {
if (checkAttributes(atts, "suffix", "uri")) {
entryType = Resolver.URISUFFIX;
entryArgs.add(atts.getValue("suffix"));
entryArgs.add(atts.getValue("uri"));
Debug.message(4, "uriSuffix",
atts.getValue("suffix"),
atts.getValue("uri"));
}
} else if (localName.equals("systemSuffix")) {
if (checkAttributes(atts, "suffix", "uri")) {
entryType = Resolver.SYSTEMSUFFIX;
entryArgs.add(atts.getValue("suffix"));
entryArgs.add(atts.getValue("uri"));
Debug.message(4, "systemSuffix",
atts.getValue("suffix"),
atts.getValue("uri"));
}
} else {
// This is equivalent to an invalid catalog entry type
Debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
}
/** <p>The SAX <code>endElement</code> method does nothing.</p> */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
super.endElement(namespaceURI, localName, qName);
// Check after popping the stack so we don't erroneously think we
// are our own extension namespace...
boolean inExtension = inExtensionNamespace();
int entryType = -1;
Vector entryArgs = new Vector();
if (namespaceURI != null
&& (extendedNamespaceName.equals(namespaceURI))
&& !inExtension) {
String popURI = (String) baseURIStack.pop();
String baseURI = (String) baseURIStack.peek();
if (!baseURI.equals(popURI)) {
entryType = catalog.BASE;
entryArgs.add(baseURI);
Debug.message(4, "(reset) xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (rbase)", localName);
}
}
}
}
}
}
@@ -0,0 +1,565 @@
// OASISXMLCatalogReader.java - Read XML Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.util.Stack;
import java.util.Vector;
import java.util.Enumeration;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.PublicId;
import org.apache.xml.resolver.helpers.Debug;
import org.xml.sax.*;
import org.w3c.dom.*;
/**
* <p>Parse OASIS Entity Resolution Technical Committee
* XML Catalog files.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalogParser {
/** The catalog object needs to be stored by the object so that
* SAX callbacks can use it.
*/
protected Catalog catalog = null;
/** The namespace name of OASIS ERTC catalogs */
public static final String namespaceName = "urn:oasis:names:tc:entity:xmlns:xml:catalog";
/** The namespace name of OASIS ERTC TR9401 catalog extension */
public static final String tr9401NamespaceName = "urn:oasis:names:tc:entity:xmlns:tr9401:catalog";
protected Stack baseURIStack = new Stack();
protected Stack overrideStack = new Stack();
protected Stack namespaceStack = new Stack();
/** Set the current catalog. */
public void setCatalog (Catalog catalog) {
this.catalog = catalog;
}
/** Get the current catalog. */
public Catalog getCatalog () {
return catalog;
}
/**
* <p>Are we in an extension namespace?</p>
*
* @returns true if the current stack of open namespaces includes
* an extension namespace.
*/
protected boolean inExtensionNamespace() {
boolean inExtension = false;
Enumeration elements = namespaceStack.elements();
while (!inExtension && elements.hasMoreElements()) {
String ns = (String) elements.nextElement();
if (ns == null) {
inExtension = true;
} else {
inExtension = (!ns.equals(tr9401NamespaceName)
&& !ns.equals(namespaceName));
}
}
return inExtension;
}
// ----------------------------------------------------------------------
// Implement the SAX ContentHandler interface
/** <p>The SAX <code>setDocumentLocator</code> method does nothing.</p> */
public void setDocumentLocator (Locator locator) {
return;
}
/** <p>The SAX <code>startDocument</code> method does nothing.</p> */
public void startDocument ()
throws SAXException {
baseURIStack.push(catalog.getCurrentBase());
overrideStack.push(catalog.getDefaultOverride());
return;
}
/** <p>The SAX <code>endDocument</code> method does nothing.</p> */
public void endDocument ()
throws SAXException {
return;
}
/**
* <p>The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.</p>
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
namespaceStack.push(namespaceURI);
boolean inExtension = inExtensionNamespace();
if (namespaceURI != null && namespaceName.equals(namespaceURI)
&& !inExtension) {
// This is an XML Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
Debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if ((localName.equals("catalog") || localName.equals("group"))
&& atts.getValue("prefer") != null) {
String override = atts.getValue("prefer");
if (override.equals("public")) {
override = "yes";
} else if (override.equals("system")) {
override = "no";
} else {
Debug.message(1,
"Invalid prefer: must be 'system' or 'public'",
localName);
override = catalog.getDefaultOverride();
}
entryType = Catalog.OVERRIDE;
entryArgs.add(override);
overrideStack.push(override);
Debug.message(4, "override", override);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (override)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
overrideStack.push(overrideStack.peek());
}
if (localName.equals("delegatePublic")) {
if (checkAttributes(atts, "publicIdStartString", "catalog")) {
entryType = Catalog.DELEGATE_PUBLIC;
entryArgs.add(atts.getValue("publicIdStartString"));
entryArgs.add(atts.getValue("catalog"));
Debug.message(4, "delegatePublic",
PublicId.normalize(atts.getValue("publicIdStartString")),
atts.getValue("catalog"));
}
} else if (localName.equals("delegateSystem")) {
if (checkAttributes(atts, "systemIdStartString", "catalog")) {
entryType = Catalog.DELEGATE_SYSTEM;
entryArgs.add(atts.getValue("systemIdStartString"));
entryArgs.add(atts.getValue("catalog"));
Debug.message(4, "delegateSystem",
atts.getValue("systemIdStartString"),
atts.getValue("catalog"));
}
} else if (localName.equals("delegateURI")) {
if (checkAttributes(atts, "uriStartString", "catalog")) {
entryType = Catalog.DELEGATE_URI;
entryArgs.add(atts.getValue("uriStartString"));
entryArgs.add(atts.getValue("catalog"));
Debug.message(4, "delegateURI",
atts.getValue("uriStartString"),
atts.getValue("catalog"));
}
} else if (localName.equals("rewriteSystem")) {
if (checkAttributes(atts, "systemIdStartString", "rewritePrefix")) {
entryType = Catalog.REWRITE_SYSTEM;
entryArgs.add(atts.getValue("systemIdStartString"));
entryArgs.add(atts.getValue("rewritePrefix"));
Debug.message(4, "rewriteSystem",
atts.getValue("systemIdStartString"),
atts.getValue("rewritePrefix"));
}
} else if (localName.equals("rewriteURI")) {
if (checkAttributes(atts, "uriStartString", "rewritePrefix")) {
entryType = Catalog.REWRITE_URI;
entryArgs.add(atts.getValue("uriStartString"));
entryArgs.add(atts.getValue("rewritePrefix"));
Debug.message(4, "rewriteURI",
atts.getValue("uriStartString"),
atts.getValue("rewritePrefix"));
}
} else if (localName.equals("nextCatalog")) {
if (checkAttributes(atts, "catalog")) {
entryType = Catalog.CATALOG;
entryArgs.add(atts.getValue("catalog"));
Debug.message(4, "nextCatalog", atts.getValue("catalog"));
}
} else if (localName.equals("public")) {
if (checkAttributes(atts, "publicId", "uri")) {
entryType = Catalog.PUBLIC;
entryArgs.add(atts.getValue("publicId"));
entryArgs.add(atts.getValue("uri"));
Debug.message(4, "public",
PublicId.normalize(atts.getValue("publicId")),
atts.getValue("uri"));
}
} else if (localName.equals("system")) {
if (checkAttributes(atts, "systemId", "uri")) {
entryType = Catalog.SYSTEM;
entryArgs.add(atts.getValue("systemId"));
entryArgs.add(atts.getValue("uri"));
Debug.message(4, "system",
atts.getValue("systemId"),
atts.getValue("uri"));
}
} else if (localName.equals("uri")) {
if (checkAttributes(atts, "name", "uri")) {
entryType = Catalog.URI;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
Debug.message(4, "uri",
atts.getValue("name"),
atts.getValue("uri"));
}
} else if (localName.equals("catalog")) {
// nop, start of catalog
} else if (localName.equals("group")) {
// nop, a group
} else {
// This is equivalent to an invalid catalog entry type
Debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
if (namespaceURI != null && tr9401NamespaceName.equals(namespaceURI)
&& !inExtension) {
// This is a TR9401 Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
Debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if (localName.equals("doctype")) {
entryType = catalog.DOCTYPE;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("document")) {
entryType = catalog.DOCUMENT;
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("dtddecl")) {
entryType = catalog.DTDDECL;
entryArgs.add(atts.getValue("publicId"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("entity")) {
entryType = Catalog.ENTITY;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("linktype")) {
entryType = Catalog.LINKTYPE;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("notation")) {
entryType = Catalog.NOTATION;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("sgmldecl")) {
entryType = Catalog.SGMLDECL;
entryArgs.add(atts.getValue("uri"));
} else {
// This is equivalent to an invalid catalog entry type
Debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
}
public boolean checkAttributes (Attributes atts, String attName) {
if (atts.getValue(attName) == null) {
Debug.message(1, "Error: required attribute " + attName + " missing.");
return false;
} else {
return true;
}
}
public boolean checkAttributes (Attributes atts,
String attName1,
String attName2) {
return checkAttributes(atts, attName1)
&& checkAttributes(atts, attName2);
}
/** <p>The SAX <code>endElement</code> method does nothing.</p> */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
boolean inExtension = inExtensionNamespace();
if (namespaceURI != null
&& !inExtension
&& (namespaceName.equals(namespaceURI)
|| tr9401NamespaceName.equals(namespaceURI))) {
String popURI = (String) baseURIStack.pop();
String baseURI = (String) baseURIStack.peek();
if (!baseURI.equals(popURI)) {
entryType = catalog.BASE;
entryArgs.add(baseURI);
Debug.message(4, "(reset) xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (rbase)", localName);
}
}
}
}
if (namespaceURI != null && namespaceName.equals(namespaceURI)
&& !inExtension) {
if (localName.equals("catalog") || localName.equals("group")) {
String popOverride = (String) overrideStack.pop();
String override = (String) overrideStack.peek();
if (!override.equals(popOverride)) {
entryType = catalog.OVERRIDE;
entryArgs.add(override);
overrideStack.push(override);
Debug.message(4, "(reset) override", override);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry (roverride)", localName);
}
}
}
}
}
namespaceStack.pop();
return;
}
/** <p>The SAX <code>characters</code> method does nothing.</p> */
public void characters (char ch[], int start, int length)
throws SAXException {
return;
}
/** <p>The SAX <code>ignorableWhitespace</code> method does nothing.</p> */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
return;
}
/** <p>The SAX <code>processingInstruction</code> method does nothing.</p> */
public void processingInstruction (String target, String data)
throws SAXException {
return;
}
/** <p>The SAX <code>skippedEntity</code> method does nothing.</p> */
public void skippedEntity (String name)
throws SAXException {
return;
}
/** <p>The SAX <code>startPrefixMapping</code> method does nothing.</p> */
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
return;
}
/** <p>The SAX <code>endPrefixMapping</code> method does nothing.</p> */
public void endPrefixMapping(String prefix)
throws SAXException {
return;
}
}
@@ -0,0 +1,82 @@
// SAXCatalogParser.java - An interface for reading catalog files
/*
* 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.readers;
import org.apache.xml.resolver.Catalog;
import org.xml.sax.*;
/**
* <p>The SAXCatalogParser interface.</p>
*
* <p>This interface must be implemented in order for a class to
* participate as a parser for the SAXCatalogReader.
*
* @see Catalog
* @see SAXCatalogReader
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public interface SAXCatalogParser extends ContentHandler, DocumentHandler {
/** Set the Catalog for which parsing is being performed. */
public void setCatalog(Catalog catalog);
}
@@ -0,0 +1,515 @@
// SAXCatalogReader.java - Read XML Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.Debug;
import org.apache.xml.resolver.helpers.PublicId;
import org.apache.xml.resolver.helpers.Namespaces;
import org.xml.sax.*;
import javax.xml.parsers.*;
/**
* <p>A SAX-based CatalogReader</p>
*
* <p>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.</p>
*
* <p>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.</p>
*
* <p>The selection of CatalogParsers is made on the basis of the QName
* of the root element of the document.</p>
*
* @see Catalog
* @see CatalogReader
* @see SAXCatalogReader
* @see TextCatalogReader
* @see DOMCatalogParser
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class SAXCatalogReader implements CatalogReader, ContentHandler, DocumentHandler {
/** The SAX Parser Factory */
protected SAXParserFactory parserFactory = null;
/** The SAX Parser Class */
protected String parserClass = null;
/**
* <p>Mapping table from QNames to CatalogParser classes.</p>
*
* <p>Each key in this hash table has the form "elementname"
* or "{namespaceuri}elementname". The former is used if the
* namespace URI is null.</p>
*/
protected Hashtable namespaceMap = new Hashtable();
/** The parser in use for the current catalog. */
private SAXCatalogParser saxParser = null;
/** Set if something goes horribly wrong. It allows the class to
* ignore the rest of the events that are received.
*/
private boolean abandonHope = false;
/** The Catalog that we're working for. */
private Catalog catalog;
/** Set the XML SAX Parser Factory.
*/
public void setParserFactory(SAXParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
/** Set the XML SAX Parser Class
*/
public void setParserClass(String parserClass) {
this.parserClass = parserClass;
}
/** Get the parser factory currently in use. */
public SAXParserFactory getParserFactory() {
return parserFactory;
}
/** Get the parser class currently in use. */
public String getParserClass() {
return parserClass;
}
/** Set the SAXCatalogParser class for the given namespace/root
* element type.
*/
public void setCatalogParser(String namespaceURI,
String rootElement,
String parserClass) {
if (namespaceURI == null) {
namespaceMap.put(rootElement, parserClass);
} else {
namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
}
}
/** Get the SAXCatalogParser class for the given namespace/root
* element type.
*/
public String getCatalogParser(String namespaceURI,
String rootElement) {
if (namespaceURI == null) {
return (String) namespaceMap.get(rootElement);
} else {
return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
}
}
/** The constructor */
public SAXCatalogReader() {
parserFactory = null;
parserClass = null;
}
/** The constructor */
public SAXCatalogReader(SAXParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
/** The constructor */
public SAXCatalogReader(String parserClass) {
this.parserClass = parserClass;
}
/**
* <p>Parse an XML Catalog file.</p>
*
* @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
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException,
CatalogException {
URL url = null;
try {
url = new URL(fileUrl);
} catch (MalformedURLException e) {
url = new URL("file:///" + fileUrl);
}
try {
URLConnection urlCon = url.openConnection();
readCatalog(catalog, urlCon.getInputStream());
} catch (FileNotFoundException e) {
Debug.message(1, "Failed to load catalog, file not found",
url.toString());
}
}
/**
* <p>Parse an XML Catalog stream.</p>
*
* @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
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException {
// 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);
}
this.catalog = catalog;
try {
if (parserFactory != null) {
SAXParser parser = parserFactory.newSAXParser();
SAXParserHandler spHandler = new SAXParserHandler();
spHandler.setContentHandler(this);
parser.parse(new InputSource(is), spHandler);
} else {
Parser parser = (Parser) Class.forName(parserClass).newInstance();
parser.setDocumentHandler(this);
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);
}
}
// ----------------------------------------------------------------------
// Implement the SAX ContentHandler interface
/** <p>The SAX <code>setDocumentLocator</code> method. Does nothing.</p> */
public void setDocumentLocator (Locator locator) {
if (saxParser != null) {
saxParser.setDocumentLocator(locator);
}
}
/** <p>The SAX <code>startDocument</code> method. Does nothing.</p> */
public void startDocument () throws SAXException {
saxParser = null;
abandonHope = false;
return;
}
/** <p>The SAX <code>endDocument</code> method. Does nothing.</p> */
public void endDocument ()throws SAXException {
if (saxParser != null) {
saxParser.endDocument();
}
}
/**
* <p>The SAX <code>startElement</code> method.</p>
*
* <p>The catalog parser is selected based on the namespace of the
* first element encountered in the catalog.</p>
*/
public void startElement (String name,
AttributeList atts)
throws SAXException {
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);
}
}
/**
* <p>The SAX2 <code>startElement</code> method.</p>
*
* <p>The catalog parser is selected based on the namespace of the
* first element encountered in the catalog.</p>
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
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);
}
}
/** <p>The SAX <code>endElement</code> method. Does nothing.</p> */
public void endElement (String name) throws SAXException {
if (saxParser != null) {
saxParser.endElement(name);
}
}
/** <p>The SAX2 <code>endElement</code> method. Does nothing.</p> */
public void endElement (String namespaceURI,
String localName,
String qName) throws SAXException {
if (saxParser != null) {
saxParser.endElement(namespaceURI, localName, qName);
}
}
/** <p>The SAX <code>characters</code> method. Does nothing.</p> */
public void characters (char ch[], int start, int length)
throws SAXException {
if (saxParser != null) {
saxParser.characters(ch, start, length);
}
}
/** <p>The SAX <code>ignorableWhitespace</code> method. Does nothing.</p> */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
if (saxParser != null) {
saxParser.ignorableWhitespace(ch, start, length);
}
}
/** <p>The SAX <code>processingInstruction</code> method. Does nothing.</p> */
public void processingInstruction (String target, String data)
throws SAXException {
if (saxParser != null) {
saxParser.processingInstruction(target, data);
}
}
/** <p>The SAX <code>startPrefixMapping</code> method. Does nothing.</p> */
public void startPrefixMapping (String prefix, String uri)
throws SAXException {
if (saxParser != null) {
saxParser.startPrefixMapping (prefix, uri);
}
}
/** <p>The SAX <code>endPrefixMapping</code> method. Does nothing.</p> */
public void endPrefixMapping (String prefix)
throws SAXException {
if (saxParser != null) {
saxParser.endPrefixMapping (prefix);
}
}
/** <p>The SAX <code>skippedentity</code> method. Does nothing.</p> */
public void skippedEntity (String name)
throws SAXException {
if (saxParser != null) {
saxParser.skippedEntity(name);
}
}
}
@@ -0,0 +1,187 @@
// SAXParserHandler.java - An entity-resolving DefaultHandler
/*
* 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.readers;
import java.io.IOException;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
/**
* <p>An entity-resolving DefaultHandler</p>
*
* <p>This class provides a SAXParser DefaultHandler that performs
* entity resolution.
* </p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
* @version 1.0
*/
public class SAXParserHandler extends DefaultHandler {
private EntityResolver er = null;
private ContentHandler ch = null;
public SAXParserHandler() {
super();
}
public void setEntityResolver(EntityResolver er) {
this.er = er;
}
public void setContentHandler(ContentHandler ch) {
this.ch = ch;
}
// Entity Resolver
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException {
if (er != null) {
try {
return er.resolveEntity(publicId, systemId);
} catch (IOException e) {
System.out.println("resolveEntity threw IOException!");
return null;
}
} else {
return null;
}
}
// Content Handler
public void characters(char[] ch, int start, int length)
throws SAXException {
if (this.ch != null) {
this.ch.characters(ch, start, length);
}
}
public void endDocument()
throws SAXException {
if (ch != null) {
ch.endDocument();
}
}
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (ch != null) {
ch.endElement(namespaceURI, localName, qName);
}
}
public void endPrefixMapping(String prefix)
throws SAXException {
if (ch != null) {
ch.endPrefixMapping(prefix);
}
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
if (this.ch != null) {
this.ch.ignorableWhitespace(ch, start, length);
}
}
public void processingInstruction(String target, String data)
throws SAXException {
if (ch != null) {
ch.processingInstruction(target, data);
}
}
public void setDocumentLocator(Locator locator) {
if (ch != null) {
ch.setDocumentLocator(locator);
}
}
public void skippedEntity(String name)
throws SAXException {
if (ch != null) {
ch.skippedEntity(name);
}
}
public void startDocument()
throws SAXException {
if (ch != null) {
ch.startDocument();
}
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException {
if (ch != null) {
ch.startElement(namespaceURI, localName, qName, atts);
}
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
if (ch != null) {
ch.startPrefixMapping(prefix, uri);
}
}
}
@@ -0,0 +1,179 @@
// TR9401CatalogReader.java - Read OASIS Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.util.Vector;
import java.util.Stack;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.Debug;
import org.apache.xml.resolver.helpers.PublicId;
/**
* <p>Parses OASIS Open Catalog files.</p>
*
* <p>This class reads OASIS Open Catalog files, returning a stream
* of tokens.</p>
*
* <p>This code interrogates the following non-standard system properties:</p>
*
* <dl>
* <dt><b>xml.catalog.debug</b></dt>
* <dd><p>Sets the debug level. A value of 0 is assumed if the
* property is not set or is not a number.</p></dd>
* </dl>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class TR9401CatalogReader extends TextCatalogReader {
/**
* <p>Start parsing an OASIS TR9401 Open Catalog file. The file is
* actually read and parsed
* as needed by <code>nextEntry</code>.</p>
*
* <p>In a TR9401 Catalog the 'DELEGATE' entry delegates public
* identifiers. There is no delegate entry for system identifiers
* or URIs.</p>
*
* @param fileUrl The URL or filename of the catalog file to process
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
*/
public void readCatalog(Catalog catalog, InputStream is)
throws MalformedURLException, IOException {
catfile = is;
if (catfile == null) {
return;
}
Vector unknownEntry = null;
while (true) {
String token = nextToken();
if (token == null) {
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
catfile.close();
catfile = null;
return;
}
String entryToken = null;
if (caseSensitive) {
entryToken = token;
} else {
entryToken = token.toUpperCase();
}
if (entryToken.equals("DELEGATE")) {
entryToken = "DELEGATE_PUBLIC";
}
try {
int type = CatalogEntry.getEntryType(entryToken);
int numArgs = CatalogEntry.getEntryArgCount(type);
Vector args = new Vector();
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
for (int count = 0; count < numArgs; count++) {
args.addElement(nextToken());
}
catalog.addEntry(new CatalogEntry(entryToken, args));
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
if (unknownEntry == null) {
unknownEntry = new Vector();
}
unknownEntry.addElement(token);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", token);
unknownEntry = null;
}
}
}
}
}
@@ -0,0 +1,328 @@
// TextCatalogReader.java - Read text/plain Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.util.Vector;
import java.util.Stack;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.Debug;
import org.apache.xml.resolver.helpers.PublicId;
/**
* <p>Parses plain text Catalog files.</p>
*
* <p>This class reads plain text Open Catalog files.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class TextCatalogReader implements CatalogReader {
/** The input stream used to read the catalog */
protected InputStream catfile = null;
/**
* Character lookahead stack. Reading a catalog sometimes requires
* up to two characters of lookahead.
*/
protected int[] stack = new int[3];
/**
* Token stack. Recognizing an unexpected catalog entry requires
* the ability to "push back" a token.
*/
protected Stack tokenStack = new Stack();
/** The current position on the lookahead stack */
protected int top = -1;
/** Are keywords in the catalog case sensitive? */
protected boolean caseSensitive = false;
/**
* <p>Construct a CatalogReader object.</p>
*/
public TextCatalogReader() { }
public void setCaseSensitive(boolean isCaseSensitive) {
caseSensitive = isCaseSensitive;
}
public boolean getCaseSensitive() {
return caseSensitive;
}
/**
* <p>Start parsing a text catalog file. The file is
* actually read and parsed
* as needed by <code>nextEntry</code>.</p>
*
* @param fileUrl The URL or filename of the catalog file to process
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException {
URL catURL = null;
try {
catURL = new URL(fileUrl);
} catch (MalformedURLException e) {
catURL = new URL("file:///" + fileUrl);
}
URLConnection urlCon = catURL.openConnection();
try {
readCatalog(catalog, urlCon.getInputStream());
} catch (FileNotFoundException e) {
Debug.message(1, "Failed to load catalog, file not found",
catURL.toString());
}
}
public void readCatalog(Catalog catalog, InputStream is)
throws MalformedURLException, IOException {
catfile = is;
if (catfile == null) {
return;
}
Vector unknownEntry = null;
while (true) {
String token = nextToken();
if (token == null) {
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
catfile.close();
catfile = null;
return;
}
String entryToken = null;
if (caseSensitive) {
entryToken = token;
} else {
entryToken = token.toUpperCase();
}
try {
int type = CatalogEntry.getEntryType(entryToken);
int numArgs = CatalogEntry.getEntryArgCount(type);
Vector args = new Vector();
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
for (int count = 0; count < numArgs; count++) {
args.addElement(nextToken());
}
catalog.addEntry(new CatalogEntry(entryToken, args));
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
if (unknownEntry == null) {
unknownEntry = new Vector();
}
unknownEntry.addElement(token);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", token);
unknownEntry = null;
}
}
}
}
/**
* <p>The destructor.</p>
*
* <p>Makes sure the catalog file is closed.</p>
*/
protected void finalize() {
if (catfile != null) {
try {
catfile.close();
} catch (IOException e) {
// whatever...
}
}
catfile = null;
}
// -----------------------------------------------------------------
/**
* <p>Return the next token in the catalog file.</p>
*
* @return The Catalog file token from the input stream.
* @throws IOException If an error occurs reading from the stream.
*/
protected String nextToken() throws IOException {
String token = "";
int ch, nextch;
if (!tokenStack.empty()) {
return (String) tokenStack.pop();
}
// Skip over leading whitespace and comments
while (true) {
// skip leading whitespace
ch = catfile.read();
while (ch <= ' ') { // all ctrls are whitespace
ch = catfile.read();
if (ch < 0) {
return null;
}
}
// now 'ch' is the current char from the file
nextch = catfile.read();
if (nextch < 0) {
return null;
}
if (ch == '-' && nextch == '-') {
// we've found a comment, skip it...
ch = ' ';
nextch = nextChar();
while (ch != '-' || nextch != '-') {
ch = nextch;
nextch = nextChar();
}
// Ok, we've found the end of the comment,
// loop back to the top and start again...
} else {
stack[++top] = nextch;
stack[++top] = ch;
break;
}
}
ch = nextChar();
if (ch == '"' || ch == '\'') {
int quote = ch;
while ((ch = nextChar()) != quote) {
char[] chararr = new char[1];
chararr[0] = (char) ch;
String s = new String(chararr);
token = token.concat(s);
}
return token;
} else {
// return the next whitespace or comment delimited
// string
while (ch > ' ') {
nextch = nextChar();
if (ch == '-' && nextch == '-') {
stack[++top] = ch;
stack[++top] = nextch;
return token;
} else {
char[] chararr = new char[1];
chararr[0] = (char) ch;
String s = new String(chararr);
token = token.concat(s);
ch = nextch;
}
}
return token;
}
}
/**
* <p>Return the next logical character from the input stream.</p>
*
* @return The next (logical) character from the input stream. The
* character may be buffered from a previous lookahead.
*
* @throws IOException If an error occurs reading from the stream.
*/
protected int nextChar() throws IOException {
if (top < 0) {
return catfile.read();
} else {
return stack[top--];
}
}
}
@@ -0,0 +1,234 @@
// XCatalogReader.java - Read XML Catalog files
/*
* 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.readers;
import java.lang.Integer;
import java.util.Vector;
import java.util.Enumeration;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import org.apache.xml.resolver.Catalog;
import org.apache.xml.resolver.CatalogEntry;
import org.apache.xml.resolver.CatalogException;
import org.apache.xml.resolver.readers.CatalogReader;
import org.apache.xml.resolver.helpers.PublicId;
import org.apache.xml.resolver.helpers.Debug;
import org.xml.sax.*;
import javax.xml.parsers.*;
/**
* <p>Parse "xcatalog" XML Catalog files, this is the XML Catalog format
* developed by John Cowan and supported by Apache.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser {
/** The catalog object needs to be stored by the object so that
* SAX callbacks can use it.
*/
protected Catalog catalog = null;
/** Set the current catalog. */
public void setCatalog (Catalog catalog) {
this.catalog = catalog;
}
/** Get the current catalog. */
public Catalog getCatalog () {
return catalog;
}
/** The constructor */
public XCatalogReader(SAXParserFactory parserFactory) {
super(parserFactory);
}
// ----------------------------------------------------------------------
// Implement the SAX DocumentHandler interface
/** <p>The SAX <code>setDocumentLocator</code> method does nothing.</p> */
public void setDocumentLocator (Locator locator) {
return;
}
/** <p>The SAX <code>startDocument</code> method does nothing.</p> */
public void startDocument ()
throws SAXException {
return;
}
/** <p>The SAX <code>endDocument</code> method does nothing.</p> */
public void endDocument ()
throws SAXException {
return;
}
/**
* <p>The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.</p>
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
if (localName.equals("Base")) {
entryType = catalog.BASE;
entryArgs.add(atts.getValue("HRef"));
Debug.message(4, "Base", atts.getValue("HRef"));
} else if (localName.equals("Delegate")) {
entryType = catalog.DELEGATE_PUBLIC;
entryArgs.add(atts.getValue("PublicId"));
entryArgs.add(atts.getValue("HRef"));
Debug.message(4, "Delegate",
PublicId.normalize(atts.getValue("PublicId")),
atts.getValue("HRef"));
} else if (localName.equals("Extend")) {
entryType = catalog.CATALOG;
entryArgs.add(atts.getValue("HRef"));
Debug.message(4, "Extend", atts.getValue("HRef"));
} else if (localName.equals("Map")) {
entryType = catalog.PUBLIC;
entryArgs.add(atts.getValue("PublicId"));
entryArgs.add(atts.getValue("HRef"));
Debug.message(4, "Map",
PublicId.normalize(atts.getValue("PublicId")),
atts.getValue("HRef"));
} else if (localName.equals("Remap")) {
entryType = catalog.SYSTEM;
entryArgs.add(atts.getValue("SystemId"));
entryArgs.add(atts.getValue("HRef"));
Debug.message(4, "Remap",
atts.getValue("SystemId"),
atts.getValue("HRef"));
} else if (localName.equals("XMLCatalog")) {
// nop, start of catalog
} else {
// This is equivalent to an invalid catalog entry type
Debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
Debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
Debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
/** <p>The SAX <code>endElement</code> method does nothing.</p> */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
return;
}
/** <p>The SAX <code>characters</code> method does nothing.</p> */
public void characters (char ch[], int start, int length)
throws SAXException {
return;
}
/** <p>The SAX <code>ignorableWhitespace</code> method does nothing.</p> */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
return;
}
/** <p>The SAX <code>processingInstruction</code> method does nothing.</p> */
public void processingInstruction (String target, String data)
throws SAXException {
return;
}
}
@@ -0,0 +1,12 @@
<html>
<head>
<title>Apache XML Commons Resolver Readers package</title>
</head>
<body>
<p>Apache XML Commons Resolver Readers package</p>
<p>This package provides the set of classes that read catalog files
and extract catalog entries from them.</p>
</body>
</html>