133 * @param originalType
134 * The Class object of the type being cast
135 * @param targetType
136 * The Class object of the type that is being cast to
137 * @return JAXBException to be thrown.
138 */
139 private static JAXBException handleClassCastException(Class originalType, Class targetType) {
140 final URL targetTypeURL = which(targetType);
141
142 return new JAXBException(Messages.format(Messages.ILLEGAL_CAST,
143 // we don't care where the impl class is, we want to know where JAXBContext lives in the impl
144 // class' ClassLoader
145 getClassClassLoader(originalType).getResource("javax/xml/bind/JAXBContext.class"),
146 targetTypeURL));
147 }
148
149 /**
150 * Create an instance of a class using the specified ClassLoader
151 */
152 static JAXBContext newInstance(String contextPath,
153 String className,
154 ClassLoader classLoader,
155 Map properties) throws JAXBException {
156
157 try {
158 Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
159 return newInstance(contextPath, spFactory, classLoader, properties);
160 } catch (ClassNotFoundException x) {
161 throw new JAXBException(Messages.format(Messages.DEFAULT_PROVIDER_NOT_FOUND), x);
162
163 } catch (RuntimeException | JAXBException x) {
164 // avoid wrapping RuntimeException to JAXBException,
165 // because it indicates a bug in this code.
166 // JAXBException re-thrown as is
167 throw x;
168 } catch (Exception x) {
169 // can't catch JAXBException because the method is hidden behind
170 // reflection. Root element collisions detected in the call to
171 // createContext() are reported as JAXBExceptions - just re-throw it
172 // some other type of exception - just wrap it
173 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
174 }
175 }
176
177 static JAXBContext newInstance(String contextPath,
178 Class spFactory,
179 ClassLoader classLoader,
180 Map properties) throws JAXBException {
181
182 try {
183 /*
184 * javax.xml.bind.context.factory points to a class which has a
185 * static method called 'createContext' that
186 * returns a javax.xml.JAXBContext.
187 */
188
189 Object context = null;
190
191 // first check the method that takes Map as the third parameter.
192 // this is added in 2.0.
193 try {
194 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class);
195 // any failure in invoking this method would be considered fatal
196 Object obj = instantiateProviderIfNecessary(spFactory);
197 context = m.invoke(obj, contextPath, classLoader, properties);
198 } catch (NoSuchMethodException ignored) {
199 // it's not an error for the provider not to have this method.
200 }
201
202 if (context == null) {
203 // try the old method that doesn't take properties. compatible with 1.0.
204 // it is an error for an implementation not to have both forms of the createContext method.
205 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class);
206 Object obj = instantiateProviderIfNecessary(spFactory);
207 // any failure in invoking this method would be considered fatal
208 context = m.invoke(obj, contextPath, classLoader);
209 }
210
211 if (!(context instanceof JAXBContext)) {
212 // the cast would fail, so generate an exception with a nice message
213 throw handleClassCastException(context.getClass(), JAXBContext.class);
214 }
215 return (JAXBContext) context;
216 } catch (InvocationTargetException x) {
217 // throw if it is exception not to be wrapped
218 // otherwise, wrap with a JAXBException
219 Throwable e = handleInvocationTargetException(x);
220 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e);
221
222 } catch (Exception x) {
223 // can't catch JAXBException because the method is hidden behind
224 // reflection. Root element collisions detected in the call to
225 // createContext() are reported as JAXBExceptions - just re-throw it
226 // some other type of exception - just wrap it
227 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, x), x);
228 }
229 }
230
231 private static Object instantiateProviderIfNecessary(final Class<?> implClass) throws JAXBException {
232 try {
233 if (JAXBContextFactory.class.isAssignableFrom(implClass)) {
234 return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
260 if (logger.isLoggable(Level.FINE)) {
261 // extra check to avoid costly which operation if not logged
262 logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
263 }
264
265 return newInstance(classes, properties, spi);
266 }
267
268 static JAXBContext newInstance(Class[] classes,
269 Map properties,
270 Class spFactory) throws JAXBException {
271 try {
272
273 Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
274 Object obj = instantiateProviderIfNecessary(spFactory);
275 Object context = m.invoke(obj, classes, properties);
276 if (!(context instanceof JAXBContext)) {
277 // the cast would fail, so generate an exception with a nice message
278 throw handleClassCastException(context.getClass(), JAXBContext.class);
279 }
280 return (JAXBContext) context;
281
282 } catch (NoSuchMethodException | IllegalAccessException e) {
283 throw new JAXBException(e);
284 } catch (InvocationTargetException e) {
285 // throw if it is exception not to be wrapped
286 // otherwise, wrap with a JAXBException
287 Throwable x = handleInvocationTargetException(e);
288
289 throw new JAXBException(x);
290 }
291 }
292
293 static JAXBContext find(String factoryId,
294 String contextPath,
295 ClassLoader classLoader,
296 Map properties) throws JAXBException {
297
298 StringTokenizer packages = new StringTokenizer(contextPath, ":");
299 if (!packages.hasMoreTokens()) {
300 // no context is specified
301 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
302 }
303
304 // search for jaxb.properties in the class loader of each class first
305 logger.fine("Searching jaxb.properties");
306 while (packages.hasMoreTokens()) {
307 // com.acme.foo - > com/acme/foo/jaxb.properties
308 String factoryClassName =
309 classNameFromPackageProperties(
310 classLoader,
311 packages.nextToken(":").replace('.', '/'),
312 factoryId,
313 JAXB_CONTEXT_FACTORY_DEPRECATED);
314
315 if (factoryClassName != null) {
316 return newInstance(contextPath, factoryClassName, classLoader, properties);
317 }
318 }
319
320 String factoryName = classNameFromSystemProperties();
321 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
322
323 JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
324 JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
325
326 if (obj != null) return obj.createContext(contextPath, classLoader, properties);
327
328 // to ensure backwards compatibility
329 factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
330 if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
331
332 Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
333 "javax.xml.bind.JAXBContext", logger);
334
335 if (ctxFactory != null) {
336 return newInstance(contextPath, ctxFactory, classLoader, properties);
337 }
338
339 // else no provider found
340 logger.fine("Trying to create the platform default provider");
341 return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
342 }
343
344 static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
345
346 // search for jaxb.properties in the class loader of each class first
347 logger.fine("Searching jaxb.properties");
348 for (final Class c : classes) {
349 // this classloader is used only to load jaxb.properties, so doing this should be safe.
350 // this is possible for primitives, arrays, and classes that are
351 // loaded by poorly implemented ClassLoaders
352 if (c.getPackage() == null) continue;
353
354 // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
355 // classes from the same package might come from different class loades, so it might be a bad idea
356 // TODO: it's easier to look things up from the class
357 // c.getResourceAsStream("jaxb.properties");
358
359 String factoryClassName =
360 classNameFromPackageProperties(
361 getClassClassLoader(c),
362 c.getPackage().getName().replace('.', '/'),
363 JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
364
365 if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
366 }
367
368 String factoryClassName = classNameFromSystemProperties();
369 if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
370
371 JAXBContextFactory factory =
372 ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
373
374 if (factory != null) return factory.createContext(classes, properties);
375
376 // to ensure backwards compatibility
377 String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
378 if (className != null) return newInstance(classes, properties, className);
379
380 logger.fine("Trying to create the platform default provider");
381 Class ctxFactoryClass =
382 (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
383
384 if (ctxFactoryClass != null) {
385 return newInstance(classes, properties, ctxFactoryClass);
386 }
387
388 // else no provider found
389 logger.fine("Trying to create the platform default provider");
390 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
391 }
392
393
394 /**
395 * first factoryId should be the preferred one,
396 * more of those can be provided to support backwards compatibility
397 */
398 private static String classNameFromPackageProperties(ClassLoader classLoader,
399 String packageName,
400 String ... factoryIds) throws JAXBException {
401
402 String resourceName = packageName + "/jaxb.properties";
403 logger.log(Level.FINE, "Trying to locate {0}", resourceName);
404 Properties props = loadJAXBProperties(classLoader, resourceName);
405 if (props != null) {
406 for(String factoryId : factoryIds) {
407 if (props.containsKey(factoryId)) {
408 return props.getProperty(factoryId);
409 }
410 }
411 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
412 }
413 return null;
414 }
415
416 private static String classNameFromSystemProperties() throws JAXBException {
417
418 String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
419 if (factoryClassName != null) {
420 return factoryClassName;
421 }
422 // leave this here to assure compatibility
423 factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
424 if (factoryClassName != null) {
425 return factoryClassName;
426 }
427 // leave this here to assure compatibility
428 factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
429 if (factoryClassName != null) {
430 return factoryClassName;
431 }
432 return null;
433 }
434
435 private static String getDeprecatedSystemProperty(String property) {
436 String value = getSystemProperty(property);
437 if (value != null) {
438 logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
439 new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
440 }
441 return value;
442 }
443
444 private static String getSystemProperty(String property) {
445 logger.log(Level.FINE, "Checking system property {0}", property);
446 String value = AccessController.doPrivileged(new GetPropertyAction(property));
447 if (value != null) {
448 logger.log(Level.FINE, " found {0}", value);
449 } else {
450 logger.log(Level.FINE, " not found");
451 }
452 return value;
453 }
454
455 private static Properties loadJAXBProperties(ClassLoader classLoader,
456 String propFileName) throws JAXBException {
457
458 Properties props = null;
459 try {
460 URL url;
461 if (classLoader == null)
462 url = ClassLoader.getSystemResource(propFileName);
463 else
464 url = classLoader.getResource(propFileName);
465
466 if (url != null) {
467 logger.log(Level.FINE, "loading props from {0}", url);
468 props = new Properties();
469 InputStream is = url.openStream();
470 props.load(is);
471 is.close();
472 }
473 } catch (IOException ioe) {
474 logger.log(Level.FINE, "Unable to load " + propFileName, ioe);
475 throw new JAXBException(ioe.toString(), ioe);
476 }
477
478 return props;
479 }
480
481
482 /**
483 * Search the given ClassLoader for an instance of the specified class and
484 * return a string representation of the URL that points to the resource.
485 *
486 * @param clazz
487 * The class to search for
488 * @param loader
489 * The ClassLoader to search. If this parameter is null, then the
490 * system class loader will be searched
491 * @return
492 * the URL for the class or null if it wasn't found
493 */
494 static URL which(Class clazz, ClassLoader loader) {
495
496 String classnameAsResource = clazz.getName().replace('.', '/') + ".class";
497
498 if (loader == null) {
587 factoryClassName = factoryClassName.trim();
588 }
589 r.close();
590 logger.log(Level.FINE, "Configured factorty class:{0}", factoryClassName);
591 return factoryClassName;
592 } else {
593 logger.log(Level.FINE, "Unable to load:{0}", resource);
594 return null;
595 }
596 } catch (IOException e) {
597 throw new JAXBException(e);
598 } finally {
599 try {
600 if (r != null) {
601 r.close();
602 }
603 } catch (IOException ex) {
604 logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
605 }
606 }
607 }
608
609 }
|
133 * @param originalType
134 * The Class object of the type being cast
135 * @param targetType
136 * The Class object of the type that is being cast to
137 * @return JAXBException to be thrown.
138 */
139 private static JAXBException handleClassCastException(Class originalType, Class targetType) {
140 final URL targetTypeURL = which(targetType);
141
142 return new JAXBException(Messages.format(Messages.ILLEGAL_CAST,
143 // we don't care where the impl class is, we want to know where JAXBContext lives in the impl
144 // class' ClassLoader
145 getClassClassLoader(originalType).getResource("javax/xml/bind/JAXBContext.class"),
146 targetTypeURL));
147 }
148
149 /**
150 * Create an instance of a class using the specified ClassLoader
151 */
152 static JAXBContext newInstance(String contextPath,
153 Class[] contextPathClasses,
154 String className,
155 ClassLoader classLoader,
156 Map properties) throws JAXBException {
157
158 try {
159 Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
160 return newInstance(contextPath, contextPathClasses, spFactory, classLoader, properties);
161 } catch (ClassNotFoundException x) {
162 throw new JAXBException(Messages.format(Messages.DEFAULT_PROVIDER_NOT_FOUND), x);
163
164 } catch (RuntimeException | JAXBException x) {
165 // avoid wrapping RuntimeException to JAXBException,
166 // because it indicates a bug in this code.
167 // JAXBException re-thrown as is
168 throw x;
169 } catch (Exception x) {
170 // can't catch JAXBException because the method is hidden behind
171 // reflection. Root element collisions detected in the call to
172 // createContext() are reported as JAXBExceptions - just re-throw it
173 // some other type of exception - just wrap it
174 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
175 }
176 }
177
178 static JAXBContext newInstance(String contextPath,
179 Class[] contextPathClasses,
180 Class spFactory,
181 ClassLoader classLoader,
182 Map properties) throws JAXBException {
183
184 try {
185 /*
186 * javax.xml.bind.context.factory points to a class which has a
187 * static method called 'createContext' that
188 * returns a javax.xml.JAXBContext.
189 */
190
191 Object context = null;
192
193 // first check the method that takes Map as the third parameter.
194 // this is added in 2.0.
195 try {
196 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class);
197 // any failure in invoking this method would be considered fatal
198 Object obj = instantiateProviderIfNecessary(spFactory);
199 context = m.invoke(obj, contextPath, classLoader, properties);
200 } catch (NoSuchMethodException ignored) {
201 // it's not an error for the provider not to have this method.
202 }
203
204 if (context == null) {
205 // try the old method that doesn't take properties. compatible with 1.0.
206 // it is an error for an implementation not to have both forms of the createContext method.
207 Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class);
208 Object obj = instantiateProviderIfNecessary(spFactory);
209 // any failure in invoking this method would be considered fatal
210 context = m.invoke(obj, contextPath, classLoader);
211 }
212
213 if (!(context instanceof JAXBContext)) {
214 // the cast would fail, so generate an exception with a nice message
215 throw handleClassCastException(context.getClass(), JAXBContext.class);
216 }
217
218 ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, spFactory);
219
220 return (JAXBContext) context;
221 } catch (InvocationTargetException x) {
222 // throw if it is exception not to be wrapped
223 // otherwise, wrap with a JAXBException
224 Throwable e = handleInvocationTargetException(x);
225 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e);
226
227 } catch (Exception x) {
228 // can't catch JAXBException because the method is hidden behind
229 // reflection. Root element collisions detected in the call to
230 // createContext() are reported as JAXBExceptions - just re-throw it
231 // some other type of exception - just wrap it
232 throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, x), x);
233 }
234 }
235
236 private static Object instantiateProviderIfNecessary(final Class<?> implClass) throws JAXBException {
237 try {
238 if (JAXBContextFactory.class.isAssignableFrom(implClass)) {
239 return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
265 if (logger.isLoggable(Level.FINE)) {
266 // extra check to avoid costly which operation if not logged
267 logger.log(Level.FINE, "loaded {0} from {1}", new Object[]{className, which(spi)});
268 }
269
270 return newInstance(classes, properties, spi);
271 }
272
273 static JAXBContext newInstance(Class[] classes,
274 Map properties,
275 Class spFactory) throws JAXBException {
276 try {
277
278 Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
279 Object obj = instantiateProviderIfNecessary(spFactory);
280 Object context = m.invoke(obj, classes, properties);
281 if (!(context instanceof JAXBContext)) {
282 // the cast would fail, so generate an exception with a nice message
283 throw handleClassCastException(context.getClass(), JAXBContext.class);
284 }
285 ModuleUtil.delegateAddOpensToImplModule(classes, spFactory);
286 return (JAXBContext) context;
287
288 } catch (NoSuchMethodException | IllegalAccessException e) {
289 throw new JAXBException(e);
290 } catch (InvocationTargetException e) {
291 // throw if it is exception not to be wrapped
292 // otherwise, wrap with a JAXBException
293 Throwable x = handleInvocationTargetException(e);
294
295 throw new JAXBException(x);
296 }
297 }
298
299 static JAXBContext find(String factoryId,
300 String contextPath,
301 ClassLoader classLoader,
302 Map properties) throws JAXBException {
303
304 if (contextPath == null || contextPath.isEmpty()) {
305 // no context is specified
306 throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
307 }
308
309 //ModuleUtil is mr-jar class, scans context path for jaxb classes on jdk9 and higher
310 Class[] contextPathClasses = ModuleUtil.getClassesFromContextPath(contextPath, classLoader);
311
312 //first try with classloader#getResource
313 String factoryClassName = jaxbProperties(contextPath, classLoader, factoryId);
314 if (factoryClassName == null && contextPathClasses != null) {
315 //try with class#getResource
316 factoryClassName = jaxbProperties(contextPathClasses, factoryId);
317 }
318
319 if (factoryClassName != null) {
320 return newInstance(contextPath, contextPathClasses, factoryClassName, classLoader, properties);
321 }
322
323
324 String factoryName = classNameFromSystemProperties();
325 if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
326
327 JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
328 JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
329
330 if (obj != null) {
331 JAXBContext context = obj.createContext(contextPath, classLoader, properties);
332 ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, obj.getClass());
333 return context;
334 }
335
336 // to ensure backwards compatibility
337 factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
338 if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
339
340 Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
341 "javax.xml.bind.JAXBContext", logger);
342
343 if (ctxFactory != null) {
344 return newInstance(contextPath, contextPathClasses, ctxFactory, classLoader, properties);
345 }
346
347 // else no provider found
348 logger.fine("Trying to create the platform default provider");
349 return newInstance(contextPath, contextPathClasses, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
350 }
351
352 static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
353
354 // search for jaxb.properties in the class loader of each class first
355 logger.fine("Searching jaxb.properties");
356 for (final Class c : classes) {
357 // this classloader is used only to load jaxb.properties, so doing this should be safe.
358 // this is possible for primitives, arrays, and classes that are
359 // loaded by poorly implemented ClassLoaders
360 if (c.getPackage() == null) continue;
361
362 // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
363 // classes from the same package might come from different class loades, so it might be a bad idea
364 // TODO: it's easier to look things up from the class
365 // c.getResourceAsStream("jaxb.properties");
366
367 URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
368
369 if (jaxbPropertiesUrl != null) {
370
371 String factoryClassName =
372 classNameFromPackageProperties(
373 jaxbPropertiesUrl,
374 JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
375
376 return newInstance(classes, properties, factoryClassName);
377 }
378
379 }
380
381 String factoryClassName = classNameFromSystemProperties();
382 if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
383
384 JAXBContextFactory factory =
385 ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
386
387 if (factory != null) {
388 JAXBContext context = factory.createContext(classes, properties);
389 ModuleUtil.delegateAddOpensToImplModule(classes, factory.getClass());
390 return context;
391 }
392
393 // to ensure backwards compatibility
394 String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
395 if (className != null) return newInstance(classes, properties, className);
396
397 logger.fine("Trying to create the platform default provider");
398 Class ctxFactoryClass =
399 (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
400
401 if (ctxFactoryClass != null) {
402 return newInstance(classes, properties, ctxFactoryClass);
403 }
404
405 // else no provider found
406 logger.fine("Trying to create the platform default provider");
407 return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
408 }
409
410
411 /**
412 * first factoryId should be the preferred one,
413 * more of those can be provided to support backwards compatibility
414 */
415 private static String classNameFromPackageProperties(URL packagePropertiesUrl,
416 String ... factoryIds) throws JAXBException {
417
418 logger.log(Level.FINE, "Trying to locate {0}", packagePropertiesUrl.toString());
419 Properties props = loadJAXBProperties(packagePropertiesUrl);
420 for(String factoryId : factoryIds) {
421 if (props.containsKey(factoryId)) {
422 return props.getProperty(factoryId);
423 }
424 }
425 //Factory key not found
426 String propertiesUrl = packagePropertiesUrl.toExternalForm();
427 String packageName = propertiesUrl.substring(0, propertiesUrl.indexOf("/jaxb.properties"));
428 throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
429 }
430
431 private static String classNameFromSystemProperties() throws JAXBException {
432
433 String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
434 if (factoryClassName != null) {
435 return factoryClassName;
436 }
437 // leave this here to assure compatibility
438 factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
439 if (factoryClassName != null) {
440 return factoryClassName;
441 }
442 // leave this here to assure compatibility
443 factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
444 if (factoryClassName != null) {
445 return factoryClassName;
446 }
447 return null;
448 }
449
450 private static String getDeprecatedSystemProperty(String property) {
451 String value = getSystemProperty(property);
452 if (value != null) {
453 logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
454 new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
455 }
456 return value;
457 }
458
459 private static String getSystemProperty(String property) {
460 logger.log(Level.FINE, "Checking system property {0}", property);
461 String value = AccessController.doPrivileged(new GetPropertyAction(property));
462 if (value != null) {
463 logger.log(Level.FINE, " found {0}", value);
464 } else {
465 logger.log(Level.FINE, " not found");
466 }
467 return value;
468 }
469
470 private static Properties loadJAXBProperties(URL url) throws JAXBException {
471
472 try {
473 Properties props;
474 logger.log(Level.FINE, "loading props from {0}", url);
475 props = new Properties();
476 InputStream is = url.openStream();
477 props.load(is);
478 is.close();
479 return props;
480 } catch (IOException ioe) {
481 logger.log(Level.FINE, "Unable to load " + url.toString(), ioe);
482 throw new JAXBException(ioe.toString(), ioe);
483 }
484 }
485
486 /**
487 * If run on JPMS package containing resource must be open unconditionally.
488 *
489 * @param classLoader classloader to load resource with
490 * @param resourceName qualified name of the resource
491 * @return resource url if found
492 */
493 private static URL getResourceUrl(ClassLoader classLoader, String resourceName) {
494 URL url;
495 if (classLoader == null)
496 url = ClassLoader.getSystemResource(resourceName);
497 else
498 url = classLoader.getResource(resourceName);
499 return url;
500 }
501
502 private static URL getResourceUrl(Class<?> clazz, String resourceName) {
503 return clazz.getResource(resourceName);
504 }
505
506
507 /**
508 * Search the given ClassLoader for an instance of the specified class and
509 * return a string representation of the URL that points to the resource.
510 *
511 * @param clazz
512 * The class to search for
513 * @param loader
514 * The ClassLoader to search. If this parameter is null, then the
515 * system class loader will be searched
516 * @return
517 * the URL for the class or null if it wasn't found
518 */
519 static URL which(Class clazz, ClassLoader loader) {
520
521 String classnameAsResource = clazz.getName().replace('.', '/') + ".class";
522
523 if (loader == null) {
612 factoryClassName = factoryClassName.trim();
613 }
614 r.close();
615 logger.log(Level.FINE, "Configured factorty class:{0}", factoryClassName);
616 return factoryClassName;
617 } else {
618 logger.log(Level.FINE, "Unable to load:{0}", resource);
619 return null;
620 }
621 } catch (IOException e) {
622 throw new JAXBException(e);
623 } finally {
624 try {
625 if (r != null) {
626 r.close();
627 }
628 } catch (IOException ex) {
629 logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
630 }
631 }
632 }
633
634 private static String jaxbProperties(String contextPath, ClassLoader classLoader, String factoryId) throws JAXBException {
635 String[] packages = contextPath.split(":");
636
637 for (String pkg : packages) {
638 String pkgUrl = pkg.replace('.', '/');
639 URL jaxbPropertiesUrl = getResourceUrl(classLoader, pkgUrl + "/jaxb.properties");
640 if (jaxbPropertiesUrl != null) {
641 return classNameFromPackageProperties(jaxbPropertiesUrl,
642 factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
643 }
644 }
645 return null;
646 }
647
648 private static String jaxbProperties(Class[] classesFromContextPath, String factoryId) throws JAXBException {
649 for (Class c : classesFromContextPath) {
650 URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
651 if (jaxbPropertiesUrl != null) {
652 return classNameFromPackageProperties(jaxbPropertiesUrl, factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
653 }
654 }
655 return null;
656 }
657
658 }
|