From 2199ea51b3f1470b075394fb4012bbbd13d35250 Mon Sep 17 00:00:00 2001 From: Vaclav Haisman Date: Wed, 29 Jul 2026 17:50:11 +0200 Subject: [PATCH] Fail on misconfigured plugin-requested toolchains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Propagate toolchain construction failures instead of returning an empty selection that lets plugins silently fall back to Maven’s runtime JDK. Keep ordinary nonmatching selections and missing factories unchanged. Fixes apache/maven-compiler-plugin#618 --- .../toolchain/DefaultToolchainManager.java | 3 +- .../maven/toolchain/ToolchainManager.java | 2 + .../DefaultToolchainManagerTest.java | 55 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java index 3c1a36ffa18b..3c30f442b78d 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java @@ -88,7 +88,8 @@ private List selectToolchains( toolchains.add(toolchain); } } catch (MisconfiguredToolchainException ex) { - logger.error("Misconfigured toolchain.", ex); + throw new IllegalStateException( + "Misconfigured toolchain of type " + type + ": " + ex.getMessage(), ex); } } } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainManager.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainManager.java index e760b6b9a435..dfeabc7cd157 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainManager.java @@ -44,6 +44,7 @@ public interface ToolchainManager { * @param type the type, must not be {@code null} * @param context the Maven session, must not be {@code null} * @return the toolchain selected by maven-toolchains-plugin + * @throws IllegalStateException if the configured toolchain cannot be created */ Toolchain getToolchainFromBuildContext(String type, MavenSession context); @@ -55,6 +56,7 @@ public interface ToolchainManager { * @param type the type, must not be {@code null} * @param requirements the requirements, may be {@code null} * @return the matching toolchains, never {@code null} + * @throws IllegalStateException if a configured toolchain cannot be created * @since 3.3.0 */ List getToolchains(MavenSession session, String type, Map requirements); diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java index 5a2b5ab680e5..1facf1eacd2c 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java @@ -18,6 +18,7 @@ */ package org.apache.maven.toolchain; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -27,16 +28,22 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; +import org.apache.maven.toolchain.java.JavaToolchainFactory; import org.apache.maven.toolchain.model.ToolchainModel; import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -144,4 +151,52 @@ public void testRequirements() throws Exception { assertEquals(1, toolchains.size()); } + + @Test + public void testMatchingMisconfiguredJdkToolchain(@TempDir Path temporaryDirectory) { + Path invalidJdkHome = temporaryDirectory.resolve("non-existing-jdk"); + ToolchainModel model = new ToolchainModel(); + model.setType("jdk"); + model.addProvide("version", "17"); + + Xpp3Dom jdkHome = new Xpp3Dom("jdkHome"); + jdkHome.setValue(invalidJdkHome.toString()); + Xpp3Dom configuration = new Xpp3Dom("configuration"); + configuration.addChild(jdkHome); + model.setConfiguration(configuration); + + MavenSession session = mock(MavenSession.class); + MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); + executionRequest.setToolchains(Collections.singletonMap("jdk", Collections.singletonList(model))); + when(session.getRequest()).thenReturn(executionRequest); + toolchainManager.factories.put("jdk", new JavaToolchainFactory()); + + IllegalStateException exception = assertThrows( + IllegalStateException.class, + () -> toolchainManager.getToolchains(session, "jdk", Collections.singletonMap("version", "17"))); + + assertTrue(exception.getMessage().contains("Misconfigured toolchain of type jdk")); + assertTrue(exception.getMessage().contains(invalidJdkHome.toString())); + assertInstanceOf(MisconfiguredToolchainException.class, exception.getCause()); + } + + @Test + public void testValidNonmatchingToolchain() throws Exception { + ToolchainModel model = new ToolchainModel(); + model.setType("basic"); + + MavenSession session = mock(MavenSession.class); + MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); + executionRequest.setToolchains(Collections.singletonMap("basic", Collections.singletonList(model))); + when(session.getRequest()).thenReturn(executionRequest); + ToolchainPrivate toolchain = mock(ToolchainPrivate.class); + when(toolchainFactoryBasicType.createToolchain(model)).thenReturn(toolchain); + when(toolchain.matchesRequirements(Collections.singletonMap("version", "21"))) + .thenReturn(false); + + List toolchains = + toolchainManager.getToolchains(session, "basic", Collections.singletonMap("version", "21")); + + assertEquals(0, toolchains.size()); + } }