You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/08/26 21:47:32 UTC
(maven) branch master updated: Support Maven version ranges in profile activation (#12767)
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 79f7ee41cd Support Maven version ranges in profile activation (#12767)
79f7ee41cd is described below
commit 79f7ee41cd24e46f4527fc5db71b333d9b255fa6
Author: Goutam Adwant <86...@users.noreply.github.com>
AuthorDate: Wed Aug 26 14:47:26 2026 -0700
Support Maven version ranges in profile activation (#12767)
Recognize version ranges for the existing maven.version activation property without changing the POM model. Preserve exact matching for other values and report malformed ranges as warnings.\n\nCover bounded, open-ended, negated, and malformed ranges, including activation through the model builder.
---
.../model/profile/PropertyProfileActivator.java | 42 ++++++++-
.../maven/impl/model/DefaultModelBuilderTest.java | 15 +++
.../profile/PropertyProfileActivatorTest.java | 105 ++++++++++++++++++++-
.../poms/factory/maven-version-range-profile.xml | 37 ++++++++
4 files changed, 196 insertions(+), 3 deletions(-)
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/profile/PropertyProfileActivator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/profile/PropertyProfileActivator.java
index 8b2114ad36..f83f7ab072 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/profile/PropertyProfileActivator.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/profile/PropertyProfileActivator.java
@@ -18,6 +18,8 @@
*/
package org.apache.maven.impl.model.profile;
+import org.apache.maven.api.Constants;
+import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.model.Activation;
@@ -26,6 +28,8 @@
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.ModelProblem;
import org.apache.maven.api.services.ModelProblemCollector;
+import org.apache.maven.api.services.VersionParserException;
+import org.apache.maven.api.services.model.ModelVersionParser;
import org.apache.maven.api.services.model.ProfileActivationContext;
import org.apache.maven.api.services.model.ProfileActivator;
@@ -38,6 +42,13 @@
@Singleton
public class PropertyProfileActivator implements ProfileActivator {
+ private final ModelVersionParser versionParser;
+
+ @Inject
+ public PropertyProfileActivator(ModelVersionParser versionParser) {
+ this.versionParser = versionParser;
+ }
+
@Override
public boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
Activation activation = profile.getActivation();
@@ -85,13 +96,40 @@ public boolean isActive(Profile profile, ProfileActivationContext context, Model
propValue = propValue.substring(1);
}
- // we have a value, so it has to match the system value...
- return reverseValue != propValue.equals(sysValue);
+ boolean result;
+ if (Constants.MAVEN_VERSION.equals(name) && isVersionRange(propValue)) {
+ if (sysValue == null || sysValue.isEmpty()) {
+ result = false;
+ } else {
+ try {
+ result = versionParser
+ .parseVersionRange(propValue)
+ .contains(versionParser.parseVersion(sysValue));
+ } catch (VersionParserException e) {
+ problems.add(
+ BuilderProblem.Severity.WARNING,
+ ModelProblem.Version.BASE,
+ "Failed to determine Maven version activation for profile " + profile.getId()
+ + " due to invalid version range: '" + propValue + "'",
+ property.getLocation("value"),
+ e);
+ return false;
+ }
+ }
+ } else {
+ // we have a value, so it has to match the system value...
+ result = propValue.equals(sysValue);
+ }
+ return reverseValue != result;
} else {
return reverseName != (sysValue != null && !sysValue.isEmpty());
}
}
+ private static boolean isVersionRange(String value) {
+ return value.startsWith("[") || value.startsWith("(");
+ }
+
@Override
public boolean presentInConfig(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
Activation activation = profile.getActivation();
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
index 17e8f24e64..905b5035f0 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
@@ -33,6 +33,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.apache.maven.api.Constants;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.model.Dependency;
@@ -184,6 +185,20 @@ void testMappedSourcesSuppressesDuplicateSources() {
assertEquals(source, state.getSource(null, "duplicate-artifact"));
}
+ @Test
+ void testMavenVersionRangeProfileActivation() {
+ ModelBuilderRequest request = ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(getPom("maven-version-range-profile")))
+ .systemProperties(Map.of(Constants.MAVEN_VERSION, "4.1.0"))
+ .build();
+
+ ModelBuilderResult result = builder.newSession().build(request);
+
+ assertEquals("true", result.getEffectiveModel().getProperties().get("maven.range.profile.active"));
+ }
+
@Test
public void testMergeRepositories() throws Exception {
// this is here only to trigger mainSession creation; unrelated
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/profile/PropertyProfileActivatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/profile/PropertyProfileActivatorTest.java
index 0f193614b2..9b378fe76d 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/profile/PropertyProfileActivatorTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/profile/PropertyProfileActivatorTest.java
@@ -20,12 +20,19 @@
import java.util.Map;
+import org.apache.maven.api.Constants;
import org.apache.maven.api.model.Activation;
import org.apache.maven.api.model.ActivationProperty;
import org.apache.maven.api.model.Profile;
+import org.apache.maven.api.services.model.ProfileActivationContext;
+import org.apache.maven.impl.DefaultModelVersionParser;
+import org.eclipse.aether.util.version.GenericVersionScheme;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
/**
* Tests {@link PropertyProfileActivator}.
*
@@ -35,7 +42,7 @@ class PropertyProfileActivatorTest extends AbstractProfileActivatorTest<Property
@BeforeEach
@Override
void setUp() throws Exception {
- activator = new PropertyProfileActivator();
+ activator = new PropertyProfileActivator(new DefaultModelVersionParser(new GenericVersionScheme()));
}
private Profile newProfile(String key, String value) {
@@ -163,4 +170,100 @@ void testWithValueUserPropertyDominantOverSystemProperty() throws Exception {
assertActivation(false, profile, newContext(props2, props1));
}
+
+ @Test
+ void testMavenVersionRange() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "[4.0.0-rc-5,4.0.0)");
+
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-5")));
+ assertActivation(
+ true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-6-SNAPSHOT")));
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0")));
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "3.9.11")));
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "")));
+ assertActivation(false, profile, newContext(null, Map.of()));
+ }
+
+ @Test
+ void testMavenVersionLowerBoundedRange() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "[4.0.0,)");
+
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-5")));
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0")));
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.1.0")));
+ }
+
+ @Test
+ void testMavenVersionUpperBoundedRange() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "(,4.0.0)");
+
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "3.9.11")));
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-5")));
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0")));
+ }
+
+ @Test
+ void testMavenVersionRangeBoundaries() {
+ Profile inclusive = newProfile(Constants.MAVEN_VERSION, "[4.0.0,5.0.0]");
+ Profile exclusive = newProfile(Constants.MAVEN_VERSION, "(4.0.0,5.0.0)");
+
+ assertActivation(true, inclusive, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0")));
+ assertActivation(true, inclusive, newContext(null, newProperties(Constants.MAVEN_VERSION, "5.0.0")));
+ assertActivation(false, exclusive, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0")));
+ assertActivation(true, exclusive, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.1.0")));
+ assertActivation(false, exclusive, newContext(null, newProperties(Constants.MAVEN_VERSION, "5.0.0")));
+ }
+
+ @Test
+ void testNegatedMavenVersionRange() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "![4.0.0,5.0.0)");
+
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.1.0")));
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "5.0.0")));
+ assertActivation(true, profile, newContext(null, Map.of()));
+ }
+
+ @Test
+ void testMavenVersionExactMatchIsPreserved() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "4.0.0-rc-5");
+
+ assertActivation(true, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-5")));
+ assertActivation(false, profile, newContext(null, newProperties(Constants.MAVEN_VERSION, "4.0.0-rc-6")));
+ }
+
+ @Test
+ void testRangeSyntaxRemainsAnExactMatchForOtherProperties() {
+ Profile profile = newProfile("prop", "[1,2)");
+
+ assertActivation(true, profile, newContext(null, newProperties("prop", "[1,2)")));
+ assertActivation(false, profile, newContext(null, newProperties("prop", "1.5")));
+ }
+
+ @Test
+ void testMalformedMavenVersionRangeDoesNotActivate() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "[4.0.0,");
+ ProfileActivationContext context = newContext(null, newProperties(Constants.MAVEN_VERSION, "4.1.0"));
+ SimpleProblemCollector problems = new SimpleProblemCollector();
+
+ assertFalse(activator.isActive(profile, context, problems));
+ assertEquals(0, problems.getErrors().size());
+ assertEquals(1, problems.getWarnings().size());
+ assertEquals(
+ "Failed to determine Maven version activation for profile default due to invalid version range: '[4.0.0,'",
+ problems.getWarnings().get(0));
+ }
+
+ @Test
+ void testMalformedNegatedMavenVersionRangeDoesNotActivate() {
+ Profile profile = newProfile(Constants.MAVEN_VERSION, "![4.0.0,");
+ ProfileActivationContext context = newContext(null, newProperties(Constants.MAVEN_VERSION, "4.1.0"));
+ SimpleProblemCollector problems = new SimpleProblemCollector();
+
+ assertFalse(activator.isActive(profile, context, problems));
+ assertEquals(0, problems.getErrors().size());
+ assertEquals(1, problems.getWarnings().size());
+ assertEquals(
+ "Failed to determine Maven version activation for profile default due to invalid version range: '[4.0.0,'",
+ problems.getWarnings().get(0));
+ }
}
diff --git a/impl/maven-impl/src/test/resources/poms/factory/maven-version-range-profile.xml b/impl/maven-impl/src/test/resources/poms/factory/maven-version-range-profile.xml
new file mode 100644
index 0000000000..f64b05b4ad
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/maven-version-range-profile.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.1.0">
+ <groupId>org.apache.maven.tests</groupId>
+ <artifactId>maven-version-range-profile</artifactId>
+ <version>1.0</version>
+
+ <profiles>
+ <profile>
+ <id>maven-version-range</id>
+ <activation>
+ <property>
+ <name>maven.version</name>
+ <value>[4.0.0,)</value>
+ </property>
+ </activation>
+ <properties>
+ <maven.range.profile.active>true</maven.range.profile.active>
+ </properties>
+ </profile>
+ </profiles>
+</project>