📄 xcat.java
字号:
* 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:")) { StringBuffer buf = new StringBuffer (); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -