This is an automated email from the ASF dual-hosted git repository. slachiewicz pushed a commit to branch copilot/mng-11011-settings-interpolation in repository https://gitbox.apache.org/repos/asf/maven.git
commit d625323ca1b96101589e3a6a11a1397003a03800 Author: Sylwester Lachiewicz <[email protected]> AuthorDate: Sat Mar 7 20:13:00 2026 +0000 MNG-11011 Fix proxy settings interpolation --- .../settings/building/DefaultSettingsBuilder.java | 4 +- .../validation/DefaultSettingsValidator.java | 11 +++++ .../DefaultSettingsBuilderFactoryTest.java | 44 ++++++++++++++++++ .../validation/DefaultSettingsValidatorTest.java | 16 +++++++ maven-settings/src/main/mdo/settings.mdo | 52 +++++++++++++++++----- 5 files changed, 113 insertions(+), 14 deletions(-) diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java index 3addf78ea5..4f1db62326 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java @@ -100,8 +100,6 @@ public SettingsBuildingResult build(SettingsBuildingRequest request) throws Sett problems.setSource(""); - userSettings = interpolate(userSettings, request, problems); - // for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble String localRepository = userSettings.getLocalRepository(); if (localRepository != null && localRepository.length() > 0) { @@ -180,6 +178,8 @@ private Settings readSettings( return new Settings(); } + settings = interpolate(settings, request, problems); + settingsValidator.validate(settings, problems); return settings; diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java index 3706775f73..3baec828d2 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java @@ -159,6 +159,17 @@ public void validate(Settings settings, SettingsProblemCollector problems) { "must be unique but found duplicate proxy with id " + proxy.getId()); } validateStringNotEmpty(problems, "proxies.proxy.host", proxy.getHost(), proxy.getId()); + + try { + Integer.parseInt(proxy.getPortString()); + } catch (NumberFormatException e) { + addViolation( + problems, + Severity.ERROR, + "proxies.proxy[" + proxy.getId() + "].port", + null, + "must be a valid integer but found '" + proxy.getPortString() + "'"); + } } } } diff --git a/maven-settings-builder/src/test/java/org/apache/maven/settings/building/DefaultSettingsBuilderFactoryTest.java b/maven-settings-builder/src/test/java/org/apache/maven/settings/building/DefaultSettingsBuilderFactoryTest.java index 7aadfcb070..2aab804232 100644 --- a/maven-settings-builder/src/test/java/org/apache/maven/settings/building/DefaultSettingsBuilderFactoryTest.java +++ b/maven-settings-builder/src/test/java/org/apache/maven/settings/building/DefaultSettingsBuilderFactoryTest.java @@ -19,10 +19,16 @@ package org.apache.maven.settings.building; import java.io.File; +import java.util.Properties; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Settings; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Benjamin Bentmann @@ -46,4 +52,42 @@ public void testCompleteWiring() throws Exception { assertNotNull(result); assertNotNull(result.getEffectiveSettings()); } + + @Test + public void testInterpolatesProxyTypedFields() throws Exception { + SettingsBuilder builder = new DefaultSettingsBuilderFactory().newInstance(); + + Properties systemProperties = new Properties(); + systemProperties.setProperty("proxy.host", "proxy.example.com"); + systemProperties.setProperty("proxy.port", "18080"); + systemProperties.setProperty("proxy.active", "false"); + + DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); + request.setSystemProperties(systemProperties); + request.setUserSettingsSource(new StringSettingsSource( + "<settings>" + + "<proxies>" + + "<proxy>" + + "<id>test-proxy</id>" + + "<active>${proxy.active}</active>" + + "<protocol>https</protocol>" + + "<host>${proxy.host}</host>" + + "<port>${proxy.port}</port>" + + "</proxy>" + + "</proxies>" + + "</settings>", + "test")); + + SettingsBuildingResult result = builder.build(request); + Settings settings = result.getEffectiveSettings(); + + assertTrue(result.getProblems().isEmpty(), () -> "Unexpected problems: " + result.getProblems()); + assertNotNull(settings); + assertEquals(1, settings.getProxies().size()); + + Proxy proxy = settings.getProxies().get(0); + assertEquals("proxy.example.com", proxy.getHost()); + assertEquals(18080, proxy.getPort()); + assertFalse(proxy.isActive()); + } } diff --git a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java index ea91fe7388..2bac53950a 100644 --- a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java +++ b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java @@ -214,6 +214,22 @@ public void testValidateProxy() throws Exception { assertContains(problems.messages.get(0), "'proxies.proxy.host' for default is missing"); } + @Test + public void testValidateProxyPortIsInteger() throws Exception { + Settings settings = new Settings(); + Proxy proxy = new Proxy(); + proxy.setHost("www.example.com"); + proxy.setPortString("not-a-number"); + settings.addProxy(proxy); + + SimpleProblemCollector problems = new SimpleProblemCollector(); + validator.validate(settings, problems); + assertEquals(1, problems.messages.size()); + assertContains( + problems.messages.get(0), + "'proxies.proxy[default].port' must be a valid integer but found 'not-a-number'"); + } + private static class SimpleProblemCollector implements SettingsProblemCollector { private final List<String> messages = new ArrayList<>(); diff --git a/maven-settings/src/main/mdo/settings.mdo b/maven-settings/src/main/mdo/settings.mdo index ebc6ce8127..67205087be 100644 --- a/maven-settings/src/main/mdo/settings.mdo +++ b/maven-settings/src/main/mdo/settings.mdo @@ -426,17 +426,17 @@ The <code><proxy></code> element contains informations required to a proxy settings. ]]></description> <fields> - <field> - <name>active</name> + <field xml.tagName="active"> + <name>activeString</name> <version>1.0.0+</version> <required>false</required> <defaultValue>true</defaultValue> <description> - <![CDATA[ - Whether this proxy configuration is the active one. - ]]> + Whether this proxy configuration is the active one. Note: While the type of this field + is {@code String} for technical reasons, the semantic type is actually {@code boolean}. + @see #isActive() </description> - <type>boolean</type> + <type>String</type> </field> <field> <name>protocol</name> @@ -469,15 +469,15 @@ </description> <type>String</type> </field> - <field> - <name>port</name> + <field xml.tagName="port"> + <name>portString</name> <version>1.0.0+</version> <description> - <![CDATA[ - The proxy port. - ]]> + The proxy port. Note: While the type of this field is {@code String} for technical + reasons, the semantic type is actually {@code int}. + @see #getPort() </description> - <type>int</type> + <type>String</type> <defaultValue>8080</defaultValue> </field> <field> @@ -502,6 +502,34 @@ <type>String</type> </field> </fields> + <codeSegments> + <codeSegment> + <version>1.0.0+</version> + <code> + <![CDATA[ + public boolean isActive() + { + return ( getActiveString() != null ) ? Boolean.parseBoolean( getActiveString() ) : true; + } + + public void setActive( boolean active ) + { + setActiveString( String.valueOf( active ) ); + } + + public int getPort() + { + return ( getPortString() != null ) ? Integer.parseInt( getPortString() ) : 8080; + } + + public void setPort( int port ) + { + setPortString( String.valueOf( port ) ); + } + ]]> + </code> + </codeSegment> + </codeSegments> </class> <class> <name>Server</name>
