/* XCat.java -- 
   Copyright (C) 2001 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.xml.util;

import gnu.java.lang.CPStringBuilder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Stack;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

import org.xml.sax.ext.DefaultHandler2;
import org.xml.sax.ext.EntityResolver2;

import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Packages <a href=
    "http://www.oasis-open.org/committees/entity/spec-2001-08-06.html"
    >OASIS XML Catalogs</a>,
 * primarily for entity resolution by parsers.
 * That specification defines an XML syntax for mappings between
 * identifiers declared in DTDs (particularly PUBLIC identifiers) and
 * locations.  SAX has always supported such mappings, but conventions for
 * an XML file syntax to maintain them have previously been lacking.
 *
 * <p> This has three main operational modes.  The primary intended mode is
 * to create a resolver, then preloading it with one or more site-standard
 * catalogs before using it with one or more SAX parsers: <pre>
 *	XCat	catalog = new XCat ();
 *	catalog.setErrorHandler (diagnosticErrorHandler);
 *	catalog.loadCatalog ("file:/local/catalogs/catalog.cat");
 *	catalog.loadCatalog ("http://shared/catalog.cat");
 *	...
 *	catalog.disableLoading ();
 *	parser1.setEntityResolver (catalog);
 *	parser2.setEntityResolver (catalog);
 *	...</pre>
 *
 * <p>A second mode is to arrange that your application uses instances of
 * this class as its entity resolver, and automatically loads catalogs
 * referenced by <em>&lt;?oasis-xml-catalog...?&gt;</em> processing
 * instructions found before the DTD in documents it parses.
 * It would then discard the resolver after each parse.
 *
 * <p> A third mode applies catalogs in contexts other than entity
 * resolution for parsers.
 * The {@link #resolveURI resolveURI()} method supports resolving URIs
 * stored in XML application data, rather than inside DTDs.
 * Catalogs would be loaded as shown above, and the catalog could
 * be used concurrently for parser entity resolution and for
 * application URI resolution.
 * </p>
 *
 * <center><hr width='70%'></center>
 *
 * <p>Errors in catalogs implicitly loaded (during resolution) are ignored
 * beyond being reported through any <em>ErrorHandler</em> assigned using
 * {@link #setErrorHandler setErrorHandler()}.  SAX exceptions
 * thrown from such a handler won't abort resolution, although throwing a
 * <em>RuntimeException</em> or <em>Error</em> will normally abort both
 * resolution and parsing.  Useful diagnostic information is available to
 * any <em>ErrorHandler</em> used to report problems, or from any exception
 * thrown from an explicit {@link #loadCatalog loadCatalog()} invocation.
 * Applications can use that information as troubleshooting aids.
 *
 * <p>While this class requires <em>SAX2 Extensions 1.1</em> classes in
 * its class path, basic functionality does not require using a SAX2
 * parser that supports the extended entity resolution functionality.
 * See the original SAX1
 * {@link #resolveEntity(java.lang.String,java.lang.String) resolveEntity()}
 * method for a list of restrictions which apply when it is used with
 * older SAX parsers.
 *
 * @see EntityResolver2
 *
 * @author David Brownell
 */
public class XCat implements EntityResolver2
{
    private Catalog		catalogs [];
    private boolean		usingPublic = true;
    private boolean		loadingPermitted = true;
    private boolean		unified = true;
    private String		parserClass;
    private ErrorHandler	errorHandler;

    // private EntityResolver	next;	// chain to next if we fail...

    //
    // NOTE:  This is a straightforward implementation, and if
    // there are lots of "nextCatalog" or "delegate*" entries
    // in use, two tweaks would be worth considering:
    //
    //	- Centralize some sort of cache (key by URI) for individual
    //	  resolvers.  That'd avoid multiple copies of a given catalog.
    //
    //	- Have resolution track what catalogs (+modes) have been
    //	  searched.  This would support loop detection.
    //


    /**
     * Initializes without preloading a catalog.
     * This API is convenient when you may want to arrange that catalogs
     * are automatically loaded when explicitly referenced in documents,
     * using the <em>oasis-xml-catalog</em> processing instruction.
     * In such cases you won't usually be able to preload catalogs.
     */
    public XCat () { }

    /**
     * Initializes, and preloads a catalog using the default SAX parser.
     * This API is convenient when you operate with one or more standard
     * catalogs.
     *
     * <p> This just delegates to {@link #loadCatalog loadCatalog()};
     * see it for exception information.
     *
     * @param uri absolute URI for the catalog file.
     */
    public XCat (String uri)
    throws SAXException, IOException
	{ loadCatalog (uri); }


    /**
     * Loads an OASIS XML Catalog.
     * It is appended to the list of currently active catalogs, or
     * reloaded if a catalog with the same URI was already loaded.
     * Callers have control over what parser is used, how catalog parsing
     * errors are reported, and whether URIs will be resolved consistently.
     *
     * <p> The OASIS specification says that errors detected when loading
     * catalogs "must recover by ignoring the catalog entry file that
     * failed, and proceeding."  In this API, that action can be the
     * responsibility of applications, when they explicitly load any
     * catalog using this method.
     *
     * <p>Note that catalogs referenced by this one will not be loaded
     * at this time.  Catalogs referenced through <em>nextCatalog</em>
     * or <em>delegate*</em> elements are normally loaded only if needed. 
     *
     * @see #setErrorHandler
     * @see #setParserClass
     * @see #setUnified
     *
     * @param uri absolute URI for the catalog file.
     *
     * @exception IOException As thrown by the parser, typically to
     *	indicate problems reading data from that URI.
     * @exception SAXException As thrown by the parser, typically to
     *	indicate problems parsing data from that URI.  It may also
     *  be thrown if the parser doesn't support necessary handlers. 
     * @exception IllegalStateException When attempting to load a
     *	catalog after loading has been {@link #disableLoading disabled},
     *	such as after any entity or URI lookup has been performed.
     */
    public synchronized void loadCatalog (String uri)
    throws SAXException, IOException
    {
	Catalog		catalog;
	int		index = -1;

	if (!loadingPermitted)
	    throw new IllegalStateException ();
	
	uri = normalizeURI (uri);
	if (catalogs != null) {
	    // maybe just reload
	    for (index = 0; index < catalogs.length; index++)
		if (uri.equals (catalogs [index].catalogURI))
		    break;
	}
	catalog = loadCatalog (parserClass, errorHandler, uri, unified);

	// add to list of catalogs
	if (catalogs == null) {
	    index = 0;
	    catalogs = new Catalog [1];
	} else if (index == catalogs.length) {
	    Catalog		tmp [];

	    tmp = new Catalog [index + 1];
	    System.arraycopy (catalogs, 0, tmp, 0, index);
	    catalogs = tmp;
	}
	catalogs [index] = catalog;
    }


    /**
     * "New Style" external entity resolution for parsers.
     * Calls to this method prevent explicit loading of additional catalogs
     * using {@link #loadCatalog loadCatalog()}.
     *
     * <p>This supports the full core catalog functionality for locating
     * (and relocating) parsed entities that have been declared in a
     * document's DTD.
     *
     * @param name Entity name, such as "dudley", "%nell", or "[dtd]".
     * @param publicId Either a normalized public ID, or null.
     * @param baseURI Absolute base URI associated with systemId.
     * @param systemId URI found in entity declaration (may be
     *	relative to baseURI).
     *
     * @return Input source for accessing the external entity, or null
     *	if no mapping was found.  The input source may have opened
     *	the stream, and will have a fully resolved URI.
     *
     * @see #getExternalSubset
     */
    public InputSource resolveEntity (
	String name,		// UNUSED ... systemId is always non-null
	String publicId,
	String baseURI,		// UNUSED ... it just lets sysId be relative
	String systemId
    ) throws SAXException, IOException
    {
	if (loadingPermitted)
	    disableLoading ();

	try {
	    // steps as found in OASIS XML catalog spec 7.1.2
	    // steps 1, 8 involve looping over the list of catalogs
	    for (int i = 0; i < catalogs.length; i++) {
		InputSource	retval;
		retval = catalogs [i].resolve (usingPublic, publicId, systemId);
		if (retval != null)
		    return retval;
	    }
	} catch (DoneDelegation x) {
	    // done!
	}
	// step 9 involves returning "no match" 
	return null;
    }


    /**
     * "New Style" parser callback to add an external subset.
     * For documents that don't include an external subset, this may
     * return one according to <em>doctype</em> catalog entries.
     * (This functionality is not a core part of the OASIS XML Catalog
     * specification, though it's presented in an appendix.)
     * If no such entry is defined, this returns null to indicate that
     * this document will not be modified to include such a subset.
     * Calls to this method prevent explicit loading of additional catalogs
     * using {@link #loadCatalog loadCatalog()}.
     *
     * <p><em>Warning:</em> That catalog functionality can be dangerous.
     * It can provide definitions of general entities, and thereby mask
     * certain well formedess errors.
     *
     * @param name Name of the document element, either as declared in
     *	a DOCTYPE declaration or as observed in the text.
     * @param baseURI Document's base URI (absolute).
     *
     * @return Input source for accessing the external subset, or null
     *	if no mapping was found.  The input source may have opened
     *	the stream, and will have a fully resolved URI.
     */
    public InputSource getExternalSubset (String name, String baseURI)
    throws SAXException, IOException
    {
	if (loadingPermitted)
	    disableLoading ();
	try {
	    for (int i = 0; i < catalogs.length; i++) {
		InputSource retval = catalogs [i].getExternalSubset (name);
		if (retval != null)
		    return retval;
	    }
	} catch (DoneDelegation x) {
	    // done!
	}
	return null;
    }


    /**
     * "Old Style" external entity resolution for parsers.
     * This API provides only core functionality.
     * Calls to this method prevent explicit loading of additional catalogs
     * using {@link #loadCatalog loadCatalog()}.
     *
     * <p>The functional limitations of this interface include:</p><ul>
     *
     *	<li>Since system IDs will be absolutized before the resolver
     *	sees them, matching against relative URIs won't work.
     *	This may affect <em>system</em>, <em>rewriteSystem</em>,
     *	and <em>delegateSystem</em> catalog entries.
     *
     *	<li>Because of that absolutization, documents declaring entities
     *	with system IDs using URI schemes that the JVM does not recognize
     *	may be unparsable.  URI schemes such as <em>file:/</em>,
     *	<em>http://</em>, <em>https://</em>, and <em>ftp://</em>
     *	will usually work reliably.
     *
     *	<li>Because missing external subsets can't be provided, the
     *	<em>doctype</em> catalog entries will be ignored.
     *	(The {@link #getExternalSubset getExternalSubset()} method is
     *	a "New Style" resolution option.)
     *
     *	</ul>
     *
     * <p>Applications can tell whether this limited functionality will be
     * used: if the feature flag associated with the {@link EntityResolver2}
     * interface is not <em>true</em>, the limitations apply.  Applications
     * can't usually know whether a given document and catalog will trigger
     * those limitations.  The issue can only be bypassed by operational
     * procedures such as not using catalogs or documents which involve
     * those features.
     *
     * @param publicId Either a normalized public ID, or null
     * @param systemId Always an absolute URI.
     *
     * @return Input source for accessing the external entity, or null
     *	if no mapping was found.  The input source may have opened
     *	the stream, and will have a fully resolved URI.
     */
    final public InputSource resolveEntity (String publicId, String systemId)
    throws SAXException, IOException
    {
	return resolveEntity (null, publicId, null, systemId);
    }


