diff --git a/api/src/main/java/jakarta/xml/bind/ContextFinder.java b/api/src/main/java/jakarta/xml/bind/ContextFinder.java index c459bca..bbb67f0 100644 --- a/api/src/main/java/jakarta/xml/bind/ContextFinder.java +++ b/api/src/main/java/jakarta/xml/bind/ContextFinder.java @@ -302,6 +302,18 @@ static JAXBContext find(String factoryId, String factoryName = classNameFromSystemProperties(); if (factoryName != null) return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties); + Object factory = properties.get(factoryId); + if (factory != null) { + if (factory instanceof String) { + factoryName = (String) factory; + } else { + throw new JAXBException(Messages.format(Messages.ILLEGAL_CAST, factory.getClass().getName(), "String")); + } + } + if (factoryName != null) { + return newInstance(contextPath, contextPathClasses, factoryName, classLoader, properties); + } + JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader( JAXBContextFactory.class, logger, EXCEPTION_HANDLER); @@ -332,6 +344,18 @@ static JAXBContext find(Class[] classes, Map properties) throws JA String factoryClassName = classNameFromSystemProperties(); if (factoryClassName != null) return newInstance(classes, properties, factoryClassName); + Object ctxFactory = properties.get(JAXBContext.JAXB_CONTEXT_FACTORY); + if (ctxFactory != null) { + if (ctxFactory instanceof String) { + factoryClassName = (String) ctxFactory; + } else { + throw new JAXBException(Messages.format(Messages.ILLEGAL_CAST, ctxFactory.getClass().getName(), "String")); + } + } + if (factoryClassName != null) { + return newInstance(classes, properties, factoryClassName); + } + JAXBContextFactory factory = ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER); diff --git a/api/src/main/java/jakarta/xml/bind/JAXBContext.java b/api/src/main/java/jakarta/xml/bind/JAXBContext.java index 220baa7..f2295f0 100644 --- a/api/src/main/java/jakarta/xml/bind/JAXBContext.java +++ b/api/src/main/java/jakarta/xml/bind/JAXBContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -179,6 +179,11 @@ * 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)} + * 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. + * + *
  • * Provider of {@link jakarta.xml.bind.JAXBContextFactory} is loaded using the service-provider loading * facilities, defined by the {@link java.util.ServiceLoader} class, to attempt * to locate and load an implementation of the service using the {@linkplain @@ -365,8 +370,8 @@ public static JAXBContext newInstance( String contextPath, ClassLoader classLoad * @param classLoader * This class loader will be used to locate the implementation classes. * @param properties - * provider-specific properties. Can be null, which means the same thing as passing - * in an empty map. + * provider-specific or provider selection-specific properties. + * Can be null, which means the same thing as passing in an empty map. * * @return a new instance of a {@code JAXBContext} * @throws JAXBException if an error was encountered while creating the @@ -559,8 +564,8 @@ public static JAXBContext newInstance( Class ... classesToBeBound ) * Can be empty, in which case a {@link JAXBContext} that only knows about * spec-defined classes will be returned. * @param properties - * provider-specific properties. Can be null, which means the same thing as passing - * in an empty map. + * provider-specific or provider selection-specific properties. + * Can be null, which means the same thing as passing in an empty map. * * @return * A new instance of a {@code JAXBContext}. diff --git a/spec/src/main/asciidoc/appI-changelog.adoc b/spec/src/main/asciidoc/appI-changelog.adoc index 5e88983..8176909 100644 --- a/spec/src/main/asciidoc/appI-changelog.adoc +++ b/spec/src/main/asciidoc/appI-changelog.adoc @@ -14,6 +14,8 @@ through `jaxb.properties` file, `jakarta.xml.bind.context.factory` and `jakarta.xml.bind.JAXBContext` properties and `/META-INF/services/jakarta.xml.bind.JAXBContext` resource file +* added Jakarta XML Binding implementation lookup through the properties `Map` +passed to `JAXBContext.newInstance` methods * dropped requirement on compatibility with JAXB 1.0 === Changes in Version 3 diff --git a/spec/src/main/asciidoc/ch04-binding_framework.adoc b/spec/src/main/asciidoc/ch04-binding_framework.adoc index be6ddb7..26359f5 100644 --- a/spec/src/main/asciidoc/ch04-binding_framework.adoc +++ b/spec/src/main/asciidoc/ch04-binding_framework.adoc @@ -1,5 +1,5 @@ // -// Copyright (c) 2020 Contributors to the Eclipse Foundation +// Copyright (c) 2020, 2022 Contributors to the Eclipse Foundation // == The Binding Framework @@ -796,6 +796,11 @@ specified (first successful resolution applies): then its value is assumed to be the provider factory class. This phase of the look up enables per-JVM override of the Jakarta XML Binding implementation. +. If the property `jakarta.xml.bind.JAXBContextFactory` exists in the `Map` +passed to `JAXBContext.newInstance(Class[], Map)` or to `JAXBContext.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. + . Provider of `jakarta.xml.bind.JAXBContextFactory` is loaded using the service-provider loading facilities, as defined by Java SE Platform, to attempt to locate and load