added impl lookup through properties passed to JAXBContext.newInstance
Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
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 @@
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 @@
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.
*
* <li>
+ * If the property {@link #JAXB_CONTEXT_FACTORY} exists in the {@code Map<String, ?>} 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.
+ *
+ * <li>
* 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 @@
* @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 @@
* 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 @@
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<String, ?>`
+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