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