diff --git a/api/src/main/java/jakarta/xml/bind/ContextFinder.java b/api/src/main/java/jakarta/xml/bind/ContextFinder.java index 10c995e..eed4b3d 100644 --- a/api/src/main/java/jakarta/xml/bind/ContextFinder.java +++ b/api/src/main/java/jakarta/xml/bind/ContextFinder.java @@ -231,13 +231,6 @@ public Object run() throws Exception { } } - /** - * Create an instance of a class using the thread context ClassLoader - */ - private static JAXBContext newInstance(Class[] classes, Map properties, String className) throws JAXBException { - return newInstance(classes, properties, className, getContextClassLoader()); - } - /** * Create an instance of a class using passed in ClassLoader */ @@ -315,7 +308,7 @@ static JAXBContext find(String factoryId, } JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader( - JAXBContextFactory.class, logger, EXCEPTION_HANDLER); + JAXBContextFactory.class, logger, EXCEPTION_HANDLER, classLoader); if (obj != null) { ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, obj.getClass()); @@ -341,8 +334,12 @@ static JAXBContext find(String factoryId, } static JAXBContext find(Class[] classes, Map properties) throws JAXBException { + return find(classes, getContextClassLoader(), properties); + } + + static JAXBContext find(Class[] classes, ClassLoader classLoader, Map properties) throws JAXBException { String factoryClassName = classNameFromSystemProperties(); - if (factoryClassName != null) return newInstance(classes, properties, factoryClassName); + if (factoryClassName != null) return newInstance(classes, properties, factoryClassName, classLoader); if (properties != null) { Object ctxFactory = properties.get(JAXBContext.JAXB_CONTEXT_FACTORY); @@ -361,12 +358,12 @@ static JAXBContext find(Class[] classes, Map properties) throws JA .stream() .filter(Predicate.not(e -> JAXBContext.JAXB_CONTEXT_FACTORY.equals(e.getKey()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - return newInstance(classes, props, factoryClassName); + return newInstance(classes, props, factoryClassName, classLoader); } } JAXBContextFactory factory = - ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER); + ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER, classLoader); if (factory != null) { ModuleUtil.delegateAddOpensToImplModule(classes, factory.getClass()); @@ -378,12 +375,12 @@ static JAXBContext find(Class[] classes, Map properties) throws JA ServiceLoaderUtil.lookupUsingOSGiServiceLoader(JAXBContext.JAXB_CONTEXT_FACTORY, logger); if (ctxFactoryClass != null) { - return newInstance(classes, properties, ctxFactoryClass); + return newInstance(classes, properties, ctxFactoryClass.toString(), classLoader); } // else no provider found logger.fine("Trying to create the platform default provider"); - return newInstance(classes, properties, DEFAULT_FACTORY_CLASS); + return newInstance(classes, properties, DEFAULT_FACTORY_CLASS, classLoader); } private static String classNameFromSystemProperties() throws JAXBException { diff --git a/api/src/main/java/jakarta/xml/bind/JAXBContext.java b/api/src/main/java/jakarta/xml/bind/JAXBContext.java index f2295f0..190421c 100644 --- a/api/src/main/java/jakarta/xml/bind/JAXBContext.java +++ b/api/src/main/java/jakarta/xml/bind/JAXBContext.java @@ -179,7 +179,7 @@ * factory class. This phase of the look up enables per-JVM override of the Jakarta XML Binding implementation. * *
  • - * If the property {@link #JAXB_CONTEXT_FACTORY} exists in the {@code Map} passed to {@link #newInstance(Class[], Map)} + * If the property {@link #JAXB_CONTEXT_FACTORY} exists in the {@code Map} passed to {@link #newInstance(Class[], ClassLoader, Map)} * or to {@link #newInstance(String, ClassLoader, Map)}, then its value is assumed to be the fully qualified provider factory class name. * This phase of the look up enables context sensitive selection of the Jakarta XML Binding implementation. * @@ -543,7 +543,12 @@ public static JAXBContext newInstance( String contextPath, public static JAXBContext newInstance( Class ... classesToBeBound ) throws JAXBException { - return newInstance(classesToBeBound,Collections.emptyMap()); + return newInstance(classesToBeBound, getContextClassLoader(), Collections.emptyMap()); + } + + public static JAXBContext newInstance( Class[] classesToBeBound, ClassLoader classLoader) + throws JAXBException { + return newInstance(classesToBeBound, classLoader, Collections.emptyMap()); } /** @@ -588,7 +593,7 @@ public static JAXBContext newInstance( Class ... classesToBeBound ) * * @since 1.6, JAXB 2.0 */ - public static JAXBContext newInstance( Class[] classesToBeBound, Map properties ) + public static JAXBContext newInstance( Class[] classesToBeBound, ClassLoader classLoader, Map properties ) throws JAXBException { if (classesToBeBound == null) { @@ -602,7 +607,7 @@ public static JAXBContext newInstance( Class[] classesToBeBound, Map - * For semantics see {@link jakarta.xml.bind.JAXBContext#newInstance(Class[], java.util.Map)} + * For semantics see {@link jakarta.xml.bind.JAXBContext#newInstance(Class[], ClassLoader, java.util.Map)} * * @param classesToBeBound * List of java classes to be recognized by the new {@link JAXBContext}. diff --git a/api/src/main/java/jakarta/xml/bind/ServiceLoaderUtil.java b/api/src/main/java/jakarta/xml/bind/ServiceLoaderUtil.java index 352beab..97f8bdb 100644 --- a/api/src/main/java/jakarta/xml/bind/ServiceLoaderUtil.java +++ b/api/src/main/java/jakarta/xml/bind/ServiceLoaderUtil.java @@ -31,10 +31,11 @@ class ServiceLoaderUtil { static P firstByServiceLoader(Class

    spiClass, Logger logger, - ExceptionHandler handler) throws T { + ExceptionHandler handler, + ClassLoader classLoader) throws T { // service discovery try { - ServiceLoader

    serviceLoader = ServiceLoader.load(spiClass); + ServiceLoader

    serviceLoader = ServiceLoader.load(spiClass, classLoader); for (P impl : serviceLoader) { logger.log(Level.FINE, "ServiceProvider loading Facility used; returning object [{0}]", @@ -129,6 +130,19 @@ static Object newInstance(String className, } } + static Object newInstance(String className, + String defaultImplClassName, + ClassLoader classLoader, + final ExceptionHandler handler) throws T { + try { + return safeLoadClass(className, defaultImplClassName, classLoader).getConstructor().newInstance(); + } catch (ClassNotFoundException x) { + throw handler.createException(x, "Provider " + className + " not found"); + } catch (Exception x) { + throw handler.createException(x, "Provider " + className + " could not be instantiated: " + x); + } + } + static Class safeLoadClass(String className, String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException {