23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package javax.xml.stream; |
26 package javax.xml.stream; |
27 |
27 |
|
28 import java.io.BufferedReader; |
|
29 import java.io.File; |
|
30 import java.io.IOException; |
28 import java.io.InputStream; |
31 import java.io.InputStream; |
29 import java.io.IOException; |
32 import java.io.InputStreamReader; |
30 import java.io.File; |
|
31 import java.io.FileInputStream; |
|
32 |
|
33 import java.util.Properties; |
33 import java.util.Properties; |
34 import java.io.BufferedReader; |
|
35 import java.io.InputStreamReader; |
|
36 |
34 |
37 /** |
35 /** |
38 * <p>Implements pluggable Datatypes.</p> |
36 * <p>Implements pluggable Datatypes.</p> |
39 * |
37 * |
40 * <p>This class is duplicated for each JAXP subpackage so keep it in |
38 * <p>This class is duplicated for each JAXP subpackage so keep it in |
41 * sync. It is package private for secure class loading.</p> |
39 * sync. It is package private for secure class loading.</p> |
42 * |
40 * |
43 * @author Santiago.PericasGeertsen@sun.com |
41 * @author Santiago.PericasGeertsen@sun.com |
44 */ |
42 */ |
45 class FactoryFinder { |
43 class FactoryFinder { |
|
44 // Check we have access to package. |
|
45 private static final String DEFAULT_PACKAGE = "com.sun.xml.internal."; |
46 |
46 |
47 /** |
47 /** |
48 * Internal debug flag. |
48 * Internal debug flag. |
49 */ |
49 */ |
50 private static boolean debug = false; |
50 private static boolean debug = false; |
92 * tried. |
92 * tried. |
93 * |
93 * |
94 * If the class loader supplied is <code>null</code>, first try using the |
94 * If the class loader supplied is <code>null</code>, first try using the |
95 * context class loader followed by the current (i.e. bootstrap) class |
95 * context class loader followed by the current (i.e. bootstrap) class |
96 * loader. |
96 * loader. |
|
97 * |
|
98 * Use bootstrap classLoader if cl = null and useBSClsLoader is true |
97 */ |
99 */ |
98 static private Class getProviderClass(String className, ClassLoader cl, |
100 static private Class getProviderClass(String className, ClassLoader cl, |
99 boolean doFallback) throws ClassNotFoundException |
101 boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException |
100 { |
102 { |
101 try { |
103 try { |
102 if (cl == null) { |
104 if (cl == null) { |
103 cl = ss.getContextClassLoader(); |
105 if (useBSClsLoader) { |
104 if (cl == null) { |
106 return Class.forName(className, true, FactoryFinder.class.getClassLoader()); |
105 throw new ClassNotFoundException(); |
107 } else { |
106 } |
108 cl = ss.getContextClassLoader(); |
107 else { |
109 if (cl == null) { |
108 return cl.loadClass(className); |
110 throw new ClassNotFoundException(); |
|
111 } |
|
112 else { |
|
113 return cl.loadClass(className); |
|
114 } |
109 } |
115 } |
110 } |
116 } |
111 else { |
117 else { |
112 return cl.loadClass(className); |
118 return cl.loadClass(className); |
113 } |
119 } |
128 * <code>getProviderClass()</code> in order to load the class. |
134 * <code>getProviderClass()</code> in order to load the class. |
129 * |
135 * |
130 * @param className Name of the concrete class corresponding to the |
136 * @param className Name of the concrete class corresponding to the |
131 * service provider |
137 * service provider |
132 * |
138 * |
133 * @param cl ClassLoader to use to load the class, null means to use |
139 * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code> |
134 * the bootstrap ClassLoader |
140 * current <code>Thread</code>'s context classLoader is used to load the factory class. |
135 * |
141 * |
136 * @param doFallback True if the current ClassLoader should be tried as |
142 * @param doFallback True if the current ClassLoader should be tried as |
137 * a fallback if the class is not found using cl |
143 * a fallback if the class is not found using cl |
138 */ |
144 */ |
139 static Object newInstance(String className, ClassLoader cl, boolean doFallback) |
145 static Object newInstance(String className, ClassLoader cl, boolean doFallback) |
140 throws ConfigurationError |
146 throws ConfigurationError |
141 { |
147 { |
142 try { |
148 return newInstance(className, cl, doFallback, false); |
143 Class providerClass = getProviderClass(className, cl, doFallback); |
149 } |
|
150 |
|
151 /** |
|
152 * Create an instance of a class. Delegates to method |
|
153 * <code>getProviderClass()</code> in order to load the class. |
|
154 * |
|
155 * @param className Name of the concrete class corresponding to the |
|
156 * service provider |
|
157 * |
|
158 * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code> |
|
159 * current <code>Thread</code>'s context classLoader is used to load the factory class. |
|
160 * |
|
161 * @param doFallback True if the current ClassLoader should be tried as |
|
162 * a fallback if the class is not found using cl |
|
163 * |
|
164 * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter |
|
165 * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader. |
|
166 */ |
|
167 static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader) |
|
168 throws ConfigurationError |
|
169 { |
|
170 // make sure we have access to restricted packages |
|
171 if (System.getSecurityManager() != null) { |
|
172 if (className != null && className.startsWith(DEFAULT_PACKAGE)) { |
|
173 cl = null; |
|
174 useBSClsLoader = true; |
|
175 } |
|
176 } |
|
177 |
|
178 try { |
|
179 Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader); |
144 Object instance = providerClass.newInstance(); |
180 Object instance = providerClass.newInstance(); |
145 if (debug) { // Extra check to avoid computing cl strings |
181 if (debug) { // Extra check to avoid computing cl strings |
146 dPrint("created new instance of " + providerClass + |
182 dPrint("created new instance of " + providerClass + |
147 " using ClassLoader: " + cl); |
183 " using ClassLoader: " + cl); |
148 } |
184 } |
231 "lib" + File.separator + "jaxp.properties"; |
267 "lib" + File.separator + "jaxp.properties"; |
232 f = new File(configFile); |
268 f = new File(configFile); |
233 if (ss.doesFileExist(f)) { |
269 if (ss.doesFileExist(f)) { |
234 dPrint("Read properties file "+f); |
270 dPrint("Read properties file "+f); |
235 cacheProps.load(ss.getFileInputStream(f)); |
271 cacheProps.load(ss.getFileInputStream(f)); |
236 } |
|
237 } |
|
238 } |
272 } |
|
273 } |
|
274 } |
239 } |
275 } |
240 } |
276 } |
241 factoryClassName = cacheProps.getProperty(factoryId); |
277 factoryClassName = cacheProps.getProperty(factoryId); |
242 |
278 |
243 if (factoryClassName != null) { |
279 if (factoryClassName != null) { |
274 String serviceId = "META-INF/services/" + factoryId; |
310 String serviceId = "META-INF/services/" + factoryId; |
275 InputStream is = null; |
311 InputStream is = null; |
276 |
312 |
277 // First try the Context ClassLoader |
313 // First try the Context ClassLoader |
278 ClassLoader cl = ss.getContextClassLoader(); |
314 ClassLoader cl = ss.getContextClassLoader(); |
|
315 boolean useBSClsLoader = false; |
279 if (cl != null) { |
316 if (cl != null) { |
280 is = ss.getResourceAsStream(cl, serviceId); |
317 is = ss.getResourceAsStream(cl, serviceId); |
281 |
318 |
282 // If no provider found then try the current ClassLoader |
319 // If no provider found then try the current ClassLoader |
283 if (is == null) { |
320 if (is == null) { |
284 cl = FactoryFinder.class.getClassLoader(); |
321 cl = FactoryFinder.class.getClassLoader(); |
285 is = ss.getResourceAsStream(cl, serviceId); |
322 is = ss.getResourceAsStream(cl, serviceId); |
|
323 useBSClsLoader = true; |
286 } |
324 } |
287 } else { |
325 } else { |
288 // No Context ClassLoader, try the current ClassLoader |
326 // No Context ClassLoader, try the current ClassLoader |
289 cl = FactoryFinder.class.getClassLoader(); |
327 cl = FactoryFinder.class.getClassLoader(); |
290 is = ss.getResourceAsStream(cl, serviceId); |
328 is = ss.getResourceAsStream(cl, serviceId); |
|
329 useBSClsLoader = true; |
291 } |
330 } |
292 |
331 |
293 if (is == null) { |
332 if (is == null) { |
294 // No provider found |
333 // No provider found |
295 return null; |
334 return null; |
323 |
362 |
324 // Note: here we do not want to fall back to the current |
363 // Note: here we do not want to fall back to the current |
325 // ClassLoader because we want to avoid the case where the |
364 // ClassLoader because we want to avoid the case where the |
326 // resource file was found using one ClassLoader and the |
365 // resource file was found using one ClassLoader and the |
327 // provider class was instantiated using a different one. |
366 // provider class was instantiated using a different one. |
328 return newInstance(factoryClassName, cl, false); |
367 return newInstance(factoryClassName, cl, false, useBSClsLoader); |
329 } |
368 } |
330 |
369 |
331 // No provider found |
370 // No provider found |
332 return null; |
371 return null; |
333 } |
372 } |