< prev index next >

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

Print this page

        

@@ -66,10 +66,13 @@
      * <p>
      * For this reason, we have to hard-code the class name into the API.
      */
     private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
 
+    // previous value of JAXBContext.JAXB_CONTEXT_FACTORY, using also this to ensure backwards compatibility
+    private static final String JAXB_CONTEXT_FACTORY_DEPRECATED = "javax.xml.bind.context.factory";
+
     private static final Logger logger;
 
     static {
         logger = Logger.getLogger("javax.xml.bind");
         try {

@@ -90,10 +93,17 @@
             // just to be extra safe. in particular System.getProperty may throw
             // SecurityException.
         }
     }
 
+    private static ServiceLoaderUtil.ExceptionHandler<JAXBException> EXCEPTION_HANDLER = new ServiceLoaderUtil.ExceptionHandler<JAXBException>() {
+        @Override
+        public JAXBException createException(Throwable throwable, String message) {
+            return new JAXBException(message, throwable);
+        }
+    };
+
     /**
      * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
      * throw the wrapped exception.
      */
     private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException {

@@ -273,36 +283,36 @@
 
         // 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 className = classNameFromPackageProperties(factoryId, classLoader, packages.nextToken(":").replace('.', '/'));
-            if (className != null) return newInstance(contextPath, className, classLoader, properties);
+            String factoryClassName = classNameFromPackageProperties(classLoader, packages.nextToken(":").replace('.', '/'), factoryId, JAXB_CONTEXT_FACTORY_DEPRECATED);
+            if (factoryClassName != null) return newInstance(contextPath, factoryClassName, classLoader, properties);
         }
 
         String factoryName = classNameFromSystemProperties();
         if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
 
+        // TODO: SPEC change required! java.util.ServiceLoader
+        JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
+        if (obj != null) return obj.createContext(contextPath, classLoader, properties);
+
+        // to ensure backwards compatibility
+        factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
+        if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
+
         Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
         if (ctxFactory != null) {
             return newInstance(contextPath, ctxFactory, classLoader, properties);
         }
 
-        // TODO: SPEC change required! This is supposed to be!
-        // JAXBContext obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
-        // if (obj != null) return obj;
-
-        // TODO: Deprecated - SPEC change required!
-        factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
-        if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
-
         // else no provider found
         logger.fine("Trying to create the platform default provider");
         return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
     }
 
-    static JAXBContext find(Class[] classes, Map properties) throws JAXBException {
+    static JAXBContext find(Class<?>[] classes, Map<String, ?> properties) throws JAXBException {
 
         // search for jaxb.properties in the class loader of each class first
         logger.fine("Searching jaxb.properties");
         for (final Class c : classes) {
             // this classloader is used only to load jaxb.properties, so doing this should be safe.

@@ -311,71 +321,93 @@
             // 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");
 
-            String className = classNameFromPackageProperties(JAXBContext.JAXB_CONTEXT_FACTORY, getClassClassLoader(c), c.getPackage().getName().replace('.', '/'));
-            if (className != null) return newInstance(classes, properties, className);
+            String factoryClassName = classNameFromPackageProperties(getClassClassLoader(c), c.getPackage().getName().replace('.', '/'), JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
+            if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
         }
 
-        String factoryName = classNameFromSystemProperties();
-        if (factoryName != null) return newInstance(classes, properties, factoryName);
+        String factoryClassName = classNameFromSystemProperties();
+        if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
 
-        Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
-        if (ctxFactoryClass != null) {
-            return newInstance(classes, properties, ctxFactoryClass);
-        }
+        // TODO: SPEC change required! java.util.ServiceLoader
+        JAXBContextFactory factory = ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
+        if (factory != null) return factory.createContext(classes, properties);
 
-        // TODO: to be removed - deprecated!!! Requires SPEC change!!!
+        // to ensure backwards compatibility
         String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
         if (className != null) return newInstance(classes, properties, className);
 
-        //    // TODO: supposed to be:
-        //    obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
-        //    if (obj != null) return obj;
+        logger.fine("Trying to create the platform default provider");
+        Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
+        if (ctxFactoryClass != null) {
+            return newInstance(classes, properties, ctxFactoryClass);
+        }
 
         // else no provider found
         logger.fine("Trying to create the platform default provider");
         return newInstance(classes, properties, PLATFORM_DEFAULT_FACTORY_CLASS);
     }
 
 
-    private static String classNameFromPackageProperties(String factoryId, ClassLoader classLoader, String packageName) throws JAXBException {
+    /**
+     * first factoryId should be the preffered one, more of those can be provided to support backwards compatibility
+     */
+    private static String classNameFromPackageProperties(ClassLoader classLoader, String packageName, 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) {
+            for(String factoryId : factoryIds) {
             if (props.containsKey(factoryId)) {
                 return props.getProperty(factoryId);
-            } else {
-                throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId));
             }
         }
+            throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
+        }
         return null;
     }
 
     private static String classNameFromSystemProperties() throws JAXBException {
-        logger.log(Level.FINE, "Checking system property {0}", JAXBContext.JAXB_CONTEXT_FACTORY);
-        // search for a system property second (javax.xml.bind.JAXBContext)
-        String factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY));
+        String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
         if (factoryClassName != null) {
-            logger.log(Level.FINE, "  found {0}", factoryClassName);
             return factoryClassName;
-        } else { // leave this here to assure compatibility
-            logger.fine("  not found");
-            logger.log(Level.FINE, "Checking system property {0}", JAXBContext.class.getName());
-            factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.class.getName()));
+        }
+        // leave this here to assure compatibility
+        factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
             if (factoryClassName != null) {
-                logger.log(Level.FINE, "  found {0}", factoryClassName);
                 return factoryClassName;
-            } else {
-                logger.fine("  not found");
             }
+        // leave this here to assure compatibility
+        factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
+        if (factoryClassName != null) {
+            return factoryClassName;
         }
         return null;
     }
 
+    private static String getDeprecatedSystemProperty(String property) {
+        String value = getSystemProperty(property);
+        if (value != null) {
+            logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
+                    new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
+        }
+        return value;
+    }
+
+    private static String getSystemProperty(String property) {
+        logger.log(Level.FINE, "Checking system property {0}", property);
+        String value = AccessController.doPrivileged(new GetPropertyAction(property));
+        if (value != null) {
+            logger.log(Level.FINE, "  found {0}", value);
+        } else {
+            logger.log(Level.FINE, "  not found");
+        }
+        return value;
+    }
+
     private static Properties loadJAXBProperties(ClassLoader classLoader, String propFileName) throws JAXBException {
 
         Properties props = null;
         try {
             URL url;
< prev index next >