001: // BootstrapResolver.java - Resolve entities and URIs internally
002:
003: /*
004: * Copyright 2001-2004 The Apache Software Foundation or its licensors,
005: * as applicable.
006: *
007: * Licensed under the Apache License, Version 2.0 (the "License");
008: * you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: package com.sun.org.apache.xml.internal.resolver.helpers;
021:
022: import java.util.Hashtable;
023: import java.net.URL;
024: import java.net.MalformedURLException;
025: import java.io.InputStream;
026:
027: import javax.xml.transform.URIResolver;
028: import javax.xml.transform.Source;
029: import javax.xml.transform.sax.SAXSource;
030: import javax.xml.transform.TransformerException;
031:
032: import org.xml.sax.EntityResolver;
033: import org.xml.sax.InputSource;
034:
035: /**
036: * A simple bootstrapping resolver.
037: *
038: * <p>This class is used as the entity resolver when reading XML Catalogs.
039: * It searches for the OASIS XML Catalog DTD, Relax NG Grammar and W3C XML Schema
040: * as resources (e.g., in the resolver jar file).</p>
041: *
042: * <p>If you have your own DTDs or schemas, you can extend this class and
043: * set the BootstrapResolver in your CatalogManager.</p>
044: *
045: * @see com.sun.org.apache.xml.internal.resolver.CatalogManager
046: *
047: * @author Norman Walsh
048: * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
049: *
050: * @version 1.0
051: */
052: public class BootstrapResolver implements EntityResolver, URIResolver {
053: /** URI of the W3C XML Schema for OASIS XML Catalog files. */
054: public static final String xmlCatalogXSD = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.xsd";
055:
056: /** URI of the RELAX NG Grammar for OASIS XML Catalog files. */
057: public static final String xmlCatalogRNG = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.rng";
058:
059: /** Public identifier for OASIS XML Catalog files. */
060: public static final String xmlCatalogPubId = "-//OASIS//DTD XML Catalogs V1.0//EN";
061:
062: /** System identifier for OASIS XML Catalog files. */
063: public static final String xmlCatalogSysId = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd";
064:
065: /** Private hash used for public identifiers. */
066: private Hashtable publicMap = new Hashtable();
067:
068: /** Private hash used for system identifiers. */
069: private Hashtable systemMap = new Hashtable();
070:
071: /** Private hash used for URIs. */
072: private Hashtable uriMap = new Hashtable();
073:
074: /** Constructor. */
075: public BootstrapResolver() {
076: URL url = this
077: .getClass()
078: .getResource(
079: "/com/sun/org/apache/xml/internal/resolver/etc/catalog.dtd");
080: if (url != null) {
081: publicMap.put(xmlCatalogPubId, url.toString());
082: systemMap.put(xmlCatalogSysId, url.toString());
083: }
084:
085: url = this
086: .getClass()
087: .getResource(
088: "/com/sun/org/apache/xml/internal/resolver/etc/catalog.rng");
089: if (url != null) {
090: uriMap.put(xmlCatalogRNG, url.toString());
091: }
092:
093: url = this
094: .getClass()
095: .getResource(
096: "/com/sun/org/apache/xml/internal/resolver/etc/catalog.xsd");
097: if (url != null) {
098: uriMap.put(xmlCatalogXSD, url.toString());
099: }
100: }
101:
102: /** SAX resolveEntity API. */
103: public InputSource resolveEntity(String publicId, String systemId) {
104: String resolved = null;
105:
106: if (systemId != null && systemMap.containsKey(systemId)) {
107: resolved = (String) systemMap.get(systemId);
108: } else if (publicId != null && publicMap.containsKey(publicId)) {
109: resolved = (String) publicMap.get(publicId);
110: }
111:
112: if (resolved != null) {
113: try {
114: InputSource iSource = new InputSource(resolved);
115: iSource.setPublicId(publicId);
116:
117: // Ideally this method would not attempt to open the
118: // InputStream, but there is a bug (in Xerces, at least)
119: // that causes the parser to mistakenly open the wrong
120: // system identifier if the returned InputSource does
121: // not have a byteStream.
122: //
123: // It could be argued that we still shouldn't do this here,
124: // but since the purpose of calling the entityResolver is
125: // almost certainly to open the input stream, it seems to
126: // do little harm.
127: //
128: URL url = new URL(resolved);
129: InputStream iStream = url.openStream();
130: iSource.setByteStream(iStream);
131:
132: return iSource;
133: } catch (Exception e) {
134: // FIXME: silently fail?
135: return null;
136: }
137: }
138:
139: return null;
140: }
141:
142: /** Transformer resolve API. */
143: public Source resolve(String href, String base)
144: throws TransformerException {
145:
146: String uri = href;
147: String fragment = null;
148: int hashPos = href.indexOf("#");
149: if (hashPos >= 0) {
150: uri = href.substring(0, hashPos);
151: fragment = href.substring(hashPos + 1);
152: }
153:
154: String result = null;
155: if (href != null && uriMap.containsKey(href)) {
156: result = (String) uriMap.get(href);
157: }
158:
159: if (result == null) {
160: try {
161: URL url = null;
162:
163: if (base == null) {
164: url = new URL(uri);
165: result = url.toString();
166: } else {
167: URL baseURL = new URL(base);
168: url = (href.length() == 0 ? baseURL : new URL(
169: baseURL, uri));
170: result = url.toString();
171: }
172: } catch (java.net.MalformedURLException mue) {
173: // try to make an absolute URI from the current base
174: String absBase = makeAbsolute(base);
175: if (!absBase.equals(base)) {
176: // don't bother if the absBase isn't different!
177: return resolve(href, absBase);
178: } else {
179: throw new TransformerException("Malformed URL "
180: + href + "(base " + base + ")", mue);
181: }
182: }
183: }
184:
185: SAXSource source = new SAXSource();
186: source.setInputSource(new InputSource(result));
187: return source;
188: }
189:
190: /** Attempt to construct an absolute URI */
191: private String makeAbsolute(String uri) {
192: if (uri == null) {
193: uri = "";
194: }
195:
196: try {
197: URL url = new URL(uri);
198: return url.toString();
199: } catch (MalformedURLException mue) {
200: try {
201: URL fileURL = FileURL.makeURL(uri);
202: return fileURL.toString();
203: } catch (MalformedURLException mue2) {
204: // bail
205: return uri;
206: }
207: }
208: }
209: }
|