Skip to content

Commit 3b7b025

Browse files
authored
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 69b6f2d commit 3b7b025

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
@@ -280,7 +280,7 @@ private static String getProtocol() {
280280
} else {
281281
JavaVersion full =
282282
AccessController.doPrivileged(
283-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
283+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
284284
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
285285
return "TLSv1.2";
286286
}

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
@@ -204,7 +204,7 @@ private static List<String> getProtocols() {
204204
} else {
205205
JavaVersion full =
206206
AccessController.doPrivileged(
207-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
207+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
208208
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
209209
return List.of("TLSv1.2");
210210
}

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
@@ -732,7 +732,7 @@ private static List<String> getProtocols() {
732732
} else {
733733
JavaVersion full =
734734
AccessController.doPrivileged(
735-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
735+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
736736
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
737737
return List.of("TLSv1.2");
738738
}

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
@@ -164,7 +164,7 @@ private byte[] toByteArray(InputStream is) throws IOException {
164164
private static List<String> getProtocols() {
165165
JavaVersion full =
166166
AccessController.doPrivileged(
167-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
167+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
168168
if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) {
169169
return List.of("TLSv1.2");
170170
}

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
@@ -150,7 +150,7 @@ private static List<String> getProtocols() {
150150
} else {
151151
JavaVersion full =
152152
AccessController.doPrivileged(
153-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
153+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
154154
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
155155
return List.of("TLSv1.2");
156156
}

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
@@ -759,7 +759,7 @@ private static List<String> getProtocols() {
759759
} else {
760760
JavaVersion full =
761761
AccessController.doPrivileged(
762-
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.specification.version")));
762+
(PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
763763
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
764764
return List.of("TLSv1.2");
765765
}

0 commit comments

Comments
 (0)