author | joehw |
Wed, 14 Sep 2016 13:18:17 -0700 | |
changeset 41021 | 444f2b1bcc8c |
parent 26516 | 8e6a45c22cea |
permissions | -rw-r--r-- |
6 | 1 |
/* |
26516 | 2 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
3 |
* contributor license agreements. See the NOTICE file distributed with |
|
4 |
* this work for additional information regarding copyright ownership. |
|
5 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
6 |
* (the "License"); you may not use this file except in compliance with |
|
7 |
* the License. You may obtain a copy of the License at |
|
6 | 8 |
* |
9 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
10 |
* |
|
11 |
* Unless required by applicable law or agreed to in writing, software |
|
12 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
13 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 |
* See the License for the specific language governing permissions and |
|
15 |
* limitations under the License. |
|
16 |
*/ |
|
17 |
||
18 |
package com.sun.org.apache.xml.internal.resolver.tools; |
|
19 |
||
12458 | 20 |
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; |
6 | 21 |
import java.io.IOException; |
22 |
import java.io.InputStream; |
|
23 |
import java.net.URL; |
|
24 |
import java.net.MalformedURLException; |
|
25 |
||
26 |
import org.xml.sax.SAXException; |
|
27 |
import org.xml.sax.XMLReader; |
|
28 |
import org.xml.sax.InputSource; |
|
29 |
import org.xml.sax.EntityResolver; |
|
30 |
||
31 |
import javax.xml.transform.sax.SAXSource; |
|
32 |
import javax.xml.transform.Source; |
|
33 |
import javax.xml.transform.URIResolver; |
|
34 |
import javax.xml.transform.TransformerException; |
|
35 |
import javax.xml.parsers.ParserConfigurationException; |
|
36 |
import javax.xml.parsers.SAXParserFactory; |
|
37 |
||
38 |
import com.sun.org.apache.xml.internal.resolver.Catalog; |
|
39 |
import com.sun.org.apache.xml.internal.resolver.CatalogManager; |
|
40 |
import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; |
|
41 |
||
42 |
/** |
|
43 |
* A SAX EntityResolver/JAXP URIResolver that uses catalogs. |
|
44 |
* |
|
45 |
* <p>This class implements both a SAX EntityResolver and a JAXP URIResolver. |
|
46 |
* </p> |
|
47 |
* |
|
48 |
* <p>This resolver understands OASIS TR9401 catalogs, XCatalogs, and the |
|
49 |
* current working draft of the OASIS Entity Resolution Technical |
|
50 |
* Committee specification.</p> |
|
51 |
* |
|
52 |
* @see Catalog |
|
53 |
* @see org.xml.sax.EntityResolver |
|
54 |
* @see javax.xml.transform.URIResolver |
|
41021
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
55 |
* @deprecated The JDK internal Catalog API in package |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
56 |
* {@code com.sun.org.apache.xml.internal.resolver} |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
57 |
* is encapsulated in JDK 9. The entire implementation under the package is now |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
58 |
* deprecated and subject to removal in a future release. Users of the API |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
59 |
* should migrate to the {@linkplain javax.xml.catalog new public API}. |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
60 |
* <p> |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
61 |
* The new Catalog API is supported throughout the JDK XML Processors, which allows |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
62 |
* the use of Catalog by simply setting a path to a Catalog file as a property. |
6 | 63 |
* |
64 |
* @author Norman Walsh |
|
65 |
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a> |
|
66 |
* |
|
12458 | 67 |
* @version 1.0 |
6 | 68 |
*/ |
41021
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
26516
diff
changeset
|
69 |
@Deprecated(since="9", forRemoval=true) |
6 | 70 |
public class CatalogResolver implements EntityResolver, URIResolver { |
71 |
/** Make the parser Namespace aware? */ |
|
72 |
public boolean namespaceAware = true; |
|
73 |
||
74 |
/** Make the parser validating? */ |
|
75 |
public boolean validating = false; |
|
76 |
||
77 |
/** The underlying catalog */ |
|
78 |
private Catalog catalog = null; |
|
79 |
||
80 |
/** The catalog manager */ |
|
81 |
private CatalogManager catalogManager = CatalogManager.getStaticManager(); |
|
82 |
||
83 |
/** Constructor */ |
|
84 |
public CatalogResolver() { |
|
85 |
initializeCatalogs(false); |
|
86 |
} |
|
87 |
||
88 |
/** Constructor */ |
|
89 |
public CatalogResolver(boolean privateCatalog) { |
|
90 |
initializeCatalogs(privateCatalog); |
|
91 |
} |
|
92 |
||
93 |
/** Constructor */ |
|
94 |
public CatalogResolver(CatalogManager manager) { |
|
95 |
catalogManager = manager; |
|
96 |
initializeCatalogs(!catalogManager.getUseStaticCatalog()); |
|
97 |
} |
|
98 |
||
99 |
/** Initialize catalog */ |
|
100 |
private void initializeCatalogs(boolean privateCatalog) { |
|
101 |
catalog = catalogManager.getCatalog(); |
|
102 |
} |
|
103 |
||
104 |
/** Return the underlying catalog */ |
|
105 |
public Catalog getCatalog() { |
|
106 |
return catalog; |
|
107 |
} |
|
108 |
||
109 |
/** |
|
110 |
* Implements the guts of the <code>resolveEntity</code> method |
|
111 |
* for the SAX interface. |
|
112 |
* |
|
113 |
* <p>Presented with an optional public identifier and a system |
|
114 |
* identifier, this function attempts to locate a mapping in the |
|
115 |
* catalogs.</p> |
|
116 |
* |
|
117 |
* <p>If such a mapping is found, it is returned. If no mapping is |
|
118 |
* found, null is returned.</p> |
|
119 |
* |
|
120 |
* @param publicId The public identifier for the entity in question. |
|
121 |
* This may be null. |
|
122 |
* |
|
123 |
* @param systemId The system identifier for the entity in question. |
|
124 |
* XML requires a system identifier on all external entities, so this |
|
125 |
* value is always specified. |
|
126 |
* |
|
127 |
* @return The resolved identifier (a URI reference). |
|
128 |
*/ |
|
129 |
public String getResolvedEntity (String publicId, String systemId) { |
|
130 |
String resolved = null; |
|
131 |
||
132 |
if (catalog == null) { |
|
133 |
catalogManager.debug.message(1, "Catalog resolution attempted with null catalog; ignored"); |
|
134 |
return null; |
|
135 |
} |
|
136 |
||
137 |
if (systemId != null) { |
|
138 |
try { |
|
139 |
resolved = catalog.resolveSystem(systemId); |
|
140 |
} catch (MalformedURLException me) { |
|
141 |
catalogManager.debug.message(1, "Malformed URL exception trying to resolve", |
|
142 |
publicId); |
|
143 |
resolved = null; |
|
144 |
} catch (IOException ie) { |
|
145 |
catalogManager.debug.message(1, "I/O exception trying to resolve", publicId); |
|
146 |
resolved = null; |
|
147 |
} |
|
148 |
} |
|
149 |
||
150 |
if (resolved == null) { |
|
151 |
if (publicId != null) { |
|
152 |
try { |
|
153 |
resolved = catalog.resolvePublic(publicId, systemId); |
|
154 |
} catch (MalformedURLException me) { |
|
155 |
catalogManager.debug.message(1, "Malformed URL exception trying to resolve", |
|
156 |
publicId); |
|
157 |
} catch (IOException ie) { |
|
158 |
catalogManager.debug.message(1, "I/O exception trying to resolve", publicId); |
|
159 |
} |
|
160 |
} |
|
161 |
||
162 |
if (resolved != null) { |
|
163 |
catalogManager.debug.message(2, "Resolved public", publicId, resolved); |
|
164 |
} |
|
165 |
} else { |
|
166 |
catalogManager.debug.message(2, "Resolved system", systemId, resolved); |
|
167 |
} |
|
168 |
||
169 |
return resolved; |
|
170 |
} |
|
171 |
||
172 |
/** |
|
173 |
* Implements the <code>resolveEntity</code> method |
|
174 |
* for the SAX interface. |
|
175 |
* |
|
176 |
* <p>Presented with an optional public identifier and a system |
|
177 |
* identifier, this function attempts to locate a mapping in the |
|
178 |
* catalogs.</p> |
|
179 |
* |
|
180 |
* <p>If such a mapping is found, the resolver attempts to open |
|
181 |
* the mapped value as an InputSource and return it. Exceptions are |
|
182 |
* ignored and null is returned if the mapped value cannot be opened |
|
183 |
* as an input source.</p> |
|
184 |
* |
|
185 |
* <p>If no mapping is found (or an error occurs attempting to open |
|
186 |
* the mapped value as an input source), null is returned and the system |
|
187 |
* will use the specified system identifier as if no entityResolver |
|
188 |
* was specified.</p> |
|
189 |
* |
|
190 |
* @param publicId The public identifier for the entity in question. |
|
191 |
* This may be null. |
|
192 |
* |
|
193 |
* @param systemId The system identifier for the entity in question. |
|
194 |
* XML requires a system identifier on all external entities, so this |
|
195 |
* value is always specified. |
|
196 |
* |
|
197 |
* @return An InputSource for the mapped identifier, or null. |
|
198 |
*/ |
|
199 |
public InputSource resolveEntity (String publicId, String systemId) { |
|
200 |
String resolved = getResolvedEntity(publicId, systemId); |
|
201 |
||
202 |
if (resolved != null) { |
|
203 |
try { |
|
204 |
InputSource iSource = new InputSource(resolved); |
|
205 |
iSource.setPublicId(publicId); |
|
206 |
||
207 |
// Ideally this method would not attempt to open the |
|
208 |
// InputStream, but there is a bug (in Xerces, at least) |
|
209 |
// that causes the parser to mistakenly open the wrong |
|
210 |
// system identifier if the returned InputSource does |
|
211 |
// not have a byteStream. |
|
212 |
// |
|
213 |
// It could be argued that we still shouldn't do this here, |
|
214 |
// but since the purpose of calling the entityResolver is |
|
215 |
// almost certainly to open the input stream, it seems to |
|
216 |
// do little harm. |
|
217 |
// |
|
218 |
URL url = new URL(resolved); |
|
219 |
InputStream iStream = url.openStream(); |
|
220 |
iSource.setByteStream(iStream); |
|
221 |
||
222 |
return iSource; |
|
223 |
} catch (Exception e) { |
|
26516 | 224 |
catalogManager.debug.message(1, |
225 |
"Failed to create InputSource (" |
|
226 |
+ e.toString() |
|
227 |
+ ")", resolved); |
|
6 | 228 |
return null; |
229 |
} |
|
230 |
} |
|
231 |
||
232 |
return null; |
|
233 |
} |
|
234 |
||
235 |
/** JAXP URIResolver API */ |
|
236 |
public Source resolve(String href, String base) |
|
237 |
throws TransformerException { |
|
238 |
||
239 |
String uri = href; |
|
240 |
String fragment = null; |
|
241 |
int hashPos = href.indexOf("#"); |
|
242 |
if (hashPos >= 0) { |
|
243 |
uri = href.substring(0, hashPos); |
|
244 |
fragment = href.substring(hashPos+1); |
|
245 |
} |
|
246 |
||
247 |
String result = null; |
|
248 |
||
249 |
try { |
|
250 |
result = catalog.resolveURI(href); |
|
251 |
} catch (Exception e) { |
|
252 |
// nop; |
|
253 |
} |
|
254 |
||
255 |
if (result == null) { |
|
256 |
try { |
|
257 |
URL url = null; |
|
258 |
||
259 |
if (base==null) { |
|
260 |
url = new URL(uri); |
|
261 |
result = url.toString(); |
|
262 |
} else { |
|
263 |
URL baseURL = new URL(base); |
|
264 |
url = (href.length()==0 ? baseURL : new URL(baseURL, uri)); |
|
265 |
result = url.toString(); |
|
266 |
} |
|
267 |
} catch (java.net.MalformedURLException mue) { |
|
268 |
// try to make an absolute URI from the current base |
|
269 |
String absBase = makeAbsolute(base); |
|
270 |
if (!absBase.equals(base)) { |
|
271 |
// don't bother if the absBase isn't different! |
|
272 |
return resolve(href, absBase); |
|
273 |
} else { |
|
274 |
throw new TransformerException("Malformed URL " |
|
275 |
+ href + "(base " + base + ")", |
|
276 |
mue); |
|
277 |
} |
|
278 |
} |
|
279 |
} |
|
280 |
||
281 |
catalogManager.debug.message(2, "Resolved URI", href, result); |
|
282 |
||
283 |
SAXSource source = new SAXSource(); |
|
284 |
source.setInputSource(new InputSource(result)); |
|
285 |
setEntityResolver(source); |
|
286 |
return source; |
|
287 |
} |
|
288 |
||
289 |
/** |
|
290 |
* <p>Establish an entityResolver for newly resolved URIs.</p> |
|
291 |
* |
|
292 |
* <p>This is called from the URIResolver to set an EntityResolver |
|
293 |
* on the SAX parser to be used for new XML documents that are |
|
294 |
* encountered as a result of the document() function, xsl:import, |
|
295 |
* or xsl:include. This is done because the XSLT processor calls |
|
296 |
* out to the SAXParserFactory itself to create a new SAXParser to |
|
297 |
* parse the new document. The new parser does not automatically |
|
298 |
* inherit the EntityResolver of the original (although arguably |
|
299 |
* it should). See below:</p> |
|
300 |
* |
|
301 |
* <tt>"If an application wants to set the ErrorHandler or |
|
302 |
* EntityResolver for an XMLReader used during a transformation, |
|
303 |
* it should use a URIResolver to return the SAXSource which |
|
304 |
* provides (with getXMLReader) a reference to the XMLReader"</tt> |
|
305 |
* |
|
306 |
* <p>...quoted from page 118 of the Java API for XML |
|
307 |
* Processing 1.1 specification</p> |
|
308 |
* |
|
309 |
*/ |
|
310 |
private void setEntityResolver(SAXSource source) throws TransformerException { |
|
311 |
XMLReader reader = source.getXMLReader(); |
|
312 |
if (reader == null) { |
|
12458 | 313 |
SAXParserFactory spFactory = catalogManager.useServicesMechanism() ? |
314 |
SAXParserFactory.newInstance() : new SAXParserFactoryImpl(); |
|
6 | 315 |
spFactory.setNamespaceAware(true); |
316 |
try { |
|
317 |
reader = spFactory.newSAXParser().getXMLReader(); |
|
318 |
} |
|
319 |
catch (ParserConfigurationException ex) { |
|
320 |
throw new TransformerException(ex); |
|
321 |
} |
|
322 |
catch (SAXException ex) { |
|
323 |
throw new TransformerException(ex); |
|
324 |
} |
|
325 |
} |
|
326 |
reader.setEntityResolver(this); |
|
327 |
source.setXMLReader(reader); |
|
328 |
} |
|
329 |
||
330 |
/** Attempt to construct an absolute URI */ |
|
331 |
private String makeAbsolute(String uri) { |
|
332 |
if (uri == null) { |
|
333 |
uri = ""; |
|
334 |
} |
|
335 |
||
336 |
try { |
|
337 |
URL url = new URL(uri); |
|
338 |
return url.toString(); |
|
339 |
} catch (MalformedURLException mue) { |
|
340 |
try { |
|
341 |
URL fileURL = FileURL.makeURL(uri); |
|
342 |
return fileURL.toString(); |
|
343 |
} catch (MalformedURLException mue2) { |
|
344 |
// bail |
|
345 |
return uri; |
|
346 |
} |
|
347 |
} |
|
348 |
} |
|
349 |
} |