KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > io > XMLEntityResolver


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: XMLEntityResolver.java,v 1.3 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.io;
25
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.PrintWriter JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import org.enhydra.apache.xerces.readers.XCatalog;
33 import org.xml.sax.EntityResolver JavaDoc;
34 import org.xml.sax.InputSource JavaDoc;
35 import org.xml.sax.SAXException JavaDoc;
36
37 /**
38  * A flexable entity resolver for use with parsing XML files.
39  * This implements:
40  * <UL>
41  * <LI> XCatalog support.
42  * <LI> Resolving entities from class loaders.
43  * <LI> Resolving standard URL entities.
44  * <LI> A debug output stream, useful for debugging resolution problems.
45  * </UL>
46  * <P>
47  * A list of class loaders maybe associated with this object. If so
48  * an attempt will be made to resolve <code>file:</code> URLs from
49  * the class path.
50  *
51  * @see org.enhydra.apache.xerces.readers.XCatalog
52  */

53 public class XMLEntityResolver implements EntityResolver JavaDoc {
54     /**
55      * Protocol to use in specifying a URL pointing to the CLASSPATH.
56      */

57     public static final String JavaDoc CLASSPATH_PROTOCOL = "file";
58
59     /**
60      * Protocol prefix.
61      */

62     public static final String JavaDoc CLASSPATH_PROTOCOL_PREFIX
63         = CLASSPATH_PROTOCOL + ":";
64
65     /**
66      * URL for Enhydra default entity catalog.
67      * @see #setDefaultResolving
68      */

69     public static final String JavaDoc DEFAULT_ENTITY_CATALOG
70         = CLASSPATH_PROTOCOL_PREFIX + "/org/enhydra/xml/catalog/default.xcat";
71
72     /**
73      * URL for Lutrus Enhydra default entity catalog. Only loaded if
74      * available.
75      * @see #setDefaultResolving
76      */

77     public static final String JavaDoc LUTRIS_ENTITY_CATALOG
78         = CLASSPATH_PROTOCOL_PREFIX + "/org/enhydra/xml/catalog/lutris.xcat";
79
80     /**
81      * If not null, write debug information to this writer.
82      */

83     private PrintWriter JavaDoc fDebugWriter = null;
84
85     /**
86      * XCatalog catalog and entity resolver..
87      */

88     private XCatalog fXCatalog = new XCatalog();
89
90     /**
91      * List of ClassLoaders use to resolve entities.
92      */

93     private Vector JavaDoc fClassLoaders = new Vector JavaDoc();
94
95     /**
96      * Set a writer used to output debug messages.
97      */

98     public void setDebugWriter(PrintWriter JavaDoc writer) {
99         fDebugWriter = writer;
100     }
101     
102     /**
103      * Get the debug writer.
104      */

105     public PrintWriter JavaDoc getDebugWriter() {
106         return fDebugWriter;
107     }
108
109     /**
110      * Loads a catalog specified by the given input source and
111      * appends the contents to the catalog object.
112      *
113      * @param source The catalog source.
114      *
115      * @exception org.xml.sax.SAXException Throws exception on SAX error.
116      * @exception java.io.IOException Throws exception on i/o error.
117      */

118     public void loadCatalog(InputSource JavaDoc source)
119         throws SAXException JavaDoc, IOException JavaDoc {
120         if (fDebugWriter != null) {
121             fDebugWriter.println("loadCatalog(" + InputSourceOps.getName(source) + ")");
122         }
123         // Check for catalog on the CLASSPATH
124
InputSource JavaDoc loadSource = searchClassPath(source);
125         if (loadSource == null) {
126             loadSource = source;
127         }
128         if (fDebugWriter != null) {
129             fDebugWriter.println("loading catalog from(" + InputSourceOps.getName(loadSource) + ")");
130         }
131         fXCatalog.loadCatalog(loadSource);
132     }
133
134     /**
135      * Load the default entity catalog and enable loading entities the
136      * classloader for the classloader that loaded this class.
137      */

138     public void setDefaultResolving() throws SAXException JavaDoc, IOException JavaDoc {
139         // JDeveloper JVM doesn't correctly return system class loader
140
// if it loaded this class, so we do it explictly.
141
ClassLoader JavaDoc classLoader = XMLEntityResolver.class.getClassLoader();
142         if (classLoader == null) {
143             classLoader = ClassLoader.getSystemClassLoader();
144         }
145         addClassLoader(classLoader);
146         loadCatalog(new InputSource JavaDoc(DEFAULT_ENTITY_CATALOG));
147
148         // Check for optional default catalog
149
InputSource JavaDoc optSource = searchClassPath(LUTRIS_ENTITY_CATALOG);
150         if (optSource != null) {
151             loadCatalog(optSource);
152         }
153     }
154
155     /**
156      * Adds a public to system identifier mapping.
157      *
158      * @param publicId The public identifier, or "key".
159      * @param systemId The system identifier, or "value".
160      */

161     public void addPublicMapping(String JavaDoc publicId, String JavaDoc systemId) {
162         fXCatalog.addPublicMapping(publicId, systemId);
163     }
164
165     /**
166      * Removes a public identifier mapping.
167      *
168      * @param publicId The public identifier to remove.
169      */

170     public void removePublicMapping(System JavaDoc publicId) {
171         fXCatalog.removePublicMapping(publicId);
172     }
173
174     /** Returns an enumeration of public identifier mapping keys. */
175     public Enumeration JavaDoc getPublicMappingKeys() {
176         return fXCatalog.getPublicMappingKeys();
177     }
178
179     /**
180      * Returns a public identifier mapping.
181      *
182      * @param publicId The public identifier, or "key".
183      *
184      * @return Returns the system identifier value or null if there
185      * is no mapping defined.
186      */

187     public String JavaDoc getPublicMapping(String JavaDoc publicId) {
188         return fXCatalog.getPublicMapping(publicId);
189     }
190
191     /**
192      * Adds a system identifier alias.
193      *
194      * @param publicId The system identifier "key".
195      * @param systemId The system identifier "value".
196      */

197     public void addSystemMapping(String JavaDoc systemId1, String JavaDoc systemId2) {
198         fXCatalog.addSystemMapping(systemId1, systemId2);
199     }
200
201     /**
202      * Removes a system identifier alias.
203      *
204      * @param systemId The system identifier to remove.
205      */

206     public void removeSystemMapping(String JavaDoc systemId) {
207         fXCatalog.removeSystemMapping(systemId);
208     }
209
210     /** Returns an enumeration of system identifier mapping keys. */
211     public Enumeration JavaDoc getSystemMappingKeys() {
212         return fXCatalog.getSystemMappingKeys();
213     }
214
215     /**
216      * Returns a system identifier alias.
217      *
218      * @param systemId The system identifier "key".
219      *
220      * @return Returns the system identifier alias value or null if there
221      * is no alias defined.
222      */

223     public String JavaDoc getSystemMapping(String JavaDoc systemId) {
224         return fXCatalog.getSystemMapping(systemId);
225     }
226
227     /**
228      * Add a classloader to the end of the order list of classloaders to
229      * search for entities.
230      */

231     public void addClassLoader(ClassLoader JavaDoc classLoader) {
232         fClassLoaders.add(classLoader);
233     }
234
235     /**
236      * Get an enumeration of the class loaders.
237      */

238     public Enumeration JavaDoc getClassLoaders() {
239         return fClassLoaders.elements();
240     }
241
242     /**
243      * Attempt to load a systemId from a classloader.
244      */

245     private InputSource JavaDoc loadFromClassLoader(ClassLoader JavaDoc loader,
246                                             String JavaDoc resourceId)
247             throws IOException JavaDoc {
248         // Drop leading `/' from path.
249
if (resourceId.startsWith("/")) {
250             resourceId = resourceId.substring(1);
251         }
252         InputStream JavaDoc in = loader.getResourceAsStream(resourceId);
253         if (in != null) {
254             return new ClosingInputSource(in);
255         } else {
256             return null;
257         }
258     }
259
260     /**
261      * Determine if a a system id is a CLASSPATH URL.
262      */

263     private boolean isClassPathURL(String JavaDoc systemId) {
264         return ((systemId != null) && systemId.startsWith(CLASSPATH_PROTOCOL_PREFIX));
265     }
266
267     /**
268      * Get the file name from a CLASSPATH URL.
269      */

270     private String JavaDoc parseClassPathURL(String JavaDoc url) {
271         return url.substring(CLASSPATH_PROTOCOL_PREFIX.length());
272     }
273
274     /**
275      * Attempt to load a systemId from a classpath. Will return an
276      * InputSource with a contained byte stream (doesn't need closed). If
277      * systemId is null or dosen't have the file: protocal, then null is
278      * returned.
279      */

280     private InputSource JavaDoc searchClassPath(String JavaDoc systemId)
281             throws IOException JavaDoc {
282         InputSource JavaDoc source = null;
283         if ((systemId != null) && isClassPathURL(systemId)) {
284             String JavaDoc resourceName = parseClassPathURL(systemId);
285             int len = fClassLoaders.size();
286             for (int idx = 0; (idx < len) && (source == null); idx++) {
287                 source = loadFromClassLoader((ClassLoader JavaDoc)fClassLoaders.get(idx),
288                                              resourceName);
289             }
290             if (source != null) {
291                 source.setSystemId(systemId);
292             }
293         }
294         if (fDebugWriter != null) {
295             fDebugWriter.println("Entity " + ((source == null) ? "not " : "")
296                                  + "found searching " + fClassLoaders.size()
297                                  + " class loader(s): " + systemId
298                                  + " => " + InputSourceOps.getName(source));
299         }
300         return source;
301     }
302
303     /**
304      * @see #searchClassPath#String
305      */

306     private InputSource JavaDoc searchClassPath(InputSource JavaDoc source)
307             throws IOException JavaDoc {
308         if ((source.getByteStream() != null)
309             || (source.getCharacterStream() != null)) {
310             return null; // Already open.
311
} else {
312             return searchClassPath(source.getSystemId());
313         }
314     }
315
316
317     /**
318      * @see org.xml.sax.EntityResolver
319      */

320     public InputSource JavaDoc resolveEntity(String JavaDoc publicId,
321                                      String JavaDoc systemId)
322     throws SAXException JavaDoc, IOException JavaDoc {
323         if (fDebugWriter != null) {
324             fDebugWriter.println("resolveEntity(" + publicId + ", " + systemId + ")");
325         }
326
327         InputSource JavaDoc source;
328         InputSource JavaDoc catalogSource = fXCatalog.resolveEntity(publicId,
329                                                             systemId);
330         if (catalogSource != null) {
331             if (fDebugWriter != null) {
332                 fDebugWriter.println("XMLCatalog maps entity to: " + catalogSource.getSystemId()); //
333
}
334             source = searchClassPath(catalogSource);
335             if (source == null) {
336                 source = catalogSource; // Use unchanged.
337
}
338         } else {
339             source = searchClassPath(systemId);
340         }
341         if (fDebugWriter != null) {
342             fDebugWriter.println("Resolved: " + InputSourceOps.getName(source));
343         }
344         return source;
345     }
346 }
347
Popular Tags