diff options
Diffstat (limited to 'libjava/classpath/gnu/xml/util/XCat.java')
-rw-r--r-- | libjava/classpath/gnu/xml/util/XCat.java | 2250 |
1 files changed, 1125 insertions, 1125 deletions
diff --git a/libjava/classpath/gnu/xml/util/XCat.java b/libjava/classpath/gnu/xml/util/XCat.java index 93127f4..ea23ad6 100644 --- a/libjava/classpath/gnu/xml/util/XCat.java +++ b/libjava/classpath/gnu/xml/util/XCat.java @@ -1,4 +1,4 @@ -/* XCat.java -- +/* XCat.java -- Copyright (C) 2001 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -76,15 +76,15 @@ import org.xml.sax.helpers.XMLReaderFactory; * <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> + * 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 @@ -127,25 +127,25 @@ import org.xml.sax.helpers.XMLReaderFactory; */ 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 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... + // 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. + // - 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. + // - Have resolution track what catalogs (+modes) have been + // searched. This would support loop detection. // @@ -170,7 +170,7 @@ public class XCat implements EntityResolver2 */ public XCat (String uri) throws SAXException, IOException - { loadCatalog (uri); } + { loadCatalog (uri); } /** @@ -188,7 +188,7 @@ public class XCat implements EntityResolver2 * * <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. + * or <em>delegate*</em> elements are normally loaded only if needed. * * @see #setErrorHandler * @see #setParserClass @@ -197,44 +197,44 @@ public class XCat implements EntityResolver2 * @param uri absolute URI for the catalog file. * * @exception IOException As thrown by the parser, typically to - * indicate problems reading data from that URI. + * 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. + * 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. + * 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; + 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; } @@ -251,38 +251,38 @@ public class XCat implements EntityResolver2 * @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). + * 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. + * 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 + 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; + 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; } @@ -302,28 +302,28 @@ public class XCat implements EntityResolver2 * certain well formedess errors. * * @param name Name of the document element, either as declared in - * a DOCTYPE declaration or as observed in the text. + * 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. + * 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; + 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; } @@ -335,23 +335,23 @@ public class XCat implements EntityResolver2 * * <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>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 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.) + * <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> + * </ul> * * <p>Applications can tell whether this limited functionality will be * used: if the feature flag associated with the {@link EntityResolver2} @@ -365,13 +365,13 @@ public class XCat implements EntityResolver2 * @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. + * 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); + return resolveEntity (null, publicId, null, systemId); } @@ -398,40 +398,40 @@ public class XCat implements EntityResolver2 * @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. + * 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. + * 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; + 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 @@ -440,12 +440,12 @@ public class XCat implements EntityResolver2 */ 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; + // 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; } @@ -457,12 +457,12 @@ public class XCat implements EntityResolver2 * @see #setErrorHandler */ public ErrorHandler getErrorHandler () - { return errorHandler; } + { 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. + * 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. @@ -470,10 +470,10 @@ public class XCat implements EntityResolver2 * @see #getErrorHandler * * @param parser The error handler, or null saying to use the default - * (no diagnostics, and only fatal errors terminate loading). + * (no diagnostics, and only fatal errors terminate loading). */ public void setErrorHandler (ErrorHandler handler) - { errorHandler = handler; } + { errorHandler = handler; } /** @@ -482,7 +482,7 @@ public class XCat implements EntityResolver2 * @see #setParserClass */ public String getParserClass () - { return parserClass; } + { return parserClass; } /** * Names the SAX2 parser class used to parse catalogs. @@ -498,10 +498,10 @@ public class XCat implements EntityResolver2 * @see #getParserClass * * @param parser The parser class name, or null saying to use the - * system default SAX2 parser. + * system default SAX2 parser. */ public void setParserClass (String parser) - { parserClass = parser; } + { parserClass = parser; } /** @@ -527,7 +527,7 @@ public class XCat implements EntityResolver2 * @see #setUnified */ public boolean isUnified () - { return unified; } + { return unified; } /** * Assigns the value of the flag returned by {@link #isUnified}. @@ -540,7 +540,7 @@ public class XCat implements EntityResolver2 * @param value new flag setting */ public void setUnified (boolean value) - { unified = value; } + { unified = value; } /** @@ -556,7 +556,7 @@ public class XCat implements EntityResolver2 * @see #setUsingPublic */ public boolean isUsingPublic () - { return usingPublic; } + { return usingPublic; } /** * Specifies which catalog search mode is used. @@ -572,150 +572,150 @@ public class XCat implements EntityResolver2 * @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. + * false to only use them for system ids using the <em>urn:publicid:</em> + * URI scheme. */ public void setUsingPublic (boolean value) - { usingPublic = value; } + { usingPublic = value; } // hmm, what's this do? :) private static Catalog loadCatalog ( - String parserClass, - ErrorHandler eh, - String uri, - boolean unified + 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; + 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 (); + 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 '%': + 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 (); + 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; + 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; } + { return c <= 0x20 || c >= 0x7f || "\"<>^`{|}".indexOf (c) != -1; } private static int hexNibble (int c) { - if (c < 10) - return c + '0'; - return ('a' - 10) + 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; + 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 () { } + DoneDelegation () { } } @@ -725,359 +725,359 @@ System.err.println ("nyet unhexing public id: " + publicId); */ 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 (); - } + // 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"; + private static final String catalogNamespace = + "urn:oasis:names:tc:entity:xmlns:xml:catalog"; /** @@ -1085,527 +1085,527 @@ System.err.println ("nyet unhexing public id: " + publicId); */ 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 + 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)) { + 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) { + } + } + } 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 (); - } + } + + // + // 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 (); + } } } |