< prev index next >

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

Print this page

        

@@ -148,17 +148,18 @@
 
     /**
      * Create an instance of a class using the specified ClassLoader
      */
     static JAXBContext newInstance(String contextPath,
+                                   Class[] contextPathClasses,
                                    String className,
                                    ClassLoader classLoader,
                                    Map properties) throws JAXBException {
 
         try {
             Class spFactory = ServiceLoaderUtil.safeLoadClass(className, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader);
-            return newInstance(contextPath, spFactory, classLoader, properties);
+            return newInstance(contextPath, contextPathClasses, spFactory, classLoader, properties);
         } catch (ClassNotFoundException x) {
             throw new JAXBException(Messages.format(Messages.DEFAULT_PROVIDER_NOT_FOUND), x);
 
         } catch (RuntimeException | JAXBException x) {
             // avoid wrapping RuntimeException to JAXBException,

@@ -173,10 +174,11 @@
             throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, className, x), x);
         }
     }
 
     static JAXBContext newInstance(String contextPath,
+                                   Class[] contextPathClasses,
                                    Class spFactory,
                                    ClassLoader classLoader,
                                    Map properties) throws JAXBException {
 
         try {

@@ -210,10 +212,13 @@
 
             if (!(context instanceof JAXBContext)) {
                 // the cast would fail, so generate an exception with a nice message
                 throw handleClassCastException(context.getClass(), JAXBContext.class);
             }
+
+            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, spFactory);
+
             return (JAXBContext) context;
         } catch (InvocationTargetException x) {
             // throw if it is exception not to be wrapped
             // otherwise, wrap with a JAXBException
             Throwable e = handleInvocationTargetException(x);

@@ -275,10 +280,11 @@
             Object context = m.invoke(obj, classes, properties);
             if (!(context instanceof JAXBContext)) {
                 // the cast would fail, so generate an exception with a nice message
                 throw handleClassCastException(context.getClass(), JAXBContext.class);
             }
+            ModuleUtil.delegateAddOpensToImplModule(classes,  spFactory);
             return (JAXBContext) context;
 
         } catch (NoSuchMethodException | IllegalAccessException e) {
             throw new JAXBException(e);
         } catch (InvocationTargetException e) {

@@ -293,54 +299,56 @@
     static JAXBContext find(String factoryId,
                             String contextPath,
                             ClassLoader classLoader,
                             Map properties) throws JAXBException {
 
-        StringTokenizer packages = new StringTokenizer(contextPath, ":");
-        if (!packages.hasMoreTokens()) {
+        if (contextPath == null || contextPath.isEmpty()) {
             // no context is specified
             throw new JAXBException(Messages.format(Messages.NO_PACKAGE_IN_CONTEXTPATH));
         }
 
-        // search for jaxb.properties in the class loader of each class first
-        logger.fine("Searching jaxb.properties");
-        while (packages.hasMoreTokens()) {
-            // com.acme.foo - > com/acme/foo/jaxb.properties
-            String factoryClassName =
-                    classNameFromPackageProperties(
-                        classLoader,
-                        packages.nextToken(":").replace('.', '/'),
-                        factoryId,
-                        JAXB_CONTEXT_FACTORY_DEPRECATED);
+        //ModuleUtil is mr-jar class, scans context path for jaxb classes on jdk9 and higher
+        Class[] contextPathClasses = ModuleUtil.getClassesFromContextPath(contextPath, classLoader);
 
-            if (factoryClassName != null) {
-                return newInstance(contextPath, factoryClassName, classLoader, properties);
+        //first try with classloader#getResource
+        String factoryClassName = jaxbProperties(contextPath, classLoader, factoryId);
+        if (factoryClassName == null && contextPathClasses != null) {
+            //try with class#getResource
+            factoryClassName = jaxbProperties(contextPathClasses, factoryId);
             }
+
+        if (factoryClassName != null) {
+            return newInstance(contextPath, contextPathClasses, factoryClassName, classLoader, properties);
         }
 
+
         String factoryName = classNameFromSystemProperties();
-        if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
+        if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
 
         JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
                 JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
 
-        if (obj != null) return obj.createContext(contextPath, classLoader, properties);
+        if (obj != null) {
+            JAXBContext context = obj.createContext(contextPath, classLoader, properties);
+            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, obj.getClass());
+            return context;
+        }
 
         // to ensure backwards compatibility
         factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
-        if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
+        if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties);
 
         Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
                 "javax.xml.bind.JAXBContext", logger);
 
         if (ctxFactory != null) {
-            return newInstance(contextPath, ctxFactory, classLoader, properties);
+            return newInstance(contextPath, contextPathClasses, ctxFactory, classLoader, properties);
         }
 
         // else no provider found
         logger.fine("Trying to create the platform default provider");
-        return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
+        return newInstance(contextPath, contextPathClasses, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
     }
 
     static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
 
         // search for jaxb.properties in the class loader of each class first

@@ -354,26 +362,35 @@
             // TODO: do we want to optimize away searching the same package?  org.Foo, org.Bar, com.Baz
             // classes from the same package might come from different class loades, so it might be a bad idea
             // TODO: it's easier to look things up from the class
             // c.getResourceAsStream("jaxb.properties");
 
+            URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
+
+            if (jaxbPropertiesUrl != null) {
+
             String factoryClassName =
                     classNameFromPackageProperties(
-                            getClassClassLoader(c),
-                            c.getPackage().getName().replace('.', '/'),
+                                jaxbPropertiesUrl,
                             JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
 
-            if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
+                return newInstance(classes, properties, factoryClassName);
+            }
+
         }
 
         String factoryClassName = classNameFromSystemProperties();
         if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
 
         JAXBContextFactory factory =
                 ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
 
-        if (factory != null) return factory.createContext(classes, properties);
+        if (factory != null) {
+            JAXBContext context = factory.createContext(classes, properties);
+            ModuleUtil.delegateAddOpensToImplModule(classes, factory.getClass());
+            return context;
+        }
 
         // to ensure backwards compatibility
         String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
         if (className != null) return newInstance(classes, properties, className);
 

@@ -393,27 +410,25 @@
 
     /**
      * first factoryId should be the preferred one,
      * more of those can be provided to support backwards compatibility
      */
-    private static String classNameFromPackageProperties(ClassLoader classLoader,
-                                                         String packageName,
+    private static String classNameFromPackageProperties(URL packagePropertiesUrl,
                                                          String ... factoryIds) throws JAXBException {
 
-        String resourceName = packageName + "/jaxb.properties";
-        logger.log(Level.FINE, "Trying to locate {0}", resourceName);
-        Properties props = loadJAXBProperties(classLoader, resourceName);
-        if (props != null) {
+        logger.log(Level.FINE, "Trying to locate {0}", packagePropertiesUrl.toString());
+        Properties props = loadJAXBProperties(packagePropertiesUrl);
             for(String factoryId : factoryIds) {
                 if (props.containsKey(factoryId)) {
                     return props.getProperty(factoryId);
                 }
             }
+        //Factory key not found
+        String propertiesUrl = packagePropertiesUrl.toExternalForm();
+        String packageName = propertiesUrl.substring(0, propertiesUrl.indexOf("/jaxb.properties"));
             throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
         }
-        return null;
-    }
 
     private static String classNameFromSystemProperties() throws JAXBException {
 
         String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
         if (factoryClassName != null) {

@@ -450,34 +465,44 @@
             logger.log(Level.FINE, "  not found");
         }
         return value;
     }
 
-    private static Properties loadJAXBProperties(ClassLoader classLoader,
-                                                 String propFileName) throws JAXBException {
+    private static Properties loadJAXBProperties(URL url) throws JAXBException {
 
-        Properties props = null;
         try {
-            URL url;
-            if (classLoader == null)
-                url = ClassLoader.getSystemResource(propFileName);
-            else
-                url = classLoader.getResource(propFileName);
-
-            if (url != null) {
+            Properties props;
                 logger.log(Level.FINE, "loading props from {0}", url);
                 props = new Properties();
                 InputStream is = url.openStream();
                 props.load(is);
                 is.close();
-            }
+            return props;
         } catch (IOException ioe) {
-            logger.log(Level.FINE, "Unable to load " + propFileName, ioe);
+            logger.log(Level.FINE, "Unable to load " + url.toString(), ioe);
             throw new JAXBException(ioe.toString(), ioe);
         }
+    }
 
-        return props;
+    /**
+     * If run on JPMS package containing resource must be open unconditionally.
+     *
+     * @param classLoader classloader to load resource with
+     * @param resourceName qualified name of the resource
+     * @return resource url if found
+     */
+    private static URL getResourceUrl(ClassLoader classLoader, String resourceName) {
+        URL url;
+        if (classLoader == null)
+            url = ClassLoader.getSystemResource(resourceName);
+        else
+            url = classLoader.getResource(resourceName);
+        return url;
+    }
+
+    private static URL getResourceUrl(Class<?> clazz, String resourceName) {
+        return clazz.getResource(resourceName);
     }
 
 
     /**
      * Search the given ClassLoader for an instance of the specified class and

@@ -604,6 +629,30 @@
                 logger.log(Level.SEVERE, "Unable to close resource: " + resource, ex);
             }
         }
     }
 
+    private static String jaxbProperties(String contextPath, ClassLoader classLoader, String factoryId) throws JAXBException {
+        String[] packages = contextPath.split(":");
+
+        for (String pkg : packages) {
+            String pkgUrl = pkg.replace('.', '/');
+            URL jaxbPropertiesUrl = getResourceUrl(classLoader, pkgUrl + "/jaxb.properties");
+            if (jaxbPropertiesUrl != null) {
+                return classNameFromPackageProperties(jaxbPropertiesUrl,
+                                                      factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
+            }
+        }
+        return null;
+    }
+
+    private static String jaxbProperties(Class[] classesFromContextPath, String factoryId) throws JAXBException {
+        for (Class c : classesFromContextPath) {
+            URL jaxbPropertiesUrl = getResourceUrl(c, "jaxb.properties");
+            if (jaxbPropertiesUrl != null) {
+                return classNameFromPackageProperties(jaxbPropertiesUrl, factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
+            }
+        }
+        return null;
+    }
+
 }
< prev index next >