Skip to content

Commit d064fc4

Browse files
authored
Merge pull request #3960 from adamretter/hotfix/fine-grained-java-compatibility-checks
Make the Compatible Java Version Check more fine-grained
2 parents 4c0a44a + ad705f4 commit d064fc4

File tree

3 files changed

+336
-18
lines changed

3 files changed

+336
-18
lines changed

exist-start/pom.xml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@
4545
<tag>HEAD</tag>
4646
</scm>
4747

48+
<dependencies>
49+
<dependency>
50+
<groupId>junit</groupId>
51+
<artifactId>junit</artifactId>
52+
<scope>test</scope>
53+
</dependency>
54+
<dependency>
55+
<groupId>org.hamcrest</groupId>
56+
<artifactId>hamcrest</artifactId>
57+
<scope>test</scope>
58+
</dependency>
59+
</dependencies>
60+
4861
<build>
4962
<plugins>
5063
<plugin>
@@ -92,6 +105,24 @@ The original license statement is also included below.]]></preamble>
92105

93106
</configuration>
94107
</plugin>
108+
<plugin>
109+
<groupId>org.apache.maven.plugins</groupId>
110+
<artifactId>maven-dependency-plugin</artifactId>
111+
<executions>
112+
<execution>
113+
<id>analyze</id>
114+
<goals>
115+
<goal>analyze-only</goal>
116+
</goals>
117+
<configuration>
118+
<failOnWarning>true</failOnWarning>
119+
<ignoredUnusedDeclaredDependencies>
120+
<ignoredUnusedDeclaredDependency>org.hamcrest:hamcrest:jar</ignoredUnusedDeclaredDependency>
121+
</ignoredUnusedDeclaredDependencies>
122+
</configuration>
123+
</execution>
124+
</executions>
125+
</plugin>
95126
</plugins>
96127
</build>
97128

exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
package org.exist.start;
31
/*
42
* eXist-db Open Source Native XML Database
53
* Copyright (C) 2001 The eXist-db Authors
@@ -21,20 +19,30 @@
2119
* License along with this library; if not, write to the Free Software
2220
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2321
*/
22+
package org.exist.start;
23+
2424
import java.util.Optional;
25+
import java.util.stream.Stream;
2526

27+
import static org.exist.start.CompatibleJavaVersionCheck.IncompatibleJavaVersion.IncompatibleJavaVersion;
2628
import static org.exist.start.Main.ERROR_CODE_INCOMPATIBLE_JAVA_DETECTED;
2729

