KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > xml > xpath > XPathFactoryFinder


1
2 // $Id: XPathFactoryFinder.java,v 1.2.8.1.2.1 2004/09/16 09:25:16 nb131165 Exp $
3

4 /*
5  * @(#)XPathFactoryFinder.java 1.5 05/01/04
6  *
7  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
8  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
9  */

10
11 package javax.xml.xpath;
12
13 import java.io.File JavaDoc;
14 import java.io.FileInputStream JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.net.URL JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Enumeration JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.NoSuchElementException JavaDoc;
22 import java.util.Properties JavaDoc;
23
24 /**
25  * Implementation of {@link XPathFactory#newInstance(String)}.
26  *
27  * @author <a HREF="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a>
28  * @version $Revision: 1.2.8.1.2.1 $, $Date: 2004/09/16 09:25:16 $
29  * @since 1.5
30  */

31 class XPathFactoryFinder {
32
33     private static SecuritySupport JavaDoc ss = new SecuritySupport JavaDoc() ;
34     /** debug support code. */
35     private static boolean debug = false;
36     static {
37         // Use try/catch block to support applets
38
try {
39             debug = ss.getSystemProperty("jaxp.debug") != null;
40         } catch (Exception JavaDoc _) {
41             debug = false;
42         }
43     }
44
45     /**
46      * <p>Cache properties for performance.</p>
47      */

48     private static Properties JavaDoc cacheProps = new Properties JavaDoc();
49     
50     /**
51      * <p>First time requires initialization overhead.</p>
52      */

53     private static boolean firstTime = true;
54     
55     /**
56      * <p>Conditional debug printing.</p>
57      *
58      * @param msg to print
59      */

60     private static void debugPrintln(String JavaDoc msg) {
61         if (debug) {
62             System.err.println("JAXP: " + msg);
63         }
64     }
65     
66     /**
67      * <p><code>ClassLoader</code> to use to find <code>SchemaFactory</code>.</p>
68      */

69     private final ClassLoader JavaDoc classLoader;
70     
71     /**
72      * <p>Constructor that specifies <code>ClassLoader</code> to use
73      * to find <code>SchemaFactory</code>.</p>
74      *
75      * @param loader
76      * to be used to load resource, {@link SchemaFactory}, and
77      * {@link SchemaFactoryLoader} implementations during
78      * the resolution process.
79      * If this parameter is null, the default system class loader
80      * will be used.
81      */

82     public XPathFactoryFinder(ClassLoader JavaDoc loader) {
83         this.classLoader = loader;
84         if( debug ) {
85             debugDisplayClassLoader();
86         }
87     }
88     
89     private void debugDisplayClassLoader() {
90         try {
91             if( classLoader == ss.getContextClassLoader() ) {
92                 debugPrintln("using thread context class loader ("+classLoader+") for search");
93                 return;
94             }
95         } catch( Throwable JavaDoc _ ) {
96             ; // getContextClassLoader() undefined in JDK1.1
97
}
98         
99         if( classLoader==ClassLoader.getSystemClassLoader() ) {
100             debugPrintln("using system class loader ("+classLoader+") for search");
101             return;
102         }
103
104         debugPrintln("using class loader ("+classLoader+") for search");
105     }
106     
107     /**
108      * <p>Creates a new {@link XPathFactory} object for the specified
109      * schema language.</p>
110      *
111      * @param uri
112      * Identifies the underlying object model.
113      *
114      * @return <code>null</code> if the callee fails to create one.
115      *
116      * @throws NullPointerException
117      * If the parameter is null.
118      */

119     public XPathFactory JavaDoc newFactory(String JavaDoc uri) {
120         if(uri==null) throw new NullPointerException JavaDoc();
121         XPathFactory JavaDoc f = _newFactory(uri);
122         if (f != null) {
123             debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri);
124         } else {
125             debugPrintln("unable to find a factory for " + uri);
126         }
127         return f;
128     }
129     
130     /**
131      * <p>Lookup a {@link XPathFactory} for the given object model.</p>
132      *
133      * @param uri identifies the object model.
134      *
135      * @return {@link XPathFactory} for the given object model.
136      */

