KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > w3c > dom > bootstrap > DOMImplementationRegistry


1 /*
2  * Copyright (c) 2004 World Wide Web Consortium,
3  *
4  * (Massachusetts Institute of Technology, European Research Consortium for
5  * Informatics and Mathematics, Keio University). All Rights Reserved. This
6  * work is distributed under the W3C(r) Software License [1] in the hope that
7  * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
8  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  *
10  * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
11  */

12
13
14 package org.w3c.dom.bootstrap;
15
16 import java.util.StringTokenizer JavaDoc;
17 import java.util.Vector JavaDoc;
18 import org.w3c.dom.DOMImplementationSource JavaDoc;
19 import org.w3c.dom.DOMImplementationList JavaDoc;
20 import org.w3c.dom.DOMImplementation JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.BufferedReader JavaDoc;
23 import java.io.InputStreamReader JavaDoc;
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedAction JavaDoc;
26
27 /**
28  * A factory that enables applications to obtain instances of
29  * <code>DOMImplementation</code>.
30  *
31  * <p>
32  * Example:
33  * </p>
34  *
35  * <pre class='example'>
36  * // get an instance of the DOMImplementation registry
37  * DOMImplementationRegistry registry =
38  * DOMImplementationRegistry.newInstance();
39  * // get a DOM implementation the Level 3 XML module
40  * DOMImplementation domImpl =
41  * registry.getDOMImplementation("XML 3.0");
42  * </pre>
43  *
44  * <p>
45  * This provides an application with an implementation-independent starting
46  * point. DOM implementations may modify this class to meet new security
47  * standards or to provide *additional* fallbacks for the list of
48  * DOMImplementationSources.
49  * </p>
50  *
51  * @see DOMImplementation
52  * @see DOMImplementationSource
53  * @since DOM Level 3
54  */

