51 * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li></ul>
52 * @see JAXBContext
53 */
54 class ContextFinder {
55
56 /**
57 * When JAXB is in J2SE, rt.jar has to have a JAXB implementation.
58 * However, rt.jar cannot have META-INF/services/javax.xml.bind.JAXBContext
59 * because if it has, it will take precedence over any file that applications have
60 * in their jar files.
61 *
62 * <p>
63 * When the user bundles his own JAXB implementation, we'd like to use it, and we
64 * want the platform default to be used only when there's no other JAXB provider.
65 *
66 * <p>
67 * For this reason, we have to hard-code the class name into the API.
68 */
69 private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
70
71 private static final Logger logger;
72
73 static {
74 logger = Logger.getLogger("javax.xml.bind");
75 try {
76 if (AccessController.doPrivileged(new GetPropertyAction("jaxb.debug")) != null) {
77 // disconnect the logger from a bigger framework (if any)
78 // and take the matters into our own hands
79 logger.setUseParentHandlers(false);
80 logger.setLevel(Level.ALL);
81 ConsoleHandler handler = new ConsoleHandler();
82 handler.setLevel(Level.ALL);
83 logger.addHandler(handler);
84 } else {
85 // don't change the setting of this logger
86 // to honor what other frameworks
87 // have done on configurations.
88 }
89 } catch (Throwable t) {
90 // just to be extra safe. in particular System.getProperty may throw
91 // SecurityException.
92 }
93 }
94
95 /**
96 * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
97 * throw the wrapped exception.
98 */
99 private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException {
100 Throwable t = x.getTargetException();
101 if (t != null) {
102 if (t instanceof JAXBException)
103 // one of our exceptions, just re-throw
104 throw (JAXBException) t;
105 if (t instanceof RuntimeException)
106 // avoid wrapping exceptions unnecessarily
107 throw (RuntimeException) t;
108 if (t instanceof Error)
109 throw (Error) t;
110 }
111 }
112
113
114 /**
142
143 try {
144 Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
145 return newInstance(contextPath, spFactory, classLoader, properties);
146 } catch (ClassNotFoundException x) {
147 throw new JAXBException(Messages.format(Messages.PROVIDER_NOT_FOUND, className), x);
148
149 } catch (RuntimeException x) {
150 // avoid wrapping RuntimeException to JAXBException,
151 // because it indicates a bug in this code.
152 throw x;
153 } catch (Exception x) {
154 // can't catch JAXBException because the method is hidden behind
155 // reflection. Root element collisions detected in the call to
156 // createContext() are reported as JAXBExceptions - just re-throw it
157 // some other type of exception - just wrap it
158 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
159 }
160 }
161
162 static JAXBContext newInstance(String contextPath, Class spFactory, ClassLoader classLoader, Map properties) throws JAXBException {
163
164 try {
165 /*
166 * javax.xml.bind.context.factory points to a class which has a
167 * static method called 'createContext' that
168 * returns a javax.xml.JAXBContext.
169 */
170
171 Object context = null;
172
173 // first check the method that takes Map as the third parameter.
174 // this is added in 2.0.
175 try {
176 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class);
177 // any failure in invoking this method would be considered fatal
178 context = m.invoke(null, contextPath, classLoader, properties);
179 } catch (NoSuchMethodException e) {
180 // it's not an error for the provider not to have this method.
181 }
182
222
223 Class spi;
224 try {
225 spi = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, getContextClassLoader());
226 } catch (ClassNotFoundException e) {
227 throw new JAXBException(e);
228 }
229
230 if (logger.isLoggable(Level.FINE)) {
231 // extra check to avoid costly which operation if not logged
232 logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
233 }
234
235 return newInstance(classes, properties, spi);
236 }
237
238 static JAXBContext newInstance(Class[] classes,
239 Map properties,
240 Class spFactory) throws JAXBException {
241 try {
242 Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
243 Object context = m.invoke(null, classes, properties);
244 if (!(context instanceof JAXBContext)) {
245 // the cast would fail, so generate an exception with a nice message
246 throw handleClassCastException(context.getClass(), JAXBContext.class);
247 }
248 return (JAXBContext) context;
249 } catch (NoSuchMethodException e) {
250 throw new JAXBException(e);
251 } catch (IllegalAccessException e) {
252 throw new JAXBException(e);
253 } catch (InvocationTargetException e) {
254 handleInvocationTargetException(e);
255
256 Throwable x = e;
257 if (e.getTargetException() != null)
258 x = e.getTargetException();
259
260 throw new JAXBException(x);
261 }
262 }
263
264 static JAXBContext find(String factoryId, String contextPath, ClassLoader classLoader, Map properties) throws JAXBException {
265
266 // TODO: do we want/need another layer of searching in $java.home/lib/jaxb.properties like JAXP?
267
268 StringTokenizer packages = new StringTokenizer(contextPath, ":");
269 if (!packages.hasMoreTokens()) {
270 // no context is specified
271 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
272 }
273
274 // search for jaxb.properties in the class loader of each class first
275 logger.fine("Searching jaxb.properties");
276 while (packages.hasMoreTokens()) {
277 // com.acme.foo - > com/acme/foo/jaxb.properties
278 String className = classNameFromPackageProperties(factoryId, classLoader, packages.nextToken(":").replace('.', '/'));
279 if (className != null) return newInstance(contextPath, className, classLoader, properties);
280 }
281
282 String factoryName = classNameFromSystemProperties();
283 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
284
285 Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
286 if (ctxFactory != null) {
287 return newInstance(contextPath, ctxFactory, classLoader, properties);
288 }
289
290 // TODO: SPEC change required! This is supposed to be!
291 // JAXBContext obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
292 // if (obj != null) return obj;
293
294 // TODO: Deprecated - SPEC change required!
295 factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
296 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
297
298 // else no provider found
299 logger.fine("Trying to create the platform default provider");
300 return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
301 }
302
303 static JAXBContext find(Class[] classes, Map properties) throws JAXBException {
304
305 // search for jaxb.properties in the class loader of each class first
306 logger.fine("Searching jaxb.properties");
307 for (final Class c : classes) {
308 // this classloader is used only to load jaxb.properties, so doing this should be safe.
309 if (c.getPackage() == null) continue; // this is possible for primitives, arrays, and classes that are loaded by poorly implemented ClassLoaders
310
311 // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
312 // classes from the same package might come from different class loades, so it might be a bad idea
313 // TODO: it's easier to look things up from the class
314 // c.getResourceAsStream("jaxb.properties");
315
316 String className = classNameFromPackageProperties(JAXBContext.JAXB_CONTEXT_FACTORY, getClassClassLoader(c), c.getPackage().getName().replace('.', '/'));
317 if (className != null) return newInstance(classes, properties, className);
318 }
319
320 String factoryName = classNameFromSystemProperties();
321 if (factoryName != null) return newInstance(classes, properties, factoryName);
322
323 Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
324 if (ctxFactoryClass != null) {
325 return newInstance(classes, properties, ctxFactoryClass);
326 }
327
328 // TODO: to be removed - deprecated!!! Requires SPEC change!!!
329 String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
330 if (className != null) return newInstance(classes, properties, className);
331
332 // // TODO: supposed to be:
333 // obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
334 // if (obj != null) return obj;
335
336 // else no provider found
337 logger.fine("Trying to create the platform default provider");
338 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
339 }
340
341
342 private static String classNameFromPackageProperties(String factoryId, ClassLoader classLoader, String packageName) throws JAXBException {
343 String resourceName = packageName + "/jaxb.properties";
344 logger.log(Level.FINE, "Trying to locate {0}", resourceName);
345 Properties props = loadJAXBProperties(classLoader, resourceName);
346 if (props != null) {
347 if (props.containsKey(factoryId)) {
348 return props.getProperty(factoryId);
349 } else {
350 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId));
351 }
352 }
353 return null;
354 }
355
356 private static String classNameFromSystemProperties() throws JAXBException {
357 logger.log(Level.FINE, "Checking system property {0}", JAXBContext.JAXB_CONTEXT_FACTORY);
358 // search for a system property second (javax.xml.bind.JAXBContext)
359 String factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY));
360 if (factoryClassName != null) {
361 logger.log(Level.FINE, " found {0}", factoryClassName);
362 return factoryClassName;
363 } else { // leave this here to assure compatibility
364 logger.fine(" not found");
365 logger.log(Level.FINE, "Checking system property {0}", JAXBContext.class.getName());
366 factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.class.getName()));
367 if (factoryClassName != null) {
368 logger.log(Level.FINE, " found {0}", factoryClassName);
369 return factoryClassName;
370 } else {
371 logger.fine(" not found");
372 }
373 }
374 return null;
375 }
376
377 private static Properties loadJAXBProperties(ClassLoader classLoader, String propFileName) throws JAXBException {
378
379 Properties props = null;
380 try {
381 URL url;
382 if (classLoader == null)
383 url = ClassLoader.getSystemResource(propFileName);
384 else
385 url = classLoader.getResource(propFileName);
386
387 if (url != null) {
388 logger.log(Level.FINE, "loading props from {0}", url);
389 props = new Properties();
390 InputStream is = url.openStream();
391 props.load(is);
392 is.close();
393 }
394 } catch (IOException ioe) {
395 logger.log(Level.FINE, "Unable to load " + propFileName, ioe);
396 throw new JAXBException(ioe.toString(), ioe);
397 }
463 public java.lang.Object run() {
464 return c.getClassLoader();
465 }
466 });
467 }
468 }
469
470 private static ClassLoader getSystemClassLoader() {
471 if (System.getSecurityManager() == null) {
472 return ClassLoader.getSystemClassLoader();
473 } else {
474 return (ClassLoader) java.security.AccessController.doPrivileged(
475 new java.security.PrivilegedAction() {
476 public java.lang.Object run() {
477 return ClassLoader.getSystemClassLoader();
478 }
479 });
480 }
481 }
482
483 // TODO: to be removed - SPEC change required
484 // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead.
485 @Deprecated
486 static String firstByServiceLoaderDeprecated(Class spiClass, ClassLoader classLoader) throws JAXBException {
487 final String jaxbContextFQCN = spiClass.getName();
488
489 logger.fine("Searching META-INF/services");
490
491 // search META-INF services next
492 BufferedReader r = null;
493 final String resource = new StringBuilder().append("META-INF/services/").append(jaxbContextFQCN).toString();
494 try {
495 final InputStream resourceStream =
496 (classLoader == null) ?
497 ClassLoader.getSystemResourceAsStream(resource) :
498 classLoader.getResourceAsStream(resource);
499
500 if (resourceStream != null) {
501 r = new BufferedReader(new InputStreamReader(resourceStream, "UTF-8"));
502 String factoryClassName = r.readLine();
503 if (factoryClassName != null) {
504 factoryClassName = factoryClassName.trim();
505 }
506 r.close();
507 logger.log(Level.FINE, "Configured factorty class:{0}", factoryClassName);
508 return factoryClassName;
509 } else {
510 logger.log(Level.FINE, "Unable to load:{0}", resource);
511 return null;
512 }
513 } catch (UnsupportedEncodingException e) {
514 // should never happen
515 throw new JAXBException(e);
516 } catch (IOException e) {
517 throw new JAXBException(e);
518 } finally {
519 try {
520 if (r != null) {
521 r.close();
522 }
523 } catch (IOException ex) {
524 logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
525 }
526 }
527 }
528
529 }
|
51 * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li></ul>
52 * @see JAXBContext
53 */
54 class ContextFinder {
55
56 /**
57 * When JAXB is in J2SE, rt.jar has to have a JAXB implementation.
58 * However, rt.jar cannot have META-INF/services/javax.xml.bind.JAXBContext
59 * because if it has, it will take precedence over any file that applications have
60 * in their jar files.
61 *
62 * <p>
63 * When the user bundles his own JAXB implementation, we'd like to use it, and we
64 * want the platform default to be used only when there's no other JAXB provider.
65 *
66 * <p>
67 * For this reason, we have to hard-code the class name into the API.
68 */
69 private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
70
71 // previous value of JAXBContext.JAXB_CONTEXT_FACTORY, using also this to ensure backwards compatibility
72 private static final String JAXB_CONTEXT_FACTORY_DEPRECATED = "javax.xml.bind.context.factory";
73
74 private static final Logger logger;
75
76 static {
77 logger = Logger.getLogger("javax.xml.bind");
78 try {
79 if (AccessController.doPrivileged(new GetPropertyAction("jaxb.debug")) != null) {
80 // disconnect the logger from a bigger framework (if any)
81 // and take the matters into our own hands
82 logger.setUseParentHandlers(false);
83 logger.setLevel(Level.ALL);
84 ConsoleHandler handler = new ConsoleHandler();
85 handler.setLevel(Level.ALL);
86 logger.addHandler(handler);
87 } else {
88 // don't change the setting of this logger
89 // to honor what other frameworks
90 // have done on configurations.
91 }
92 } catch (Throwable t) {
93 // just to be extra safe. in particular System.getProperty may throw
94 // SecurityException.
95 }
96 }
97
98 private static ServiceLoaderUtil.ExceptionHandler<JAXBException> EXCEPTION_HANDLER =
99 new ServiceLoaderUtil.ExceptionHandler<JAXBException>() {
100 @Override
101 public JAXBException createException(Throwable throwable, String message) {
102 return new JAXBException(message, throwable);
103 }
104 };
105
106 /**
107 * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
108 * throw the wrapped exception.
109 */
110 private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException {
111 Throwable t = x.getTargetException();
112 if (t != null) {
113 if (t instanceof JAXBException)
114 // one of our exceptions, just re-throw
115 throw (JAXBException) t;
116 if (t instanceof RuntimeException)
117 // avoid wrapping exceptions unnecessarily
118 throw (RuntimeException) t;
119 if (t instanceof Error)
120 throw (Error) t;
121 }
122 }
123
124
125 /**
153
154 try {
155 Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
156 return newInstance(contextPath, spFactory, classLoader, properties);
157 } catch (ClassNotFoundException x) {
158 throw new JAXBException(Messages.format(Messages.PROVIDER_NOT_FOUND, className), x);
159
160 } catch (RuntimeException x) {
161 // avoid wrapping RuntimeException to JAXBException,
162 // because it indicates a bug in this code.
163 throw x;
164 } catch (Exception x) {
165 // can't catch JAXBException because the method is hidden behind
166 // reflection. Root element collisions detected in the call to
167 // createContext() are reported as JAXBExceptions - just re-throw it
168 // some other type of exception - just wrap it
169 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
170 }
171 }
172
173 static JAXBContext newInstance(String contextPath,
174 Class spFactory,
175 ClassLoader classLoader,
176 Map properties) throws JAXBException {
177
178 try {
179 /*
180 * javax.xml.bind.context.factory points to a class which has a
181 * static method called 'createContext' that
182 * returns a javax.xml.JAXBContext.
183 */
184
185 Object context = null;
186
187 // first check the method that takes Map as the third parameter.
188 // this is added in 2.0.
189 try {
190 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class);
191 // any failure in invoking this method would be considered fatal
192 context = m.invoke(null, contextPath, classLoader, properties);
193 } catch (NoSuchMethodException e) {
194 // it's not an error for the provider not to have this method.
195 }
196
236
237 Class spi;
238 try {
239 spi = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, getContextClassLoader());
240 } catch (ClassNotFoundException e) {
241 throw new JAXBException(e);
242 }
243
244 if (logger.isLoggable(Level.FINE)) {
245 // extra check to avoid costly which operation if not logged
246 logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
247 }
248
249 return newInstance(classes, properties, spi);
250 }
251
252 static JAXBContext newInstance(Class[] classes,
253 Map properties,
254 Class spFactory) throws JAXBException {
255 try {
256
257 Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
258 Object context = m.invoke(null, classes, properties);
259 if (!(context instanceof JAXBContext)) {
260 // the cast would fail, so generate an exception with a nice message
261 throw handleClassCastException(context.getClass(), JAXBContext.class);
262 }
263 return (JAXBContext) context;
264
265 } catch (NoSuchMethodException | IllegalAccessException e) {
266 throw new JAXBException(e);
267
268 } catch (InvocationTargetException e) {
269 handleInvocationTargetException(e);
270
271 Throwable x = e;
272 if (e.getTargetException() != null)
273 x = e.getTargetException();
274
275 throw new JAXBException(x);
276 }
277 }
278
279 static JAXBContext find(String factoryId,
280 String contextPath,
281 ClassLoader classLoader,
282 Map properties) throws JAXBException {
283
284 StringTokenizer packages = new StringTokenizer(contextPath, ":");
285 if (!packages.hasMoreTokens()) {
286 // no context is specified
287 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
288 }
289
290 // search for jaxb.properties in the class loader of each class first
291 logger.fine("Searching jaxb.properties");
292 while (packages.hasMoreTokens()) {
293 // com.acme.foo - > com/acme/foo/jaxb.properties
294 String factoryClassName =
295 classNameFromPackageProperties(
296 classLoader,
297 packages.nextToken(":").replace('.', '/'),
298 factoryId,
299 JAXB_CONTEXT_FACTORY_DEPRECATED);
300
301 if (factoryClassName != null) {
302 return newInstance(contextPath, factoryClassName, classLoader, properties);
303 }
304 }
305
306 String factoryName = classNameFromSystemProperties();
307 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
308
309 JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
310 JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
311
312 if (obj != null) return obj.createContext(contextPath, classLoader, properties);
313
314 // to ensure backwards compatibility
315 factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
316 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
317
318 Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
319 "javax.xml.bind.JAXBContext", logger);
320
321 if (ctxFactory != null) {
322 return newInstance(contextPath, ctxFactory, classLoader, properties);
323 }
324
325 // else no provider found
326 logger.fine("Trying to create the platform default provider");
327 return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
328 }
329
330 static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
331
332 // search for jaxb.properties in the class loader of each class first
333 logger.fine("Searching jaxb.properties");
334 for (final Class c : classes) {
335 // this classloader is used only to load jaxb.properties, so doing this should be safe.
336 // this is possible for primitives, arrays, and classes that are
337 // loaded by poorly implemented ClassLoaders
338 if (c.getPackage() == null) continue;
339
340 // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
341 // classes from the same package might come from different class loades, so it might be a bad idea
342 // TODO: it's easier to look things up from the class
343 // c.getResourceAsStream("jaxb.properties");
344
345 String factoryClassName =
346 classNameFromPackageProperties(
347 getClassClassLoader(c),
348 c.getPackage().getName().replace('.', '/'),
349 JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
350
351 if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
352 }
353
354 String factoryClassName = classNameFromSystemProperties();
355 if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
356
357 JAXBContextFactory factory =
358 ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
359
360 if (factory != null) return factory.createContext(classes, properties);
361
362 // to ensure backwards compatibility
363 String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
364 if (className != null) return newInstance(classes, properties, className);
365
366 logger.fine("Trying to create the platform default provider");
367 Class ctxFactoryClass =
368 (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
369
370 if (ctxFactoryClass != null) {
371 return newInstance(classes, properties, ctxFactoryClass);
372 }
373
374 // else no provider found
375 logger.fine("Trying to create the platform default provider");
376 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
377 }
378
379
380 /**
381 * first factoryId should be the preffered one,
382 * more of those can be provided to support backwards compatibility
383 */
384 private static String classNameFromPackageProperties(ClassLoader classLoader,
385 String packageName,
386 String ... factoryIds) throws JAXBException {
387
388 String resourceName = packageName + "/jaxb.properties";
389 logger.log(Level.FINE, "Trying to locate {0}", resourceName);
390 Properties props = loadJAXBProperties(classLoader, resourceName);
391 if (props != null) {
392 for(String factoryId : factoryIds) {
393 if (props.containsKey(factoryId)) {
394 return props.getProperty(factoryId);
395 }
396 }
397 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
398 }
399 return null;
400 }
401
402 private static String classNameFromSystemProperties() throws JAXBException {
403
404 String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
405 if (factoryClassName != null) {
406 return factoryClassName;
407 }
408 // leave this here to assure compatibility
409 factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
410 if (factoryClassName != null) {
411 return factoryClassName;
412 }
413 // leave this here to assure compatibility
414 factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
415 if (factoryClassName != null) {
416 return factoryClassName;
417 }
418 return null;
419 }
420
421 private static String getDeprecatedSystemProperty(String property) {
422 String value = getSystemProperty(property);
423 if (value != null) {
424 logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
425 new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
426 }
427 return value;
428 }
429
430 private static String getSystemProperty(String property) {
431 logger.log(Level.FINE, "Checking system property {0}", property);
432 String value = AccessController.doPrivileged(new GetPropertyAction(property));
433 if (value != null) {
434 logger.log(Level.FINE, " found {0}", value);
435 } else {
436 logger.log(Level.FINE, " not found");
437 }
438 return value;
439 }
440
441 private static Properties loadJAXBProperties(ClassLoader classLoader,
442 String propFileName) throws JAXBException {
443
444 Properties props = null;
445 try {
446 URL url;
447 if (classLoader == null)
448 url = ClassLoader.getSystemResource(propFileName);
449 else
450 url = classLoader.getResource(propFileName);
451
452 if (url != null) {
453 logger.log(Level.FINE, "loading props from {0}", url);
454 props = new Properties();
455 InputStream is = url.openStream();
456 props.load(is);
457 is.close();
458 }
459 } catch (IOException ioe) {
460 logger.log(Level.FINE, "Unable to load " + propFileName, ioe);
461 throw new JAXBException(ioe.toString(), ioe);
462 }
528 public java.lang.Object run() {
529 return c.getClassLoader();
530 }
531 });
532 }
533 }
534
535 private static ClassLoader getSystemClassLoader() {
536 if (System.getSecurityManager() == null) {
537 return ClassLoader.getSystemClassLoader();
538 } else {
539 return (ClassLoader) java.security.AccessController.doPrivileged(
540 new java.security.PrivilegedAction() {
541 public java.lang.Object run() {
542 return ClassLoader.getSystemClassLoader();
543 }
544 });
545 }
546 }
547
548 // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead.
549 @Deprecated
550 static String firstByServiceLoaderDeprecated(Class spiClass,
551 ClassLoader classLoader) throws JAXBException {
552
553 final String jaxbContextFQCN = spiClass.getName();
554
555 logger.fine("Searching META-INF/services");
556
557 // search META-INF services next
558 BufferedReader r = null;
559 final String resource = "META-INF/services/" + jaxbContextFQCN;
560 try {
561 final InputStream resourceStream =
562 (classLoader == null) ?
563 ClassLoader.getSystemResourceAsStream(resource) :
564 classLoader.getResourceAsStream(resource);
565
566 if (resourceStream != null) {
567 r = new BufferedReader(new InputStreamReader(resourceStream, "UTF-8"));
568 String factoryClassName = r.readLine();
569 if (factoryClassName != null) {
570 factoryClassName = factoryClassName.trim();
571 }
572 r.close();
573 logger.log(Level.FINE, "Configured factorty class:{0}", factoryClassName);
574 return factoryClassName;
575 } else {
576 logger.log(Level.FINE, "Unable to load:{0}", resource);
577 return null;
578 }
579 } catch (IOException e) {
580 throw new JAXBException(e);
581 } finally {
582 try {
583 if (r != null) {
584 r.close();
585 }
586 } catch (IOException ex) {
587 logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
588 }
589 }
590 }
591
592 }
|