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>