Source Code Cross Referenced for Catalog.java in  » 6.0-JDK-Modules » jaxb-xjc » com » sun » org » apache » xml » internal » resolver » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » jaxb xjc » com.sun.org.apache.xml.internal.resolver 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Catalog.java - Represents OASIS Open Catalog files.
0002:
0003:        /*
0004:         * Copyright 2001-2004 The Apache Software Foundation or its licensors,
0005:         * as applicable.
0006:         * 
0007:         * Licensed under the Apache License, Version 2.0 (the "License");
0008:         * you may not use this file except in compliance with the License.
0009:         * You may obtain a copy of the License at
0010:         * 
0011:         *      http://www.apache.org/licenses/LICENSE-2.0
0012:         * 
0013:         * Unless required by applicable law or agreed to in writing, software
0014:         * distributed under the License is distributed on an "AS IS" BASIS,
0015:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016:         * See the License for the specific language governing permissions and
0017:         * limitations under the License.
0018:         */
0019:
0020:        package com.sun.org.apache.xml.internal.resolver;
0021:
0022:        import java.io.IOException;
0023:        import java.io.FileNotFoundException;
0024:        import java.io.InputStream;
0025:        import java.io.UnsupportedEncodingException;
0026:        import java.io.DataInputStream;
0027:
0028:        import java.util.Enumeration;
0029:        import java.util.Hashtable;
0030:        import java.util.Vector;
0031:
0032:        import java.net.URL;
0033:        import java.net.MalformedURLException;
0034:
0035:        import javax.xml.parsers.SAXParserFactory;
0036:
0037:        import com.sun.org.apache.xml.internal.resolver.CatalogManager;
0038:        import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
0039:        import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
0040:        import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
0041:        import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader;
0042:        import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
0043:        import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
0044:
0045:        /**
0046:         * Represents OASIS Open Catalog files.
0047:         *
0048:         * <p>This class implements the semantics of OASIS Open Catalog files
0049:         * (defined by
0050:         * <a href="http://www.oasis-open.org/html/a401.htm">OASIS Technical
0051:         * Resolution 9401:1997 (Amendment 2 to TR 9401)</a>).</p>
0052:         *
0053:         * <p>The primary purpose of the Catalog is to associate resources in the
0054:         * document with local system identifiers. Some entities
0055:         * (document types, XML entities, and notations) have names and all of them
0056:         * can have either public or system identifiers or both. (In XML, only a
0057:         * notation can have a public identifier without a system identifier, but
0058:         * the methods implemented in this class obey the Catalog semantics
0059:         * from the SGML
0060:         * days when system identifiers were optional.)</p>
0061:         *
0062:         * <p>The system identifiers returned by the resolution methods in this
0063:         * class are valid, i.e. usable by, and in fact constructed by, the
0064:         * <tt>java.net.URL</tt> class. Unfortunately, this class seems to behave in
0065:         * somewhat non-standard ways and the system identifiers returned may
0066:         * not be directly usable in a browser or filesystem context.
0067:         *
0068:         * <p>This class recognizes all of the Catalog entries defined in
0069:         * TR9401:1997:</p>
0070:         *
0071:         * <ul>
0072:         * <li><b>BASE</b>
0073:         * changes the base URI for resolving relative system identifiers. The
0074:         * initial base URI is the URI of the location of the catalog (which is,
0075:         * in turn, relative to the location of the current working directory
0076:         * at startup, as returned by the <tt>user.dir</tt> system property).</li>
0077:         * <li><b>CATALOG</b>
0078:         * processes other catalog files. An included catalog occurs logically
0079:         * at the end of the including catalog.</li>
0080:         * <li><b>DELEGATE_PUBLIC</b>
0081:         * specifies alternate catalogs for some public identifiers. The delegated
0082:         * catalogs are not loaded until they are needed, but they are cached
0083:         * once loaded.</li>
0084:         * <li><b>DELEGATE_SYSTEM</b>
0085:         * specifies alternate catalogs for some system identifiers. The delegated
0086:         * catalogs are not loaded until they are needed, but they are cached
0087:         * once loaded.</li>
0088:         * <li><b>DELEGATE_URI</b>
0089:         * specifies alternate catalogs for some URIs. The delegated
0090:         * catalogs are not loaded until they are needed, but they are cached
0091:         * once loaded.</li>
0092:         * <li><b>REWRITE_SYSTEM</b>
0093:         * specifies alternate prefix for a system identifier.</li>
0094:         * <li><b>REWRITE_URI</b>
0095:         * specifies alternate prefix for a URI.</li>
0096:         * <li><b>SYSTEM_SUFFIX</b>
0097:         * maps any system identifier that ends with a particular suffix to another
0098:         * system identifier.</li>
0099:         * <li><b>URI_SUFFIX</b>
0100:         * maps any URI that ends with a particular suffix to another URI.</li>
0101:         * <li><b>DOCTYPE</b>
0102:         * associates the names of root elements with URIs. (In other words, an XML
0103:         * processor might infer the doctype of an XML document that does not include
0104:         * a doctype declaration by looking for the DOCTYPE entry in the
0105:         * catalog which matches the name of the root element of the document.)</li>
0106:         * <li><b>DOCUMENT</b>
0107:         * provides a default document.</li>
0108:         * <li><b>DTDDECL</b>
0109:         * recognized and silently ignored. Not relevant for XML.</li>
0110:         * <li><b>ENTITY</b>
0111:         * associates entity names with URIs.</li>
0112:         * <li><b>LINKTYPE</b>
0113:         * recognized and silently ignored. Not relevant for XML.</li>
0114:         * <li><b>NOTATION</b>
0115:         * associates notation names with URIs.</li>
0116:         * <li><b>OVERRIDE</b>
0117:         * changes the override behavior. Initial behavior is set by the
0118:         * system property <tt>xml.catalog.override</tt>. The default initial
0119:         * behavior is 'YES', that is, entries in the catalog override
0120:         * system identifiers specified in the document.</li>
0121:         * <li><b>PUBLIC</b>
0122:         * maps a public identifier to a system identifier.</li>
0123:         * <li><b>SGMLDECL</b>
0124:         * recognized and silently ignored. Not relevant for XML.</li>
0125:         * <li><b>SYSTEM</b>
0126:         * maps a system identifier to another system identifier.</li>
0127:         * <li><b>URI</b>
0128:         * maps a URI to another URI.</li>
0129:         * </ul>
0130:         *
0131:         * <p>Note that BASE entries are treated as described by RFC2396. In
0132:         * particular, this has the counter-intuitive property that after a BASE
0133:         * entry identifing "http://example.com/a/b/c" as the base URI,
0134:         * the relative URI "foo" is resolved to the absolute URI
0135:         * "http://example.com/a/b/foo". You must provide the trailing slash if
0136:         * you do not want the final component of the path to be discarded as a
0137:         * filename would in a URI for a resource: "http://example.com/a/b/c/".
0138:         * </p>
0139:         *
0140:         * <p>Note that subordinate catalogs (all catalogs except the first,
0141:         * including CATALOG and DELEGATE* catalogs) are only loaded if and when
0142:         * they are required.</p>
0143:         *
0144:         * <p>This class relies on classes which implement the CatalogReader
0145:         * interface to actually load catalog files. This allows the catalog
0146:         * semantics to be implemented for TR9401 text-based catalogs, XML
0147:         * catalogs, or any number of other storage formats.</p>
0148:         *
0149:         * <p>Additional catalogs may also be loaded with the
0150:         * {@link #parseCatalog} method.</p>
0151:         * </dd>
0152:         * </dl>
0153:         *
0154:         * <p><b>Change Log:</b></p>
0155:         * <dl>
0156:         * <dt>2.0</dt>
0157:         * <dd><p>Rewrite to use CatalogReaders.</p></dd>
0158:         * <dt>1.1</dt>
0159:         * <dd><p>Allow quoted components in <tt>xml.catalog.files</tt>
0160:         * so that URLs containing colons can be used on Unix.
0161:         * The string passed to <tt>xml.catalog.files</tt> can now have the form:</p>
0162:         * <pre>
0163:         * unquoted-path-with-no-sep-chars:"double-quoted path with or without sep chars":'single-quoted path with or without sep chars'
0164:         * </pre>
0165:         * <p>(Where ":" is the separater character in this example.)</p>
0166:         * <p>If an unquoted path contains an embedded double or single quote
0167:         * character, no special processig is performed on that character. No
0168:         * path can contain separater characters, double, and single quotes
0169:         * simultaneously.</p>
0170:         * <p>Fix bug in calculation of BASE entries: if
0171:         * a catalog contains multiple BASE entries, each is relative to the preceding
0172:         * base, not the default base URI of the catalog.</p>
0173:         * </dd>
0174:         * <dt>1.0.1</dt>
0175:         * <dd><p>Fixed a bug in the calculation of the list of subordinate catalogs.
0176:         * This bug caused an infinite loop where parsing would alternately process
0177:         * two catalogs indefinitely.</p>
0178:         * </dd>
0179:         * </dl>
0180:         *
0181:         * @see CatalogReader
0182:         * @see CatalogEntry
0183:         *
0184:         * @author Norman Walsh
0185:         * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
0186:         *
0187:         * @version 1.0
0188:         *
0189:         * <p>Derived from public domain code originally published by Arbortext,
0190:         * Inc.</p>
0191:         */
0192:        public class Catalog {
0193:            /** The BASE Catalog Entry type. */
0194:            public static final int BASE = CatalogEntry.addEntryType("BASE", 1);
0195:
0196:            /** The CATALOG Catalog Entry type. */
0197:            public static final int CATALOG = CatalogEntry.addEntryType(
0198:                    "CATALOG", 1);
0199:
0200:            /** The DOCUMENT Catalog Entry type. */
0201:            public static final int DOCUMENT = CatalogEntry.addEntryType(
0202:                    "DOCUMENT", 1);
0203:
0204:            /** The OVERRIDE Catalog Entry type. */
0205:            public static final int OVERRIDE = CatalogEntry.addEntryType(
0206:                    "OVERRIDE", 1);
0207:
0208:            /** The SGMLDECL Catalog Entry type. */
0209:            public static final int SGMLDECL = CatalogEntry.addEntryType(
0210:                    "SGMLDECL", 1);
0211:
0212:            /** The DELEGATE_PUBLIC Catalog Entry type. */
0213:            public static final int DELEGATE_PUBLIC = CatalogEntry
0214:                    .addEntryType("DELEGATE_PUBLIC", 2);
0215:
0216:            /** The DELEGATE_SYSTEM Catalog Entry type. */
0217:            public static final int DELEGATE_SYSTEM = CatalogEntry
0218:                    .addEntryType("DELEGATE_SYSTEM", 2);
0219:
0220:            /** The DELEGATE_URI Catalog Entry type. */
0221:            public static final int DELEGATE_URI = CatalogEntry.addEntryType(
0222:                    "DELEGATE_URI", 2);
0223:
0224:            /** The DOCTYPE Catalog Entry type. */
0225:            public static final int DOCTYPE = CatalogEntry.addEntryType(
0226:                    "DOCTYPE", 2);
0227:
0228:            /** The DTDDECL Catalog Entry type. */
0229:            public static final int DTDDECL = CatalogEntry.addEntryType(
0230:                    "DTDDECL", 2);
0231:
0232:            /** The ENTITY Catalog Entry type. */
0233:            public static final int ENTITY = CatalogEntry.addEntryType(
0234:                    "ENTITY", 2);
0235:
0236:            /** The LINKTYPE Catalog Entry type. */
0237:            public static final int LINKTYPE = CatalogEntry.addEntryType(
0238:                    "LINKTYPE", 2);
0239:
0240:            /** The NOTATION Catalog Entry type. */
0241:            public static final int NOTATION = CatalogEntry.addEntryType(
0242:                    "NOTATION", 2);
0243:
0244:            /** The PUBLIC Catalog Entry type. */
0245:            public static final int PUBLIC = CatalogEntry.addEntryType(
0246:                    "PUBLIC", 2);
0247:
0248:            /** The SYSTEM Catalog Entry type. */
0249:            public static final int SYSTEM = CatalogEntry.addEntryType(
0250:                    "SYSTEM", 2);
0251:
0252:            /** The URI Catalog Entry type. */
0253:            public static final int URI = CatalogEntry.addEntryType("URI", 2);
0254:
0255:            /** The REWRITE_SYSTEM Catalog Entry type. */
0256:            public static final int REWRITE_SYSTEM = CatalogEntry.addEntryType(
0257:                    "REWRITE_SYSTEM", 2);
0258:
0259:            /** The REWRITE_URI Catalog Entry type. */
0260:            public static final int REWRITE_URI = CatalogEntry.addEntryType(
0261:                    "REWRITE_URI", 2);
0262:            /** The SYSTEM_SUFFIX Catalog Entry type. */
0263:            public static final int SYSTEM_SUFFIX = CatalogEntry.addEntryType(
0264:                    "SYSTEM_SUFFIX", 2);
0265:            /** The URI_SUFFIX Catalog Entry type. */
0266:            public static final int URI_SUFFIX = CatalogEntry.addEntryType(
0267:                    "URI_SUFFIX", 2);
0268:
0269:            /**
0270:             * The base URI for relative system identifiers in the catalog.
0271:             * This may be changed by BASE entries in the catalog.
0272:             */
0273:            protected URL base;
0274:
0275:            /** The base URI of the Catalog file currently being parsed. */
0276:            protected URL catalogCwd;
0277:
0278:            /** The catalog entries currently known to the system. */
0279:            protected Vector catalogEntries = new Vector();
0280:
0281:            /** The default initial override setting. */
0282:            protected boolean default_override = true;
0283:
0284:            /** The catalog manager in use for this instance. */
0285:            protected CatalogManager catalogManager = CatalogManager
0286:                    .getStaticManager();
0287:
0288:            /**
0289:             * A vector of catalog files to be loaded.
0290:             *
0291:             * <p>This list is initially established by
0292:             * <code>loadSystemCatalogs</code> when
0293:             * it parses the system catalog list, but CATALOG entries may
0294:             * contribute to it during the course of parsing.</p>
0295:             *
0296:             * @see #loadSystemCatalogs
0297:             * @see #localCatalogFiles
0298:             */
0299:            protected Vector catalogFiles = new Vector();
0300:
0301:            /**
0302:             * A vector of catalog files constructed during processing of
0303:             * CATALOG entries in the current catalog.
0304:             *
0305:             * <p>This two-level system is actually necessary to correctly implement
0306:             * the semantics of the CATALOG entry. If one catalog file includes
0307:             * another with a CATALOG entry, the included catalog logically
0308:             * occurs <i>at the end</i> of the including catalog, and after any
0309:             * preceding CATALOG entries. In other words, the CATALOG entry
0310:             * cannot insert anything into the middle of a catalog file.</p>
0311:             *
0312:             * <p>When processing reaches the end of each catalog files, any
0313:             * elements on this vector are added to the front of the
0314:             * <code>catalogFiles</code> vector.</p>
0315:             *
0316:             * @see #catalogFiles
0317:             */
0318:            protected Vector localCatalogFiles = new Vector();
0319:
0320:            /**
0321:             * A vector of Catalogs.
0322:             *
0323:             * <p>The semantics of Catalog resolution are such that each
0324:             * catalog is effectively a list of Catalogs (in other words,
0325:             * a recursive list of Catalog instances).</p>
0326:             *
0327:             * <p>Catalogs that are processed as the result of CATALOG or
0328:             * DELEGATE* entries are subordinate to the catalog that contained
0329:             * them, but they may in turn have subordinate catalogs.</p>
0330:             *
0331:             * <p>Catalogs are only loaded when they are needed, so this vector
0332:             * initially contains a list of Catalog filenames (URLs). If, during
0333:             * processing, one of these catalogs has to be loaded, the resulting
0334:             * Catalog object is placed in the vector, effectively caching it
0335:             * for the next query.</p>
0336:             */
0337:            protected Vector catalogs = new Vector();
0338:
0339:            /**
0340:             * A vector of DELEGATE* Catalog entries constructed during
0341:             * processing of the Catalog.
0342:             *
0343:             * <p>This two-level system has two purposes; first, it allows
0344:             * us to sort the DELEGATE* entries by the length of the partial
0345:             * public identifier so that a linear search encounters them in
0346:             * the correct order and second, it puts them all at the end of
0347:             * the Catalog.</p>
0348:             *
0349:             * <p>When processing reaches the end of each catalog file, any
0350:             * elements on this vector are added to the end of the
0351:             * <code>catalogEntries</code> vector. This assures that matching
0352:             * PUBLIC keywords are encountered before DELEGATE* entries.</p>
0353:             */
0354:            protected Vector localDelegate = new Vector();
0355:
0356:            /**
0357:             * A hash of CatalogReaders.
0358:             *
0359:             * <p>This hash maps MIME types to elements in the readerArr
0360:             * vector. This allows the Catalog to quickly locate the reader
0361:             * for a particular MIME type.</p>
0362:             */
0363:            protected Hashtable readerMap = new Hashtable();
0364:
0365:            /**
0366:             * A vector of CatalogReaders.
0367:             *
0368:             * <p>This vector contains all of the readers in the order that they
0369:             * were added. In the event that a catalog is read from a file, where
0370:             * the MIME type is unknown, each reader is attempted in turn until
0371:             * one succeeds.</p>
0372:             */
0373:            protected Vector readerArr = new Vector();
0374:
0375:            /**
0376:             * Constructs an empty Catalog.
0377:             *
0378:             * <p>The constructor interrogates the relevant system properties
0379:             * using the default (static) CatalogManager
0380:             * and initializes the catalog data structures.</p>
0381:             */
0382:            public Catalog() {
0383:                // nop;
0384:            }
0385:
0386:            /**
0387:             * Constructs an empty Catalog with a specific CatalogManager.
0388:             *
0389:             * <p>The constructor interrogates the relevant system properties
0390:             * using the specified Catalog Manager
0391:             * and initializes the catalog data structures.</p>
0392:             */
0393:            public Catalog(CatalogManager manager) {
0394:                catalogManager = manager;
0395:            }
0396:
0397:            /**
0398:             * Return the CatalogManager used by this catalog.
0399:             *
0400:             */
0401:            public CatalogManager getCatalogManager() {
0402:                return catalogManager;
0403:            }
0404:
0405:            /**
0406:             * Establish the CatalogManager used by this catalog.
0407:             *
0408:             */
0409:            public void setCatalogManager(CatalogManager manager) {
0410:                catalogManager = manager;
0411:            }
0412:
0413:            /**
0414:             * Setup readers.
0415:             */
0416:            public void setupReaders() {
0417:                SAXParserFactory spf = SAXParserFactory.newInstance();
0418:                spf.setNamespaceAware(true);
0419:                spf.setValidating(false);
0420:
0421:                SAXCatalogReader saxReader = new SAXCatalogReader(spf);
0422:
0423:                saxReader
0424:                        .setCatalogParser(null, "XMLCatalog",
0425:                                "com.sun.org.apache.xml.internal.resolver.readers.XCatalogReader");
0426:
0427:                saxReader
0428:                        .setCatalogParser(OASISXMLCatalogReader.namespaceName,
0429:                                "catalog",
0430:                                "com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader");
0431:
0432:                addReader("application/xml", saxReader);
0433:
0434:                TR9401CatalogReader textReader = new TR9401CatalogReader();
0435:                addReader("text/plain", textReader);
0436:            }
0437:
0438:            /**
0439:             * Add a new CatalogReader to the Catalog.
0440:             *
0441:             * <p>This method allows you to add a new CatalogReader to the
0442:             * catalog. The reader will be associated with the specified mimeType.
0443:             * You can only have one reader per mimeType.</p>
0444:             *
0445:             * <p>In the absence of a mimeType (e.g., when reading a catalog
0446:             * directly from a file on the local system), the readers are attempted
0447:             * in the order that you add them to the Catalog.</p>
0448:             *
0449:             * <p>Note that subordinate catalogs (created by CATALOG or
0450:             * DELEGATE* entries) get a copy of the set of readers present in
0451:             * the primary catalog when they are created. Readers added subsequently
0452:             * will not be available. For this reason, it is best to add all
0453:             * of the readers before the first call to parse a catalog.</p>
0454:             *
0455:             * @param mimeType The MIME type associated with this reader.
0456:             * @param reader The CatalogReader to use.
0457:             */
0458:            public void addReader(String mimeType, CatalogReader reader) {
0459:                if (readerMap.containsKey(mimeType)) {
0460:                    Integer pos = (Integer) readerMap.get(mimeType);
0461:                    readerArr.set(pos.intValue(), reader);
0462:                } else {
0463:                    readerArr.add(reader);
0464:                    Integer pos = new Integer(readerArr.size() - 1);
0465:                    readerMap.put(mimeType, pos);
0466:                }
0467:            }
0468:
0469:            /**
0470:             * Copies the reader list from the current Catalog to a new Catalog.
0471:             *
0472:             * <p>This method is used internally when constructing a new catalog.
0473:             * It copies the current reader associations over to the new catalog.
0474:             * </p>
0475:             *
0476:             * @param newCatalog The new Catalog.
0477:             */
0478:            protected void copyReaders(Catalog newCatalog) {
0479:                // Have to copy the readers in the right order...convert hash to arr
0480:                Vector mapArr = new Vector(readerMap.size());
0481:
0482:                // Pad the mapArr out to the right length
0483:                for (int count = 0; count < readerMap.size(); count++) {
0484:                    mapArr.add(null);
0485:                }
0486:
0487:                Enumeration en = readerMap.keys();
0488:                while (en.hasMoreElements()) {
0489:                    String mimeType = (String) en.nextElement();
0490:                    Integer pos = (Integer) readerMap.get(mimeType);
0491:                    mapArr.set(pos.intValue(), mimeType);
0492:                }
0493:
0494:                for (int count = 0; count < mapArr.size(); count++) {
0495:                    String mimeType = (String) mapArr.get(count);
0496:                    Integer pos = (Integer) readerMap.get(mimeType);
0497:                    newCatalog.addReader(mimeType, (CatalogReader) readerArr
0498:                            .get(pos.intValue()));
0499:                }
0500:            }
0501:
0502:            /**
0503:             * Create a new Catalog object.
0504:             *
0505:             * <p>This method constructs a new instance of the running Catalog
0506:             * class (which might be a subtype of com.sun.org.apache.xml.internal.resolver.Catalog).
0507:             * All new catalogs are managed by the same CatalogManager.
0508:             * </p>
0509:             *
0510:             * <p>N.B. All Catalog subtypes should call newCatalog() to construct
0511:             * a new Catalog. Do not simply use "new Subclass()" since that will
0512:             * confuse future subclasses.</p>
0513:             */
0514:            protected Catalog newCatalog() {
0515:                String catalogClass = this .getClass().getName();
0516:
0517:                try {
0518:                    Catalog c = (Catalog) (Class.forName(catalogClass)
0519:                            .newInstance());
0520:                    c.setCatalogManager(catalogManager);
0521:                    copyReaders(c);
0522:                    return c;
0523:                } catch (ClassNotFoundException cnfe) {
0524:                    catalogManager.debug.message(1,
0525:                            "Class Not Found Exception: " + catalogClass);
0526:                } catch (IllegalAccessException iae) {
0527:                    catalogManager.debug.message(1,
0528:                            "Illegal Access Exception: " + catalogClass);
0529:                } catch (InstantiationException ie) {
0530:                    catalogManager.debug.message(1, "Instantiation Exception: "
0531:                            + catalogClass);
0532:                } catch (ClassCastException cce) {
0533:                    catalogManager.debug.message(1, "Class Cast Exception: "
0534:                            + catalogClass);
0535:                } catch (Exception e) {
0536:                    catalogManager.debug.message(1, "Other Exception: "
0537:                            + catalogClass);
0538:                }
0539:
0540:                Catalog c = new Catalog();
0541:                c.setCatalogManager(catalogManager);
0542:                copyReaders(c);
0543:                return c;
0544:            }
0545:
0546:            /**
0547:             * Returns the current base URI.
0548:             */
0549:            public String getCurrentBase() {
0550:                return base.toString();
0551:            }
0552:
0553:            /**
0554:             * Returns the default override setting associated with this
0555:             * catalog.
0556:             *
0557:             * <p>All catalog files loaded by this catalog will have the
0558:             * initial override setting specified by this default.</p>
0559:             */
0560:            public String getDefaultOverride() {
0561:                if (default_override) {
0562:                    return "yes";
0563:                } else {
0564:                    return "no";
0565:                }
0566:            }
0567:
0568:            /**
0569:             * Load the system catalog files.
0570:             *
0571:             * <p>The method adds all of the
0572:             * catalogs specified in the <tt>xml.catalog.files</tt> property
0573:             * to the Catalog list.</p>
0574:             *
0575:             * @throws MalformedURLException  One of the system catalogs is
0576:             * identified with a filename that is not a valid URL.
0577:             * @throws IOException One of the system catalogs cannot be read.
0578:             */
0579:            public void loadSystemCatalogs() throws MalformedURLException,
0580:                    IOException {
0581:
0582:                Vector catalogs = catalogManager.getCatalogFiles();
0583:                if (catalogs != null) {
0584:                    for (int count = 0; count < catalogs.size(); count++) {
0585:                        catalogFiles.addElement(catalogs.elementAt(count));
0586:                    }
0587:                }
0588:
0589:                if (catalogFiles.size() > 0) {
0590:                    // This is a little odd. The parseCatalog() method expects
0591:                    // a filename, but it adds that name to the end of the
0592:                    // catalogFiles vector, and then processes that vector.
0593:                    // This allows the system to handle CATALOG entries
0594:                    // correctly.
0595:                    //
0596:                    // In this init case, we take the last element off the
0597:                    // catalogFiles vector and pass it to parseCatalog. This
0598:                    // will "do the right thing" in the init case, and allow
0599:                    // parseCatalog() to do the right thing in the non-init
0600:                    // case. Honest.
0601:                    //
0602:                    String catfile = (String) catalogFiles.lastElement();
0603:                    catalogFiles.removeElement(catfile);
0604:                    parseCatalog(catfile);
0605:                }
0606:            }
0607:
0608:            /**
0609:             * Parse a catalog file, augmenting internal data structures.
0610:             *
0611:             * @param fileName The filename of the catalog file to process
0612:             *
0613:             * @throws MalformedURLException The fileName cannot be turned into
0614:             * a valid URL.
0615:             * @throws IOException Error reading catalog file.
0616:             */
0617:            public synchronized void parseCatalog(String fileName)
0618:                    throws MalformedURLException, IOException {
0619:
0620:                default_override = catalogManager.getPreferPublic();
0621:                catalogManager.debug.message(4, "Parse catalog: " + fileName);
0622:
0623:                // Put the file into the list of catalogs to process...
0624:                // In all cases except the case when initCatalog() is the
0625:                // caller, this will be the only catalog initially in the list...
0626:                catalogFiles.addElement(fileName);
0627:
0628:                // Now process all the pending catalogs...
0629:                parsePendingCatalogs();
0630:            }
0631:
0632:            /**
0633:             * Parse a catalog file, augmenting internal data structures.
0634:             *
0635:             * <p>Catalogs retrieved over the net may have an associated MIME type.
0636:             * The MIME type can be used to select an appropriate reader.</p>
0637:             *
0638:             * @param mimeType The MIME type of the catalog file.
0639:             * @param is The InputStream from which the catalog should be read
0640:             *
0641:             * @throws CatalogException Failed to load catalog
0642:             * mimeType.
0643:             * @throws IOException Error reading catalog file.
0644:             */
0645:            public synchronized void parseCatalog(String mimeType,
0646:                    InputStream is) throws IOException, CatalogException {
0647:
0648:                default_override = catalogManager.getPreferPublic();
0649:                catalogManager.debug.message(4, "Parse " + mimeType
0650:                        + " catalog on input stream");
0651:
0652:                CatalogReader reader = null;
0653:
0654:                if (readerMap.containsKey(mimeType)) {
0655:                    int arrayPos = ((Integer) readerMap.get(mimeType))
0656:                            .intValue();
0657:                    reader = (CatalogReader) readerArr.get(arrayPos);
0658:                }
0659:
0660:                if (reader == null) {
0661:                    String msg = "No CatalogReader for MIME type: " + mimeType;
0662:                    catalogManager.debug.message(2, msg);
0663:                    throw new CatalogException(CatalogException.UNPARSEABLE,
0664:                            msg);
0665:                }
0666:
0667:                reader.readCatalog(this , is);
0668:
0669:                // Now process all the pending catalogs...
0670:                parsePendingCatalogs();
0671:            }
0672:
0673:            /**
0674:             * Parse a catalog document, augmenting internal data structures.
0675:             *
0676:             * <p>This method supports catalog files stored in jar files: e.g.,
0677:             * jar:file:///path/to/filename.jar!/path/to/catalog.xml". That URI
0678:             * doesn't survive transmogrification through the URI processing that
0679:             * the parseCatalog(String) performs and passing it as an input stream
0680:             * doesn't set the base URI appropriately.</p>
0681:             *
0682:             * <p>Written by Stefan Wachter (2002-09-26)</p>
0683:             *
0684:             * @param aUrl The URL of the catalog document to process
0685:             *
0686:             * @throws IOException Error reading catalog file.
0687:             */
0688:            public synchronized void parseCatalog(URL aUrl) throws IOException {
0689:                catalogCwd = aUrl;
0690:                base = aUrl;
0691:
0692:                default_override = catalogManager.getPreferPublic();
0693:                catalogManager.debug.message(4, "Parse catalog: "
0694:                        + aUrl.toString());
0695:
0696:                DataInputStream inStream = null;
0697:                boolean parsed = false;
0698:
0699:                for (int count = 0; !parsed && count < readerArr.size(); count++) {
0700:                    CatalogReader reader = (CatalogReader) readerArr.get(count);
0701:
0702:                    try {
0703:                        inStream = new DataInputStream(aUrl.openStream());
0704:                    } catch (FileNotFoundException fnfe) {
0705:                        // No catalog; give up!
0706:                        break;
0707:                    }
0708:
0709:                    try {
0710:                        reader.readCatalog(this , inStream);
0711:                        parsed = true;
0712:                    } catch (CatalogException ce) {
0713:                        if (ce.getExceptionType() == CatalogException.PARSE_FAILED) {
0714:                            // give up!
0715:                            break;
0716:                        } else {
0717:                            // try again!
0718:                        }
0719:                    }
0720:
0721:                    try {
0722:                        inStream.close();
0723:                    } catch (IOException e) {
0724:                        //nop
0725:                    }
0726:                }
0727:
0728:                if (parsed)
0729:                    parsePendingCatalogs();
0730:            }
0731:
0732:            /**
0733:             * Parse all of the pending catalogs.
0734:             *
0735:             * <p>Catalogs may refer to other catalogs, this method parses
0736:             * all of the currently pending catalog files.</p>
0737:             */
0738:            protected synchronized void parsePendingCatalogs()
0739:                    throws MalformedURLException, IOException {
0740:
0741:                if (!localCatalogFiles.isEmpty()) {
0742:                    // Move all the localCatalogFiles into the front of
0743:                    // the catalogFiles queue
0744:                    Vector newQueue = new Vector();
0745:                    Enumeration q = localCatalogFiles.elements();
0746:                    while (q.hasMoreElements()) {
0747:                        newQueue.addElement(q.nextElement());
0748:                    }
0749:
0750:                    // Put the rest of the catalogs on the end of the new list
0751:                    for (int curCat = 0; curCat < catalogFiles.size(); curCat++) {
0752:                        String catfile = (String) catalogFiles
0753:                                .elementAt(curCat);
0754:                        newQueue.addElement(catfile);
0755:                    }
0756:
0757:                    catalogFiles = newQueue;
0758:                    localCatalogFiles.clear();
0759:                }
0760:
0761:                // Suppose there are no catalog files to process, but the
0762:                // single catalog already parsed included some delegate
0763:                // entries? Make sure they don't get lost.
0764:                if (catalogFiles.isEmpty() && !localDelegate.isEmpty()) {
0765:                    Enumeration e = localDelegate.elements();
0766:                    while (e.hasMoreElements()) {
0767:                        catalogEntries.addElement(e.nextElement());
0768:                    }
0769:                    localDelegate.clear();
0770:                }
0771:
0772:                // Now process all the files on the catalogFiles vector. This
0773:                // vector can grow during processing if CATALOG entries are
0774:                // encountered in the catalog
0775:                while (!catalogFiles.isEmpty()) {
0776:                    String catfile = (String) catalogFiles.elementAt(0);
0777:                    try {
0778:                        catalogFiles.remove(0);
0779:                    } catch (ArrayIndexOutOfBoundsException e) {
0780:                        // can't happen
0781:                    }
0782:
0783:                    if (catalogEntries.size() == 0 && catalogs.size() == 0) {
0784:                        // We haven't parsed any catalogs yet, let this
0785:                        // catalog be the first...
0786:                        try {
0787:                            parseCatalogFile(catfile);
0788:                        } catch (CatalogException ce) {
0789:                            System.out.println("FIXME: " + ce.toString());
0790:                        }
0791:                    } else {
0792:                        // This is a subordinate catalog. We save its name,
0793:                        // but don't bother to load it unless it's necessary.
0794:                        catalogs.addElement(catfile);
0795:                    }
0796:
0797:                    if (!localCatalogFiles.isEmpty()) {
0798:                        // Move all the localCatalogFiles into the front of
0799:                        // the catalogFiles queue
0800:                        Vector newQueue = new Vector();
0801:                        Enumeration q = localCatalogFiles.elements();
0802:                        while (q.hasMoreElements()) {
0803:                            newQueue.addElement(q.nextElement());
0804:                        }
0805:
0806:                        // Put the rest of the catalogs on the end of the new list
0807:                        for (int curCat = 0; curCat < catalogFiles.size(); curCat++) {
0808:                            catfile = (String) catalogFiles.elementAt(curCat);
0809:                            newQueue.addElement(catfile);
0810:                        }
0811:
0812:                        catalogFiles = newQueue;
0813:                        localCatalogFiles.clear();
0814:                    }
0815:
0816:                    if (!localDelegate.isEmpty()) {
0817:                        Enumeration e = localDelegate.elements();
0818:                        while (e.hasMoreElements()) {
0819:                            catalogEntries.addElement(e.nextElement());
0820:                        }
0821:                        localDelegate.clear();
0822:                    }
0823:                }
0824:
0825:                // We've parsed them all, reinit the vector...
0826:                catalogFiles.clear();
0827:            }
0828:
0829:            /**
0830:             * Parse a single catalog file, augmenting internal data structures.
0831:             *
0832:             * @param fileName The filename of the catalog file to process
0833:             *
0834:             * @throws MalformedURLException The fileName cannot be turned into
0835:             * a valid URL.
0836:             * @throws IOException Error reading catalog file.
0837:             */
0838:            protected synchronized void parseCatalogFile(String fileName)
0839:                    throws MalformedURLException, IOException, CatalogException {
0840:
0841:                CatalogEntry entry;
0842:
0843:                // The base-base is the cwd. If the catalog file is specified
0844:                // with a relative path, this assures that it gets resolved
0845:                // properly...
0846:                try {
0847:                    // tack on a basename because URLs point to files not dirs
0848:                    catalogCwd = FileURL.makeURL("basename");
0849:                } catch (MalformedURLException e) {
0850:                    String userdir = System.getProperty("user.dir");
0851:                    userdir.replace('\\', '/');
0852:                    catalogManager.debug.message(1, "Malformed URL on cwd",
0853:                            userdir);
0854:                    catalogCwd = null;
0855:                }
0856:
0857:                // The initial base URI is the location of the catalog file
0858:                try {
0859:                    base = new URL(catalogCwd, fixSlashes(fileName));
0860:                } catch (MalformedURLException e) {
0861:                    try {
0862:                        base = new URL("file:" + fixSlashes(fileName));
0863:                    } catch (MalformedURLException e2) {
0864:                        catalogManager.debug.message(1,
0865:                                "Malformed URL on catalog filename",
0866:                                fixSlashes(fileName));
0867:                        base = null;
0868:                    }
0869:                }
0870:
0871:                catalogManager.debug.message(2, "Loading catalog", fileName);
0872:                catalogManager.debug
0873:                        .message(4, "Default BASE", base.toString());
0874:
0875:                fileName = base.toString();
0876:
0877:                DataInputStream inStream = null;
0878:                boolean parsed = false;
0879:                boolean notFound = false;
0880:
0881:                for (int count = 0; !parsed && count < readerArr.size(); count++) {
0882:                    CatalogReader reader = (CatalogReader) readerArr.get(count);
0883:
0884:                    try {
0885:                        notFound = false;
0886:                        inStream = new DataInputStream(base.openStream());
0887:                    } catch (FileNotFoundException fnfe) {
0888:                        // No catalog; give up!
0889:                        notFound = true;
0890:                        break;
0891:                    }
0892:
0893:                    try {
0894:                        reader.readCatalog(this , inStream);
0895:                        parsed = true;
0896:                    } catch (CatalogException ce) {
0897:                        if (ce.getExceptionType() == CatalogException.PARSE_FAILED) {
0898:                            // give up!
0899:                            break;
0900:                        } else {
0901:                            // try again!
0902:                        }
0903:                    }
0904:
0905:                    try {
0906:                        inStream.close();
0907:                    } catch (IOException e) {
0908:                        //nop
0909:                    }
0910:                }
0911:
0912:                if (!parsed) {
0913:                    if (notFound) {
0914:                        catalogManager.debug.message(3,
0915:                                "Catalog does not exist", fileName);
0916:                    } else {
0917:                        catalogManager.debug.message(1,
0918:                                "Failed to parse catalog", fileName);
0919:                    }
0920:                }
0921:            }
0922:
0923:            /**
0924:             * Cleanup and process a Catalog entry.
0925:             *
0926:             * <p>This method processes each Catalog entry, changing mapped
0927:             * relative system identifiers into absolute ones (based on the current
0928:             * base URI), and maintaining other information about the current
0929:             * catalog.</p>
0930:             *
0931:             * @param entry The CatalogEntry to process.
0932:             */
0933:            public void addEntry(CatalogEntry entry) {
0934:                int type = entry.getEntryType();
0935:
0936:                if (type == BASE) {
0937:                    String value = entry.getEntryArg(0);
0938:                    URL newbase = null;
0939:
0940:                    if (base == null) {
0941:                        catalogManager.debug.message(5, "BASE CUR", "null");
0942:                    } else {
0943:                        catalogManager.debug.message(5, "BASE CUR", base
0944:                                .toString());
0945:                    }
0946:                    catalogManager.debug.message(4, "BASE STR", value);
0947:
0948:                    try {
0949:                        value = fixSlashes(value);
0950:                        newbase = new URL(base, value);
0951:                    } catch (MalformedURLException e) {
0952:                        try {
0953:                            newbase = new URL("file:" + value);
0954:                        } catch (MalformedURLException e2) {
0955:                            catalogManager.debug.message(1,
0956:                                    "Malformed URL on base", value);
0957:                            newbase = null;
0958:                        }
0959:                    }
0960:
0961:                    if (newbase != null) {
0962:                        base = newbase;
0963:                    }
0964:
0965:                    catalogManager.debug
0966:                            .message(5, "BASE NEW", base.toString());
0967:                } else if (type == CATALOG) {
0968:                    String fsi = makeAbsolute(entry.getEntryArg(0));
0969:
0970:                    catalogManager.debug.message(4, "CATALOG", fsi);
0971:
0972:                    localCatalogFiles.addElement(fsi);
0973:                } else if (type == PUBLIC) {
0974:                    String publicid = PublicId.normalize(entry.getEntryArg(0));
0975:                    String systemid = makeAbsolute(normalizeURI(entry
0976:                            .getEntryArg(1)));
0977:
0978:                    entry.setEntryArg(0, publicid);
0979:                    entry.setEntryArg(1, systemid);
0980:
0981:                    catalogManager.debug.message(4, "PUBLIC", publicid,
0982:                            systemid);
0983:
0984:                    catalogEntries.addElement(entry);
0985:                } else if (type == SYSTEM) {
0986:                    String systemid = normalizeURI(entry.getEntryArg(0));
0987:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
0988:
0989:                    entry.setEntryArg(1, fsi);
0990:
0991:                    catalogManager.debug.message(4, "SYSTEM", systemid, fsi);
0992:
0993:                    catalogEntries.addElement(entry);
0994:                } else if (type == URI) {
0995:                    String uri = normalizeURI(entry.getEntryArg(0));
0996:                    String altURI = makeAbsolute(normalizeURI(entry
0997:                            .getEntryArg(1)));
0998:
0999:                    entry.setEntryArg(1, altURI);
1000:
1001:                    catalogManager.debug.message(4, "URI", uri, altURI);
1002:
1003:                    catalogEntries.addElement(entry);
1004:                } else if (type == DOCUMENT) {
1005:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(0)));
1006:                    entry.setEntryArg(0, fsi);
1007:
1008:                    catalogManager.debug.message(4, "DOCUMENT", fsi);
1009:
1010:                    catalogEntries.addElement(entry);
1011:                } else if (type == OVERRIDE) {
1012:                    catalogManager.debug.message(4, "OVERRIDE", entry
1013:                            .getEntryArg(0));
1014:
1015:                    catalogEntries.addElement(entry);
1016:                } else if (type == SGMLDECL) {
1017:                    // meaningless in XML
1018:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(0)));
1019:                    entry.setEntryArg(0, fsi);
1020:
1021:                    catalogManager.debug.message(4, "SGMLDECL", fsi);
1022:
1023:                    catalogEntries.addElement(entry);
1024:                } else if (type == DELEGATE_PUBLIC) {
1025:                    String ppi = PublicId.normalize(entry.getEntryArg(0));
1026:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1027:
1028:                    entry.setEntryArg(0, ppi);
1029:                    entry.setEntryArg(1, fsi);
1030:
1031:                    catalogManager.debug
1032:                            .message(4, "DELEGATE_PUBLIC", ppi, fsi);
1033:
1034:                    addDelegate(entry);
1035:                } else if (type == DELEGATE_SYSTEM) {
1036:                    String psi = normalizeURI(entry.getEntryArg(0));
1037:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1038:
1039:                    entry.setEntryArg(0, psi);
1040:                    entry.setEntryArg(1, fsi);
1041:
1042:                    catalogManager.debug
1043:                            .message(4, "DELEGATE_SYSTEM", psi, fsi);
1044:
1045:                    addDelegate(entry);
1046:                } else if (type == DELEGATE_URI) {
1047:                    String pui = normalizeURI(entry.getEntryArg(0));
1048:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1049:
1050:                    entry.setEntryArg(0, pui);
1051:                    entry.setEntryArg(1, fsi);
1052:
1053:                    catalogManager.debug.message(4, "DELEGATE_URI", pui, fsi);
1054:
1055:                    addDelegate(entry);
1056:                } else if (type == REWRITE_SYSTEM) {
1057:                    String psi = normalizeURI(entry.getEntryArg(0));
1058:                    String rpx = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1059:
1060:                    entry.setEntryArg(0, psi);
1061:                    entry.setEntryArg(1, rpx);
1062:
1063:                    catalogManager.debug.message(4, "REWRITE_SYSTEM", psi, rpx);
1064:
1065:                    catalogEntries.addElement(entry);
1066:                } else if (type == REWRITE_URI) {
1067:                    String pui = normalizeURI(entry.getEntryArg(0));
1068:                    String upx = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1069:
1070:                    entry.setEntryArg(0, pui);
1071:                    entry.setEntryArg(1, upx);
1072:
1073:                    catalogManager.debug.message(4, "REWRITE_URI", pui, upx);
1074:
1075:                    catalogEntries.addElement(entry);
1076:                } else if (type == SYSTEM_SUFFIX) {
1077:                    String pui = normalizeURI(entry.getEntryArg(0));
1078:                    String upx = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1079:
1080:                    entry.setEntryArg(0, pui);
1081:                    entry.setEntryArg(1, upx);
1082:
1083:                    catalogManager.debug.message(4, "SYSTEM_SUFFIX", pui, upx);
1084:
1085:                    catalogEntries.addElement(entry);
1086:                } else if (type == URI_SUFFIX) {
1087:                    String pui = normalizeURI(entry.getEntryArg(0));
1088:                    String upx = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1089:
1090:                    entry.setEntryArg(0, pui);
1091:                    entry.setEntryArg(1, upx);
1092:
1093:                    catalogManager.debug.message(4, "URI_SUFFIX", pui, upx);
1094:
1095:                    catalogEntries.addElement(entry);
1096:                } else if (type == DOCTYPE) {
1097:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1098:                    entry.setEntryArg(1, fsi);
1099:
1100:                    catalogManager.debug.message(4, "DOCTYPE", entry
1101:                            .getEntryArg(0), fsi);
1102:
1103:                    catalogEntries.addElement(entry);
1104:                } else if (type == DTDDECL) {
1105:                    // meaningless in XML
1106:                    String fpi = PublicId.normalize(entry.getEntryArg(0));
1107:                    entry.setEntryArg(0, fpi);
1108:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1109:                    entry.setEntryArg(1, fsi);
1110:
1111:                    catalogManager.debug.message(4, "DTDDECL", fpi, fsi);
1112:
1113:                    catalogEntries.addElement(entry);
1114:                } else if (type == ENTITY) {
1115:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1116:                    entry.setEntryArg(1, fsi);
1117:
1118:                    catalogManager.debug.message(4, "ENTITY", entry
1119:                            .getEntryArg(0), fsi);
1120:
1121:                    catalogEntries.addElement(entry);
1122:                } else if (type == LINKTYPE) {
1123:                    // meaningless in XML
1124:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1125:                    entry.setEntryArg(1, fsi);
1126:
1127:                    catalogManager.debug.message(4, "LINKTYPE", entry
1128:                            .getEntryArg(0), fsi);
1129:
1130:                    catalogEntries.addElement(entry);
1131:                } else if (type == NOTATION) {
1132:                    String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
1133:                    entry.setEntryArg(1, fsi);
1134:
1135:                    catalogManager.debug.message(4, "NOTATION", entry
1136:                            .getEntryArg(0), fsi);
1137:
1138:                    catalogEntries.addElement(entry);
1139:                } else {
1140:                    catalogEntries.addElement(entry);
1141:                }
1142:            }
1143:
1144:            /**
1145:             * Handle unknown CatalogEntry types.
1146:             *
1147:             * <p>This method exists to allow subclasses to deal with unknown
1148:             * entry types.</p>
1149:             */
1150:            public void unknownEntry(Vector strings) {
1151:                if (strings != null && strings.size() > 0) {
1152:                    String keyword = (String) strings.elementAt(0);
1153:                    catalogManager.debug.message(2,
1154:                            "Unrecognized token parsing catalog", keyword);
1155:                }
1156:            }
1157:
1158:            /**
1159:             * Parse all subordinate catalogs.
1160:             *
1161:             * <p>This method recursively parses all of the subordinate catalogs.
1162:             * If this method does not throw an exception, you can be confident that
1163:             * no subsequent call to any resolve*() method will either, with two
1164:             * possible exceptions:</p>
1165:             *
1166:             * <ol>
1167:             * <li><p>Delegated catalogs are re-parsed each time they are needed
1168:             * (because a variable list of them may be needed in each case,
1169:             * depending on the length of the matching partial public identifier).</p>
1170:             * <p>But they are parsed by this method, so as long as they don't
1171:             * change or disappear while the program is running, they shouldn't
1172:             * generate errors later if they don't generate errors now.</p>
1173:             * <li><p>If you add new catalogs with <code>parseCatalog</code>, they
1174:             * won't be loaded until they are needed or until you call
1175:             * <code>parseAllCatalogs</code> again.</p>
1176:             * </ol>
1177:             *
1178:             * <p>On the other hand, if you don't call this method, you may
1179:             * successfully parse documents without having to load all possible
1180:             * catalogs.</p>
1181:             *
1182:             * @throws MalformedURLException The filename (URL) for a
1183:             * subordinate or delegated catalog is not a valid URL.
1184:             * @throws IOException Error reading some subordinate or delegated
1185:             * catalog file.
1186:             */
1187:            public void parseAllCatalogs() throws MalformedURLException,
1188:                    IOException {
1189:
1190:                // Parse all the subordinate catalogs
1191:                for (int catPos = 0; catPos < catalogs.size(); catPos++) {
1192:                    Catalog c = null;
1193:
1194:                    try {
1195:                        c = (Catalog) catalogs.elementAt(catPos);
1196:                    } catch (ClassCastException e) {
1197:                        String catfile = (String) catalogs.elementAt(catPos);
1198:                        c = newCatalog();
1199:
1200:                        c.parseCatalog(catfile);
1201:                        catalogs.setElementAt(c, catPos);
1202:                        c.parseAllCatalogs();
1203:                    }
1204:                }
1205:
1206:                // Parse all the DELEGATE catalogs
1207:                Enumeration en = catalogEntries.elements();
1208:                while (en.hasMoreElements()) {
1209:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1210:                    if (e.getEntryType() == DELEGATE_PUBLIC
1211:                            || e.getEntryType() == DELEGATE_SYSTEM
1212:                            || e.getEntryType() == DELEGATE_URI) {
1213:                        Catalog dcat = newCatalog();
1214:                        dcat.parseCatalog(e.getEntryArg(1));
1215:                    }
1216:                }
1217:            }
1218:
1219:            /**
1220:             * Return the applicable DOCTYPE system identifier.
1221:             *
1222:             * @param entityName The name of the entity (element) for which
1223:             * a doctype is required.
1224:             * @param publicId The nominal public identifier for the doctype
1225:             * (as provided in the source document).
1226:             * @param systemId The nominal system identifier for the doctype
1227:             * (as provided in the source document).
1228:             *
1229:             * @return The system identifier to use for the doctype.
1230:             *
1231:             * @throws MalformedURLException The formal system identifier of a
1232:             * subordinate catalog cannot be turned into a valid URL.
1233:             * @throws IOException Error reading subordinate catalog file.
1234:             */
1235:            public String resolveDoctype(String entityName, String publicId,
1236:                    String systemId) throws MalformedURLException, IOException {
1237:                String resolved = null;
1238:
1239:                catalogManager.debug.message(3, "resolveDoctype(" + entityName
1240:                        + "," + publicId + "," + systemId + ")");
1241:
1242:                systemId = normalizeURI(systemId);
1243:
1244:                if (publicId != null && publicId.startsWith("urn:publicid:")) {
1245:                    publicId = PublicId.decodeURN(publicId);
1246:                }
1247:
1248:                if (systemId != null && systemId.startsWith("urn:publicid:")) {
1249:                    systemId = PublicId.decodeURN(systemId);
1250:                    if (publicId != null && !publicId.equals(systemId)) {
1251:                        catalogManager.debug
1252:                                .message(
1253:                                        1,
1254:                                        "urn:publicid: system identifier differs from public identifier; using public identifier");
1255:                        systemId = null;
1256:                    } else {
1257:                        publicId = systemId;
1258:                        systemId = null;
1259:                    }
1260:                }
1261:
1262:                if (systemId != null) {
1263:                    // If there's a SYSTEM entry in this catalog, use it
1264:                    resolved = resolveLocalSystem(systemId);
1265:                    if (resolved != null) {
1266:                        return resolved;
1267:                    }
1268:                }
1269:
1270:                if (publicId != null) {
1271:                    // If there's a PUBLIC entry in this catalog, use it
1272:                    resolved = resolveLocalPublic(DOCTYPE, entityName,
1273:                            publicId, systemId);
1274:                    if (resolved != null) {
1275:                        return resolved;
1276:                    }
1277:                }
1278:
1279:                // If there's a DOCTYPE entry in this catalog, use it
1280:                boolean over = default_override;
1281:                Enumeration en = catalogEntries.elements();
1282:                while (en.hasMoreElements()) {
1283:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1284:                    if (e.getEntryType() == OVERRIDE) {
1285:                        over = e.getEntryArg(0).equalsIgnoreCase("YES");
1286:                        continue;
1287:                    }
1288:
1289:                    if (e.getEntryType() == DOCTYPE
1290:                            && e.getEntryArg(0).equals(entityName)) {
1291:                        if (over || systemId == null) {
1292:                            return e.getEntryArg(1);
1293:                        }
1294:                    }
1295:                }
1296:
1297:                // Otherwise, look in the subordinate catalogs
1298:                return resolveSubordinateCatalogs(DOCTYPE, entityName,
1299:                        publicId, systemId);
1300:            }
1301:
1302:            /**
1303:             * Return the applicable DOCUMENT entry.
1304:             *
1305:             * @return The system identifier to use for the doctype.
1306:             *
1307:             * @throws MalformedURLException The formal system identifier of a
1308:             * subordinate catalog cannot be turned into a valid URL.
1309:             * @throws IOException Error reading subordinate catalog file.
1310:             */
1311:            public String resolveDocument() throws MalformedURLException,
1312:                    IOException {
1313:                // If there's a DOCUMENT entry, return it
1314:
1315:                catalogManager.debug.message(3, "resolveDocument");
1316:
1317:                Enumeration en = catalogEntries.elements();
1318:                while (en.hasMoreElements()) {
1319:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1320:                    if (e.getEntryType() == DOCUMENT) {
1321:                        return e.getEntryArg(0);
1322:                    }
1323:                }
1324:
1325:                return resolveSubordinateCatalogs(DOCUMENT, null, null, null);
1326:            }
1327:
1328:            /**
1329:             * Return the applicable ENTITY system identifier.
1330:             *
1331:             * @param entityName The name of the entity for which
1332:             * a system identifier is required.
1333:             * @param publicId The nominal public identifier for the entity
1334:             * (as provided in the source document).
1335:             * @param systemId The nominal system identifier for the entity
1336:             * (as provided in the source document).
1337:             *
1338:             * @return The system identifier to use for the entity.
1339:             *
1340:             * @throws MalformedURLException The formal system identifier of a
1341:             * subordinate catalog cannot be turned into a valid URL.
1342:             * @throws IOException Error reading subordinate catalog file.
1343:             */
1344:            public String resolveEntity(String entityName, String publicId,
1345:                    String systemId) throws MalformedURLException, IOException {
1346:                String resolved = null;
1347:
1348:                catalogManager.debug.message(3, "resolveEntity(" + entityName
1349:                        + "," + publicId + "," + systemId + ")");
1350:
1351:                systemId = normalizeURI(systemId);
1352:
1353:                if (publicId != null && publicId.startsWith("urn:publicid:")) {
1354:                    publicId = PublicId.decodeURN(publicId);
1355:                }
1356:
1357:                if (systemId != null && systemId.startsWith("urn:publicid:")) {
1358:                    systemId = PublicId.decodeURN(systemId);
1359:                    if (publicId != null && !publicId.equals(systemId)) {
1360:                        catalogManager.debug
1361:                                .message(
1362:                                        1,
1363:                                        "urn:publicid: system identifier differs from public identifier; using public identifier");
1364:                        systemId = null;
1365:                    } else {
1366:                        publicId = systemId;
1367:                        systemId = null;
1368:                    }
1369:                }
1370:
1371:                if (systemId != null) {
1372:                    // If there's a SYSTEM entry in this catalog, use it
1373:                    resolved = resolveLocalSystem(systemId);
1374:                    if (resolved != null) {
1375:                        return resolved;
1376:                    }
1377:                }
1378:
1379:                if (publicId != null) {
1380:                    // If there's a PUBLIC entry in this catalog, use it
1381:                    resolved = resolveLocalPublic(ENTITY, entityName, publicId,
1382:                            systemId);
1383:                    if (resolved != null) {
1384:                        return resolved;
1385:                    }
1386:                }
1387:
1388:                // If there's a ENTITY entry in this catalog, use it
1389:                boolean over = default_override;
1390:                Enumeration en = catalogEntries.elements();
1391:                while (en.hasMoreElements()) {
1392:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1393:                    if (e.getEntryType() == OVERRIDE) {
1394:                        over = e.getEntryArg(0).equalsIgnoreCase("YES");
1395:                        continue;
1396:                    }
1397:
1398:                    if (e.getEntryType() == ENTITY
1399:                            && e.getEntryArg(0).equals(entityName)) {
1400:                        if (over || systemId == null) {
1401:                            return e.getEntryArg(1);
1402:                        }
1403:                    }
1404:                }
1405:
1406:                // Otherwise, look in the subordinate catalogs
1407:                return resolveSubordinateCatalogs(ENTITY, entityName, publicId,
1408:                        systemId);
1409:            }
1410:
1411:            /**
1412:             * Return the applicable NOTATION system identifier.
1413:             *
1414:             * @param notationName The name of the notation for which
1415:             * a doctype is required.
1416:             * @param publicId The nominal public identifier for the notation
1417:             * (as provided in the source document).
1418:             * @param systemId The nominal system identifier for the notation
1419:             * (as provided in the source document).
1420:             *
1421:             * @return The system identifier to use for the notation.
1422:             *
1423:             * @throws MalformedURLException The formal system identifier of a
1424:             * subordinate catalog cannot be turned into a valid URL.
1425:             * @throws IOException Error reading subordinate catalog file.
1426:             */
1427:            public String resolveNotation(String notationName, String publicId,
1428:                    String systemId) throws MalformedURLException, IOException {
1429:                String resolved = null;
1430:
1431:                catalogManager.debug.message(3, "resolveNotation("
1432:                        + notationName + "," + publicId + "," + systemId + ")");
1433:
1434:                systemId = normalizeURI(systemId);
1435:
1436:                if (publicId != null && publicId.startsWith("urn:publicid:")) {
1437:                    publicId = PublicId.decodeURN(publicId);
1438:                }
1439:
1440:                if (systemId != null && systemId.startsWith("urn:publicid:")) {
1441:                    systemId = PublicId.decodeURN(systemId);
1442:                    if (publicId != null && !publicId.equals(systemId)) {
1443:                        catalogManager.debug
1444:                                .message(
1445:                                        1,
1446:                                        "urn:publicid: system identifier differs from public identifier; using public identifier");
1447:                        systemId = null;
1448:                    } else {
1449:                        publicId = systemId;
1450:                        systemId = null;
1451:                    }
1452:                }
1453:
1454:                if (systemId != null) {
1455:                    // If there's a SYSTEM entry in this catalog, use it
1456:                    resolved = resolveLocalSystem(systemId);
1457:                    if (resolved != null) {
1458:                        return resolved;
1459:                    }
1460:                }
1461:
1462:                if (publicId != null) {
1463:                    // If there's a PUBLIC entry in this catalog, use it
1464:                    resolved = resolveLocalPublic(NOTATION, notationName,
1465:                            publicId, systemId);
1466:                    if (resolved != null) {
1467:                        return resolved;
1468:                    }
1469:                }
1470:
1471:                // If there's a NOTATION entry in this catalog, use it
1472:                boolean over = default_override;
1473:                Enumeration en = catalogEntries.elements();
1474:                while (en.hasMoreElements()) {
1475:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1476:                    if (e.getEntryType() == OVERRIDE) {
1477:                        over = e.getEntryArg(0).equalsIgnoreCase("YES");
1478:                        continue;
1479:                    }
1480:
1481:                    if (e.getEntryType() == NOTATION
1482:                            && e.getEntryArg(0).equals(notationName)) {
1483:                        if (over || systemId == null) {
1484:                            return e.getEntryArg(1);
1485:                        }
1486:                    }
1487:                }
1488:
1489:                // Otherwise, look in the subordinate catalogs
1490:                return resolveSubordinateCatalogs(NOTATION, notationName,
1491:                        publicId, systemId);
1492:            }
1493:
1494:            /**
1495:             * Return the applicable PUBLIC or SYSTEM identifier.
1496:             *
1497:             * <p>This method searches the Catalog and returns the system
1498:             * identifier specified for the given system or
1499:             * public identifiers. If
1500:             * no appropriate PUBLIC or SYSTEM entry is found in the Catalog,
1501:             * null is returned.</p>
1502:             *
1503:             * @param publicId The public identifier to locate in the catalog.
1504:             * Public identifiers are normalized before comparison.
1505:             * @param systemId The nominal system identifier for the entity
1506:             * in question (as provided in the source document).
1507:             *
1508:             * @throws MalformedURLException The formal system identifier of a
1509:             * subordinate catalog cannot be turned into a valid URL.
1510:             * @throws IOException Error reading subordinate catalog file.
1511:             *
1512:             * @return The system identifier to use.
1513:             * Note that the nominal system identifier is not returned if a
1514:             * match is not found in the catalog, instead null is returned
1515:             * to indicate that no match was found.
1516:             */
1517:            public String resolvePublic(String publicId, String systemId)
1518:                    throws MalformedURLException, IOException {
1519:
1520:                catalogManager.debug.message(3, "resolvePublic(" + publicId
1521:                        + "," + systemId + ")");
1522:
1523:                systemId = normalizeURI(systemId);
1524:
1525:                if (publicId != null && publicId.startsWith("urn:publicid:")) {
1526:                    publicId = PublicId.decodeURN(publicId);
1527:                }
1528:
1529:                if (systemId != null && systemId.startsWith("urn:publicid:")) {
1530:                    systemId = PublicId.decodeURN(systemId);
1531:                    if (publicId != null && !publicId.equals(systemId)) {
1532:                        catalogManager.debug
1533:                                .message(
1534:                                        1,
1535:                                        "urn:publicid: system identifier differs from public identifier; using public identifier");
1536:                        systemId = null;
1537:                    } else {
1538:                        publicId = systemId;
1539:                        systemId = null;
1540:                    }
1541:                }
1542:
1543:                // If there's a SYSTEM entry in this catalog, use it
1544:                if (systemId != null) {
1545:                    String resolved = resolveLocalSystem(systemId);
1546:                    if (resolved != null) {
1547:                        return resolved;
1548:                    }
1549:                }
1550:
1551:                // If there's a PUBLIC entry in this catalog, use it
1552:                String resolved = resolveLocalPublic(PUBLIC, null, publicId,
1553:                        systemId);
1554:                if (resolved != null) {
1555:                    return resolved;
1556:                }
1557:
1558:                // Otherwise, look in the subordinate catalogs
1559:                return resolveSubordinateCatalogs(PUBLIC, null, publicId,
1560:                        systemId);
1561:            }
1562:
1563:            /**
1564:             * Return the applicable PUBLIC or SYSTEM identifier.
1565:             *
1566:             * <p>This method searches the Catalog and returns the system
1567:             * identifier specified for the given system or public identifiers.
1568:             * If no appropriate PUBLIC or SYSTEM entry is found in the Catalog,
1569:             * delegated Catalogs are interrogated.</p>
1570:             *
1571:             * <p>There are four possible cases:</p>
1572:             *
1573:             * <ul>
1574:             * <li>If the system identifier provided matches a SYSTEM entry
1575:             * in the current catalog, the SYSTEM entry is returned.
1576:             * <li>If the system identifier is not null, the PUBLIC entries
1577:             * that were encountered when OVERRIDE YES was in effect are
1578:             * interrogated and the first matching entry is returned.</li>
1579:             * <li>If the system identifier is null, then all of the PUBLIC
1580:             * entries are interrogated and the first matching entry
1581:             * is returned. This may not be the same as the preceding case, if
1582:             * some PUBLIC entries are encountered when OVERRIDE NO is in effect. In
1583:             * XML, the only place where a public identifier may occur without
1584:             * a system identifier is in a notation declaration.</li>
1585:             * <li>Finally, if the public identifier matches one of the partial
1586:             * public identifiers specified in a DELEGATE* entry in
1587:             * the Catalog, the delegated catalog is interrogated. The first
1588:             * time that the delegated catalog is required, it will be
1589:             * retrieved and parsed. It is subsequently cached.
1590:             * </li>
1591:             * </ul>
1592:             *
1593:             * @param entityType The CatalogEntry type for which this query is
1594:             * being conducted. This is necessary in order to do the approprate
1595:             * query on a delegated catalog.
1596:             * @param entityName The name of the entity being searched for, if
1597:             * appropriate.
1598:             * @param publicId The public identifier of the entity in question.
1599:             * @param systemId The nominal system identifier for the entity
1600:             * in question (as provided in the source document).
1601:             *
1602:             * @throws MalformedURLException The formal system identifier of a
1603:             * delegated catalog cannot be turned into a valid URL.
1604:             * @throws IOException Error reading delegated catalog file.
1605:             *
1606:             * @return The system identifier to use.
1607:             * Note that the nominal system identifier is not returned if a
1608:             * match is not found in the catalog, instead null is returned
1609:             * to indicate that no match was found.
1610:             */
1611:            protected synchronized String resolveLocalPublic(int entityType,
1612:                    String entityName, String publicId, String systemId)
1613:                    throws MalformedURLException, IOException {
1614:
1615:                // Always normalize the public identifier before attempting a match
1616:                publicId = PublicId.normalize(publicId);
1617:
1618:                // If there's a SYSTEM entry in this catalog, use it
1619:                if (systemId != null) {
1620:                    String resolved = resolveLocalSystem(systemId);
1621:                    if (resolved != null) {
1622:                        return resolved;
1623:                    }
1624:                }
1625:
1626:                // If there's a PUBLIC entry in this catalog, use it
1627:                boolean over = default_override;
1628:                Enumeration en = catalogEntries.elements();
1629:                while (en.hasMoreElements()) {
1630:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1631:                    if (e.getEntryType() == OVERRIDE) {
1632:                        over = e.getEntryArg(0).equalsIgnoreCase("YES");
1633:                        continue;
1634:                    }
1635:
1636:                    if (e.getEntryType() == PUBLIC
1637:                            && e.getEntryArg(0).equals(publicId)) {
1638:                        if (over || systemId == null) {
1639:                            return e.getEntryArg(1);
1640:                        }
1641:                    }
1642:                }
1643:
1644:                // If there's a DELEGATE_PUBLIC entry in this catalog, use it
1645:                over = default_override;
1646:                en = catalogEntries.elements();
1647:                Vector delCats = new Vector();
1648:                while (en.hasMoreElements()) {
1649:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1650:                    if (e.getEntryType() == OVERRIDE) {
1651:                        over = e.getEntryArg(0).equalsIgnoreCase("YES");
1652:                        continue;
1653:                    }
1654:
1655:                    if (e.getEntryType() == DELEGATE_PUBLIC
1656:                            && (over || systemId == null)) {
1657:                        String p = (String) e.getEntryArg(0);
1658:                        if (p.length() <= publicId.length()
1659:                                && p.equals(publicId.substring(0, p.length()))) {
1660:                            // delegate this match to the other catalog
1661:
1662:                            delCats.addElement(e.getEntryArg(1));
1663:                        }
1664:                    }
1665:                }
1666:
1667:                if (delCats.size() > 0) {
1668:                    Enumeration enCats = delCats.elements();
1669:
1670:                    if (catalogManager.debug.getDebug() > 1) {
1671:                        catalogManager.debug.message(2,
1672:                                "Switching to delegated catalog(s):");
1673:                        while (enCats.hasMoreElements()) {
1674:                            String delegatedCatalog = (String) enCats
1675:                                    .nextElement();
1676:                            catalogManager.debug.message(2, "\t"
1677:                                    + delegatedCatalog);
1678:                        }
1679:                    }
1680:
1681:                    Catalog dcat = newCatalog();
1682:
1683:                    enCats = delCats.elements();
1684:                    while (enCats.hasMoreElements()) {
1685:                        String delegatedCatalog = (String) enCats.nextElement();
1686:                        dcat.parseCatalog(delegatedCatalog);
1687:                    }
1688:
1689:                    return dcat.resolvePublic(publicId, null);
1690:                }
1691:
1692:                // Nada!
1693:                return null;
1694:            }
1695:
1696:            /**
1697:             * Return the applicable SYSTEM system identifier.
1698:             *
1699:             * <p>If a SYSTEM entry exists in the Catalog
1700:             * for the system ID specified, return the mapped value.</p>
1701:             *
1702:             * <p>On Windows-based operating systems, the comparison between
1703:             * the system identifier provided and the SYSTEM entries in the
1704:             * Catalog is case-insensitive.</p>
1705:             *
1706:             * @param systemId The system ID to locate in the catalog.
1707:             *
1708:             * @return The resolved system identifier.
1709:             *
1710:             * @throws MalformedURLException The formal system identifier of a
1711:             * subordinate catalog cannot be turned into a valid URL.
1712:             * @throws IOException Error reading subordinate catalog file.
1713:             */
1714:            public String resolveSystem(String systemId)
1715:                    throws MalformedURLException, IOException {
1716:
1717:                catalogManager.debug.message(3, "resolveSystem(" + systemId
1718:                        + ")");
1719:
1720:                systemId = normalizeURI(systemId);
1721:
1722:                if (systemId != null && systemId.startsWith("urn:publicid:")) {
1723:                    systemId = PublicId.decodeURN(systemId);
1724:                    return resolvePublic(systemId, null);
1725:                }
1726:
1727:                // If there's a SYSTEM entry in this catalog, use it
1728:                if (systemId != null) {
1729:                    String resolved = resolveLocalSystem(systemId);
1730:                    if (resolved != null) {
1731:                        return resolved;
1732:                    }
1733:                }
1734:
1735:                // Otherwise, look in the subordinate catalogs
1736:                return resolveSubordinateCatalogs(SYSTEM, null, null, systemId);
1737:            }
1738:
1739:            /**
1740:             * Return the applicable SYSTEM system identifier in this
1741:             * catalog.
1742:             *
1743:             * <p>If a SYSTEM entry exists in the catalog file
1744:             * for the system ID specified, return the mapped value.</p>
1745:             *
1746:             * @param systemId The system ID to locate in the catalog
1747:             *
1748:             * @return The mapped system identifier or null
1749:             */
1750:            protected String resolveLocalSystem(String systemId)
1751:                    throws MalformedURLException, IOException {
1752:
1753:                String osname = System.getProperty("os.name");
1754:                boolean windows = (osname.indexOf("Windows") >= 0);
1755:                Enumeration en = catalogEntries.elements();
1756:                while (en.hasMoreElements()) {
1757:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1758:                    if (e.getEntryType() == SYSTEM
1759:                            && (e.getEntryArg(0).equals(systemId) || (windows && e
1760:                                    .getEntryArg(0).equalsIgnoreCase(systemId)))) {
1761:                        return e.getEntryArg(1);
1762:                    }
1763:                }
1764:
1765:                // If there's a REWRITE_SYSTEM entry in this catalog, use it
1766:                en = catalogEntries.elements();
1767:                String startString = null;
1768:                String prefix = null;
1769:                while (en.hasMoreElements()) {
1770:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1771:
1772:                    if (e.getEntryType() == REWRITE_SYSTEM) {
1773:                        String p = (String) e.getEntryArg(0);
1774:                        if (p.length() <= systemId.length()
1775:                                && p.equals(systemId.substring(0, p.length()))) {
1776:                            // Is this the longest prefix?
1777:                            if (startString == null
1778:                                    || p.length() > startString.length()) {
1779:                                startString = p;
1780:                                prefix = e.getEntryArg(1);
1781:                            }
1782:                        }
1783:                    }
1784:                }
1785:
1786:                if (prefix != null) {
1787:                    // return the systemId with the new prefix
1788:                    return prefix + systemId.substring(startString.length());
1789:                }
1790:
1791:                // If there's a SYSTEM_SUFFIX entry in this catalog, use it
1792:                en = catalogEntries.elements();
1793:                String suffixString = null;
1794:                String suffixURI = null;
1795:                while (en.hasMoreElements()) {
1796:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1797:
1798:                    if (e.getEntryType() == SYSTEM_SUFFIX) {
1799:                        String p = (String) e.getEntryArg(0);
1800:                        if (p.length() <= systemId.length()
1801:                                && systemId.endsWith(p)) {
1802:                            // Is this the longest prefix?
1803:                            if (suffixString == null
1804:                                    || p.length() > suffixString.length()) {
1805:                                suffixString = p;
1806:                                suffixURI = e.getEntryArg(1);
1807:                            }
1808:                        }
1809:                    }
1810:                }
1811:
1812:                if (suffixURI != null) {
1813:                    // return the systemId for the suffix
1814:                    return suffixURI;
1815:                }
1816:
1817:                // If there's a DELEGATE_SYSTEM entry in this catalog, use it
1818:                en = catalogEntries.elements();
1819:                Vector delCats = new Vector();
1820:                while (en.hasMoreElements()) {
1821:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1822:
1823:                    if (e.getEntryType() == DELEGATE_SYSTEM) {
1824:                        String p = (String) e.getEntryArg(0);
1825:                        if (p.length() <= systemId.length()
1826:                                && p.equals(systemId.substring(0, p.length()))) {
1827:                            // delegate this match to the other catalog
1828:
1829:                            delCats.addElement(e.getEntryArg(1));
1830:                        }
1831:                    }
1832:                }
1833:
1834:                if (delCats.size() > 0) {
1835:                    Enumeration enCats = delCats.elements();
1836:
1837:                    if (catalogManager.debug.getDebug() > 1) {
1838:                        catalogManager.debug.message(2,
1839:                                "Switching to delegated catalog(s):");
1840:                        while (enCats.hasMoreElements()) {
1841:                            String delegatedCatalog = (String) enCats
1842:                                    .nextElement();
1843:                            catalogManager.debug.message(2, "\t"
1844:                                    + delegatedCatalog);
1845:                        }
1846:                    }
1847:
1848:                    Catalog dcat = newCatalog();
1849:
1850:                    enCats = delCats.elements();
1851:                    while (enCats.hasMoreElements()) {
1852:                        String delegatedCatalog = (String) enCats.nextElement();
1853:                        dcat.parseCatalog(delegatedCatalog);
1854:                    }
1855:
1856:                    return dcat.resolveSystem(systemId);
1857:                }
1858:
1859:                return null;
1860:            }
1861:
1862:            /**
1863:             * Return the applicable URI.
1864:             *
1865:             * <p>If a URI entry exists in the Catalog
1866:             * for the URI specified, return the mapped value.</p>
1867:             *
1868:             * <p>URI comparison is case sensitive.</p>
1869:             *
1870:             * @param uri The URI to locate in the catalog.
1871:             *
1872:             * @return The resolved URI.
1873:             *
1874:             * @throws MalformedURLException The system identifier of a
1875:             * subordinate catalog cannot be turned into a valid URL.
1876:             * @throws IOException Error reading subordinate catalog file.
1877:             */
1878:            public String resolveURI(String uri) throws MalformedURLException,
1879:                    IOException {
1880:
1881:                catalogManager.debug.message(3, "resolveURI(" + uri + ")");
1882:
1883:                uri = normalizeURI(uri);
1884:
1885:                if (uri != null && uri.startsWith("urn:publicid:")) {
1886:                    uri = PublicId.decodeURN(uri);
1887:                    return resolvePublic(uri, null);
1888:                }
1889:
1890:                // If there's a URI entry in this catalog, use it
1891:                if (uri != null) {
1892:                    String resolved = resolveLocalURI(uri);
1893:                    if (resolved != null) {
1894:                        return resolved;
1895:                    }
1896:                }
1897:
1898:                // Otherwise, look in the subordinate catalogs
1899:                return resolveSubordinateCatalogs(URI, null, null, uri);
1900:            }
1901:
1902:            /**
1903:             * Return the applicable URI in this catalog.
1904:             *
1905:             * <p>If a URI entry exists in the catalog file
1906:             * for the URI specified, return the mapped value.</p>
1907:             *
1908:             * @param uri The URI to locate in the catalog
1909:             *
1910:             * @return The mapped URI or null
1911:             */
1912:            protected String resolveLocalURI(String uri)
1913:                    throws MalformedURLException, IOException {
1914:                Enumeration en = catalogEntries.elements();
1915:                while (en.hasMoreElements()) {
1916:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1917:                    if (e.getEntryType() == URI
1918:                            && (e.getEntryArg(0).equals(uri))) {
1919:                        return e.getEntryArg(1);
1920:                    }
1921:                }
1922:
1923:                // If there's a REWRITE_URI entry in this catalog, use it
1924:                en = catalogEntries.elements();
1925:                String startString = null;
1926:                String prefix = null;
1927:                while (en.hasMoreElements()) {
1928:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1929:
1930:                    if (e.getEntryType() == REWRITE_URI) {
1931:                        String p = (String) e.getEntryArg(0);
1932:                        if (p.length() <= uri.length()
1933:                                && p.equals(uri.substring(0, p.length()))) {
1934:                            // Is this the longest prefix?
1935:                            if (startString == null
1936:                                    || p.length() > startString.length()) {
1937:                                startString = p;
1938:                                prefix = e.getEntryArg(1);
1939:                            }
1940:                        }
1941:                    }
1942:                }
1943:
1944:                if (prefix != null) {
1945:                    // return the uri with the new prefix
1946:                    return prefix + uri.substring(startString.length());
1947:                }
1948:
1949:                // If there's a URI_SUFFIX entry in this catalog, use it
1950:                en = catalogEntries.elements();
1951:                String suffixString = null;
1952:                String suffixURI = null;
1953:                while (en.hasMoreElements()) {
1954:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1955:
1956:                    if (e.getEntryType() == URI_SUFFIX) {
1957:                        String p = (String) e.getEntryArg(0);
1958:                        if (p.length() <= uri.length() && uri.endsWith(p)) {
1959:                            // Is this the longest prefix?
1960:                            if (suffixString == null
1961:                                    || p.length() > suffixString.length()) {
1962:                                suffixString = p;
1963:                                suffixURI = e.getEntryArg(1);
1964:                            }
1965:                        }
1966:                    }
1967:                }
1968:
1969:                if (suffixURI != null) {
1970:                    // return the uri for the suffix
1971:                    return suffixURI;
1972:                }
1973:
1974:                // If there's a DELEGATE_URI entry in this catalog, use it
1975:                en = catalogEntries.elements();
1976:                Vector delCats = new Vector();
1977:                while (en.hasMoreElements()) {
1978:                    CatalogEntry e = (CatalogEntry) en.nextElement();
1979:
1980:                    if (e.getEntryType() == DELEGATE_URI) {
1981:                        String p = (String) e.getEntryArg(0);
1982:                        if (p.length() <= uri.length()
1983:                                && p.equals(uri.substring(0, p.length()))) {
1984:                            // delegate this match to the other catalog
1985:
1986:                            delCats.addElement(e.getEntryArg(1));
1987:                        }
1988:                    }
1989:                }
1990:
1991:                if (delCats.size() > 0) {
1992:                    Enumeration enCats = delCats.elements();
1993:
1994:                    if (catalogManager.debug.getDebug() > 1) {
1995:                        catalogManager.debug.message(2,
1996:                                "Switching to delegated catalog(s):");
1997:                        while (enCats.hasMoreElements()) {
1998:                            String delegatedCatalog = (String) enCats
1999:                                    .nextElement();
2000:                            catalogManager.debug.message(2, "\t"
2001:                                    + delegatedCatalog);
2002:                        }
2003:                    }
2004:
2005:                    Catalog dcat = newCatalog();
2006:
2007:                    enCats = delCats.elements();
2008:                    while (enCats.hasMoreElements()) {
2009:                        String delegatedCatalog = (String) enCats.nextElement();
2010:                        dcat.parseCatalog(delegatedCatalog);
2011:                    }
2012:
2013:                    return dcat.resolveURI(uri);
2014:                }
2015:
2016:                return null;
2017:            }
2018:
2019:            /**
2020:             * Search the subordinate catalogs, in order, looking for a match.
2021:             *
2022:             * <p>This method searches the Catalog and returns the system
2023:             * identifier specified for the given entity type with the given
2024:             * name, public, and system identifiers. In some contexts, these
2025:             * may be null.</p>
2026:             *
2027:             * @param entityType The CatalogEntry type for which this query is
2028:             * being conducted. This is necessary in order to do the approprate
2029:             * query on a subordinate catalog.
2030:             * @param entityName The name of the entity being searched for, if
2031:             * appropriate.
2032:             * @param publicId The public identifier of the entity in question
2033:             * (as provided in the source document).
2034:             * @param systemId The nominal system identifier for the entity
2035:             * in question (as provided in the source document). This parameter is
2036:             * overloaded for the URI entry type.
2037:             *
2038:             * @throws MalformedURLException The formal system identifier of a
2039:             * delegated catalog cannot be turned into a valid URL.
2040:             * @throws IOException Error reading delegated catalog file.
2041:             *
2042:             * @return The system identifier to use.
2043:             * Note that the nominal system identifier is not returned if a
2044:             * match is not found in the catalog, instead null is returned
2045:             * to indicate that no match was found.
2046:             */
2047:            protected synchronized String resolveSubordinateCatalogs(
2048:                    int entityType, String entityName, String publicId,
2049:                    String systemId) throws MalformedURLException, IOException {
2050:
2051:                for (int catPos = 0; catPos < catalogs.size(); catPos++) {
2052:                    Catalog c = null;
2053:
2054:                    try {
2055:                        c = (Catalog) catalogs.elementAt(catPos);
2056:                    } catch (ClassCastException e) {
2057:                        String catfile = (String) catalogs.elementAt(catPos);
2058:                        c = newCatalog();
2059:
2060:                        try {
2061:                            c.parseCatalog(catfile);
2062:                        } catch (MalformedURLException mue) {
2063:                            catalogManager.debug.message(1,
2064:                                    "Malformed Catalog URL", catfile);
2065:                        } catch (FileNotFoundException fnfe) {
2066:                            catalogManager.debug.message(1,
2067:                                    "Failed to load catalog, file not found",
2068:                                    catfile);
2069:                        } catch (IOException ioe) {
2070:                            catalogManager.debug.message(1,
2071:                                    "Failed to load catalog, I/O error",
2072:                                    catfile);
2073:                        }
2074:
2075:                        catalogs.setElementAt(c, catPos);
2076:                    }
2077:
2078:                    String resolved = null;
2079:
2080:                    // Ok, now what are we supposed to call here?
2081:                    if (entityType == DOCTYPE) {
2082:                        resolved = c.resolveDoctype(entityName, publicId,
2083:                                systemId);
2084:                    } else if (entityType == DOCUMENT) {
2085:                        resolved = c.resolveDocument();
2086:                    } else if (entityType == ENTITY) {
2087:                        resolved = c.resolveEntity(entityName, publicId,
2088:                                systemId);
2089:                    } else if (entityType == NOTATION) {
2090:                        resolved = c.resolveNotation(entityName, publicId,
2091:                                systemId);
2092:                    } else if (entityType == PUBLIC) {
2093:                        resolved = c.resolvePublic(publicId, systemId);
2094:                    } else if (entityType == SYSTEM) {
2095:                        resolved = c.resolveSystem(systemId);
2096:                    } else if (entityType == URI) {
2097:                        resolved = c.resolveURI(systemId);
2098:                    }
2099:
2100:                    if (resolved != null) {
2101:                        return resolved;
2102:                    }
2103:                }
2104:
2105:                return null;
2106:            }
2107:
2108:            // -----------------------------------------------------------------
2109:
2110:            /**
2111:             * Replace backslashes with forward slashes. (URLs always use
2112:             * forward slashes.)
2113:             *
2114:             * @param sysid The input system identifier.
2115:             * @return The same system identifier with backslashes turned into
2116:             * forward slashes.
2117:             */
2118:            protected String fixSlashes(String sysid) {
2119:                return sysid.replace('\\', '/');
2120:            }
2121:
2122:            /**
2123:             * Construct an absolute URI from a relative one, using the current
2124:             * base URI.
2125:             *
2126:             * @param sysid The (possibly relative) system identifier
2127:             * @return The system identifier made absolute with respect to the
2128:             * current {@link #base}.
2129:             */
2130:            protected String makeAbsolute(String sysid) {
2131:                URL local = null;
2132:
2133:                sysid = fixSlashes(sysid);
2134:
2135:                try {
2136:                    local = new URL(base, sysid);
2137:                } catch (MalformedURLException e) {
2138:                    catalogManager.debug.message(1,
2139:                            "Malformed URL on system identifier", sysid);
2140:                }
2141:
2142:                if (local != null) {
2143:                    return local.toString();
2144:                } else {
2145:                    return sysid;
2146:                }
2147:            }
2148:
2149:            /**
2150:             * Perform character normalization on a URI reference.
2151:             *
2152:             * @param uriref The URI reference
2153:             * @return The normalized URI reference.
2154:             */
2155:            protected String normalizeURI(String uriref) {
2156:                String newRef = "";
2157:                byte[] bytes;
2158:
2159:                if (uriref == null) {
2160:                    return null;
2161:                }
2162:
2163:                try {
2164:                    bytes = uriref.getBytes("UTF-8");
2165:                } catch (UnsupportedEncodingException uee) {
2166:                    // this can't happen
2167:                    catalogManager.debug.message(1,
2168:                            "UTF-8 is an unsupported encoding!?");
2169:                    return uriref;
2170:                }
2171:
2172:                for (int count = 0; count < bytes.length; count++) {
2173:                    int ch = bytes[count] & 0xFF;
2174:
2175:                    if ((ch <= 0x20) // ctrl
2176:                            || (ch > 0x7F) // high ascii
2177:                            || (ch == 0x22) // "
2178:                            || (ch == 0x3C) // <
2179:                            || (ch == 0x3E) // >
2180:                            || (ch == 0x5C) // \
2181:                            || (ch == 0x5E) // ^
2182:                            || (ch == 0x60) // `
2183:                            || (ch == 0x7B) // {
2184:                            || (ch == 0x7C) // |
2185:                            || (ch == 0x7D) // }
2186:                            || (ch == 0x7F)) {
2187:                        newRef += encodedByte(ch);
2188:                    } else {
2189:                        newRef += (char) bytes[count];
2190:                    }
2191:                }
2192:
2193:                return newRef;
2194:            }
2195:
2196:            /**
2197:             * Perform %-encoding on a single byte.
2198:             *
2199:             * @param b The 8-bit integer that represents th byte. (Bytes are signed
2200:                        but encoding needs to look at the bytes unsigned.)
2201:             * @return The %-encoded string for the byte in question.
2202:             */
2203:            protected String encodedByte(int b) {
2204:                String hex = Integer.toHexString(b).toUpperCase();
2205:                if (hex.length() < 2) {
2206:                    return "%0" + hex;
2207:                } else {
2208:                    return "%" + hex;
2209:                }
2210:            }
2211:
2212:            // -----------------------------------------------------------------
2213:
2214:            /**
2215:             * Add to the current list of delegated catalogs.
2216:             *
2217:             * <p>This method always constructs the {@link #localDelegate}
2218:             * vector so that it is ordered by length of partial
2219:             * public identifier.</p>
2220:             *
2221:             * @param entry The DELEGATE catalog entry
2222:             */
2223:            protected void addDelegate(CatalogEntry entry) {
2224:                int pos = 0;
2225:                String partial = entry.getEntryArg(0);
2226:
2227:                Enumeration local = localDelegate.elements();
2228:                while (local.hasMoreElements()) {
2229:                    CatalogEntry dpe = (CatalogEntry) local.nextElement();
2230:                    String dp = dpe.getEntryArg(0);
2231:                    if (dp.equals(partial)) {
2232:                        // we already have this prefix
2233:                        return;
2234:                    }
2235:                    if (dp.length() > partial.length()) {
2236:                        pos++;
2237:                    }
2238:                    if (dp.length() < partial.length()) {
2239:                        break;
2240:                    }
2241:                }
2242:
2243:                // now insert partial into the vector at [pos]
2244:                if (localDelegate.size() == 0) {
2245:                    localDelegate.addElement(entry);
2246:                } else {
2247:                    localDelegate.insertElementAt(entry, pos);
2248:                }
2249:            }
2250:        }
ww___w_._j___av__a__2__s._c_o__m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.