55 public final class DOMImplementationRegistry {
56     /**
57      * The system property to specify the
58      * DOMImplementationSource class names.
59      */

60     public static final String JavaDoc PROPERTY =
61     "org.w3c.dom.DOMImplementationSourceList";
62     
63     /**
64      * Default columns per line.
65      */

66     private static final int DEFAULT_LINE_LENGTH = 80;
67     
68     /**
69      * The list of DOMImplementationSources.
70      */

71     private Vector JavaDoc sources;
72     
73     /**
74      * Private constructor.
75      * @param srcs Vector List of DOMImplementationSources
76      */

77     private DOMImplementationRegistry(final Vector JavaDoc srcs) {
78     sources = srcs;
79     }
80     
81     /**
82      * Obtain a new instance of a <code>DOMImplementationRegistry</code>.
83      *
84
85      * The <code>DOMImplementationRegistry</code> is initialized by the
86      * application or the implementation, depending on the context, by
87      * first checking the value of the Java system property
88      * <code>org.w3c.dom.DOMImplementationSourceList</code> and
89      * the the service provider whose contents are at
90      * "<code>META_INF/services/org.w3c.dom.DOMImplementationSourceList</code>"
91      * The value of this property is a white-space separated list of
92      * names of availables classes implementing the
93      * <code>DOMImplementationSource</code> interface. Each class listed
94      * in the class name list is instantiated and any exceptions
95      * encountered are thrown to the application.
96      *
97      * @return an initialized instance of DOMImplementationRegistry
98      * @throws ClassNotFoundException
99      * If any specified class can not be found
100      * @throws InstantiationException
101      * If any specified class is an interface or abstract class
102      * @throws IllegalAccessException
103      * If the default constructor of a specified class is not accessible
104      * @throws ClassCastException
105      * If any specified class does not implement
106      * <code>DOMImplementationSource</code>
107      */

108     public static DOMImplementationRegistry JavaDoc newInstance()
109     throws
110     ClassNotFoundException JavaDoc,
111     InstantiationException JavaDoc,
112     IllegalAccessException JavaDoc,
113     ClassCastException JavaDoc {
114     Vector JavaDoc sources = new Vector JavaDoc();
115     
116     ClassLoader JavaDoc classLoader = getClassLoader();
117     // fetch system property:
118
String JavaDoc p = getSystemProperty(PROPERTY);
119     
120     //
121
// if property is not specified then use contents of
122
// META_INF/org.w3c.dom.DOMImplementationSourceList from classpath
123
if (p == null) {
124         p = getServiceValue(classLoader);
125     }
126         if (p == null) {
127         //
128
// DOM Implementations can modify here to add *additional* fallback
129
// mechanisms to access a list of default DOMImplementationSources.
130

131     }
132     if (p != null) {
133         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(p);
134         while (st.hasMoreTokens()) {
135         String JavaDoc sourceName = st.nextToken();
136         // Use context class loader, falling back to Class.forName
137
// if and only if this fails...
138
Class JavaDoc sourceClass = null;
139         if (classLoader != null) {
140             sourceClass = classLoader.loadClass(sourceName);
141         } else {
142             sourceClass = Class.forName(sourceName);
143         }
144         DOMImplementationSource JavaDoc source =
145             (DOMImplementationSource JavaDoc) sourceClass.newInstance();
146         sources.addElement(source);
147         }
148     }
149     return new DOMImplementationRegistry JavaDoc(sources);
150     }
151     
152     /**
153      * Return the first implementation that has the desired
154      * features, or <code>null</code> if none is found.
155      *
156      * @param features
157      * A string that specifies which features are required. This is
158      * a space separated list in which each feature is specified by
159      * its name optionally followed by a space and a version number.
160      * This is something like: "XML 1.0 Traversal +Events 2.0"
161      * @return An implementation that has the desired features,
162      * or <code>null</code> if none found.
163      */

164     public DOMImplementation JavaDoc getDOMImplementation(final String JavaDoc features) {
165     int size = sources.size();
166     String JavaDoc name = null;
167     for (int i = 0; i < size; i++) {
168         DOMImplementationSource JavaDoc source =
169         (DOMImplementationSource JavaDoc) sources.elementAt(i);
170         DOMImplementation JavaDoc impl = source.getDOMImplementation(features);
171         if (impl != null) {
172         return impl;
173         }
174     }
175     return null;
176     }
177     
178     /**
179      * Return a list of implementations that support the
180      * desired features.
181      *
182      * @param features
183      * A string that specifies which features are required. This is
184      * a space separated list in which each feature is specified by
185      * its name optionally followed by a space and a version number.
186      * This is something like: "XML 1.0 Traversal +Events 2.0"
187      * @return A list of DOMImplementations that support the desired features.
188      */

189     public DOMImplementationList JavaDoc getDOMImplementationList(final String JavaDoc features) {
190     final Vector JavaDoc implementations = new Vector JavaDoc();
191     int size = sources.size();
192     for (int i = 0; i < size; i++) {
193         DOMImplementationSource JavaDoc source =
194         (DOMImplementationSource JavaDoc) sources.elementAt(i);
195         DOMImplementationList JavaDoc impls =
196         source.getDOMImplementationList(features);
197         for (int j = 0; j < impls.getLength(); j++) {
198         DOMImplementation JavaDoc impl = impls.item(j);
199         implementations.addElement(impl);
200         }
201     }
202     return new DOMImplementationList JavaDoc() {
203         public DOMImplementation JavaDoc item(final int index) {
204             if (index >= 0 && index < implementations.size()) {
205             try {
206                 return (DOMImplementation JavaDoc)
207                 implementations.elementAt(index);
208             } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
209                 return null;
210             }
211             }
212             return null;
213         }
214         
215         public int getLength() {
216             return implementations.size();
217         }
218         };
219     }
220     
221     /**
222      * Register an implementation.
223      *
224      * @param s The source to be registered, may not be <code>null</code>
225      */

226     public void addSource(final DOMImplementationSource JavaDoc s) {
227     if (s == null) {
228         throw new NullPointerException JavaDoc();
229     }
230     if (!sources.contains(s)) {
231         sources.addElement(s);
232     }
233     }
234     
235     /**
236      *
237      * Gets a class loader.
238      *
239      * @return A class loader, possibly <code>null</code>
240      */

