KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > xml > rpc > FactoryFinder


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package javax.xml.rpc;
18
19 import java.io.BufferedReader JavaDoc;
20 import java.io.File JavaDoc;
21 import java.io.FileInputStream JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.InputStreamReader JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 /**
29  * This code is designed to implement the pluggability
30  * feature and is designed to both compile and run on JDK version 1.1 and
31  * later. The code also runs both as part of an unbundled jar file and
32  * when bundled as part of the JDK.
33  *
34  * This class is duplicated for each subpackage so keep it in sync.
35  * It is package private and therefore is not exposed as part of the JAXRPC
36  * API.
37  */

38 class FactoryFinder {
39     /** Set to true for debugging. */
40     private static final boolean debug = false;
41
42     private static void debugPrintln(String JavaDoc msg) {
43         if (debug) {
44             System.err.println("JAXRPC: " + msg);
45         }
46     }
47
48     /**
49      * Figure out which ClassLoader to use. For JDK 1.2 and later use
50      * the context ClassLoader.
51      *
52      * @return the <code>ClassLoader</code>
53      * @throws ConfigurationError if this class is unable to work with the
54      * host JDK
55      */

56     private static ClassLoader JavaDoc findClassLoader()
57         throws ConfigurationError
58     {
59         Method JavaDoc m = null;
60
61         try {
62             m = Thread JavaDoc.class.getMethod("getContextClassLoader", null);
63         } catch (NoSuchMethodException JavaDoc e) {
64             // Assume that we are running JDK 1.1, use the current ClassLoader
65
debugPrintln("assuming JDK 1.1");
66             return FactoryFinder JavaDoc.class.getClassLoader();
67         }
68
69         try {
70             return (ClassLoader JavaDoc) m.invoke(Thread.currentThread(), null);
71         } catch (IllegalAccessException JavaDoc e) {
72             // assert(false)
73
throw new ConfigurationError("Unexpected IllegalAccessException",
74                                          e);
75         } catch (InvocationTargetException JavaDoc e) {
76             // assert(e.getTargetException() instanceof SecurityException)
77
throw new ConfigurationError("Unexpected InvocationTargetException",
78                                          e);
79         }
80     }
81
82     /**
83      * Create an instance of a class using the specified
84      * <code>ClassLoader</code>, or if that fails from the
85      * <code>ClassLoader</code> that loaded this class.
86      *
87      * @param className the name of the class to instantiate
88      * @param classLoader a <code>ClassLoader</code> to load the class from
89      *
90      * @return a new <code>Object</code> that is an instance of the class of
91      * the given name from the given class loader
92      * @throws ConfigurationError if the class could not be found or
93      * instantiated
94      */

95     private static Object JavaDoc newInstance(String JavaDoc className,
96                                       ClassLoader JavaDoc classLoader)
97         throws ConfigurationError
98     {
99         try {
100             if (classLoader != null) {
101                 try {
102                     return classLoader.loadClass(className).newInstance ();
103                 } catch (ClassNotFoundException JavaDoc x) {
104                       // try again
105
}
106             }
107             return Class.forName(className).newInstance();
108         } catch (ClassNotFoundException JavaDoc x) {
109             throw new ConfigurationError(
110                 "Provider " + className + " not found", x);
111         } catch (Exception JavaDoc x) {
112             throw new ConfigurationError(
113                 "Provider " + className + " could not be instantiated: " + x,
114                 x);
115         }
116     }
117
118     /**
119      * Finds the implementation Class object in the specified order. Main
120      * entry point.
121      * @return Class object of factory, never null
122      *
123      * @param factoryId Name of the factory to find, same as
124      * a property name
125      * @param fallbackClassName Implementation class name, if nothing else
126      * is found. Use null to mean no fallback.
127      *
128      * @exception FactoryFinder.ConfigurationError
129      *
130      * Package private so this code can be shared.
131      */

132     static Object JavaDoc find(String JavaDoc factoryId, String JavaDoc fallbackClassName)
133         throws ConfigurationError
134     {
135         debugPrintln("debug is on");
136
137         ClassLoader JavaDoc classLoader = findClassLoader();
138
139         // Use the system property first
140
try {
141             String JavaDoc systemProp =
142                 System.getProperty( factoryId );
143             if( systemProp!=null) {
144                 debugPrintln("found system property " + systemProp);
145                 return newInstance(systemProp, classLoader);
146             }
147         } catch (SecurityException JavaDoc se) {
148         }
149
150         // try to read from $java.home/lib/xml.properties
151
try {
152             String JavaDoc javah=System.getProperty( "java.home" );
153             String JavaDoc configFile = javah + File.separator +
154                 "lib" + File.separator + "jaxrpc.properties";
155             File JavaDoc f=new File JavaDoc( configFile );
156             if( f.exists()) {
157                 Properties JavaDoc props=new Properties JavaDoc();
158                 props.load( new FileInputStream JavaDoc(f));
159                 String JavaDoc factoryClassName = props.getProperty(factoryId);
160                 debugPrintln("found java.home property " + factoryClassName);
161                 return newInstance(factoryClassName, classLoader);
162             }
163         } catch(Exception JavaDoc ex ) {
164             if( debug ) ex.printStackTrace();
165         }
166
167         String JavaDoc serviceId = "META-INF/services/" + factoryId;
168         // try to find services in CLASSPATH
169
try {
170             InputStream JavaDoc is=null;
171             if (classLoader == null) {
172                 is=ClassLoader.getSystemResourceAsStream( serviceId );
173             } else {
174                 is=classLoader.getResourceAsStream( serviceId );
175             }
176
177             if( is!=null ) {
178                 debugPrintln("found " + serviceId);
179
180                 // Read the service provider name in UTF-8 as specified in
181
// the jar spec. Unfortunately this fails in Microsoft
182
// VJ++, which does not implement the UTF-8
183
// encoding. Theoretically, we should simply let it fail in
184
// that case, since the JVM is obviously broken if it
185
// doesn't support such a basic standard. But since there
186
// are still some users attempting to use VJ++ for
187
// development, we have dropped in a fallback which makes a
188
// second attempt using the platform's default encoding. In
189
// VJ++ this is apparently ASCII, which is a subset of
190
// UTF-8... and since the strings we'll be reading here are
191
// also primarily limited to the 7-bit ASCII range (at
192
// least, in English versions), this should work well
193
// enough to keep us on the air until we're ready to
194
// officially decommit from VJ++. [Edited comment from
195
// jkesselm]
196
BufferedReader JavaDoc rd;
197                 try {
198                     rd = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is, "UTF-8"));
199                 } catch (java.io.UnsupportedEncodingException JavaDoc e) {
200                     rd = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is));
201                 }
202
203                 String JavaDoc factoryClassName = rd.readLine();
204                 rd.close();
205
206                 if (factoryClassName != null &&
207                     ! "".equals(factoryClassName)) {
208                     debugPrintln("loaded from services: " + factoryClassName);
209                     return newInstance(factoryClassName, classLoader);
210                 }
211             }
212         } catch( Exception JavaDoc ex ) {
213             if( debug ) ex.printStackTrace();
214         }
215
216         if (fallbackClassName == null) {
217             throw new ConfigurationError(
218                 "Provider for " + factoryId + " cannot be found", null);
219         }
220
221         debugPrintln("loaded from fallback value: " + fallbackClassName);
222         return newInstance(fallbackClassName, classLoader);
223     }
224
225     static class ConfigurationError extends Error JavaDoc {
226         // fixme: should this be refactored to use the jdk1.4 exception
227
// wrapping?
228

229         private Exception JavaDoc exception;
230
231         /**
232          * Construct a new instance with the specified detail string and
233          * exception.
234          *
235          * @param msg the Message for this error
236          * @param x an Exception that caused this failure, or null
237          */

238         ConfigurationError(String JavaDoc msg, Exception JavaDoc x) {
239             super(msg);
240             this.exception = x;
241         }
242
243         Exception JavaDoc getException() {
244             return exception;
245         }
246     }
247 }
248
Popular Tags