1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package javax.xml.rpc;
18
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.util.Properties;
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 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 findClassLoader()
57 throws ConfigurationError
58 {
59 Method m = null;
60
61 try {
62 m = Thread.class.getMethod("getContextClassLoader", null);
63 } catch (NoSuchMethodException e) {
64
65 debugPrintln("assuming JDK 1.1");
66 return FactoryFinder.class.getClassLoader();
67 }
68
69 try {
70 return (ClassLoader) m.invoke(Thread.currentThread(), null);
71 } catch (IllegalAccessException e) {
72
73 throw new ConfigurationError("Unexpected IllegalAccessException",
74 e);
75 } catch (InvocationTargetException e) {
76
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 newInstance(String className,
96 ClassLoader classLoader)
97 throws ConfigurationError
98 {
99 try {
100 if (classLoader != null) {
101 try {
102 return classLoader.loadClass(className).newInstance ();
103 } catch (ClassNotFoundException x) {
104
105 }
106 }
107 return Class.forName(className).newInstance();
108 } catch (ClassNotFoundException x) {
109 throw new ConfigurationError(
110 "Provider " + className + " not found", x);
111 } catch (Exception 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 find(String factoryId, String fallbackClassName)
133 throws ConfigurationError
134 {
135 debugPrintln("debug is on");
136
137 ClassLoader classLoader = findClassLoader();
138
139
140 try {
141 String systemProp =
142 System.getProperty( factoryId );
143 if( systemProp!=null) {
144 debugPrintln("found system property " + systemProp);
145 return newInstance(systemProp, classLoader);
146 }
147 } catch (SecurityException se) {
148 }
149
150
151 try {
152 String javah=System.getProperty( "java.home" );
153 String configFile = javah + File.separator +
154 "lib" + File.separator + "jaxrpc.properties";
155 File f=new File( configFile );
156 if( f.exists()) {
157 Properties props=new Properties();
158 props.load( new FileInputStream(f));
159 String factoryClassName = props.getProperty(factoryId);
160 debugPrintln("found java.home property " + factoryClassName);
161 return newInstance(factoryClassName, classLoader);
162 }
163 } catch(Exception ex ) {
164 if( debug ) ex.printStackTrace();
165 }
166
167 String serviceId = "META-INF/services/" + factoryId;
168
169 try {
170 InputStream 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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 BufferedReader rd;
197 try {
198 rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
199 } catch (java.io.UnsupportedEncodingException e) {
200 rd = new BufferedReader(new InputStreamReader(is));
201 }
202
203 String 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 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 {
226
227
228
229 private Exception 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 msg, Exception x) {
239 super(msg);
240 this.exception = x;
241 }
242
243 Exception getException() {
244 return exception;
245 }
246 }
247 }