137     private XPathFactory JavaDoc _newFactory(String JavaDoc uri) {
138         XPathFactory JavaDoc sf;
139         
140         String JavaDoc propertyName = SERVICE_CLASS.getName() + ":" + uri;
141         
142         // system property look up
143
try {
144             debugPrintln("Looking up system property '"+propertyName+"'" );
145             String JavaDoc r = ss.getSystemProperty(propertyName);
146             if(r!=null) {
147                 debugPrintln("The value is '"+r+"'");
148                 sf = createInstance(r);
149                 if(sf!=null) return sf;
150             } else
151                 debugPrintln("The property is undefined.");
152         } catch( Throwable JavaDoc t ) {
153             if( debug ) {
154                 debugPrintln("failed to look up system property '"+propertyName+"'" );
155                 t.printStackTrace();
156             }
157         }
158         
159         String JavaDoc javah = ss.getSystemProperty( "java.home" );
160         String JavaDoc configFile = javah + File.separator +
161         "lib" + File.separator + "jaxp.properties";
162
163         String JavaDoc factoryClassName = null ;
164
165         // try to read from $java.home/lib/jaxp.properties
166
try {
167             if(firstTime){
168                 synchronized(cacheProps){
169                     if(firstTime){
170                         File JavaDoc f=new File JavaDoc( configFile );
171                         firstTime = false;
172                         if(ss.doesFileExist(f)){
173                             debugPrintln("Read properties file " + f);
174                             cacheProps.load(ss.getFileInputStream(f));
175                         }
176                     }
177                 }
178             }
179             factoryClassName = cacheProps.getProperty(propertyName);
180             debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
181
182             if (factoryClassName != null) {
183                 sf = createInstance(factoryClassName);
184                 if(sf != null){
185                     return sf;
186                 }
187             }
188         } catch (Exception JavaDoc ex) {
189             if (debug) {
190                 ex.printStackTrace();
191             }
192         }
193                     
194         // try META-INF/services files
195
Iterator JavaDoc sitr = createServiceFileIterator();
196         while(sitr.hasNext()) {
197             URL JavaDoc resource = (URL JavaDoc)sitr.next();
198             debugPrintln("looking into " + resource);
199             try {
200                 //sf = loadFromProperty(uri,resource.toExternalForm(),resource.openStream());
201
sf = loadFromProperty(uri,resource.toExternalForm(),ss.getURLInputStream(resource));
202                 if(sf!=null) return sf;
203             } catch(IOException JavaDoc e) {
204                 if( debug ) {
205                     debugPrintln("failed to read "+resource);
206                     e.printStackTrace();
207                 }
208             }
209         }
210         
211         // platform default
212
if(uri.equals(XPathFactory.DEFAULT_OBJECT_MODEL_URI)) {
213             debugPrintln("attempting to use the platform default W3C DOM XPath lib");
214             return createInstance("com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl");
215         }
216         
217         debugPrintln("all things were tried, but none was found. bailing out.");
218         return null;
219     }
220     
221     /**
222      * <p>Creates an instance of the specified and returns it.</p>
223      *
224      * @param className
225      * fully qualified class name to be instanciated.
226      *
227      * @return null
228      * if it fails. Error messages will be printed by this method.
229      */

230     private XPathFactory JavaDoc createInstance( String JavaDoc className ) {
231         try {
232             debugPrintln("instanciating "+className);
233             Class JavaDoc clazz;
234             if( classLoader!=null )
235                 clazz = classLoader.loadClass(className);
236             else
237                 clazz = Class.forName(className);
238             if(debug) debugPrintln("loaded it from "+which(clazz));
239             Object JavaDoc o = clazz.newInstance();
240             
241             if( o instanceof XPathFactory JavaDoc )
242                 return (XPathFactory JavaDoc)o;
243             
244             debugPrintln(className+" is not assignable to "+SERVICE_CLASS.getName());
245         } catch( Throwable JavaDoc t ) {
246             debugPrintln("failed to instanciate "+className);
247             if(debug) t.printStackTrace();
248         }
249         return null;
250     }
251     
252     /** Iterator that lazily computes one value and returns it. */
253     private static abstract class SingleIterator implements Iterator JavaDoc {
254         private boolean seen = false;
255         
256         public final void remove() { throw new UnsupportedOperationException JavaDoc(); }
257         public final boolean hasNext() { return !seen; }
258         public final Object JavaDoc next() {
259             if(seen) throw new NoSuchElementException JavaDoc();
260             seen = true;
261             return value();
262         }
263         
264         protected abstract Object JavaDoc value();
265     }
266     
267     /**
268      * Looks up a value in a property file
269      * while producing all sorts of debug messages.
270      *
271      * @return null
272      * if there was an error.
273      */

