Skip to content

Commit 8b7e5c1

Browse files
authored
Explicitly register jdk ToolchainFactory for Maven 3 plugins (#11318)
Fixes #11314 and apache/maven-toolchains-plugin#128
1 parent 39bd4b7 commit 8b7e5c1

File tree

6 files changed

+300
-11
lines changed

6 files changed

+300
-11
lines changed

compat/maven-compat/src/main/java/org/apache/maven/toolchain/ToolchainManagerFactory.java

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,64 @@ DefaultToolchainManagerV4 v4Manager() {
7272
return new DefaultToolchainManagerV4();
7373
}
7474

75-
private org.apache.maven.impl.DefaultToolchainManager getDelegate() {
76-
return getToolchainManager(lookup, logger);
75+
@Provides
76+
@Typed(ToolchainFactory.class)
77+
@Named("jdk")
78+
ToolchainFactory jdkFactory() {
79+
return createV3FactoryBridge("jdk");
80+
}
81+
82+
/**
83+
* Creates a v3 ToolchainFactory bridge that wraps a v4 ToolchainFactory.
84+
*/
85+
public ToolchainFactory createV3FactoryBridge(String type) {
86+
try {
87+
org.apache.maven.api.services.ToolchainFactory v4Factory =
88+
lookup.lookup(org.apache.maven.api.services.ToolchainFactory.class, type);
89+
if (v4Factory == null) {
90+
return null;
91+
}
92+
return createV3FactoryBridgeForV4Factory(v4Factory);
93+
} catch (Exception e) {
94+
// If lookup fails, no v4 factory exists for this type
95+
return null;
96+
}
7797
}
7898

79-
private org.apache.maven.impl.DefaultToolchainManager getToolchainManager(Lookup lookup, Logger logger) {
80-
return getToolchainManager(
81-
lookup.lookupMap(ToolchainFactory.class),
82-
lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class),
83-
logger);
99+
/**
100+
* Creates a v3 ToolchainFactory bridge that wraps a specific v4 ToolchainFactory instance.
101+
*/
102+
public ToolchainFactory createV3FactoryBridgeForV4Factory(
103+
org.apache.maven.api.services.ToolchainFactory v4Factory) {
104+
return new ToolchainFactory() {
105+
@Override
106+
public ToolchainPrivate createToolchain(ToolchainModel model) throws MisconfiguredToolchainException {
107+
try {
108+
org.apache.maven.api.Toolchain v4Toolchain = v4Factory.createToolchain(model.getDelegate());
109+
return getToolchainV3(v4Toolchain);
110+
} catch (ToolchainFactoryException e) {
111+
throw new MisconfiguredToolchainException(e.getMessage(), e);
112+
}
113+
}
114+
115+
@Override
116+
public ToolchainPrivate createDefaultToolchain() {
117+
try {
118+
return v4Factory
119+
.createDefaultToolchain()
120+
.map(ToolchainManagerFactory.this::getToolchainV3)
121+
.orElse(null);
122+
} catch (ToolchainFactoryException e) {
123+
return null;
124+
}
125+
}
126+
};
84127
}
85128

86-
private org.apache.maven.impl.DefaultToolchainManager getToolchainManager(
87-
Map<String, ToolchainFactory> v3Factories,
88-
Map<String, org.apache.maven.api.services.ToolchainFactory> v4Factories,
89-
Logger logger) {
129+
private org.apache.maven.impl.DefaultToolchainManager getDelegate() {
130+
Map<String, ToolchainFactory> v3Factories = lookup.lookupMap(ToolchainFactory.class);
131+
Map<String, org.apache.maven.api.services.ToolchainFactory> v4Factories =
132+
lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class);
90133
Map<String, org.apache.maven.api.services.ToolchainFactory> allFactories = new HashMap<>();
91134
for (Map.Entry<String, ToolchainFactory> entry : v3Factories.entrySet()) {
92135
ToolchainFactory v3Factory = entry.getValue();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.it;
20+
21+
import java.io.File;
22+
23+
import org.junit.jupiter.api.Test;
24+
25+
/**
26+
* This is a test set for <a href="https://github.com/apache/maven/issues/11314">GH-11314</a>.
27+
*
28+
* Verifies that V3 Mojos can be injected with v3 API beans that are bridged from v4 API
29+
* implementations. Specifically tests the case where a plugin needs to inject ToolchainFactory
30+
* with a named qualifier.
31+
*
32+
* @see <a href="https://github.com/apache/maven-toolchains-plugin/issues/128">maven-toolchains-plugin#128</a>
33+
*/
34+
public class MavenITgh11314PluginInjectionTest extends AbstractMavenIntegrationTestCase {
35+
36+
/**
37+
* Verify that V3 Mojos can be injected with v3 ToolchainFactory which is bridged from
38+
* the v4 ToolchainFactory implementation. This test reproduces the issue where a plugin
39+
* with a field requiring injection of ToolchainFactory with @Named("jdk") fails with
40+
* NullInjectedIntoNonNullable error.
41+
*
42+
* @throws Exception in case of failure
43+
*/
44+
@Test
45+
public void testV3MojoWithMavenContainerInjection() throws Exception {
46+
File testDir = extractResources("/gh-11314-v3-mojo-injection");
47+
48+
// First, build and install the test plugin
49+
File pluginDir = new File(testDir, "plugin");
50+
Verifier pluginVerifier = newVerifier(pluginDir.getAbsolutePath(), false);
51+
pluginVerifier.addCliArgument("install");
52+
pluginVerifier.execute();
53+
pluginVerifier.verifyErrorFreeLog();
54+
55+
// Now run the test project that uses the plugin
56+
File consumerDir = new File(testDir, "consumer");
57+
Verifier verifier = newVerifier(consumerDir.getAbsolutePath(), false);
58+
verifier.addCliArguments("test:test-goal");
59+
verifier.execute();
60+
verifier.verifyErrorFreeLog();
61+
}
62+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>org.apache.maven.its.gh11314</groupId>
7+
<artifactId>test-project</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>consumer</artifactId>
12+
<packaging>jar</packaging>
13+
14+
<properties>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<maven.compiler.source>17</maven.compiler.source>
17+
<maven.compiler.target>17</maven.compiler.target>
18+
</properties>
19+
20+
<build>
21+
<plugins>
22+
<plugin>
23+
<groupId>org.apache.maven.its.gh11314</groupId>
24+
<artifactId>test-plugin</artifactId>
25+
<version>0.0.1-SNAPSHOT</version>
26+
<executions>
27+
<execution>
28+
<goals>
29+
<goal>test-goal</goal>
30+
</goals>
31+
</execution>
32+
</executions>
33+
</plugin>
34+
</plugins>
35+
</build>
36+
</project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>org.apache.maven.its.gh11314</groupId>
7+
<artifactId>test-project</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>test-plugin</artifactId>
12+
<packaging>maven-plugin</packaging>
13+
14+
<properties>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<maven.version>4.1.0-SNAPSHOT</maven.version>
17+
<maven.compiler.source>17</maven.compiler.source>
18+
<maven.compiler.target>17</maven.compiler.target>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.apache.maven</groupId>
24+
<artifactId>maven-plugin-api</artifactId>
25+
<version>${maven.version}</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.apache.maven</groupId>
30+
<artifactId>maven-core</artifactId>
31+
<version>${maven.version}</version>
32+
<scope>provided</scope>
33+
</dependency>
34+
<dependency>
35+
<groupId>org.apache.maven</groupId>
36+
<artifactId>maven-compat</artifactId>
37+
<version>${maven.version}</version>
38+
<scope>provided</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.apache.maven.plugin-tools</groupId>
42+
<artifactId>maven-plugin-annotations</artifactId>
43+
<version>3.11.0</version>
44+
<scope>provided</scope>
45+
</dependency>
46+
<dependency>
47+
<groupId>javax.inject</groupId>
48+
<artifactId>javax.inject</artifactId>
49+
<version>1</version>
50+
<scope>provided</scope>
51+
</dependency>
52+
</dependencies>
53+
54+
<build>
55+
<plugins>
56+
<plugin>
57+
<groupId>org.apache.maven.plugins</groupId>
58+
<artifactId>maven-plugin-plugin</artifactId>
59+
<version>3.11.0</version>
60+
<configuration>
61+
<goalPrefix>test</goalPrefix>
62+
</configuration>
63+
<executions>
64+
<execution>
65+
<id>default-descriptor</id>
66+
<goals>
67+
<goal>descriptor</goal>
68+
</goals>
69+
</execution>
70+
</executions>
71+
</plugin>
72+
</plugins>
73+
</build>
74+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.its.gh11314;
20+
21+
import java.util.Map;
22+
import javax.inject.Inject;
23+
import javax.inject.Named;
24+
25+
import org.apache.maven.plugin.AbstractMojo;
26+
import org.apache.maven.plugin.MojoExecutionException;
27+
import org.apache.maven.plugins.annotations.Mojo;
28+
import org.apache.maven.plugins.annotations.Parameter;
29+
import org.apache.maven.toolchain.ToolchainFactory;
30+
31+
/**
32+
* A test Mojo that requires injection of ToolchainFactory from the Maven container.
33+
* This reproduces the issue where V3 Mojos cannot be injected with v3 API beans
34+
* when only v4 API implementations are available.
35+
*
36+
* Tests both named injection (@Named("jdk")) and toolchain manager functionality.
37+
*/
38+
@Mojo(name = "test-goal")
39+
public class TestMojo extends AbstractMojo {
40+
41+
/**
42+
* The ToolchainFactory from the Maven container.
43+
* This field requires injection of the v3 API ToolchainFactory with "jdk" hint.
44+
*/
45+
@Inject
46+
@Named("jdk")
47+
private ToolchainFactory jdkFactory;
48+
49+
@Override
50+
public void execute() throws MojoExecutionException {
51+
if (jdkFactory == null) {
52+
throw new MojoExecutionException("JDK ToolchainFactory was not injected!");
53+
}
54+
getLog().info("JDK ToolchainFactory successfully injected: "
55+
+ jdkFactory.getClass().getName());
56+
}
57+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>org.apache.maven.its.gh11314</groupId>
5+
<artifactId>test-project</artifactId>
6+
<version>0.0.1-SNAPSHOT</version>
7+
<packaging>pom</packaging>
8+
9+
<properties>
10+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
11+
</properties>
12+
13+
<modules>
14+
<module>plugin</module>
15+
<module>consumer</module>
16+
</modules>
17+
</project>

0 commit comments

Comments
 (0)