diff --git a/src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java b/src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java index fa9455d..bda806a 100644 --- a/src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java +++ b/src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java @@ -370,24 +370,51 @@ Comparator version() { String[] b = v2.split("\\."); int length = Math.min(a.length, b.length); for (int i = 0; i < length; i++) { - String oa = a[i]; - String ob = b[i]; - if (!Objects.equals(oa, ob)) { - // A null element is less than a non-null element - if (oa == null || ob == null) { - return oa == null ? -1 : 1; - } - int v = oa.compareTo(ob); - if (v != 0) { - return v; - } + int cmp = compareVersionSegments(a[i], b[i]); + if (cmp != 0) { + return cmp; } } - return a.length - b.length; + return Integer.compare(a.length, b.length); }) .reversed(); } + private static int compareVersionSegments(String sa, String sb) { + int cmp = Long.compare(parseVersionSegment(sa), parseVersionSegment(sb)); + if (cmp != 0) { + return cmp; + } + String suffixA = suffix(sa); + String suffixB = suffix(sb); + if (suffixA.isEmpty() != suffixB.isEmpty()) { + return suffixA.isEmpty() ? 1 : -1; + } + return suffixA.compareTo(suffixB); + } + + private static String suffix(String s) { + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c < '0' || c > '9') { + return s.substring(i); + } + } + return ""; + } + + private static long parseVersionSegment(String s) { + long n = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c < '0' || c > '9') { + break; + } + n = n * 10 + (c - '0'); + } + return n; + } + private Set findJdks() { if (foundJdks == null) { synchronized (this) { diff --git a/src/test/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscovererTest.java b/src/test/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscovererTest.java index 11657c0..3a2a056 100644 --- a/src/test/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscovererTest.java +++ b/src/test/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscovererTest.java @@ -18,7 +18,11 @@ */ package org.apache.maven.plugins.toolchain.jdk; +import java.util.ArrayList; +import java.util.List; + import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.toolchain.model.ToolchainModel; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnJre; @@ -27,6 +31,7 @@ import org.slf4j.LoggerFactory; import static org.apache.maven.plugins.toolchain.jdk.ToolchainDiscoverer.CURRENT; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -51,4 +56,101 @@ void testDiscovery() { assertTrue(persistedToolchains.getToolchains().stream() .anyMatch(tc -> tc.getProvides().containsKey(CURRENT))); } + + @Test + void testVersionComparatorSimple() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("8")); + list.add(toolchain("17")); + list.add(toolchain("11")); + + list.sort(discoverer.version()); + + assertEquals("17", list.get(0).getProvides().getProperty("version")); + assertEquals("11", list.get(1).getProvides().getProperty("version")); + assertEquals("8", list.get(2).getProvides().getProperty("version")); + } + + @Test + void testVersionComparatorMultiPart() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("11.0.1")); + list.add(toolchain("11.0.31")); + list.add(toolchain("17.0.1")); + list.add(toolchain("1.8")); + + list.sort(discoverer.version()); + + assertEquals("17.0.1", list.get(0).getProvides().getProperty("version")); + assertEquals("11.0.31", list.get(1).getProvides().getProperty("version")); + assertEquals("11.0.1", list.get(2).getProvides().getProperty("version")); + assertEquals("1.8", list.get(3).getProvides().getProperty("version")); + } + + @Test + void testVersionComparatorMultiDigitSegments() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("17.0.2")); + list.add(toolchain("17.0.10")); + + list.sort(discoverer.version()); + + assertEquals("17.0.10", list.get(0).getProvides().getProperty("version")); + assertEquals("17.0.2", list.get(1).getProvides().getProperty("version")); + } + + @Test + void testVersionComparatorWithNonNumericSuffix() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("1.8.0_202")); + list.add(toolchain("1.8.0_121")); + + list.sort(discoverer.version()); + + assertEquals("1.8.0_202", list.get(0).getProvides().getProperty("version")); + assertEquals("1.8.0_121", list.get(1).getProvides().getProperty("version")); + } + + @Test + void testVersionComparatorWithEAPreRelease() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("11-ea")); + list.add(toolchain("11")); + + list.sort(discoverer.version()); + + assertEquals("11", list.get(0).getProvides().getProperty("version")); + assertEquals("11-ea", list.get(1).getProvides().getProperty("version")); + } + + @Test + void testVersionComparatorSuffixVsSuffix() { + ToolchainDiscoverer discoverer = new ToolchainDiscoverer(); + + List list = new ArrayList<>(); + list.add(toolchain("17.0.2+8")); + list.add(toolchain("17.0.2+4")); + + list.sort(discoverer.version()); + + assertEquals("17.0.2+8", list.get(0).getProvides().getProperty("version")); + assertEquals("17.0.2+4", list.get(1).getProvides().getProperty("version")); + } + + private static ToolchainModel toolchain(String version) { + ToolchainModel model = new ToolchainModel(); + model.setType("jdk"); + model.addProvide("version", version); + return model; + } }