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 422334a7d0be..5123ff11d081 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 v3Factories, - Map v4Factories, - Logger logger) { + private org.apache.maven.impl.DefaultToolchainManager getDelegate() { + Map v3Factories = lookup.lookupMap(ToolchainFactory.class); + Map v4Factories = + lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class); Map allFactories = new HashMap<>(); for (Map.Entry 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 000000000000..5c5b87a55682 --- /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 GH-11314. + * + * 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 maven-toolchains-plugin#128 + */ +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 000000000000..f3541ec21975 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/consumer/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + + org.apache.maven.its.gh11314 + test-project + 0.0.1-SNAPSHOT + + + consumer + jar + + + UTF-8 + 17 + 17 + + + + + + org.apache.maven.its.gh11314 + test-plugin + 0.0.1-SNAPSHOT + + + + test-goal + + + + + + + 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 000000000000..804ff9e93157 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/plugin/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + + org.apache.maven.its.gh11314 + test-project + 0.0.1-SNAPSHOT + + + test-plugin + maven-plugin + + + UTF-8 + 4.1.0-SNAPSHOT + 17 + 17 + + + + + org.apache.maven + maven-plugin-api + ${maven.version} + provided + + + org.apache.maven + maven-core + ${maven.version} + provided + + + org.apache.maven + maven-compat + ${maven.version} + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.11.0 + provided + + + javax.inject + javax.inject + 1 + provided + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.11.0 + + test + + + + default-descriptor + + descriptor + + + + + + + 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 000000000000..003248ad6d64 --- /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 000000000000..facffae04ddf --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-11314-v3-mojo-injection/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + org.apache.maven.its.gh11314 + test-project + 0.0.1-SNAPSHOT + pom + + + UTF-8 + + + + plugin + consumer + +