From a8c0d5b076b0163d60fb56176870317033f89bbe Mon Sep 17 00:00:00 2001 From: Niels Basjes Date: Mon, 9 Mar 2026 16:50:35 +0100 Subject: [PATCH 1/4] feat: Improve the matching of required versions --- .../toolchain/RequirementMatcherFactory.java | 27 ++++++++++++++++++- .../RequirementMatcherFactoryTest.java | 11 ++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java index 4c7476bdc162..b8f2d89ae0e5 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java @@ -18,6 +18,8 @@ */ package org.apache.maven.toolchain; +import java.util.regex.Pattern; + import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; @@ -66,7 +68,7 @@ private VersionMatcher(String version) { @Override public boolean matches(String requirement) { try { - VersionRange range = VersionRange.createFromVersionSpec(requirement); + VersionRange range = convertRequirementToVersionRange(requirement); if (range.hasRestrictions()) { return range.containsVersion(version); } else { @@ -79,6 +81,29 @@ public boolean matches(String requirement) { } } + private VersionRange convertRequirementToVersionRange(String requirement) + throws InvalidVersionSpecificationException { + // Specific for Version _requirement_ matching; + // If the version is a simple integer (like "25") + // then treat this as the requirement "the major version is 25" + if (Pattern.matches("^[0-9]+$", requirement)) { + int majorVersion = Integer.parseInt(requirement); + return VersionRange.createFromVersionSpec("[" + majorVersion + "," + (majorVersion + 1) + ")"); + } + + // If the version is a major.minor (like "1.5") + // then treat this as the requirement "the major version is 1 and the minor is 5" + if (Pattern.matches("^[0-9]\\.[0-9]+$", requirement)) { + String[] split = requirement.split("\\.", 2); + int majorVersion = Integer.parseInt(split[0]); + int minorVersion = Integer.parseInt(split[1]); + return VersionRange.createFromVersionSpec( + "[" + majorVersion + "." + minorVersion + "," + majorVersion + "." + (minorVersion + 1) + ")"); + } + + return VersionRange.createFromVersionSpec(requirement); + } + @Override public String toString() { return version.toString(); diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java index 6b9cc2d8003d..083e9b260e19 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java @@ -50,11 +50,18 @@ public void testCreateExactMatcher() { public void testCreateVersionMatcher() { RequirementMatcher matcher; matcher = RequirementMatcherFactory.createVersionMatcher("1.5.2"); - assertFalse(matcher.matches("1.5")); - assertTrue(matcher.matches("1.5.2")); + assertTrue(matcher.matches("1")); // Major matches + assertTrue(matcher.matches("1.5")); // Major.Minor matches + assertTrue(matcher.matches("1.5.2")); // Full match + assertFalse(matcher.matches("1.6")); // Wrong minor + assertFalse(matcher.matches("2")); // Wrong major + assertFalse(matcher.matches("2.5")); // Wrong major, right minor assertFalse(matcher.matches("[1.4,1.5)")); assertFalse(matcher.matches("[1.5,1.5.2)")); + assertTrue(matcher.matches("[1.5,1.5.3)")); + assertTrue(matcher.matches("(1.5.1,1.6)")); assertFalse(matcher.matches("(1.5.2,1.6)")); + assertTrue(matcher.matches("[1.5.2,1.6)")); assertTrue(matcher.matches("(1.4,1.5.2]")); assertTrue(matcher.matches("(1.5,)")); assertEquals("1.5.2", matcher.toString()); From f4fdc9beef3c6a888d205b2df3abb3bb1eb49d31 Mon Sep 17 00:00:00 2001 From: Niels Basjes Date: Sun, 26 Jul 2026 09:30:00 +0200 Subject: [PATCH 2/4] fix: Compile regexes only once. --- .../apache/maven/toolchain/RequirementMatcherFactory.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java index b8f2d89ae0e5..cb1274d9620d 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java @@ -81,19 +81,21 @@ public boolean matches(String requirement) { } } + private static final Pattern PATTERN_MAJOR_VERSION = Pattern.compile("^[0-9]+$"); + private static final Pattern PATTERN_MAJOR_MINOR_VERSION = Pattern.compile("^[0-9]\\.[0-9]+$"); private VersionRange convertRequirementToVersionRange(String requirement) throws InvalidVersionSpecificationException { // Specific for Version _requirement_ matching; // If the version is a simple integer (like "25") // then treat this as the requirement "the major version is 25" - if (Pattern.matches("^[0-9]+$", requirement)) { + if (PATTERN_MAJOR_VERSION.matcher(requirement).matches()) { int majorVersion = Integer.parseInt(requirement); return VersionRange.createFromVersionSpec("[" + majorVersion + "," + (majorVersion + 1) + ")"); } // If the version is a major.minor (like "1.5") // then treat this as the requirement "the major version is 1 and the minor is 5" - if (Pattern.matches("^[0-9]\\.[0-9]+$", requirement)) { + if (PATTERN_MAJOR_MINOR_VERSION.matcher(requirement).matches()) { String[] split = requirement.split("\\.", 2); int majorVersion = Integer.parseInt(split[0]); int minorVersion = Integer.parseInt(split[1]); From 8c439aa7546b80bf0f38b2c75af65fcee0d7c342 Mon Sep 17 00:00:00 2001 From: Niels Basjes Date: Sun, 26 Jul 2026 09:35:37 +0200 Subject: [PATCH 3/4] fix: Regex bug not supporting multi digit major versions. --- .../toolchain/RequirementMatcherFactory.java | 2 +- .../RequirementMatcherFactoryTest.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java index cb1274d9620d..8507612989d0 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java @@ -82,7 +82,7 @@ public boolean matches(String requirement) { } private static final Pattern PATTERN_MAJOR_VERSION = Pattern.compile("^[0-9]+$"); - private static final Pattern PATTERN_MAJOR_MINOR_VERSION = Pattern.compile("^[0-9]\\.[0-9]+$"); + private static final Pattern PATTERN_MAJOR_MINOR_VERSION = Pattern.compile("^[0-9]+\\.[0-9]+$"); private VersionRange convertRequirementToVersionRange(String requirement) throws InvalidVersionSpecificationException { // Specific for Version _requirement_ matching; diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java index 083e9b260e19..cc8d05e62d9f 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java @@ -70,4 +70,31 @@ public void testCreateVersionMatcher() { matcher = RequirementMatcherFactory.createVersionMatcher("1.5"); assertEquals("1.5", matcher.toString()); } + + @Test + public void testCreateVersionMatcherMultiDigit() { + RequirementMatcher matcher; + matcher = RequirementMatcherFactory.createVersionMatcher("11.55.22"); + assertTrue(matcher.matches("11")); // Major matches + assertTrue(matcher.matches("11.55")); // Major.Minor matches + assertTrue(matcher.matches("11.55.22")); // Full match + assertFalse(matcher.matches("11.66")); // Wrong minor + assertFalse(matcher.matches("22")); // Wrong major + assertFalse(matcher.matches("22.55")); // Wrong major, right minor + assertFalse(matcher.matches("[11.54,11.55)")); + assertFalse(matcher.matches("[11.55,11.55.22)")); + assertTrue(matcher.matches("[11.55,11.55.33)")); + assertTrue(matcher.matches("(11.55.11,11.56)")); + assertFalse(matcher.matches("(11.55.22,11.56)")); + assertTrue(matcher.matches("[11.55.22,11.56)")); + assertTrue(matcher.matches("(11.54,11.55.22]")); + assertTrue(matcher.matches("(11.55,)")); + assertEquals("11.55.22", matcher.toString()); + + // Ensure it is not printed as 1.5.0 + matcher = RequirementMatcherFactory.createVersionMatcher("11.55"); + assertEquals("11.55", matcher.toString()); + } + + } From 3f347583023837ecb2fbd938b60ee880f744aba2 Mon Sep 17 00:00:00 2001 From: Niels Basjes Date: Sun, 26 Jul 2026 09:41:43 +0200 Subject: [PATCH 4/4] fix: Spotless layout changes --- .../org/apache/maven/toolchain/RequirementMatcherFactory.java | 1 + .../apache/maven/toolchain/RequirementMatcherFactoryTest.java | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java index 8507612989d0..4f28cb0f2e32 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/RequirementMatcherFactory.java @@ -83,6 +83,7 @@ public boolean matches(String requirement) { private static final Pattern PATTERN_MAJOR_VERSION = Pattern.compile("^[0-9]+$"); private static final Pattern PATTERN_MAJOR_MINOR_VERSION = Pattern.compile("^[0-9]+\\.[0-9]+$"); + private VersionRange convertRequirementToVersionRange(String requirement) throws InvalidVersionSpecificationException { // Specific for Version _requirement_ matching; diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java index cc8d05e62d9f..2b7c9a98eb6d 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/RequirementMatcherFactoryTest.java @@ -95,6 +95,4 @@ public void testCreateVersionMatcherMultiDigit() { matcher = RequirementMatcherFactory.createVersionMatcher("11.55"); assertEquals("11.55", matcher.toString()); } - - }