274     private XPathFactory JavaDoc loadFromProperty( String JavaDoc keyName, String JavaDoc resourceName, InputStream JavaDoc in )
275         throws IOException JavaDoc {
276         debugPrintln("Reading "+resourceName );
277         
278         Properties JavaDoc props = new Properties JavaDoc();
279         props.load(in);
280         in.close();
281         String JavaDoc factoryClassName = props.getProperty(keyName);
282         if(factoryClassName != null){
283             debugPrintln("found "+keyName+" = " + factoryClassName);
284             return createInstance(factoryClassName);
285         } else {
286             debugPrintln(keyName+" is not in the property file");
287             return null;
288         }
289     }
290     
291     /**
292      * Returns an {@link Iterator} that enumerates all
293      * the META-INF/services files that we care.
294      */

295     private Iterator JavaDoc createServiceFileIterator() {
296         if (classLoader == null) {
297             return new SingleIterator() {
298                 protected Object JavaDoc value() {
299                     ClassLoader JavaDoc classLoader = XPathFactoryFinder JavaDoc.class.getClassLoader();
300                     return ss.getResourceAsURL(classLoader, SERVICE_ID);
301                     //return (ClassLoader.getSystemResource( SERVICE_ID ));
302
}
303             };
304         } else {
305             try {
306                 //final Enumeration e = classLoader.getResources(SERVICE_ID);
307
final Enumeration JavaDoc e = ss.getResources(classLoader, SERVICE_ID);
308                 if(!e.hasMoreElements()) {
309                     debugPrintln("no "+SERVICE_ID+" file was found");
310                 }
311                 
312                 // wrap it into an Iterator.
313
return new Iterator JavaDoc() {
314                     public void remove() {
315                         throw new UnsupportedOperationException JavaDoc();
316                     }
317
318                     public boolean hasNext() {
319                         return e.hasMoreElements();
320                     }
321
322                     public Object JavaDoc next() {
323                         return e.nextElement();
324                     }
325                 };
326             } catch (IOException JavaDoc e) {
327                 debugPrintln("failed to enumerate resources "+SERVICE_ID);
328                 if(debug) e.printStackTrace();
329                 return new ArrayList JavaDoc().iterator(); // empty iterator
330
}
331         }
332     }
333     
334     private static final Class JavaDoc SERVICE_CLASS = XPathFactory JavaDoc.class;
335     private static final String JavaDoc SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
336     
337     
338     
339     private static String JavaDoc which( Class JavaDoc clazz ) {
340         return which( clazz.getName(), clazz.getClassLoader() );
341     }
342
343     /**
344      * <p>Search the specified classloader for the given classname.</p>
345      *
346      * @param classname the fully qualified name of the class to search for
347      * @param loader the classloader to search
348      *
349      * @return the source location of the resource, or null if it wasn't found
350      */

351     private static String JavaDoc which(String JavaDoc classname, ClassLoader JavaDoc loader) {
352
353         String JavaDoc classnameAsResource = classname.replace('.', '/') + ".class";
354         
355         if( loader==null ) loader = ClassLoader.getSystemClassLoader();
356         
357         //URL it = loader.getResource(classnameAsResource);
358
URL JavaDoc it = ss.getResourceAsURL(loader, classnameAsResource);
359         if (it != null) {
360             return it.toString();
361         } else {
362             return null;
363         }
364     }
365 }
366
Popular Tags