< prev index next >

jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java

Print this page




 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 }
< prev index next >