241     private static ClassLoader JavaDoc getClassLoader() {
242     try {
243         ClassLoader JavaDoc contextClassLoader = getContextClassLoader();
244         
245         if (contextClassLoader != null) {
246         return contextClassLoader;
247         }
248     } catch (Exception JavaDoc e) {
249         // Assume that the DOM application is in a JRE 1.1, use the
250
// current ClassLoader
251
return DOMImplementationRegistry JavaDoc.class.getClassLoader();
252     }
253     return DOMImplementationRegistry JavaDoc.class.getClassLoader();
254     }
255     
256     /**
257      * This method attempts to return the first line of the resource
258      * META_INF/services/org.w3c.dom.DOMImplementationSourceList
259      * from the provided ClassLoader.
260      *
261      * @param classLoader classLoader, may not be <code>null</code>.
262      * @return first line of resource, or <code>null</code>
263      */

264     private static String JavaDoc getServiceValue(final ClassLoader JavaDoc classLoader) {
265     String JavaDoc serviceId = "META-INF/services/" + PROPERTY;
266     // try to find services in CLASSPATH
267
try {
268         InputStream JavaDoc is = getResourceAsStream(classLoader, serviceId);
269         
270         if (is != null) {
271         BufferedReader JavaDoc rd;
272         try {
273             rd =
274             new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is, "UTF-8"),
275                        DEFAULT_LINE_LENGTH);
276         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
277             rd =
278             new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is),
279                        DEFAULT_LINE_LENGTH);
280         }
281         String JavaDoc serviceValue = rd.readLine();
282         rd.close();
283         if (serviceValue != null && serviceValue.length() > 0) {
284             return serviceValue;
285         }
286         }
287     } catch (Exception JavaDoc ex) {
288         return null;
289     }
290     return null;
291     }
292     
293     /**
294      * A simple JRE (Java Runtime Environment) 1.1 test
295      *
296      * @return <code>true</code> if JRE 1.1
297      */

298     private static boolean isJRE11() {
299     try {
300         Class JavaDoc c = Class.forName("java.security.AccessController");
301         // java.security.AccessController existed since 1.2 so, if no
302
// exception was thrown, the DOM application is running in a JRE
303
// 1.2 or higher
304
return false;
305     } catch (Exception JavaDoc ex) {
306         // ignore
307
}
308     return true;
309     }
310     
311     /**
312      * This method returns the ContextClassLoader or <code>null</code> if
313      * running in a JRE 1.1
314      *
315      * @return The Context Classloader
316      */

317     private static ClassLoader JavaDoc getContextClassLoader() {
318     return isJRE11()
319         ? null
320         : (ClassLoader JavaDoc)
321           AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
322             public Object JavaDoc run() {
323             ClassLoader JavaDoc classLoader = null;
324             try {
325                 classLoader =
326                 Thread.currentThread().getContextClassLoader();
327             } catch (SecurityException JavaDoc ex) {
328             }
329             return classLoader;
330             }
331         });
332     }
333     
334     /**
335      * This method returns the system property indicated by the specified name
336      * after checking access control privileges. For a JRE 1.1, this check is
337      * not done.
338      *
339      * @param name the name of the system property
340      * @return the system property
341      */

342     private static String JavaDoc getSystemProperty(final String JavaDoc name) {
343     return isJRE11()
344         ? (String JavaDoc) System.getProperty(name)
345         : (String JavaDoc) AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
346             public Object JavaDoc run() {
347             return System.getProperty(name);
348             }
349         });
350     }
351     
352     /**
353      * This method returns an Inputstream for the reading resource
354      * META_INF/services/org.w3c.dom.DOMImplementationSourceList after checking
355      * access control privileges. For a JRE 1.1, this check is not done.
356      *
357      * @param classLoader classLoader
358      * @param name the resource
359      * @return an Inputstream for the resource specified
360      */

361     private static InputStream JavaDoc getResourceAsStream(final ClassLoader JavaDoc classLoader,
362                            final String JavaDoc name) {
363     if (isJRE11()) {
364         InputStream JavaDoc ris;
365         if (classLoader == null) {
366         ris = ClassLoader.getSystemResourceAsStream(name);
367         } else {
368         ris = classLoader.getResourceAsStream(name);
369         }
370         return ris;
371     } else {
372         return (InputStream JavaDoc)
373         AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
374             public Object JavaDoc run() {
375                 InputStream JavaDoc ris;
376                 if (classLoader == null) {
377                 ris =
378                     ClassLoader.getSystemResourceAsStream(name);
379                 } else {
380                 ris = classLoader.getResourceAsStream(name);
381                 }
382                 return ris;
383             }
384             });
385     }
386     }
387 }
388
Popular Tags