    /**
     * Resolves a URI reference that's not defined to the DTD.
     * This is intended for use with URIs found in document text, such as
     * <em>xml-stylesheet</em> processing instructions and in attribute
     * values, where they are not recognized as URIs by XML parsers.
     * Calls to this method prevent explicit loading of additional catalogs
     * using {@link #loadCatalog loadCatalog()}.
     *
     * <p>This functionality is supported by the OASIS XML Catalog
     * specification, but will never be invoked by an XML parser.
     * It corresponds closely to functionality for mapping system
     * identifiers for entities declared in DTDs; closely enough that
     * this implementation's default behavior is that they be
     * identical, to minimize potential confusion.
     *
     * <p>This method could be useful when implementing the
     * {@link javax.xml.transform.URIResolver} interface, wrapping the
     * input source in a {@link javax.xml.transform.sax.SAXSource}.
     *
     * @see #isUnified
     * @see #setUnified
     *
     * @param baseURI The relevant base URI as specified by the XML Base
     *	specification.  This recognizes <em>xml:base</em> attributes
     *	as overriding the actual (physical) base URI.
     * @param uri Either an absolute URI, or one relative to baseURI
     *
     * @return Input source for accessing the mapped URI, or null
     *	if no mapping was found.  The input source may have opened
     *	the stream, and will have a fully resolved URI.
     */
    public InputSource resolveURI (String baseURI, String uri)
    throws SAXException, IOException
    {
	if (loadingPermitted)
	    disableLoading ();

	// NOTE:  baseURI isn't used here, but caller MUST have it,
	// and heuristics _might_ use it in the future ... plus,
	// it's symmetric with resolveEntity ().

	// steps 1, 6 involve looping
	try {
	    for (int i = 0; i < catalogs.length; i++) {
		InputSource	tmp = catalogs [i].resolveURI (uri);
		if (tmp != null)
		    return tmp;
	    }
	} catch (DoneDelegation x) {
	    // done
	}
	// step 7 reports no match
	return null;
    }


    /** 
     * Records that catalog loading is no longer permitted.
     * Loading is automatically disabled when lookups are performed,
     * and should be manually disabled when <em>startDTD()</em> (or
     * any other DTD declaration callback) is invoked, or at the latest
     * when the document root element is seen.
     */
    public synchronized void disableLoading ()
    {
	// NOTE:  this method and loadCatalog() are synchronized
	// so that it's impossible to load (top level) catalogs
	// after lookups start.  Likewise, deferred loading is also
	// synchronized (for "next" and delegated catalogs) to
	// ensure that parsers can share resolvers.
	loadingPermitted = false;
    }


    /**
     * Returns the error handler used to report catalog errors.
     * Null is returned if the parser's default error handling
     * will be used.
     *
     * @see #setErrorHandler
     */
    public ErrorHandler getErrorHandler ()
	{ return errorHandler; }

    /**
     * Assigns the error handler used to report catalog errors.
     * These errors may come either from the SAX2 parser or
     * from the catalog parsing code driven by the parser. 
     *
     * <p> If you're sharing the resolver between parsers, don't
     * change this once lookups have begun.
     *
     * @see #getErrorHandler
     *
     * @param parser The error handler, or null saying to use the default
     *	(no diagnostics, and only fatal errors terminate loading).
     */
    public void setErrorHandler (ErrorHandler handler)
	{ errorHandler = handler; }


    /**
     * Returns the name of the SAX2 parser class used to parse catalogs.
     * Null is returned if the system default is used.
     * @see #setParserClass
     */
    public String getParserClass ()
	{ return parserClass; }

    /**
     * Names the SAX2 parser class used to parse catalogs.
     *
     * <p> If you're sharing the resolver between parsers, don't change
     * this once lookups have begun.
     *
     * <p> Note that in order to properly support the <em>xml:base</em>
     * attribute and relative URI resolution, the SAX parser used to parse
     * the catalog must provide a {@link Locator} and support the optional
     * declaration and lexical handlers.
     *
     * @see #getParserClass
     *
     * @param parser The parser class name, or null saying to use the
     *	system default SAX2 parser.
     */
    public void setParserClass (String parser)
	{ parserClass = parser; }


    /**
     * Returns true (the default) if all methods resolve
     * a given URI in the same way.
     * Returns false if calls resolving URIs as entities (such as
     * {@link #resolveEntity resolveEntity()}) use different catalog entries
     * than those resolving them as URIs ({@link #resolveURI resolveURI()}),
     * which will generally produce different results.
     *
     * <p>The OASIS XML Catalog specification defines two related schemes
     * to map URIs "as URIs" or "as system IDs".
     * URIs use <em>uri</em>, <em>rewriteURI</em>, and <em>delegateURI</em>
     * elements.  System IDs do the same things with <em>systemId</em>,
     * <em>rewriteSystemId</em>, and <em>delegateSystemId</em>.
     * It's confusing and error prone to maintain two parallel copies of
     * such data.  Accordingly, this class makes that behavior optional.
     * The <em>unified</em> interpretation of URI mappings is preferred,
     * since it prevents surprises where one URI gets mapped to different
     * contents depending on whether the reference happens to have come
     * from a DTD (or not).
     *
     * @see #setUnified
     */
    public boolean isUnified ()
	{ return unified; }

    /**
     * Assigns the value of the flag returned by {@link #isUnified}.
     * Set it to false to be strictly conformant with the OASIS XML Catalog
     * specification.  Set it to true to make all mappings for a given URI
     * give the same result, regardless of the reason for the mapping.
     *
     * <p>Don't change this once you've loaded the first catalog.
     *
     * @param value new flag setting
     */
    public void setUnified (boolean value)
	{ unified = value; }


    /**
     * Returns true (the default) if a catalog's public identifier
     * mappings will be used.
     * When false is returned, such mappings are ignored except when
     * system IDs are discarded, such as for
     * entities using the <em>urn:publicid:</em> URI scheme in their
     * system identifiers.  (See RFC 3151 for information about that
     * URI scheme.  Using it in system identifiers may not work well
     * with many SAX parsers unless the <em>resolve-dtd-uris</em>
     * feature flag is set to false.)
     * @see #setUsingPublic
     */
    public boolean isUsingPublic ()
	{ return usingPublic; }