2830
public class CompatibleJavaVersionCheck {
2931

30-
private static final int[] INCOMPATIBLE_MAJOR_JAVA_VERSIONS = { 12, 13, 14, 15 };
32+
private static final IncompatibleJavaVersion[] INCOMPATIBLE_JAVA_VERSIONS = {
33+
IncompatibleJavaVersion(12),
34+
IncompatibleJavaVersion(13),
35+
IncompatibleJavaVersion(14),
36+
IncompatibleJavaVersion(15, 0, 2)
37+
};
3138

3239
private static final String INCOMPATIBLE_JAVA_VERSION_NOTICE =
3340
"*****************************************************%n" +
3441
"Warning: Unreliable Java version has been detected!%n" +
3542
"%n" +
36-
"OpenJDK versions 12-15 suffer from a critical bug in the%n" +
37-
"JIT C2 compiler that will cause data loss in eXist-db.%n" +
43+
"OpenJDK versions 12 through 15.0.1 suffer from a critical%n" +
44+
" bug in the JIT C2 compiler that will cause data loss in%n" +
45+
"eXist-db.%n" +
3846
"%n" +
3947
"The problem has been reported to the OpenJDK community.%n" +
4048
"%n" +
@@ -57,25 +65,90 @@ public class CompatibleJavaVersionCheck {
5765
* @throws StartException if the runtime version of Java is incompatible with eXist-db.
5866
*/
5967
public static void checkForCompatibleJavaVersion() throws StartException {
60-
final Optional<Integer> maybeRuntimeMajorJavaVersion = RUNTIME_JAVA_VERSION
61-
.map(str -> str.split("\\."))
62-
.filter(ary -> ary.length > 0)
63-
.map(ary -> ary[0])
64-
.filter(str -> !str.isEmpty())
65-
.map(str -> { try { return Integer.parseInt(str); } catch (final NumberFormatException e) { return -1; }})
66-
.filter(i -> i != -1);
68+
checkForCompatibleJavaVersion(RUNTIME_JAVA_VERSION);
69+
}
70+
71+
static void checkForCompatibleJavaVersion(final Optional<String> checkJavaVersion) throws StartException {
72+
final Optional<int[]> maybeJavaVersionComponents = extractJavaVersionComponents(checkJavaVersion);
6773

68-
if (!maybeRuntimeMajorJavaVersion.isPresent()) {
69-
// Could not determine major java version of runtime, so best to let the user proceed...
74+
if (!maybeJavaVersionComponents.isPresent()) {
75+
// Could not determine major java version, so best to let the user proceed...
7076
return;
7177
}
7278

73-
// check for incompatible major java version
74-
final int runtimeMajorJavaVersion = maybeRuntimeMajorJavaVersion.get();
75-
for (int i = 0; i < INCOMPATIBLE_MAJOR_JAVA_VERSIONS.length; i++) {
76-
if (runtimeMajorJavaVersion == INCOMPATIBLE_MAJOR_JAVA_VERSIONS[i]) {
79+
// check for incompatible java version
80+
final int[] javaVersionComponents = maybeJavaVersionComponents.get();
81+
final int majorJavaVersion = javaVersionComponents[0];
82+
/* @Nullable */ final Integer minorJavaVersion = javaVersionComponents.length > 1 ? javaVersionComponents[1] : null;
83+
/* @Nullable */ final Integer patchJavaVersion = javaVersionComponents.length > 2 ? javaVersionComponents[2] : null;
84+
85+
for (int i = 0; i < INCOMPATIBLE_JAVA_VERSIONS.length; i++) {
86+
final IncompatibleJavaVersion incompatibleJavaVersion = INCOMPATIBLE_JAVA_VERSIONS[i];
87+
88+
// compare major versions
89+
if (majorJavaVersion == incompatibleJavaVersion.major) {
90+
91+
// major version might be incompatible
92+
93+
if (incompatibleJavaVersion.lessThanMinor != null && minorJavaVersion != null) {
94+
// compare minor version
95+
if (minorJavaVersion >= incompatibleJavaVersion.lessThanMinor) {
96+
// minor version is compatible
97+
98+
if (incompatibleJavaVersion.lessThanPatch != null && patchJavaVersion != null) {
99+
// compare patch version
100+
if (patchJavaVersion >= incompatibleJavaVersion.lessThanPatch) {
101+
// patch version is compatible
102+
continue;
103+
}
104+
}
105+
}
106+
}
107+
108+
// version is NOT compatible!
77109
throw new StartException(ERROR_CODE_INCOMPATIBLE_JAVA_DETECTED, String.format(INCOMPATIBLE_JAVA_VERSION_NOTICE, RUNTIME_JAVA_VERSION));
78110
}
111+
112+
// version is compatible
113+
}
114+
}
115+
116+
static Optional<int[]> extractJavaVersionComponents(final Optional<String> javaVersion) {
117+
return javaVersion
118+
.map(str -> str.split("\\.|_|-"))
119+
.filter(ary -> ary.length > 0)
120+
.map(ary ->
121+
Stream.of(ary)
122+
.filter(str -> !str.isEmpty())
123+
.map(str -> { try { return Integer.parseInt(str); } catch (final NumberFormatException e) { return -1; }})
124+
.filter(i -> i != -1)
125+
.mapToInt(Integer::intValue)
126+
.toArray()
127+
)
128+
.filter(ary -> ary.length > 0);
129+
}
130+
131+
static class IncompatibleJavaVersion {
132+
final int major;
133+
/* @Nullable */ final Integer lessThanMinor;
134+
/* @Nullable */ final Integer lessThanPatch;
135+
136+
private IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor, /* @Nullable */ Integer lessThanPatch) {
137+
this.major = major;
138+
this.lessThanMinor = lessThanMinor;
139+
this.lessThanPatch = lessThanPatch;
140+
}
141+
142+
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor, /* @Nullable */ Integer lessThanPatch) {
143+
return new IncompatibleJavaVersion(major, lessThanMinor, lessThanPatch);
144+
}
145+
146+
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor) {
147+
return IncompatibleJavaVersion(major, lessThanMinor, null);
148+
}
149+
150+
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major) {
151+
return IncompatibleJavaVersion(major, null, null);
79152
}
80153
}
81154
}

0 commit comments

Comments
 (0)