This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new 8b7e5c1bbe Explicitly register jdk ToolchainFactory for Maven 3 
plugins (#11318)
8b7e5c1bbe is described below

commit 8b7e5c1bbebafa48309b77fed5cc7ff04e0eaffd
Author: Guillaume Nodet <[email protected]>
AuthorDate: Fri Oct 31 11:58:52 2025 +0100

    Explicitly register jdk ToolchainFactory for Maven 3 plugins (#11318)
    
    Fixes #11314 and apache/maven-toolchains-plugin#128
---
 .../maven/toolchain/ToolchainManagerFactory.java   | 65 +++++++++++++++----
 .../it/MavenITgh11314PluginInjectionTest.java      | 62 ++++++++++++++++++
 .../gh-11314-v3-mojo-injection/consumer/pom.xml    | 36 +++++++++++
 .../gh-11314-v3-mojo-injection/plugin/pom.xml      | 74 ++++++++++++++++++++++
 .../org/apache/maven/its/gh11314/TestMojo.java     | 57 +++++++++++++++++
 .../resources/gh-11314-v3-mojo-injection/pom.xml   | 17 +++++
 6 files changed, 300 insertions(+), 11 deletions(-)

diff --git 
a/compat/maven-compat/src/main/java/org/apache/maven/toolchain/ToolchainManagerFactory.java
 
b/compat/maven-compat/src/main/java/org/apache/maven/toolchain/ToolchainManagerFactory.java
index 422334a7d0..5123ff11d0 100644
--- 
a/compat/maven-compat/src/main/java/org/apache/maven/toolchain/ToolchainManagerFactory.java
+++ 
b/compat/maven-compat/src/main/java/org/apache/maven/toolchain/ToolchainManagerFactory.java
@@ -72,21 +72,64 @@ DefaultToolchainManagerV4 v4Manager() {
         return new DefaultToolchainManagerV4();
     }
 
-    private org.apache.maven.impl.DefaultToolchainManager getDelegate() {
-        return getToolchainManager(lookup, logger);
+    @Provides
+    @Typed(ToolchainFactory.class)
+    @Named("jdk")
+    ToolchainFactory jdkFactory() {
+        return createV3FactoryBridge("jdk");
+    }
+
+    /**
+     * Creates a v3 ToolchainFactory bridge that wraps a v4 ToolchainFactory.
+     */
+    public ToolchainFactory createV3FactoryBridge(String type) {
+        try {
+            org.apache.maven.api.services.ToolchainFactory v4Factory =
+                    
lookup.lookup(org.apache.maven.api.services.ToolchainFactory.class, type);
+            if (v4Factory == null) {
+                return null;
+            }
+            return createV3FactoryBridgeForV4Factory(v4Factory);
+        } catch (Exception e) {
+            // If lookup fails, no v4 factory exists for this type
+            return null;
+        }
     }
 
-    private org.apache.maven.impl.DefaultToolchainManager 
getToolchainManager(Lookup lookup, Logger logger) {
-        return getToolchainManager(
-                lookup.lookupMap(ToolchainFactory.class),
-                
lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class),
-                logger);
+    /**
+     * Creates a v3 ToolchainFactory bridge that wraps a specific v4 
ToolchainFactory instance.
+     */
+    public ToolchainFactory createV3FactoryBridgeForV4Factory(
+            org.apache.maven.api.services.ToolchainFactory v4Factory) {
+        return new ToolchainFactory() {
+            @Override
+            public ToolchainPrivate createToolchain(ToolchainModel model) 
throws MisconfiguredToolchainException {
+                try {
+                    org.apache.maven.api.Toolchain v4Toolchain = 
v4Factory.createToolchain(model.getDelegate());
+                    return getToolchainV3(v4Toolchain);
+                } catch (ToolchainFactoryException e) {
+                    throw new MisconfiguredToolchainException(e.getMessage(), 
e);
+                }
+            }
+
+            @Override
+            public ToolchainPrivate createDefaultToolchain() {
+                try {
+                    return v4Factory
+                            .createDefaultToolchain()
+                            .map(ToolchainManagerFactory.this::getToolchainV3)
+                            .orElse(null);
+                } catch (ToolchainFactoryException e) {
+                    return null;
+                }
+            }
+        };
     }
 
-    private org.apache.maven.impl.DefaultToolchainManager getToolchainManager(
-            Map<String, ToolchainFactory> v3Factories,
-            Map<String, org.apache.maven.api.services.ToolchainFactory> 
v4Factories,
-            Logger logger) {
+    private org.apache.maven.impl.DefaultToolchainManager getDelegate() {
+        Map<String, ToolchainFactory> v3Factories = 
lookup.lookupMap(ToolchainFactory.class);
+        Map<String, org.apache.maven.api.services.ToolchainFactory> 
v4Factories =
+                
lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class);
         Map<String, org.apache.maven.api.services.ToolchainFactory> 
allFactories = new HashMap<>();
         for (Map.Entry<String, ToolchainFactory> entry : 
v3Factories.entrySet()) {
             ToolchainFactory v3Factory = entry.getValue();
diff --git 
a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11314PluginInjectionTest.java
 
b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11314PluginInjectionTest.java
new file mode 100644
index 0000000000..5c5b87a556
--- /dev/null
+++ 
b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh11314PluginInjectionTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.it;
+
+import java.io.File;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * This is a test set for <a 
href="https://github.com/apache/maven/issues/11314";>GH-11314</a>.
+ *
+ * Verifies that V3 Mojos can be injected with v3 API beans that are bridged 
from v4 API
+ * implementations. Specifically tests the case where a plugin needs to inject 
ToolchainFactory
+ * with a named qualifier.
+ *
+ * @see <a 
href="https://github.com/apache/maven-toolchains-plugin/issues/128";>maven-toolchains-plugin#128</a>
+ */
+public class MavenITgh11314PluginInjectionTest extends 
AbstractMavenIntegrationTestCase {
+
+    /**
+     * Verify that V3 Mojos can be injected with v3 ToolchainFactory which is 
bridged from
+     * the v4 ToolchainFactory implementation. This test reproduces the issue 
where a plugin
+     * with a field requiring injection of ToolchainFactory with @Named("jdk") 
fails with
+     * NullInjectedIntoNonNullable error.
+     *
+     * @throws Exception in case of failure
+     */
+    @Test
+    public void testV3MojoWithMavenContainerInjection() throws Exception {
+        File testDir = extractResources("/gh-11314-v3-mojo-injection");
+
+        // First, build and install the test plugin
+        File pluginDir = new File(testDir, "plugin");
+        Verifier pluginVerifier = newVerifier(pluginDir.getAbsolutePath(), 
false);
+        pluginVerifier.addCliArgument("install");
+        pluginVerifier.execute();
+        pluginVerifier.verifyErrorFreeLog();
+
+        // Now run the test project that uses the plugin
+        File consumerDir = new File(testDir, "consumer");
+        Verifier verifier = newVerifier(consumerDir.getAbsolutePath(), false);
+        verifier.addCliArguments("test:test-goal");
+        verifier.execute();
+        verifier.verifyErrorFreeLog();
+    }
+}
diff --git 
a/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/consumer/pom.xml
 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/consumer/pom.xml
new file mode 100644
index 0000000000..f3541ec219
--- /dev/null
+++ 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/consumer/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
https://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  
+  <parent>
+    <groupId>org.apache.maven.its.gh11314</groupId>
+    <artifactId>test-project</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>consumer</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.compiler.source>17</maven.compiler.source>
+    <maven.compiler.target>17</maven.compiler.target>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.its.gh11314</groupId>
+        <artifactId>test-plugin</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-goal</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git 
a/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/pom.xml
 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/pom.xml
new file mode 100644
index 0000000000..804ff9e931
--- /dev/null
+++ 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
https://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven.its.gh11314</groupId>
+    <artifactId>test-project</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>test-plugin</artifactId>
+  <packaging>maven-plugin</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.version>4.1.0-SNAPSHOT</maven.version>
+    <maven.compiler.source>17</maven.compiler.source>
+    <maven.compiler.target>17</maven.compiler.target>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-compat</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <version>3.11.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+      <version>1</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <version>3.11.0</version>
+        <configuration>
+          <goalPrefix>test</goalPrefix>
+        </configuration>
+        <executions>
+          <execution>
+            <id>default-descriptor</id>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git 
a/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/src/main/java/org/apache/maven/its/gh11314/TestMojo.java
 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/src/main/java/org/apache/maven/its/gh11314/TestMojo.java
new file mode 100644
index 0000000000..003248ad6d
--- /dev/null
+++ 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/src/main/java/org/apache/maven/its/gh11314/TestMojo.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.its.gh11314;
+
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.toolchain.ToolchainFactory;
+
+/**
+ * A test Mojo that requires injection of ToolchainFactory from the Maven 
container.
+ * This reproduces the issue where V3 Mojos cannot be injected with v3 API 
beans
+ * when only v4 API implementations are available.
+ *
+ * Tests both named injection (@Named("jdk")) and toolchain manager 
functionality.
+ */
+@Mojo(name = "test-goal")
+public class TestMojo extends AbstractMojo {
+
+    /**
+     * The ToolchainFactory from the Maven container.
+     * This field requires injection of the v3 API ToolchainFactory with "jdk" 
hint.
+     */
+    @Inject
+    @Named("jdk")
+    private ToolchainFactory jdkFactory;
+
+    @Override
+    public void execute() throws MojoExecutionException {
+        if (jdkFactory == null) {
+            throw new MojoExecutionException("JDK ToolchainFactory was not 
injected!");
+        }
+        getLog().info("JDK ToolchainFactory successfully injected: "
+                + jdkFactory.getClass().getName());
+    }
+}
diff --git 
a/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/pom.xml 
b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/pom.xml
new file mode 100644
index 0000000000..facffae04d
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
https://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.its.gh11314</groupId>
+  <artifactId>test-project</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <modules>
+    <module>plugin</module>
+    <module>consumer</module>
+  </modules>
+</project>

Reply via email to