    /**
     * Specifies which catalog search mode is used.
     * By default, public identifier mappings are able to override system
     * identifiers when both are available.
     * Applications may choose to ignore public
     * identifier mappings in such cases, so that system identifiers
     * declared in DTDs will only be overridden by an explicit catalog
     * match for that system ID.
     *
     * <p> If you're sharing the resolver between parsers, don't
     * change this once lookups have begun.
     * @see #isUsingPublic
     *
     * @param value true to always use public identifier mappings,
     *	false to only use them for system ids using the <em>urn:publicid:</em>
     *	URI scheme.
     */
    public void setUsingPublic (boolean value)
	{ usingPublic = value; }



    // hmm, what's this do? :)
    private static Catalog loadCatalog (
	String		parserClass,
	ErrorHandler	eh,
	String		uri,
	boolean		unified
    ) throws SAXException, IOException
    {
	XMLReader	parser;
	Loader		loader;
	boolean		doesIntern = false;

	if (parserClass == null)
	    parser = XMLReaderFactory.createXMLReader ();
	else
	    parser = XMLReaderFactory.createXMLReader (parserClass);
	if (eh != null)
	    parser.setErrorHandler (eh);
	// resolve-dtd-entities is at default value (unrecognized == true)

	try {
	    doesIntern = parser.getFeature (
		"http://xml.org/sax/features/string-interning");
	} catch (SAXNotRecognizedException e) { }

	loader = new Loader (doesIntern, eh, unified);
	loader.cat.parserClass = parserClass;
	loader.cat.catalogURI = uri;

	parser.setContentHandler (loader);
	parser.setProperty (
	    "http://xml.org/sax/properties/declaration-handler",
	    loader);
	parser.setProperty (
	    "http://xml.org/sax/properties/lexical-handler",
	    loader);
	parser.parse (uri);

	return loader.cat;
    }

    // perform one or both the normalizations for public ids
    private static String normalizePublicId (boolean full, String publicId)
    {
	if (publicId.startsWith ("urn:publicid:")) {
	    CPStringBuilder	buf = new CPStringBuilder ();
	    char		chars [] = publicId.toCharArray ();
boolean hasbug = false;

	    for (int i = 13; i < chars.length; i++) {
		switch (chars [i]) {
		case '+': 	buf.append (' '); continue;
		case ':': 	buf.append ("//"); continue;
		case ';': 	buf.append ("::"); continue;
		case '%':
// FIXME unhex that char!  meanwhile, warn and fallthrough ...
		    hasbug = true;
		default:	buf.append (chars [i]); continue;
		}
	    }
	    publicId = buf.toString ();
if (hasbug)
System.err.println ("nyet unhexing public id: " + publicId);
	    full = true;
	}

	// SAX parsers do everything except that URN mapping, but
	// we can't trust other sources to normalize correctly
	if (full) {
	    StringTokenizer	tokens;
	    String		token;

	    tokens = new StringTokenizer (publicId, " \r\n");
	    publicId = null;
	    while (tokens.hasMoreTokens ()) {
		if (publicId == null)
		    publicId = tokens.nextToken ();
		else
		    publicId += " " + tokens.nextToken ();
	    }
	}
	return publicId;
    }

    private static boolean isUriExcluded (int c)
	{ return c <= 0x20 || c >= 0x7f || "\"<>^`{|}".indexOf (c) != -1; }

    private static int hexNibble (int c)
    {
	if (c < 10)
	    return c + '0';
	return ('a' - 10) + c;
    }

    // handles URIs with "excluded" characters
    private static String normalizeURI (String systemId)
    {
	int			length = systemId.length ();

	for (int i = 0; i < length; i++) {
	    char	c = systemId.charAt (i);

	    // escape non-ASCII plus "excluded" characters
	    if (isUriExcluded (c)) {
		byte			buf [];
		ByteArrayOutputStream	out;
		int				b;

		// a JVM that doesn't know UTF8 and 8859_1 is unusable!
		try {
		    buf = systemId.getBytes ("UTF8");
		    out = new ByteArrayOutputStream (buf.length + 10);

		    for (i = 0; i < buf.length; i++) {
			b = buf [i] & 0x0ff;
			if (isUriExcluded (b)) {
			    out.write ((int) '%');
			    out.write (hexNibble (b >> 4));
			    out.write (hexNibble (b & 0x0f));
			} else
			    out.write (b);
		    }
		    return out.toString ("8859_1");
		} catch (IOException e) {
		    throw new RuntimeException (
			"can't normalize URI: " + e.getMessage ());
		}
	    }
	}
	return systemId;
    }

    // thrown to mark authoritative end of a search
    private static class DoneDelegation extends SAXException
    {
	DoneDelegation () { }
    }


    /**
     * Represents a OASIS XML Catalog, and encapsulates much of
     * the catalog functionality.
     */
    private static class Catalog
    {
	// loading infrastructure
	String		catalogURI;
	ErrorHandler	eh;
	boolean		unified;
	String		parserClass;

	// catalog data
	boolean		hasPreference;
	boolean		usingPublic;

	Hashtable	publicIds;
	Hashtable	publicDelegations;

	Hashtable	systemIds;
	Hashtable	systemRewrites;
	Hashtable	systemDelegations;

	Hashtable	uris;
	Hashtable	uriRewrites;
	Hashtable	uriDelegations;

	Hashtable	doctypes;

	Vector		next;

	// nonpublic!
	Catalog () { }

	
	// steps as found in OASIS XML catalog spec 7.1.2
	private InputSource locatePublicId (String publicId)
	throws SAXException, IOException
	{
	    // 5. return (first) 'public' entry
	    if (publicIds != null) {
		String	retval = (String) publicIds.get (publicId);
		if (retval != null) {
		    // IF the URI is accessible ...
		    return new InputSource (retval);
		}
	    }

	    // 6. return delegatePublic catalog match [complex]
	    if (publicDelegations != null)
		return checkDelegations (publicDelegations, publicId,
				publicId, null);
	    
	    return null;
	}

