37 * |
37 * |
38 * @exception SOAPException if the given class could not be found |
38 * @exception SOAPException if the given class could not be found |
39 * or could not be instantiated |
39 * or could not be instantiated |
40 */ |
40 */ |
41 private static Object newInstance(String className, |
41 private static Object newInstance(String className, |
42 ClassLoader classLoader) |
42 ClassLoader classLoader, |
|
43 String defaultFactoryClass) |
43 throws SOAPException |
44 throws SOAPException |
44 { |
45 { |
45 try { |
46 try { |
46 Class spiClass; |
47 Class spiClass = safeLoadClass(className, classLoader, defaultFactoryClass); |
47 if (classLoader == null) { |
|
48 spiClass = Class.forName(className); |
|
49 } else { |
|
50 spiClass = classLoader.loadClass(className); |
|
51 } |
|
52 return spiClass.newInstance(); |
48 return spiClass.newInstance(); |
53 } catch (ClassNotFoundException x) { |
49 } catch (ClassNotFoundException x) { |
54 throw new SOAPException( |
50 throw new SOAPException( |
55 "Provider " + className + " not found", x); |
51 "Provider " + className + " not found", x); |
56 } catch (Exception x) { |
52 } catch (Exception x) { |
71 * |
67 * |
72 * @param factoryId the name of the factory to find, which is |
68 * @param factoryId the name of the factory to find, which is |
73 * a system property |
69 * a system property |
74 * @exception SOAPException if there is a SOAP error |
70 * @exception SOAPException if there is a SOAP error |
75 */ |
71 */ |
76 static Object find(String factId) |
72 static Object find(String factoryId) |
77 throws SOAPException |
73 throws SOAPException |
78 { |
74 { |
79 final ClassLoader classLoader; |
75 return find(factoryId, null, false); |
80 final String factoryId = factId; |
|
81 try { |
|
82 classLoader = Thread.currentThread().getContextClassLoader(); |
|
83 } catch (Exception x) { |
|
84 throw new SOAPException(x.toString(), x); |
|
85 } |
|
86 |
|
87 // Use the system property first |
|
88 try { |
|
89 String systemProp = |
|
90 System.getProperty( factoryId ); |
|
91 if( systemProp!=null) { |
|
92 return newInstance(systemProp, classLoader); |
|
93 } |
|
94 } catch (SecurityException se) { |
|
95 } |
|
96 |
|
97 // try to read from $java.home/lib/jaxm.properties |
|
98 try { |
|
99 String javah=System.getProperty( "java.home" ); |
|
100 String configFile = javah + File.separator + |
|
101 "lib" + File.separator + "jaxm.properties"; |
|
102 final File f=new File( configFile ); |
|
103 if( f.exists()) { |
|
104 Properties props=new Properties(); |
|
105 props.load( new FileInputStream(f)); |
|
106 String factoryClassName = props.getProperty(factoryId); |
|
107 return newInstance(factoryClassName, classLoader); |
|
108 } |
|
109 } catch(Exception ex ) { |
|
110 } |
|
111 |
|
112 String serviceId = "META-INF/services/" + factoryId; |
|
113 // try to find services in CLASSPATH |
|
114 try { |
|
115 InputStream is=null; |
|
116 if (classLoader == null) { |
|
117 is=ClassLoader.getSystemResourceAsStream(serviceId); |
|
118 } else { |
|
119 is=classLoader.getResourceAsStream(serviceId); |
|
120 } |
|
121 |
|
122 if( is!=null ) { |
|
123 BufferedReader rd = |
|
124 new BufferedReader(new InputStreamReader(is, "UTF-8")); |
|
125 |
|
126 String factoryClassName = rd.readLine(); |
|
127 rd.close(); |
|
128 |
|
129 if (factoryClassName != null && |
|
130 ! "".equals(factoryClassName)) { |
|
131 return newInstance(factoryClassName, classLoader); |
|
132 } |
|
133 } |
|
134 } catch( Exception ex ) { |
|
135 } |
|
136 |
|
137 return null; |
|
138 } |
76 } |
139 |
77 |
140 /** |
78 /** |
141 * Finds the implementation <code>Class</code> object for the given |
79 * Finds the implementation <code>Class</code> object for the given |
142 * factory name, or if that fails, finds the <code>Class</code> object |
80 * factory name, or if that fails, finds the <code>Class</code> object |
158 * @exception SOAPException if there is a SOAP error |
96 * @exception SOAPException if there is a SOAP error |
159 */ |
97 */ |
160 static Object find(String factoryId, String fallbackClassName) |
98 static Object find(String factoryId, String fallbackClassName) |
161 throws SOAPException |
99 throws SOAPException |
162 { |
100 { |
163 |
101 return find(factoryId, fallbackClassName, true); |
164 Object obj = find(factoryId); |
102 } |
165 if (obj != null) |
103 |
166 return obj; |
104 /** |
167 |
105 * Finds the implementation <code>Class</code> object for the given |
|
106 * factory name, or if that fails, finds the <code>Class</code> object |
|
107 * for the given default class name, but only if <code>tryFallback</code> |
|
108 * is <code>true</code>. The arguments supplied must be used in order |
|
109 * If using the first argument is successful, the second one will not |
|
110 * be used. Note the default class name may be needed even if fallback |
|
111 * is not to be attempted, so certain error condiitons can be handled. |
|
112 * <P> |
|
113 * This method is package private so that this code can be shared. |
|
114 * |
|
115 * @return the <code>Class</code> object of the specified message factory; |
|
116 * may not be <code>null</code> |
|
117 * |
|
118 * @param factoryId the name of the factory to find, which is |
|
119 * a system property |
|
120 * @param defaultClassName the implementation class name, which is |
|
121 * to be used only if nothing else |
|
122 * is found; <code>null</code> to indicate |
|
123 * that there is no default class name |
|
124 * @param tryFallback whether to try the default class as a |
|
125 * fallback |
|
126 * @exception SOAPException if there is a SOAP error |
|
127 */ |
|
128 static Object find(String factoryId, String defaultClassName, |
|
129 boolean tryFallback) throws SOAPException { |
168 ClassLoader classLoader; |
130 ClassLoader classLoader; |
169 try { |
131 try { |
170 classLoader = Thread.currentThread().getContextClassLoader(); |
132 classLoader = Thread.currentThread().getContextClassLoader(); |
171 } catch (Exception x) { |
133 } catch (Exception x) { |
172 throw new SOAPException(x.toString(), x); |
134 throw new SOAPException(x.toString(), x); |
173 } |
135 } |
174 |
136 |
175 if (fallbackClassName == null) { |
137 // Use the system property first |
|
138 try { |
|
139 String systemProp = |
|
140 System.getProperty( factoryId ); |
|
141 if( systemProp!=null) { |
|
142 return newInstance(systemProp, classLoader, defaultClassName); |
|
143 } |
|
144 } catch (SecurityException se) { |
|
145 } |
|
146 |
|
147 // try to read from $java.home/lib/jaxm.properties |
|
148 try { |
|
149 String javah=System.getProperty( "java.home" ); |
|
150 String configFile = javah + File.separator + |
|
151 "lib" + File.separator + "jaxm.properties"; |
|
152 File f=new File( configFile ); |
|
153 if( f.exists()) { |
|
154 Properties props=new Properties(); |
|
155 props.load( new FileInputStream(f)); |
|
156 String factoryClassName = props.getProperty(factoryId); |
|
157 return newInstance(factoryClassName, classLoader, defaultClassName); |
|
158 } |
|
159 } catch(Exception ex ) { |
|
160 } |
|
161 |
|
162 String serviceId = "META-INF/services/" + factoryId; |
|
163 // try to find services in CLASSPATH |
|
164 try { |
|
165 InputStream is=null; |
|
166 if (classLoader == null) { |
|
167 is=ClassLoader.getSystemResourceAsStream(serviceId); |
|
168 } else { |
|
169 is=classLoader.getResourceAsStream(serviceId); |
|
170 } |
|
171 |
|
172 if( is!=null ) { |
|
173 BufferedReader rd = |
|
174 new BufferedReader(new InputStreamReader(is, "UTF-8")); |
|
175 |
|
176 String factoryClassName = rd.readLine(); |
|
177 rd.close(); |
|
178 |
|
179 if (factoryClassName != null && |
|
180 ! "".equals(factoryClassName)) { |
|
181 return newInstance(factoryClassName, classLoader, defaultClassName); |
|
182 } |
|
183 } |
|
184 } catch( Exception ex ) { |
|
185 } |
|
186 |
|
187 // If not found and fallback should not be tried, return a null result. |
|
188 if (!tryFallback) |
|
189 return null; |
|
190 |
|
191 // We didn't find the class through the usual means so try the default |
|
192 // (built in) factory if specified. |
|
193 if (defaultClassName == null) { |
176 throw new SOAPException( |
194 throw new SOAPException( |
177 "Provider for " + factoryId + " cannot be found", null); |
195 "Provider for " + factoryId + " cannot be found", null); |
178 } |
196 } |
179 |
197 return newInstance(defaultClassName, classLoader, defaultClassName); |
180 return newInstance(fallbackClassName, classLoader); |
198 } |
|
199 |
|
200 /** |
|
201 * Loads the class, provided that the calling thread has an access to the |
|
202 * class being loaded. If this is the specified default factory class and it |
|
203 * is restricted by package.access we get a SecurityException and can do a |
|
204 * Class.forName() on it so it will be loaded by the bootstrap class loader. |
|
205 */ |
|
206 private static Class safeLoadClass(String className, |
|
207 ClassLoader classLoader, String defaultFactoryClass) |
|
208 throws ClassNotFoundException { |
|
209 try { |
|
210 // make sure that the current thread has an access to the package of the given name. |
|
211 SecurityManager s = System.getSecurityManager(); |
|
212 if (s != null) { |
|
213 int i = className.lastIndexOf('.'); |
|
214 if (i != -1) { |
|
215 s.checkPackageAccess(className.substring(0, i)); |
|
216 } |
|
217 } |
|
218 |
|
219 if (classLoader == null) |
|
220 return Class.forName(className); |
|
221 else |
|
222 return classLoader.loadClass(className); |
|
223 } catch (SecurityException se) { |
|
224 // The FactoryFinder is in the bootstrap class loader, so |
|
225 // the following should work, but we only attempt it |
|
226 // if it the the default class. |
|
227 if (className.equals(defaultFactoryClass)) |
|
228 return Class.forName(className); |
|
229 throw se; |
|
230 } |
181 } |
231 } |
182 } |
232 } |