Skip to content

Commit 3714cb6

Browse files
committed
Allow parsing the value of java.version sysprop (#44017)
We often start testing with early access versions of new Java versions and this have caused minor issues in our tests (i.e. #43141) because the version string that the JVM reports cannot be parsed as it ends with the string -ea. This commit changes how we parse and compare Java versions to allow correct parsing and comparison of the output of java.version system property that might include an additional alphanumeric part after the version numbers (see [JEP 223[(https://openjdk.java.net/jeps/223)). In short it handles a version number part, like before, but additionally a PRE part that matches ([a-zA-Z0-9]+). It also changes a number of tests that would attempt to parse java.specification.version in order to get the full version of Java. java.specification.version only contains the major version and is thus inappropriate when trying to compare against a version that might contain a minor, patch or an early access part. We know parse java.version that can be consistently parsed. Resolves #43141
1 parent 2a4380e commit 3714cb6

File tree

9 files changed

+115
-23
lines changed

9 files changed

+115
-23
lines changed

client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private static SSLContext getSslContext() throws Exception {
134134
* 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK.
135135
*/
136136
private static String getProtocol() {
137-
String version = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("java.specification.version"));
137+
String version = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("java.version"));
138138
String[] components = version.split("\\.");
139139
if (components.length > 0) {
140140
final int major = Integer.valueOf(components[0]);

libs/core/src/main/java/org/elasticsearch/bootstrap/JavaVersion.java

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.bootstrap;
2121

22+
import java.math.BigInteger;
2223
import java.util.ArrayList;
2324
import java.util.Collections;
2425
import java.util.List;
@@ -28,12 +29,14 @@
2829
public class JavaVersion implements Comparable<JavaVersion> {
2930

3031
private final List<Integer> version;
32+
private final String prePart;
3133

3234
public List<Integer> getVersion() {
3335
return version;
3436
}
3537

36-
private JavaVersion(List<Integer> version) {
38+
private JavaVersion(List<Integer> version, String prePart) {
39+
this.prePart = prePart;
3740
if (version.size() >= 2 && version.get(0) == 1 && version.get(1) == 8) {
3841
// for Java 8 there is ambiguity since both 1.8 and 8 are supported,
3942
// so we rewrite the former to the latter
@@ -42,23 +45,38 @@ private JavaVersion(List<Integer> version) {
4245
this.version = Collections.unmodifiableList(version);
4346
}
4447

48+
/**
49+
* Parses the Java version as it can be retrieved as the value of java.version or
50+
* java.specification.version according to JEP 223.
51+
*
52+
* @param value The version String
53+
*/
4554
public static JavaVersion parse(String value) {
4655
Objects.requireNonNull(value);
56+
String prePart = null;
4757
if (!isValid(value)) {
48-
throw new IllegalArgumentException("value");
58+
throw new IllegalArgumentException("Java version string [" + value + "] could not be parsed.");
4959
}
50-
5160
List<Integer> version = new ArrayList<>();
52-
String[] components = value.split("\\.");
53-
for (String component : components) {
54-
version.add(Integer.valueOf(component));
61+
String[] parts = value.split("-");
62+
String[] numericComponents;
63+
if (parts.length == 1) {
64+
numericComponents = value.split("\\.");
65+
} else if (parts.length == 2) {
66+
numericComponents = parts[0].split("\\.");
67+
prePart = parts[1];
68+
} else {
69+
throw new IllegalArgumentException("Java version string [" + value + "] could not be parsed.");
5570
}
5671

57-
return new JavaVersion(version);
72+
for (String component : numericComponents) {
73+
version.add(Integer.valueOf(component));
74+
}
75+
return new JavaVersion(version, prePart);
5876
}
5977

6078
public static boolean isValid(String value) {
61-
return value.matches("^0*[0-9]+(\\.[0-9]+)*$");
79+
return value.matches("^0*[0-9]+(\\.[0-9]+)*(-[a-zA-Z0-9]+)?$");
6280
}
6381

6482
private static final JavaVersion CURRENT = parse(System.getProperty("java.specification.version"));
@@ -78,9 +96,26 @@ public int compareTo(JavaVersion o) {
7896
if (s > d)
7997
return -1;
8098
}
99+
if (prePart != null && o.prePart == null) {
100+
return -1;
101+
} else if (prePart == null && o.prePart != null) {
102+
return 1;
103+
} else if (prePart != null && o.prePart != null) {
104+
return comparePrePart(prePart, o.prePart);
105+
}
81106
return 0;
82107
}
83108

109+
private int comparePrePart(String prePart, String otherPrePart) {
110+
if (prePart.matches("\\d+")) {
111+
return otherPrePart.matches("\\d+") ?
112+
(new BigInteger(prePart)).compareTo(new BigInteger(otherPrePart)) : -1;
113+
} else {
114+
return otherPrePart.matches("\\d+") ?
115+
1 : prePart.compareTo(otherPrePart);
116+
}
117+
}
118+
84119
@Override
85120
public boolean equals(Object o) {
86121
if (o == null || o.getClass() != getClass()) {
@@ -96,6 +131,7 @@ public int hashCode() {
96131

97132
@Override
98133
public String toString() {
99-
return version.stream().map(v -> Integer.toString(v)).collect(Collectors.joining("."));
134+
final String versionString = version.stream().map(v -> Integer.toString(v)).collect(Collectors.joining("."));
135+
return prePart != null ? versionString + "-" + prePart : versionString;
100136
}
101137
}

plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ private static String getProtocol() {
282282
} else {
283283
JavaVersion full =
284284
AccessController.doPrivileged(
285-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
285+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
286286
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
287287
return "TLSv1.2";
288288
}

server/src/test/java/org/elasticsearch/bootstrap/JavaVersionTests.java

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,60 @@
2323

2424
import java.util.List;
2525

26+
import static org.hamcrest.CoreMatchers.equalTo;
2627
import static org.hamcrest.CoreMatchers.is;
2728

2829
public class JavaVersionTests extends ESTestCase {
2930
public void testParse() {
3031
JavaVersion javaVersion = JavaVersion.parse("1.7.0");
3132
List<Integer> version = javaVersion.getVersion();
32-
assertThat(3, is(version.size()));
33-
assertThat(1, is(version.get(0)));
34-
assertThat(7, is(version.get(1)));
35-
assertThat(0, is(version.get(2)));
33+
assertThat(version.size(), is(3));
34+
assertThat(version.get(0), is(1));
35+
assertThat(version.get(1), is(7));
36+
assertThat(version.get(2), is(0));
37+
38+
JavaVersion javaVersionEarlyAccess = JavaVersion.parse("14.0.1-ea");
39+
List<Integer> version14 = javaVersionEarlyAccess.getVersion();
40+
assertThat(version14.size(), is(3));
41+
assertThat(version14.get(0), is(14));
42+
assertThat(version14.get(1), is(0));
43+
assertThat(version14.get(2), is(1));
44+
45+
JavaVersion javaVersionOtherPrePart = JavaVersion.parse("13.2.4-somethingElseHere");
46+
List<Integer> version13 = javaVersionOtherPrePart.getVersion();
47+
assertThat(version13.size(), is(3));
48+
assertThat(version13.get(0), is(13));
49+
assertThat(version13.get(1), is(2));
50+
assertThat(version13.get(2), is(4));
51+
52+
JavaVersion javaVersionNumericPrePart = JavaVersion.parse("13.2.4-something124443");
53+
List<Integer> version11 = javaVersionNumericPrePart.getVersion();
54+
assertThat(version11.size(), is(3));
55+
assertThat(version11.get(0), is(13));
56+
assertThat(version11.get(1), is(2));
57+
assertThat(version11.get(2), is(4));
58+
}
59+
60+
public void testParseInvalidVersions() {
61+
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> JavaVersion.parse("11.2-something-else"));
62+
assertThat(e.getMessage(), equalTo("Java version string [11.2-something-else] could not be parsed."));
63+
final IllegalArgumentException e1 = expectThrows(IllegalArgumentException.class, () -> JavaVersion.parse("11.0."));
64+
assertThat(e1.getMessage(), equalTo("Java version string [11.0.] could not be parsed."));
65+
final IllegalArgumentException e2 = expectThrows(IllegalArgumentException.class, () -> JavaVersion.parse("11.a.3"));
66+
assertThat(e2.getMessage(), equalTo("Java version string [11.a.3] could not be parsed."));
3667
}
3768

3869
public void testToString() {
3970
JavaVersion javaVersion170 = JavaVersion.parse("1.7.0");
4071
assertThat(javaVersion170.toString(), is("1.7.0"));
4172
JavaVersion javaVersion9 = JavaVersion.parse("9");
4273
assertThat(javaVersion9.toString(), is("9"));
74+
JavaVersion javaVersion11 = JavaVersion.parse("11.0.1-something09random");
75+
assertThat(javaVersion11.toString(), is("11.0.1-something09random"));
76+
JavaVersion javaVersion12 = JavaVersion.parse("12.2-2019");
77+
assertThat(javaVersion12.toString(), is("12.2-2019"));
78+
JavaVersion javaVersion13ea = JavaVersion.parse("13.1-ea");
79+
assertThat(javaVersion13ea.toString(), is("13.1-ea"));
4380
}
4481

4582
public void testCompare() {
@@ -50,24 +87,43 @@ public void testCompare() {
5087
JavaVersion onePointSevenPointTwo = JavaVersion.parse("1.7.2");
5188
JavaVersion onePointSevenPointOnePointOne = JavaVersion.parse("1.7.1.1");
5289
JavaVersion onePointSevenPointTwoPointOne = JavaVersion.parse("1.7.2.1");
90+
JavaVersion thirteen = JavaVersion.parse("13");
91+
JavaVersion thirteenPointTwoPointOne = JavaVersion.parse("13.2.1");
92+
JavaVersion thirteenPointTwoPointOneTwoThousand = JavaVersion.parse("13.2.1-2000");
93+
JavaVersion thirteenPointTwoPointOneThreeThousand = JavaVersion.parse("13.2.1-3000");
94+
JavaVersion thirteenPointTwoPointOneA = JavaVersion.parse("13.2.1-aaa");
95+
JavaVersion thirteenPointTwoPointOneB = JavaVersion.parse("13.2.1-bbb");
96+
JavaVersion fourteen = JavaVersion.parse("14");
97+
JavaVersion fourteenPointTwoPointOne = JavaVersion.parse("14.2.1");
98+
JavaVersion fourteenPointTwoPointOneEarlyAccess = JavaVersion.parse("14.2.1-ea");
5399

54100
assertTrue(onePointSix.compareTo(onePointSeven) < 0);
55101
assertTrue(onePointSeven.compareTo(onePointSix) > 0);
56102
assertTrue(onePointSix.compareTo(onePointSix) == 0);
57103
assertTrue(onePointSeven.compareTo(onePointSevenPointZero) == 0);
58104
assertTrue(onePointSevenPointOnePointOne.compareTo(onePointSevenPointOne) > 0);
59105
assertTrue(onePointSevenPointTwo.compareTo(onePointSevenPointTwoPointOne) < 0);
106+
assertTrue(thirteen.compareTo(thirteenPointTwoPointOne) < 0);
107+
assertTrue(thirteen.compareTo(fourteen) < 0);
108+
assertTrue(thirteenPointTwoPointOneThreeThousand.compareTo(thirteenPointTwoPointOneTwoThousand) > 0);
109+
assertTrue(thirteenPointTwoPointOneThreeThousand.compareTo(thirteenPointTwoPointOneThreeThousand) == 0);
110+
assertTrue(thirteenPointTwoPointOneA.compareTo(thirteenPointTwoPointOneA) == 0);
111+
assertTrue(thirteenPointTwoPointOneA.compareTo(thirteenPointTwoPointOneB) < 0);
112+
assertTrue(thirteenPointTwoPointOneA.compareTo(thirteenPointTwoPointOneThreeThousand) > 0);
113+
assertTrue(fourteenPointTwoPointOneEarlyAccess.compareTo(fourteenPointTwoPointOne) < 0);
114+
assertTrue(fourteenPointTwoPointOneEarlyAccess.compareTo(fourteen) > 0);
115+
60116
}
61117

62118
public void testValidVersions() {
63-
String[] versions = new String[]{"1.7", "1.7.0", "0.1.7", "1.7.0.80"};
119+
String[] versions = new String[]{"1.7", "1.7.0", "0.1.7", "1.7.0.80", "12-ea", "13.0.2.3-ea", "14-something", "11.0.2-21002"};
64120
for (String version : versions) {
65121
assertTrue(JavaVersion.isValid(version));
66122
}
67123
}
68124

69125
public void testInvalidVersions() {
70-
String[] versions = new String[]{"", "1.7.0_80", "1.7."};
126+
String[] versions = new String[]{"", "1.7.0_80", "1.7.", "11.2-something-else"};
71127
for (String version : versions) {
72128
assertFalse(JavaVersion.isValid(version));
73129
}
@@ -76,4 +132,4 @@ public void testInvalidVersions() {
76132
public void testJava8Compat() {
77133
assertEquals(JavaVersion.parse("1.8"), JavaVersion.parse("8"));
78134
}
79-
}
135+
}

x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ private static List<String> getProtocols() {
206206
} else {
207207
JavaVersion full =
208208
AccessController.doPrivileged(
209-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
209+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
210210
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
211211
return Collections.singletonList("TLSv1.2");
212212
}

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ private static List<String> getProtocols() {
734734
} else {
735735
JavaVersion full =
736736
AccessController.doPrivileged(
737-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
737+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
738738
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
739739
return Collections.singletonList("TLSv1.2");
740740
}

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ private static List<String> getProtocols() {
214214
}
215215
JavaVersion full =
216216
AccessController.doPrivileged(
217-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
217+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
218218
if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) {
219219
return Collections.singletonList("TLSv1.2");
220220
}

x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private static List<String> getProtocols() {
152152
} else {
153153
JavaVersion full =
154154
AccessController.doPrivileged(
155-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
155+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
156156
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
157157
return Collections.singletonList("TLSv1.2");
158158
}

x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ private static List<String> getProtocols() {
761761
} else {
762762
JavaVersion full =
763763
AccessController.doPrivileged(
764-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
764+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
765765
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
766766
return Collections.singletonList("TLSv1.2");
767767
}

0 commit comments

Comments
 (0)