	// steps as found in OASIS XML catalog spec 7.1.2 or 7.2.2
	private InputSource mapURI (
	    String	uri,
	    Hashtable	ids,
	    Hashtable	rewrites,
	    Hashtable	delegations
	) throws SAXException, IOException
	{
	    // 7.1.2: 2. return (first) 'system' entry
	    // 7.2.2: 2. return (first) 'uri' entry
	    if (ids != null) {
		String	retval = (String) ids.get (uri);
		if (retval != null) {
		    // IF the URI is accessible ...
		    return new InputSource (retval);
		}
	    }

	    // 7.1.2: 3. return 'rewriteSystem' entries
	    // 7.2.2: 3. return 'rewriteURI' entries
	    if (rewrites != null) {
		String	prefix = null;
		String	replace = null;
		int	prefixLen = -1;

		for (Enumeration e = rewrites.keys ();
			e.hasMoreElements ();
			/* NOP */) {
		    String	temp = (String) e.nextElement ();
		    int		len = -1;

		    if (!uri.startsWith (temp))
			continue;
		    if (prefix != null
			    && (len = temp.length ()) < prefixLen)
			continue;
		    prefix = temp;
		    prefixLen = len;
		    replace = (String) rewrites.get (temp);
		}
		if (prefix != null) {
		    CPStringBuilder	buf = new CPStringBuilder (replace);
		    buf.append (uri.substring (prefixLen));
		    // IF the URI is accessible ...
		    return new InputSource (buf.toString ());
		}
	    }

	    // 7.1.2: 4. return 'delegateSystem' catalog match [complex]
	    // 7.2.2: 4. return 'delegateURI' catalog match [complex]
	    if (delegations != null)
		return checkDelegations (delegations, uri, null, uri);

	    return null;
	}


	/**
	 * Returns a URI for an external entity.
	 */
	public InputSource resolve (
	    boolean	usingPublic,
	    String	publicId,
	    String	systemId
	) throws SAXException, IOException
	{
	    boolean	preferSystem;
	    InputSource	retval;

	    if (hasPreference)
		preferSystem = !this.usingPublic;
	    else
		preferSystem = !usingPublic;
	    
	    if (publicId != null)
		publicId = normalizePublicId (false, publicId);

	    // behavior here matches section 7.1.1 of the oasis spec
	    if (systemId != null) {
		if (systemId.startsWith ("urn:publicid:")) {
		    String	temp = normalizePublicId (true, systemId);
		    if (publicId == null) {
			publicId = temp;
			systemId = null;
		    } else if (!publicId.equals (temp)) {
			// error; ok to recover by:
			systemId = null;
		    }
		} else
		    systemId = normalizeURI (systemId);
	    }

	    if (systemId == null && publicId == null)
		return null;

	    if (systemId != null) {
		retval = mapURI (systemId, systemIds, systemRewrites,
					systemDelegations);
		if (retval != null) {
		    retval.setPublicId (publicId);
		    return retval;
		}
	    }

	    if (publicId != null
		    && !(systemId != null && preferSystem)) {
		retval = locatePublicId (publicId);
		if (retval != null) {
		    retval.setPublicId (publicId);
		    return retval;
		}
	    }

	    // 7. apply nextCatalog entries
	    if (next != null) {
		int	length = next.size ();
		for (int i = 0; i < length; i++) {
		    Catalog	n = getNext (i);
		    retval = n.resolve (usingPublic, publicId, systemId);
		    if (retval != null)
			return retval;
		}
	    }

	    return null;
	}

	/**
	 * Maps one URI into another, for resources that are not defined
	 * using XML external entity or notation syntax.
	 */
	public InputSource resolveURI (String uri)
	throws SAXException, IOException
	{
	    if (uri.startsWith ("urn:publicid:"))
		return resolve (true, normalizePublicId (true, uri), null);

	    InputSource	retval;

	    uri = normalizeURI (uri);

	    // 7.2.2 steps 2-4
	    retval = mapURI (uri, uris, uriRewrites, uriDelegations);
	    if (retval != null)
		return retval;

	    // 7.2.2 step 5. apply nextCatalog entries
	    if (next != null) {
		int	length = next.size ();
		for (int i = 0; i < length; i++) {
		    Catalog	n = getNext (i);
		    retval = n.resolveURI (uri);
		    if (retval != null)
			return retval;
		}
	    }

	    return null;
	}


	/**
	 * Finds the external subset associated with a given root element.
	 */
	public InputSource getExternalSubset (String name)
	throws SAXException, IOException
	{
	    if (doctypes != null) {
		String	value = (String) doctypes.get (name);
		if (value != null) {
		    // IF the URI is accessible ...
		    return new InputSource (value);
		}
	    }
	    if (next != null) {
		int	length = next.size ();
		for (int i = 0; i < length; i++) {
		    Catalog	n = getNext (i);
		    if (n == null)
			continue;
		    InputSource	retval = n.getExternalSubset (name);
		    if (retval != null)
			return retval;
		}
	    }
	    return null;
	}

	private synchronized Catalog getNext (int i)
	throws SAXException, IOException
	{
	    Object	obj;

	    if (next == null || i < 0 || i >= next.size ())
		return null;
	    obj = next.elementAt (i);
	    if (obj instanceof Catalog)
		return (Catalog) obj;
	    
	    // ok, we deferred reading that catalog till now.
	    // load and cache it.
	    Catalog	cat = null;

	    try {
		cat = loadCatalog (parserClass, eh, (String) obj, unified);
		next.setElementAt (cat, i);
	    } catch (SAXException e) {
		// must fail quietly, says the OASIS spec
	    } catch (IOException e) {
		// same applies here
	    }
	    return cat;
	}

