author | joehw |
Wed, 14 Sep 2016 13:18:17 -0700 | |
changeset 41021 | 444f2b1bcc8c |
parent 39080 | 57563e513b11 |
child 44797 | 8b3b3b911b8a |
permissions | -rw-r--r-- |
6 | 1 |
/* |
2 |
* reserved comment block |
|
3 |
* DO NOT REMOVE OR ALTER! |
|
4 |
*/ |
|
5 |
/* |
|
6 |
* Copyright 2004,2005 The Apache Software Foundation. |
|
7 |
* |
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 |
* you may not use this file except in compliance with the License. |
|
10 |
* You may obtain a copy of the License at |
|
11 |
* |
|
12 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
13 |
* |
|
14 |
* Unless required by applicable law or agreed to in writing, software |
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 |
* See the License for the specific language governing permissions and |
|
18 |
* limitations under the License. |
|
19 |
*/ |
|
20 |
||
21 |
package com.sun.org.apache.xerces.internal.util; |
|
22 |
||
23 |
import java.io.IOException; |
|
24 |
||
25 |
import org.xml.sax.InputSource; |
|
26 |
import org.xml.sax.SAXException; |
|
27 |
import org.xml.sax.ext.EntityResolver2; |
|
28 |
||
29 |
import org.w3c.dom.ls.LSInput; |
|
30 |
import org.w3c.dom.ls.LSResourceResolver; |
|
31 |
||
32 |
import javax.xml.parsers.SAXParserFactory; |
|
33 |
||
34 |
import com.sun.org.apache.xerces.internal.dom.DOMInputImpl; |
|
35 |
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; |
|
36 |
||
37 |
import com.sun.org.apache.xerces.internal.xni.XNIException; |
|
38 |
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; |
|
39 |
||
40 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; |
|
41 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; |
|
42 |
||
43 |
import com.sun.org.apache.xml.internal.resolver.Catalog; |
|
44 |
import com.sun.org.apache.xml.internal.resolver.CatalogManager; |
|
45 |
import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader; |
|
46 |
import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader; |
|
47 |
||
48 |
/** |
|
49 |
* <p>The catalog resolver handles the resolution of external |
|
50 |
* identifiers and URI references through XML catalogs. This |
|
51 |
* component supports XML catalogs defined by the |
|
52 |
* <a href="http://www.oasis-open.org/committees/entity/spec.html"> |
|
53 |
* OASIS XML Catalogs Specification</a>. It encapsulates the |
|
54 |
* <a href="http://xml.apache.org/commons/">XML Commons</a> resolver. |
|
55 |
* An instance of this class may be registered on the parser |
|
56 |
* as a SAX entity resolver, as a DOM LSResourceResolver or |
|
57 |
* as an XNI entity resolver by setting the property |
|
58 |
* (http://apache.org/xml/properties/internal/entity-resolver).</p> |
|
59 |
* |
|
60 |
* <p>It is intended that this class may be used standalone to perform |
|
61 |
* catalog resolution outside of a parsing context. It may be shared |
|
62 |
* between several parsers and the application.</p> |
|
63 |
* |
|
41021
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
64 |
* @deprecated This class and the JDK internal Catalog API in package |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
65 |
* {@code com.sun.org.apache.xml.internal.resolver} |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
66 |
* 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:
39080
diff
changeset
|
67 |
* deprecated and subject to removal in a future release. Users of the API should |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
68 |
* migrate to the {@linkplain javax.xml.catalog new public API}. |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
69 |
* <p> |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
70 |
* 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:
39080
diff
changeset
|
71 |
* the use of Catalog by simply setting a path to a Catalog file as a property. |
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
72 |
* |
6 | 73 |
* @author Michael Glavassevich, IBM |
74 |
* |
|
75 |
*/ |
|
41021
444f2b1bcc8c
8165784: Deprecate the internal Catalog API in JDK 9
joehw
parents:
39080
diff
changeset
|
76 |
@Deprecated(since="9", forRemoval=true) |
6 | 77 |
public class XMLCatalogResolver |
78 |
implements XMLEntityResolver, EntityResolver2, LSResourceResolver { |
|
79 |
||
80 |
/** Internal catalog manager for Apache catalogs. **/ |
|
81 |
private CatalogManager fResolverCatalogManager = null; |
|
82 |
||
83 |
/** Internal catalog structure. **/ |
|
84 |
private Catalog fCatalog = null; |
|
85 |
||
86 |
/** An array of catalog URIs. **/ |
|
87 |
private String [] fCatalogsList = null; |
|
88 |
||
89 |
/** |
|
90 |
* Indicates whether the list of catalogs has |
|
91 |
* changed since it was processed. |
|
92 |
*/ |
|
93 |
private boolean fCatalogsChanged = true; |
|
94 |
||
95 |
/** Application specified prefer public setting. **/ |
|
96 |
private boolean fPreferPublic = true; |
|
97 |
||
98 |
/** |
|
99 |
* Indicates whether the application desires that |
|
100 |
* the parser or some other component performing catalog |
|
101 |
* resolution should use the literal system identifier |
|
102 |
* instead of the expanded system identifier. |
|
103 |
*/ |
|
104 |
private boolean fUseLiteralSystemId = true; |
|
105 |
||
106 |
/** |
|
107 |
* <p>Constructs a catalog resolver with a default configuration.</p> |
|
108 |
*/ |
|
109 |
public XMLCatalogResolver () { |
|
110 |
this(null, true); |
|
111 |
} |
|
112 |
||
113 |
/** |
|
114 |
* <p>Constructs a catalog resolver with the given |
|
115 |
* list of entry files.</p> |
|
116 |
* |
|
117 |
* @param catalogs an ordered array list of absolute URIs |
|
118 |
*/ |
|
119 |
public XMLCatalogResolver (String [] catalogs) { |
|
120 |
this(catalogs, true); |
|
121 |
} |
|
122 |
||
123 |
/** |
|
124 |
* <p>Constructs a catalog resolver with the given |
|
125 |
* list of entry files and the preference for whether |
|
126 |
* system or public matches are preferred.</p> |
|
127 |
* |
|
128 |
* @param catalogs an ordered array list of absolute URIs |
|
129 |
* @param preferPublic the prefer public setting |
|
130 |
*/ |
|
131 |
public XMLCatalogResolver (String [] catalogs, boolean preferPublic) { |
|
132 |
init(catalogs, preferPublic); |
|
133 |
} |
|
134 |
||
135 |
/** |
|
136 |
* <p>Returns the initial list of catalog entry files.</p> |
|
137 |
* |
|
138 |
* @return the initial list of catalog entry files |
|
139 |
*/ |
|
140 |
public final synchronized String [] getCatalogList () { |
|
141 |
return (fCatalogsList != null) |
|
142 |
? (String[]) fCatalogsList.clone() : null; |
|
143 |
} |
|
144 |
||
145 |
/** |
|
146 |
* <p>Sets the initial list of catalog entry files. |
|
147 |
* If there were any catalog mappings cached from |
|
148 |
* the previous list they will be replaced by catalog |
|
149 |
* mappings from the new list the next time the catalog |
|
150 |
* is queried.</p> |
|
151 |
* |
|
152 |
* @param catalogs an ordered array list of absolute URIs |
|
153 |
*/ |
|
154 |
public final synchronized void setCatalogList (String [] catalogs) { |
|
155 |
fCatalogsChanged = true; |
|
156 |
fCatalogsList = (catalogs != null) |
|
157 |
? (String[]) catalogs.clone() : null; |
|
158 |
} |
|
159 |
||
160 |
/** |
|
161 |
* <p>Forces the cache of catalog mappings to be cleared.</p> |
|
162 |
*/ |
|
163 |
public final synchronized void clear () { |
|
164 |
fCatalog = null; |
|
165 |
} |
|
166 |
||
167 |
/** |
|
168 |
* <p>Returns the preference for whether system or public |
|
169 |
* matches are preferred. This is used in the absence |
|
170 |
* of any occurence of the <code>prefer</code> attribute |
|
171 |
* on the <code>catalog</code> entry of a catalog. If this |
|
172 |
* property has not yet been explicitly set its value is |
|
173 |
* <code>true</code>.</p> |
|
174 |
* |
|
175 |
* @return the prefer public setting |
|
176 |
*/ |
|
177 |
public final boolean getPreferPublic () { |
|
178 |
return fPreferPublic; |
|
179 |
} |
|
180 |
||
181 |
/** |
|
182 |
* <p>Sets the preference for whether system or public |
|
183 |
* matches are preferred. This is used in the absence |
|
184 |
* of any occurence of the <code>prefer</code> attribute |
|
185 |
* on the <code>catalog</code> entry of a catalog.</p> |
|
186 |
* |
|
187 |
* @param preferPublic the prefer public setting |
|
188 |
*/ |
|
189 |
public final void setPreferPublic (boolean preferPublic) { |
|
190 |
fPreferPublic = preferPublic; |
|
191 |
fResolverCatalogManager.setPreferPublic(preferPublic); |
|
192 |
} |
|
193 |
||
194 |
/** |
|
195 |
* <p>Returns the preference for whether the literal system |
|
196 |
* identifier should be used when resolving system |
|
197 |
* identifiers when both it and the expanded system |
|
198 |
* identifier are available. If this property has not yet |
|
199 |
* been explicitly set its value is <code>true</code>.</p> |
|
200 |
* |
|
201 |
* @return the preference for using literal system identifers |
|
202 |
* for catalog resolution |
|
203 |
* |
|
204 |
* @see #setUseLiteralSystemId |
|
205 |
*/ |
|
206 |
public final boolean getUseLiteralSystemId () { |
|
207 |
return fUseLiteralSystemId; |
|
208 |
} |
|
209 |
||
210 |
/** |
|
211 |
* <p>Sets the preference for whether the literal system |
|
212 |
* identifier should be used when resolving system |
|
213 |
* identifiers when both it and the expanded system |
|
214 |
* identifier are available.</p> |
|
215 |
* |
|
216 |
* <p>The literal system identifier is the URI as it was |
|
217 |
* provided before absolutization. It may be embedded within |
|
218 |
* an entity. It may be provided externally or it may be the |
|
219 |
* result of redirection. For example, redirection may |
|
220 |
* have come from the protocol level through HTTP or from |
|
221 |
* an application's entity resolver.</p> |
|
222 |
* |
|
223 |
* <p>The expanded system identifier is an absolute URI |
|
224 |
* which is the result of resolving the literal system |
|
225 |
* identifier against a base URI.</p> |
|
226 |
* |
|
227 |
* @param useLiteralSystemId the preference for using |
|
228 |
* literal system identifers for catalog resolution |
|
229 |
*/ |
|
230 |
public final void setUseLiteralSystemId (boolean useLiteralSystemId) { |
|
231 |
fUseLiteralSystemId = useLiteralSystemId; |
|
232 |
} |
|
233 |
||
234 |
/** |
|
235 |
* <p>Resolves an external entity. If the entity cannot be |
|
236 |
* resolved, this method should return <code>null</code>. This |
|
237 |
* method returns an input source if an entry was found in the |
|
238 |
* catalog for the given external identifier. It should be |
|
239 |
* overrided if other behaviour is required.</p> |
|
240 |
* |
|
241 |
* @param publicId the public identifier, or <code>null</code> if none was supplied |
|
242 |
* @param systemId the system identifier |
|
243 |
* |
|
244 |
* @throws SAXException any SAX exception, possibly wrapping another exception |
|
245 |
* @throws IOException thrown if some i/o error occurs |
|
246 |
*/ |
|
247 |
public InputSource resolveEntity(String publicId, String systemId) |
|
248 |
throws SAXException, IOException { |
|
249 |
||
250 |
String resolvedId = null; |
|
251 |
if (publicId != null && systemId != null) { |
|
252 |
resolvedId = resolvePublic(publicId, systemId); |
|
253 |
} |
|
254 |
else if (systemId != null) { |
|
255 |
resolvedId = resolveSystem(systemId); |
|
256 |
} |
|
257 |
||
258 |
if (resolvedId != null) { |
|
259 |
InputSource source = new InputSource(resolvedId); |
|
260 |
source.setPublicId(publicId); |
|
261 |
return source; |
|
262 |
} |
|
263 |
return null; |
|
264 |
} |
|
265 |
||
266 |
/** |
|
267 |
* <p>Resolves an external entity. If the entity cannot be |
|
268 |
* resolved, this method should return <code>null</code>. This |
|
269 |
* method returns an input source if an entry was found in the |
|
270 |
* catalog for the given external identifier. It should be |
|
271 |
* overrided if other behaviour is required.</p> |
|
272 |
* |
|
273 |
* @param name the identifier of the external entity |
|
274 |
* @param publicId the public identifier, or <code>null</code> if none was supplied |
|
275 |
* @param baseURI the URI with respect to which relative systemIDs are interpreted. |
|
276 |
* @param systemId the system identifier |
|
277 |
* |
|
278 |
* @throws SAXException any SAX exception, possibly wrapping another exception |
|
279 |
* @throws IOException thrown if some i/o error occurs |
|
280 |
*/ |
|
281 |
public InputSource resolveEntity(String name, String publicId, |
|
282 |
String baseURI, String systemId) throws SAXException, IOException { |
|
283 |
||
284 |
String resolvedId = null; |
|
285 |
||
286 |
if (!getUseLiteralSystemId() && baseURI != null) { |
|
287 |
// Attempt to resolve the system identifier against the base URI. |
|
288 |
try { |
|
289 |
URI uri = new URI(new URI(baseURI), systemId); |
|
290 |
systemId = uri.toString(); |
|
291 |
} |
|
292 |
// Ignore the exception. Fallback to the literal system identifier. |
|
293 |
catch (URI.MalformedURIException ex) {} |
|
294 |
} |
|
295 |
||
296 |
if (publicId != null && systemId != null) { |
|
297 |
resolvedId = resolvePublic(publicId, systemId); |
|
298 |
} |
|
299 |
else if (systemId != null) { |
|
300 |
resolvedId = resolveSystem(systemId); |
|
301 |
} |
|
302 |
||
303 |
if (resolvedId != null) { |
|
304 |
InputSource source = new InputSource(resolvedId); |
|
305 |
source.setPublicId(publicId); |
|
306 |
return source; |
|
307 |
} |
|
308 |
return null; |
|
309 |
} |
|
310 |
||
311 |
/** |
|
312 |
* <p>Locates an external subset for documents which do not explicitly |
|
313 |
* provide one. This method always returns <code>null</code>. It |
|
314 |
* should be overrided if other behaviour is required.</p> |
|
315 |
* |
|
316 |
* @param name the identifier of the document root element |
|
317 |
* @param baseURI the document's base URI |
|
318 |
* |
|
319 |
* @throws SAXException any SAX exception, possibly wrapping another exception |
|
320 |
* @throws IOException thrown if some i/o error occurs |
|
321 |
*/ |
|
322 |
public InputSource getExternalSubset(String name, String baseURI) |
|
323 |
throws SAXException, IOException { |
|
324 |
return null; |
|
325 |
} |
|
326 |
||
327 |
/** |
|
328 |
* <p>Resolves a resource using the catalog. This method interprets that |
|
329 |
* the namespace URI corresponds to uri entries in the catalog. |
|
330 |
* Where both a namespace and an external identifier exist, the namespace |
|
331 |
* takes precedence.</p> |
|
332 |
* |
|
333 |
* @param type the type of the resource being resolved |
|
334 |
* @param namespaceURI the namespace of the resource being resolved, |
|
335 |
* or <code>null</code> if none was supplied |
|
336 |
* @param publicId the public identifier of the resource being resolved, |
|
337 |
* or <code>null</code> if none was supplied |
|
338 |
* @param systemId the system identifier of the resource being resolved, |
|
339 |
* or <code>null</code> if none was supplied |
|
340 |
* @param baseURI the absolute base URI of the resource being parsed, |
|
341 |
* or <code>null</code> if there is no base URI |
|
342 |
*/ |
|
343 |
public LSInput resolveResource(String type, String namespaceURI, |
|
344 |
String publicId, String systemId, String baseURI) { |
|
345 |
||
346 |
String resolvedId = null; |
|
347 |
||
348 |
try { |
|
349 |
// The namespace is useful for resolving namespace aware |
|
350 |
// grammars such as XML schema. Let it take precedence over |
|
351 |
// the external identifier if one exists. |
|
352 |
if (namespaceURI != null) { |
|
353 |
resolvedId = resolveURI(namespaceURI); |
|
354 |
} |
|
355 |
||
356 |
if (!getUseLiteralSystemId() && baseURI != null) { |
|
357 |
// Attempt to resolve the system identifier against the base URI. |
|
358 |
try { |
|
359 |
URI uri = new URI(new URI(baseURI), systemId); |
|
360 |
systemId = uri.toString(); |
|
361 |
} |
|
362 |
// Ignore the exception. Fallback to the literal system identifier. |
|
363 |
catch (URI.MalformedURIException ex) {} |
|
364 |
} |
|
365 |
||
366 |
// Resolve against an external identifier if one exists. This |
|
367 |
// is useful for resolving DTD external subsets and other |
|
368 |
// external entities. For XML schemas if there was no namespace |
|
369 |
// mapping we might be able to resolve a system identifier |
|
370 |
// specified as a location hint. |
|
371 |
if (resolvedId == null) { |
|
372 |
if (publicId != null && systemId != null) { |
|
373 |
resolvedId = resolvePublic(publicId, systemId); |
|
374 |
} |
|
375 |
else if (systemId != null) { |
|
376 |
resolvedId = resolveSystem(systemId); |
|
377 |
} |
|
378 |
} |
|
379 |
} |
|
380 |
// Ignore IOException. It cannot be thrown from this method. |
|
381 |
catch (IOException ex) {} |
|
382 |
||
383 |
if (resolvedId != null) { |
|
384 |
return new DOMInputImpl(publicId, resolvedId, baseURI); |
|
385 |
} |
|
386 |
return null; |
|
387 |
} |
|
388 |
||
389 |
||
390 |
/** |
|
391 |
* <p>Resolves an external entity. If the entity cannot be |
|
392 |
* resolved, this method should return <code>null</code>. This |
|
393 |
* method only calls <code>resolveIdentifier</code> and returns |
|
394 |
* an input source if an entry was found in the catalog. It |
|
395 |
* should be overrided if other behaviour is required.</p> |
|
396 |
* |
|
397 |
* @param resourceIdentifier location of the XML resource to resolve |
|
398 |
* |
|
399 |
* @throws XNIException thrown on general error |
|
400 |
* @throws IOException thrown if some i/o error occurs |
|
401 |
*/ |
|
402 |
public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) |
|
403 |
throws XNIException, IOException { |
|
404 |
||
405 |
String resolvedId = resolveIdentifier(resourceIdentifier); |
|
406 |
if (resolvedId != null) { |
|
407 |
return new XMLInputSource(resourceIdentifier.getPublicId(), |
|
39080
57563e513b11
8158204: accessExternalSchema property handling is inconsistent and differs from spec.
joehw
parents:
25868
diff
changeset
|
408 |
resolvedId, resourceIdentifier.getBaseSystemId(), false); |
6 | 409 |
} |
410 |
return null; |
|
411 |
} |
|
412 |
||
413 |
/** |
|
414 |
* <p>Resolves an identifier using the catalog. This method interprets that |
|
415 |
* the namespace of the identifier corresponds to uri entries in the catalog. |
|
416 |
* Where both a namespace and an external identifier exist, the namespace |
|
417 |
* takes precedence.</p> |
|
418 |
* |
|
419 |
* @param resourceIdentifier the identifier to resolve |
|
420 |
* |
|
421 |
* @throws XNIException thrown on general error |
|
422 |
* @throws IOException thrown if some i/o error occurs |
|
423 |
*/ |
|
424 |
public String resolveIdentifier(XMLResourceIdentifier resourceIdentifier) |
|
425 |
throws IOException, XNIException { |
|
426 |
||
427 |
String resolvedId = null; |
|
428 |
||
429 |
// The namespace is useful for resolving namespace aware |
|
430 |
// grammars such as XML schema. Let it take precedence over |
|
431 |
// the external identifier if one exists. |
|
432 |
String namespace = resourceIdentifier.getNamespace(); |
|
433 |
if (namespace != null) { |
|
434 |
resolvedId = resolveURI(namespace); |
|
435 |
} |
|
436 |
||
437 |
// Resolve against an external identifier if one exists. This |
|
438 |
// is useful for resolving DTD external subsets and other |
|
439 |
// external entities. For XML schemas if there was no namespace |
|
440 |
// mapping we might be able to resolve a system identifier |
|
441 |
// specified as a location hint. |
|
442 |
if (resolvedId == null) { |
|
443 |
String publicId = resourceIdentifier.getPublicId(); |
|
444 |
String systemId = getUseLiteralSystemId() |
|
445 |
? resourceIdentifier.getLiteralSystemId() |
|
446 |
: resourceIdentifier.getExpandedSystemId(); |
|
447 |
if (publicId != null && systemId != null) { |
|
448 |
resolvedId = resolvePublic(publicId, systemId); |
|
449 |
} |
|
450 |
else if (systemId != null) { |
|
451 |
resolvedId = resolveSystem(systemId); |
|
452 |
} |
|
453 |
} |
|
454 |
return resolvedId; |
|
455 |
} |
|
456 |
||
457 |
/** |
|
458 |
* <p>Returns the URI mapping in the catalog for the given |
|
459 |
* external identifier or <code>null</code> if no mapping |
|
460 |
* exists. If the system identifier is an URN in the |
|
461 |
* <code>publicid</code> namespace it is converted into |
|
462 |
* a public identifier by URN "unwrapping" as specified |
|
463 |
* in the XML Catalogs specification.</p> |
|
464 |
* |
|
465 |
* @param systemId the system identifier to locate in the catalog |
|
466 |
* |
|
467 |
* @return the mapped URI or <code>null</code> if no mapping |
|
468 |
* was found in the catalog |
|
469 |
* |
|
470 |
* @throws IOException if an i/o error occurred while reading |
|
471 |
* the catalog |
|
472 |
*/ |
|
473 |
public final synchronized String resolveSystem (String systemId) |
|
474 |
throws IOException { |
|
475 |
||
476 |
if (fCatalogsChanged) { |
|
477 |
parseCatalogs(); |
|
478 |
fCatalogsChanged = false; |
|
479 |
} |
|
480 |
return (fCatalog != null) |
|
481 |
? fCatalog.resolveSystem(systemId) : null; |
|
482 |
} |
|
483 |
||
484 |
/** |
|
485 |
* <p>Returns the URI mapping in the catalog for the given |
|
486 |
* external identifier or <code>null</code> if no mapping |
|
487 |
* exists. Public identifiers are normalized before |
|
488 |
* comparison.</p> |
|
489 |
* |
|
490 |
* @param publicId the public identifier to locate in the catalog |
|
491 |
* @param systemId the system identifier to locate in the catalog |
|
492 |
* |
|
493 |
* @return the mapped URI or <code>null</code> if no mapping |
|
494 |
* was found in the catalog |
|
495 |
* |
|
496 |
* @throws IOException if an i/o error occurred while reading |
|
497 |
* the catalog |
|
498 |
*/ |
|
499 |
public final synchronized String resolvePublic (String publicId, String systemId) |
|
500 |
throws IOException { |
|
501 |
||
502 |
if (fCatalogsChanged) { |
|
503 |
parseCatalogs(); |
|
504 |
fCatalogsChanged = false; |
|
505 |
} |
|
506 |
return (fCatalog != null) |
|
507 |
? fCatalog.resolvePublic(publicId, systemId) : null; |
|
508 |
} |
|
509 |
||
510 |
/** |
|
511 |
* <p>Returns the URI mapping in the catalog for the given URI |
|
512 |
* reference or <code>null</code> if no mapping exists. |
|
513 |
* URI comparison is case sensitive. If the URI reference |
|
514 |
* is an URN in the <code>publicid</code> namespace |
|
515 |
* it is converted into a public identifier by URN "unwrapping" |
|
516 |
* as specified in the XML Catalogs specification and then |
|
517 |
* resolution is performed following the semantics of |
|
518 |
* external identifier resolution.</p> |
|
519 |
* |
|
520 |
* @param uri the URI to locate in the catalog |
|
521 |
* |
|
522 |
* @return the mapped URI or <code>null</code> if no mapping |
|
523 |
* was found in the catalog |
|
524 |
* |
|
525 |
* @throws IOException if an i/o error occurred while reading |
|
526 |
* the catalog |
|
527 |
*/ |
|
528 |
public final synchronized String resolveURI (String uri) |
|
529 |
throws IOException { |
|
530 |
||
531 |
if (fCatalogsChanged) { |
|
532 |
parseCatalogs(); |
|
533 |
fCatalogsChanged = false; |
|
534 |
} |
|
535 |
return (fCatalog != null) |
|
536 |
? fCatalog.resolveURI(uri) : null; |
|
537 |
} |
|
538 |
||
539 |
/** |
|
540 |
* Initialization. Create a CatalogManager and set all |
|
541 |
* the properties upfront. This prevents JVM wide system properties |
|
542 |
* or a property file somewhere in the environment from affecting |
|
543 |
* the behaviour of this catalog resolver. |
|
544 |
*/ |
|
545 |
private void init (String [] catalogs, boolean preferPublic) { |
|
546 |
fCatalogsList = (catalogs != null) ? (String[]) catalogs.clone() : null; |
|
547 |
fPreferPublic = preferPublic; |
|
548 |
fResolverCatalogManager = new CatalogManager(); |
|
549 |
fResolverCatalogManager.setAllowOasisXMLCatalogPI(false); |
|
550 |
fResolverCatalogManager.setCatalogClassName("com.sun.org.apache.xml.internal.resolver.Catalog"); |
|
551 |
fResolverCatalogManager.setCatalogFiles(""); |
|
552 |
fResolverCatalogManager.setIgnoreMissingProperties(true); |
|
553 |
fResolverCatalogManager.setPreferPublic(fPreferPublic); |
|
554 |
fResolverCatalogManager.setRelativeCatalogs(false); |
|
555 |
fResolverCatalogManager.setUseStaticCatalog(false); |
|
556 |
fResolverCatalogManager.setVerbosity(0); |
|
557 |
} |
|
558 |
||
559 |
/** |
|
560 |
* Instruct the <code>Catalog</code> to parse each of the |
|
561 |
* catalogs in the list. Only the first catalog will actually be |
|
562 |
* parsed immediately. The others will be queued and read if |
|
563 |
* they are needed later. |
|
564 |
*/ |
|
565 |
private void parseCatalogs () throws IOException { |
|
566 |
if (fCatalogsList != null) { |
|
567 |
fCatalog = new Catalog(fResolverCatalogManager); |
|
568 |
attachReaderToCatalog(fCatalog); |
|
569 |
for (int i = 0; i < fCatalogsList.length; ++i) { |
|
570 |
String catalog = fCatalogsList[i]; |
|
571 |
if (catalog != null && catalog.length() > 0) { |
|
572 |
fCatalog.parseCatalog(catalog); |
|
573 |
} |
|
574 |
} |
|
575 |
} |
|
576 |
else { |
|
577 |
fCatalog = null; |
|
578 |
} |
|
579 |
} |
|
580 |
||
581 |
/** |
|
582 |
* Attaches the reader to the catalog. |
|
583 |
*/ |
|
584 |
private void attachReaderToCatalog (Catalog catalog) { |
|
585 |
||
586 |
SAXParserFactory spf = new SAXParserFactoryImpl(); |
|
587 |
spf.setNamespaceAware(true); |
|
588 |
spf.setValidating(false); |
|
589 |
||
590 |
SAXCatalogReader saxReader = new SAXCatalogReader(spf); |
|
591 |
saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName, "catalog", |
|
592 |
"com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader"); |
|
593 |
catalog.addReader("application/xml", saxReader); |
|
594 |
} |
|
595 |
} |