1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.backsource.utils.xml;
21 import java.util.Vector;
22 import java.io.File;
23 import java.io.InputStream;
24 import java.io.IOException;
25 import java.net.URL;
26 import java.net.MalformedURLException;
27
28 import javax.xml.parsers.SAXParserFactory;
29
30 import org.w3c.dom.Document;
31
32 import org.apache.xml.resolver.CatalogManager;
33 import org.apache.xml.resolver.CatalogException;
34 import org.apache.xml.resolver.readers.CatalogReader;
35 import org.apache.xml.resolver.readers.SAXCatalogReader;
36 import org.apache.xml.resolver.readers.OASISXMLCatalogReader;
37
38 import org.backsource.utils.io.DOMInputStream;
39 /***
40 * A simple extension of the {@link org.apache.xml.resolver.Catalog} to make it easier to construct instances progranatically. It is easier to add catalog entries and set a baseUri programatically than the original.</p>
41 <p>This version of the Catalog allways need a base uri to work against. This should normally be a directory where dtd:s and other files are collected. To make it easier to use in a component environment where other forms of configurations are used than system wide catalog files the {@link #addCatalogEntry} should be used. The different type of entries jave static create methods in {@link CatalogEntry}. Here is one possible way of setting up the Catalog and adding some entries. It is important to note that how the resolved uris are translated to URL:s, ie resources that are also possible to get physically is really up to the resolver that used this Catalog, see {@link Catalogresolver}.</p>
42 <pre>
43 File base = new File("resources/test/dtd/");
44 catalog = new Catalog(base.getAbsolutePath());
45
46 // Ad a systemId that will get rewritten to base+dtd2/ttnitf2.dtd
47 catalog.addCatalogEntry( CatalogEntry.getRewriteSystemEntry("http://www.tt.se/dtd/ttnitf2.dtd", "dtd2/ttnitf2.dtd") );
48
49 // add a systemId, that really shoul be looked up in classpath by resolver
50 catalog.addCatalogEntry( CatalogEntry.getSystemEntry("log4j.dtd", "/org/apache/log4j/xml/log4j.dtd") );
51
52 // Ad a publicId - amsterdam2.dtd must be in base dir
53 catalog.addCatalogEntry( CatalogEntry.getPublicEntry("-//Teknik i Meda//DTD Amsterdam//EN", "amsterdam2.dtd") );
54
55 // ad an uri that will be looked up in base + ../xsl/include.xsl
56 CatalogEntry en = CatalogEntry.getUriEntry("include.xsl", "../xsl/include.xsl");
57
58 catalog.addCatalogEntry( en );
59 </pre>
60 <p> See <a href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">The OASIS</a> spec to understand how the concept works.</p>
61 <p>Apart from all the configuration options given byte the original Catalog it is also possible to configure the Catalog with a DOM tree following the OASI spec. Say you have access to the following xml in a DOM Document: </p>
62 <pre><?xml version="1.0" ?>
63 <!-- Do NOT forget the trailing slash -->
64 <catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"
65 prefer="public"
66 xml:base="dtd2/">
67 <public publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
68 uri="docbookx.dtd"/>
69 <system systemId="ttnitf2.dtd"
70 uri="ttnitf2.dtd"/>
71
72 </catalog>
73 </pre>
74 <p>You could configure the Catalog with:</p>
75 <pre>
76 File base = new File("resources/test/dtd/");
77 Catalog cat = new Catalog(base.getAbsolutePath());
78 Document d = DocumentUtil.getDocument( new FileInputStream("resources/test/catalog.xml") );
79 cat.configure(d);
80 </pre>
81 <p>This is obsolete from 1.1. Unfortunately the parsing rutines of the resolver lib seems to be pretty sloppy, so don't be to suprised if the xml was not properly read because some XML error but with no exception.</p>
82 <p>Unfortunately the Catalog implementation is based on a lot of implicit working and static stuff: it is normally meant to be used for system wide usage. This has the disadvandage that there are a lot of stuff that the resolver tries to set in the background; and it will complain about missing propertfiles. To make it shutup, this should be run before the Catalog is used:</p>
83 <pre>
84 org.apache.xml.resolver.CatalogManager.ignoreMissingProperties(true);
85 </pre>
86 * @author <a href="mailto:pra@tim.se">Peter Antman</a>
87 * @version $Revision: 1.1.1.1 $
88 */
89
90 public class Catalog extends org.apache.xml.resolver.Catalog {
91 public Catalog (String baseUri) throws XmlException{
92 super(new CatalogManager());
93 getCatalogManager().ignoreMissingProperties(true);
94 try {
95 base = new URL(baseUri);
96 } catch (MalformedURLException e) {
97
98 try {
99 File f = new File(baseUri);
100 base = f.toURL();
101 } catch (Exception ex) {
102 throw new XmlException("The base URI "+baseUri + "was not an URL "+ex,ex);
103 }
104
105 }
106
107 }
108
109 public void setDebug(int level) {
110 getCatalogManager().setVerbosity(level);
111 }
112
113 public void setBaseUri(String baseUri) throws XmlException {
114 try {
115
116 Vector args = new Vector();
117 args.add(baseUri);
118 org.apache.xml.resolver.CatalogEntry entry = new org.apache.xml.resolver.CatalogEntry(org.apache.xml.resolver.Catalog.BASE, args);
119 addEntry(entry);
120
121 } catch (CatalogException e) {
122 throw new XmlException("Could not set base " + baseUri + ": " +e,e);
123 }
124 }
125
126 public URL getBase() {
127 return base;
128 }
129
130 public void addCatalogEntry(CatalogEntry entry) {
131 super.addEntry( entry.getEntry() );
132 }
133
134 /***
135 * Configure from an OASIS xml document.
136 * <p>Ig chaning the base of the catalog with xml:base, don't forget to ad a traling slash to any dirs mentioned!</p>
137 */
138 public void configure(Document doc) throws XmlException{
139 try {
140 SAXParserFactory spf = SAXParserFactory.newInstance();
141 spf.setNamespaceAware(true);
142 spf.setValidating(false);
143
144 SAXCatalogReader saxReader = new SAXCatalogReader(spf);
145 saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName,
146 "catalog",
147 "org.apache.xml.resolver.readers.OASISXMLCatalogReader");
148 addReader("application/xml", saxReader);
149
150 InputStream is = new DOMInputStream(doc);
151 parseCatalog("application/xml",is);
152
153 } catch (CatalogException e) {
154 throw new XmlException("Could not configure catalog from document: "+e,e);
155 } catch (IOException e) {
156 throw new XmlException("Could not configure catalog from document: "+e,e);
157 }
158
159 }
160 }