	private InputSource checkDelegations (
	    Hashtable	delegations,
	    String	id,
	    String	publicId,	// only one of public/system
	    String	systemId	// will be non-null...
	) throws SAXException, IOException
	{
	    Vector	matches = null;
	    int		length = 0;

	    // first, see if any prefixes match.
	    for (Enumeration e = delegations.keys ();
		    e.hasMoreElements ();
		    /* NOP */) {
		String	prefix = (String) e.nextElement ();

		if (!id.startsWith (prefix))
		    continue;
		if (matches == null)
		    matches = new Vector ();
		
		// maintain in longer->shorter sorted order
		// NOTE:  assumes not many matches will fire!
		int	index;

		for (index = 0; index < length; index++) {
		    String	temp = (String) matches.elementAt (index);
		    if (prefix.length () > temp.length ()) {
			matches.insertElementAt (prefix, index);
			break;
		    }
		}
		if (index == length)
		    matches.addElement (prefix);
		length++;
	    }
	    if (matches == null)
		return null;

	    // now we know the list of catalogs to replace our "top level"
	    // list ... we use it here, rather than somehow going back and
	    // restarting, since this helps avoid reading most catalogs.
	    // this assumes stackspace won't be a problem.
	    for (int i = 0; i < length; i++) {
		Catalog		catalog = null;
		InputSource	result;

		// get this catalog.  we may not have read it yet.
		synchronized (delegations) {
		    Object	prefix = matches.elementAt (i);
		    Object	cat = delegations.get (prefix);

		    if (cat instanceof Catalog)
			catalog = (Catalog) cat;
		    else {
			try {
			    // load and cache that catalog
			    catalog = loadCatalog (parserClass, eh,
				    (String) cat, unified);
			    delegations.put (prefix, catalog);
			} catch (SAXException e) {
			    // must ignore, says the OASIS spec
			} catch (IOException e) {
			    // same applies here
			}
		    }
		}

		// ignore failed loads, and proceed
		if (catalog == null)
		    continue;
		
		// we have a catalog ... resolve!
		// usingPublic value can't matter, there's no choice
		result = catalog.resolve (true, publicId, systemId);
		if (result != null)
		    return result;
	    }

	    // if there were no successes, the entire
	    // lookup failed (all the way to top level)
	    throw new DoneDelegation ();
	}
    }


    /** This is the namespace URI used for OASIS XML Catalogs.  */
    private static final String	catalogNamespace =
    	"urn:oasis:names:tc:entity:xmlns:xml:catalog";


    /**
     * Loads/unmarshals one catalog.
     */
    private static class Loader extends DefaultHandler2
    {
	private boolean		preInterned;
	private ErrorHandler	handler;
	private boolean		unified;
	private int		ignoreDepth;
	private Locator		locator;
	private boolean		started;
	private Hashtable	externals;
	private Stack		bases;

	Catalog			cat = new Catalog ();


	/**
	 * Constructor.
	 * @param flag true iff the parser already interns strings.
	 * @param eh Errors and warnings are delegated to this.
	 * @param unified true keeps one table for URI mappings;
	 *	false matches OASIS spec, storing mappings
	 *	for URIs and SYSTEM ids in parallel tables.
	 */
	Loader (boolean flag, ErrorHandler eh, boolean unified)
	{
	    preInterned = flag;
	    handler = eh;
	    this.unified = unified;
	    cat.unified = unified;
	    cat.eh = eh;
	}


	// strips out fragments
	private String nofrag (String uri)
	throws SAXException
	{
	    if (uri.indexOf ('#') != -1) {
		warn ("URI with fragment: " + uri);
		uri = uri.substring (0, uri.indexOf ('#'));
	    }
	    return uri;
	}

	// absolutizes relative URIs
	private String absolutize (String uri)
	throws SAXException
	{
	    // avoid creating URLs if they're already absolutized,
	    // or if the URI is already using a known scheme
	    if (uri.startsWith ("file:/")
		    || uri.startsWith ("http:/")
		    || uri.startsWith ("https:/")
		    || uri.startsWith ("ftp:/")
		    || uri.startsWith ("urn:")
		    )
		return uri;

	    // otherwise, let's hope the JDK handles this URI scheme.
	    try {
		URL	base = (URL) bases.peek ();
		return new URL (base, uri).toString ();
	    } catch (Exception e) {
		fatal ("can't absolutize URI: " + uri);
		return null;
	    }
	}

	// recoverable error
	private void error (String message)
	throws SAXException
	{
	    if (handler == null)
		return;
	    handler.error (new SAXParseException (message, locator));
	}

	// nonrecoverable error
	private void fatal (String message)
	throws SAXException
	{
	    SAXParseException	spe;
	    
	    spe = new SAXParseException (message, locator);
	    if (handler != null)
		handler.fatalError (spe);
	    throw spe;
	}

	// low severity problem
	private void warn (String message)
	throws SAXException
	{
	    if (handler == null)
		return;
	    handler.warning (new SAXParseException (message, locator));
	}

	// callbacks:

	public void setDocumentLocator (Locator l)
	    { locator = l; }

	public void startDocument ()
	throws SAXException
	{
	    if (locator == null)
		error ("no locator!");
	    bases = new Stack ();
	    String	uri = locator.getSystemId ();
	    try {
		bases.push (new URL (uri));
	    } catch (IOException e) {
		fatal ("bad document base URI: " + uri);
	    }
	}

	public void endDocument ()
	throws SAXException
	{
	    try {
		if (!started)
		    error ("not a catalog!");
	    } finally {
		locator = null;
		handler = null;
		externals = null;
		bases = null;
	    }
	}

	// XML Base support for external entities.

	// NOTE: expects parser is in default "resolve-dtd-uris" mode.
	public void externalEntityDecl (String name, String pub, String sys)
	throws SAXException
	{
	    if (externals == null)
		externals = new Hashtable ();
	    if (externals.get (name) == null)
		externals.put (name, pub);
	}

	public void startEntity (String name)
	throws SAXException
	{
	    if (externals == null)
		return;
	    String uri = (String) externals.get (name);

	    // NOTE: breaks if an EntityResolver substitutes these URIs.
	    // If toplevel loader supports one, must intercept calls...
	    if (uri != null) {
		try {
		    bases.push (new URL (uri));
		} catch (IOException e) {
		    fatal ("entity '" + name + "', bad URI: " + uri);
		}
	    }
	}

	public void endEntity (String name)
	{
	    if (externals == null)
		return;
	    String value = (String) externals.get (name);

	    if (value != null)
		bases.pop ();
	}

	/**
	 * Processes catalog elements, saving their data.
	 */
	public void startElement (String namespace, String local,
	    String qName, Attributes atts)
	throws SAXException
	{
	    // must ignore non-catalog elements, and their contents
	    if (ignoreDepth != 0 || !catalogNamespace.equals (namespace)) {
		ignoreDepth++;
		return;
	    }

	    // basic sanity checks
	    if (!preInterned)
		local = local.intern ();
	    if (!started) {
		started = true;
		if ("catalog" != local)
		    fatal ("root element not 'catalog': " + local);
	    }

	    // Handle any xml:base attribute
	    String	xmlbase = atts.getValue ("xml:base");

	    if (xmlbase != null) {
		URL	base = (URL) bases.peek ();
		try {
		    base = new URL (base, xmlbase);
		} catch (IOException e) {
		    fatal ("can't resolve xml:base attribute: " + xmlbase);
		}
		bases.push (base);
	    } else
		bases.push (bases.peek ());

	    // fetch multi-element attributes, apply standard tweaks
	    // values (uri, catalog, rewritePrefix) get normalized too,
	    // as a precaution and since we may compare the values
	    String	catalog = atts.getValue ("catalog");
	    if (catalog != null)
		catalog = normalizeURI (absolutize (catalog));

	    String	rewritePrefix = atts.getValue ("rewritePrefix");
	    if (rewritePrefix != null)
		rewritePrefix = normalizeURI (absolutize (rewritePrefix));

	    String	systemIdStartString;
	    systemIdStartString = atts.getValue ("systemIdStartString");
	    if (systemIdStartString != null) {
		systemIdStartString = normalizeURI (systemIdStartString);
		// unmatchable <rewriteSystemId>, <delegateSystemId> elements
		if (systemIdStartString.startsWith ("urn:publicid:")) {
		    error ("systemIdStartString is really a publicId!!");
		    return;
		}
	    }

	    String	uri = atts.getValue ("uri");
	    if (uri != null)
		uri = normalizeURI (absolutize (uri));

	    String	uriStartString;
	    uriStartString = atts.getValue ("uriStartString");
	    if (uriStartString != null) {
		uriStartString = normalizeURI (uriStartString);
		// unmatchable <rewriteURI>, <delegateURI> elements
		if (uriStartString.startsWith ("urn:publicid:")) {
		    error ("uriStartString is really a publicId!!");
		    return;
		}
	    }

	    // strictly speaking "group" and "catalog" shouldn't nest
	    // ... arbitrary restriction, no evident motivation

// FIXME stack "prefer" settings (two elements only!) and use
// them to populate different public mapping/delegation tables

	    if ("catalog" == local || "group" == local) {
		String	prefer = atts.getValue ("prefer");

		if (prefer != null && !"public".equals (prefer)) {
		    if (!"system".equals (prefer)) {
			error ("in <" + local + " ... prefer='...'>, "
			    + "assuming 'public'");
			prefer = "public";
		    }
		}
		if (prefer != null) {
		    if ("catalog" == local) {
			cat.hasPreference = true;
			cat.usingPublic = "public".equals (prefer);
		    } else {
			if (!cat.hasPreference || cat.usingPublic
				    != "public".equals (prefer)) {
fatal ("<group prefer=...> case not handled");
			}
		    }
		} else if ("group" == local && cat.hasPreference) {
fatal ("<group prefer=...> case not handled");
		}

	    //
	    // PUBLIC ids:  cleanly set up for id substitution
	    //
	    } else if ("public" == local) {
		String	publicId = atts.getValue ("publicId");
		String	value = null;

		if (publicId == null || uri == null) {
		    error ("expecting <public publicId=... uri=.../>");
		    return;
		}
		publicId = normalizePublicId (true, publicId);
		uri = nofrag (uri);
		if (cat.publicIds == null)
		    cat.publicIds = new Hashtable ();
		else
		    value = (String) cat.publicIds.get (publicId);
		if (value != null) {
		    if (!value.equals (uri))
			warn ("ignoring <public...> entry for " + publicId);
		} else
		    cat.publicIds.put (publicId, uri);

	    } else if ("delegatePublic" == local) {
		String	publicIdStartString;
		Object	value = null;

		publicIdStartString = atts.getValue ("publicIdStartString");
		if (publicIdStartString == null || catalog == null) {
		    error ("expecting <delegatePublic "
			+ "publicIdStartString=... catalog=.../>");
		    return;
		}
		publicIdStartString = normalizePublicId (true,
			publicIdStartString);
		if (cat.publicDelegations == null)
		    cat.publicDelegations = new Hashtable ();
		else
		    value = cat.publicDelegations.get (publicIdStartString);
		if (value != null) {
		    if (!value.equals (catalog))
			warn ("ignoring <delegatePublic...> entry for "
			    + uriStartString);
		} else
		    cat.publicDelegations.put (publicIdStartString, catalog);


	    //
	    // SYSTEM ids:  need substitution due to operational issues
	    //
	    } else if ("system" == local) {
		String	systemId = atts.getValue ("systemId");
		String	value = null;

		if (systemId == null || uri == null) {
		    error ("expecting <system systemId=... uri=.../>");
		    return;
		}
		systemId = normalizeURI (systemId);
		uri = nofrag (uri);
		if (systemId.startsWith ("urn:publicid:")) {
		    error ("systemId is really a publicId!!");
		    return;
		}
		if (cat.systemIds == null) {
		    cat.systemIds = new Hashtable ();
		    if (unified)
			cat.uris = cat.systemIds;
		} else
		    value = (String) cat.systemIds.get (systemId);
		if (value != null) {
		    if (!value.equals (uri))
			warn ("ignoring <system...> entry for " + systemId);
		} else
		    cat.systemIds.put (systemId, uri);

	    } else if ("rewriteSystem" == local) {
		String	value = null;

		if (systemIdStartString == null || rewritePrefix == null
			|| systemIdStartString.length () == 0
			|| rewritePrefix.length () == 0
			) {
		    error ("expecting <rewriteSystem "
			+ "systemIdStartString=... rewritePrefix=.../>");
		    return;
		}
		if (cat.systemRewrites == null) {
		    cat.systemRewrites = new Hashtable ();
		    if (unified)
			cat.uriRewrites = cat.systemRewrites;
		} else
		    value = (String) cat.systemRewrites.get (
		    				systemIdStartString);
		if (value != null) {
		    if (!value.equals (rewritePrefix))
			warn ("ignoring <rewriteSystem...> entry for "
			    + systemIdStartString);
		} else
		    cat.systemRewrites.put (systemIdStartString,
		    		rewritePrefix);

	    } else if ("delegateSystem" == local) {
		Object	value = null;

		if (systemIdStartString == null || catalog == null) {
		    error ("expecting <delegateSystem "
			+ "systemIdStartString=... catalog=.../>");
		    return;
		}
		if (cat.systemDelegations == null) {
		    cat.systemDelegations = new Hashtable ();
		    if (unified)
			cat.uriDelegations = cat.systemDelegations;
		} else
		    value = cat.systemDelegations.get (systemIdStartString);
		if (value != null) {
		    if (!value.equals (catalog))
			warn ("ignoring <delegateSystem...> entry for "
			    + uriStartString);
		} else
		    cat.systemDelegations.put (systemIdStartString, catalog);


	    //
	    // URI:  just like "system" ID support, except that
	    // fragment IDs are disallowed in "system" elements.
	    //
	    } else if ("uri" == local) {
		String	name = atts.getValue ("name");
		String	value = null;

		if (name == null || uri == null) {
		    error ("expecting <uri name=... uri=.../>");
		    return;
		}
		if (name.startsWith ("urn:publicid:")) {
		    error ("name is really a publicId!!");
		    return;
		}
		name = normalizeURI (name);
		if (cat.uris == null) {
		    cat.uris = new Hashtable ();
		    if (unified)
			cat.systemIds = cat.uris;
		} else
		    value = (String) cat.uris.get (name);
		if (value != null) {
		    if (!value.equals (uri))
			warn ("ignoring <uri...> entry for " + name);
		} else
		    cat.uris.put (name, uri);

	    } else if ("rewriteURI" == local) {
		String value = null;

		if (uriStartString == null || rewritePrefix == null
			|| uriStartString.length () == 0
			|| rewritePrefix.length () == 0
			) {
		    error ("expecting <rewriteURI "
			+ "uriStartString=... rewritePrefix=.../>");
		    return;
		}
		if (cat.uriRewrites == null) {
		    cat.uriRewrites = new Hashtable ();
		    if (unified)
			cat.systemRewrites = cat.uriRewrites;
		} else
		    value = (String) cat.uriRewrites.get (uriStartString);
		if (value != null) {
		    if (!value.equals (rewritePrefix))
			warn ("ignoring <rewriteURI...> entry for "
			    + uriStartString);
		} else
		    cat.uriRewrites.put (uriStartString, rewritePrefix);

	    } else if ("delegateURI" == local) {
		Object	value = null;

		if (uriStartString == null || catalog == null) {
		    error ("expecting <delegateURI "
			+ "uriStartString=... catalog=.../>");
		    return;
		}
		if (cat.uriDelegations == null) {
		    cat.uriDelegations = new Hashtable ();
		    if (unified)
			cat.systemDelegations = cat.uriDelegations;
		} else
		    value = cat.uriDelegations.get (uriStartString);
		if (value != null) {
		    if (!value.equals (catalog))
			warn ("ignoring <delegateURI...> entry for "
			    + uriStartString);
		} else
		    cat.uriDelegations.put (uriStartString, catalog);

	    //
	    // NON-DELEGATING approach to modularity
	    //
	    } else if ("nextCatalog" == local) {
		if (catalog == null) {
		    error ("expecting <nextCatalog catalog=.../>");
		    return;
		}
		if (cat.next == null)
		    cat.next = new Vector ();
		cat.next.addElement (catalog);

	    //
	    // EXTENSIONS from appendix E
	    //
	    } else if ("doctype" == local) {
		String	name = atts.getValue ("name");
		String	value = null;

		if (name == null || uri == null) {
		    error ("expecting <doctype name=... uri=.../>");
		    return;
		}
		name = normalizeURI (name);
		if (cat.doctypes == null)
		    cat.doctypes = new Hashtable ();
		else
		    value = (String) cat.doctypes.get (name);
		if (value != null) {
		    if (!value.equals (uri))
			warn ("ignoring <doctype...> entry for "
			    + uriStartString);
		} else
		    cat.doctypes.put (name, uri);
	    

	    //
	    // RESERVED ... ignore (like reserved attributes) but warn
	    //
	    } else {
		warn ("ignoring unknown catalog element: " + local);
		ignoreDepth++;
	    }
	}

	public void endElement (String uri, String local, String qName)
	throws SAXException
	{
	    if (ignoreDepth != 0)
		ignoreDepth--;
	    else
		bases.pop ();
	}
    }
}
