-
-
Notifications
You must be signed in to change notification settings - Fork 190
Simplify startup code #5701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Simplify startup code #5701
Changes from all commits
1a94855
88d82d9
119c09b
84118f1
5a3e16b
28ded37
063c9af
fd65c57
6ce0a16
b595488
48237ab
189b96c
251ca0c
c904065
fb099f3
8892c1d
a5dbd30
0508daa
741c399
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,47 +19,48 @@ | |
* License along with this library; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
package org.exist.start; | ||
package org.exist.webstart; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.function.Predicate; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* This class uses regex pattern matching to find the latest version of a | ||
* particular jar file. | ||
* | ||
* @see LatestFileResolver#getResolvedFileName(String) | ||
* | ||
* particular jar file. | ||
* | ||
* @author Ben Schmaus ([email protected]) | ||
* @version $Revision$ | ||
* @see LatestFileResolver#getResolvedFileName(String) | ||
*/ | ||
public class LatestFileResolver { | ||
|
||
// Pattern that can be used to indicate that the | ||
// latest version of a particular file should be added to the classpath. | ||
// E.g., commons-fileupload-%latest%.jar would resolve to something like | ||
// commons-fileupload-1.1.jar. | ||
private final static Pattern latestVersionPattern = Pattern.compile( | ||
"(%latest%)" | ||
); | ||
private final static Pattern latestVersionPattern = Pattern.compile("(%latest%)"); | ||
|
||
// Set debug mode for each file resolver instance based on whether or | ||
// not the system was started with debugging turned on. | ||
private static boolean _debug = Boolean.getBoolean("exist.start.debug"); | ||
private static final boolean _debug = Boolean.getBoolean("exist.start.debug"); | ||
|
||
/** | ||
* If the passed file name contains a %latest% token, | ||
* find the latest version of that file. Otherwise, return | ||
* the passed file name unmodified. | ||
* | ||
* | ||
* @param filename Path relative to exist home dir of | ||
* a jar file that should be added to the classpath. | ||
* a jar file that should be added to the classpath. | ||
* @return Resolved filename. | ||
*/ | ||
public String getResolvedFileName(final String filename) { | ||
|
@@ -72,9 +73,7 @@ public String getResolvedFileName(final String filename) { | |
final String uptoToken = fileinfo[0]; | ||
|
||
// Dir that should contain our jar. | ||
final String containerDirName = uptoToken.substring( | ||
0, uptoToken.lastIndexOf(File.separatorChar) | ||
); | ||
final String containerDirName = uptoToken.substring(0, uptoToken.lastIndexOf(File.separatorChar)); | ||
|
||
final Path containerDir = Paths.get(containerDirName); | ||
|
||
|
@@ -86,8 +85,8 @@ public String getResolvedFileName(final String filename) { | |
|
||
List<Path> jars; | ||
try { | ||
jars = Main.list(containerDir, p -> { | ||
matcher.reset(Main.fileName(p)); | ||
jars = list(containerDir, p -> { | ||
matcher.reset(fileName(p)); | ||
return matcher.find(); | ||
}); | ||
} catch (final IOException e) { | ||
|
@@ -99,20 +98,34 @@ public String getResolvedFileName(final String filename) { | |
if (!jars.isEmpty()) { | ||
final String actualFileName = jars.getFirst().toAbsolutePath().toString(); | ||
if (_debug) { | ||
System.err.println( | ||
"Found match: " + actualFileName | ||
+ " for jar file pattern: " + filename | ||
); | ||
System.err.println("Found match: " + actualFileName + " for jar file pattern: " + filename); | ||
} | ||
return actualFileName; | ||
} else { | ||
if (_debug) { | ||
System.err.println( | ||
"WARN: No latest version found for JAR file: '" | ||
+ filename + "'" | ||
); | ||
System.err.println("WARN: No latest version found for JAR file: '" + filename + "'"); | ||
} | ||
} | ||
return filename; | ||
} | ||
} | ||
|
||
/** | ||
* Copied from {@link org.exist.util.FileUtils#list(Path, Predicate)} | ||
* as org.exist.start is compiled into a separate Jar and doesn't have | ||
* the rest of eXist available on the classpath | ||
*/ | ||
static List<Path> list(final Path directory, final Predicate<Path> filter) throws IOException { | ||
try (final Stream<Path> entries = Files.list(directory).filter(filter)) { | ||
return entries.collect(Collectors.toList()); | ||
} | ||
} | ||
|
||
/** | ||
* Copied from {@link org.exist.util.FileUtils#fileName(Path)} | ||
* as org.exist.start is compiled into a separate Jar and doesn't have | ||
* the rest of eXist available on the classpath | ||
*/ | ||
static String fileName(final Path path) { | ||
return path.getFileName().toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,37 +24,49 @@ | |
import java.util.Optional; | ||
import java.util.stream.Stream; | ||
|
||
import static org.exist.start.CompatibleJavaVersionCheck.IncompatibleJavaVersion.IncompatibleJavaVersion; | ||
import static org.exist.start.CompatibleJavaVersionCheck.IncompatibleJavaVersion.create; | ||
import static org.exist.start.Main.ERROR_CODE_INCOMPATIBLE_JAVA_DETECTED; | ||
|
||
/** | ||
* Helper class for checking OpenJDK compatibility. | ||
* <p> | ||
* eXist-db has been compiled with Java21 (state of 2025Q2). | ||
* <p> | ||
* Older versions of Java contained a number of serious compiler bugs that caused database corruptions. | ||
* These problematic versions are deprecated and therefore this class is not relevant anymore. | ||
* <p> | ||
* The code is kept for archival purposes and potential future re-usage. | ||
* <p> | ||
* ---------------------------- | ||
* <p> | ||
* OpenJDK versions 12 through 15.0.1 suffer from a critical bug in the JIT C2 compiler that will | ||
* cause data loss in eXist-db. The problem has been reported to the OpenJDK community. | ||
* <p> | ||
* For more information, see: | ||
* - <a href="https://bugs.openjdk.java.net/browse/JDK-8253191">C2: Masked byte comparisons with large masks produce wrong result on x86</a> | ||
* - <a href="https://github.com/eXist-db/exist/issues/3375">eXist-db does not run correctly on JDKs 12, 13, 14 and 15 #3375</a> | ||
* | ||
* | ||
*/ | ||
public class CompatibleJavaVersionCheck { | ||
|
||
private static final IncompatibleJavaVersion[] INCOMPATIBLE_JAVA_VERSIONS = { | ||
IncompatibleJavaVersion(12), | ||
IncompatibleJavaVersion(13), | ||
IncompatibleJavaVersion(14), | ||
IncompatibleJavaVersion(15, 0, 2) | ||
create(12), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we decide to compile start.jar with java21 iso java8 .... these items could be removed; voiding all tests too, |
||
create(13), | ||
create(14), | ||
IncompatibleJavaVersion.create(15, 0, 2), | ||
Check notice on line 57 in exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java
|
||
}; | ||
|
||
private static final String INCOMPATIBLE_JAVA_VERSION_NOTICE = | ||
"*****************************************************%n" + | ||
"Warning: Unreliable Java version has been detected!%n" + | ||
"%n" + | ||
"OpenJDK versions 12 through 15.0.1 suffer from a critical%n" + | ||
" bug in the JIT C2 compiler that will cause data loss in%n" + | ||
"eXist-db.%n" + | ||
"%n" + | ||
"The problem has been reported to the OpenJDK community.%n" + | ||
"%n" + | ||
"For more information, see:%n" + | ||
"\t* https://bugs.openjdk.java.net/browse/JDK-8253191%n" + | ||
"\t* https://github.com/eXist-db/exist/issues/3375%n" + | ||
"%n" + | ||
"The detected version of Java on your system is: %s.%n" + | ||
"%n" + | ||
"To prevent potential data loss, eXist-db will not be started.%n" + | ||
"To start eXist-db, we recommend using Java 8 or 11.%n" + | ||
"*****************************************************"; | ||
"*****************************************************%n" | ||
+ "Incorrect version of Java detected!%n" | ||
+ "%n" | ||
+ "The detected version of Java on your system is: %s.%n" | ||
+ "%n" | ||
+ "eXist-db has been developed and qualified using Java 21.%n" | ||
+ "%n" | ||
+ "Newer versions of Java might or might not work correctly.%n" | ||
+ "*****************************************************"; | ||
|
||
private static final Optional<String> RUNTIME_JAVA_VERSION = Optional.ofNullable(System.getProperty("java.version")); | ||
|
||
|
@@ -71,16 +83,18 @@ | |
static void checkForCompatibleJavaVersion(final Optional<String> checkJavaVersion) throws StartException { | ||
final Optional<int[]> maybeJavaVersionComponents = extractJavaVersionComponents(checkJavaVersion); | ||
|
||
if (!maybeJavaVersionComponents.isPresent()) { | ||
if (maybeJavaVersionComponents.isEmpty()) { | ||
// Could not determine major java version, so best to let the user proceed... | ||
return; | ||
} | ||
|
||
// check for incompatible java version | ||
final int[] javaVersionComponents = maybeJavaVersionComponents.get(); | ||
final int majorJavaVersion = javaVersionComponents[0]; | ||
/* @Nullable */ final Integer minorJavaVersion = javaVersionComponents.length > 1 ? javaVersionComponents[1] : null; | ||
/* @Nullable */ final Integer patchJavaVersion = javaVersionComponents.length > 2 ? javaVersionComponents[2] : null; | ||
/* @Nullable */ | ||
final Integer minorJavaVersion = javaVersionComponents.length > 1 ? javaVersionComponents[1] : null; | ||
/* @Nullable */ | ||
final Integer patchJavaVersion = javaVersionComponents.length > 2 ? javaVersionComponents[2] : null; | ||
|
||
for (final IncompatibleJavaVersion incompatibleJavaVersion : INCOMPATIBLE_JAVA_VERSIONS) { | ||
// compare major versions | ||
|
@@ -104,7 +118,8 @@ | |
} | ||
|
||
// version is NOT compatible! | ||
throw new StartException(ERROR_CODE_INCOMPATIBLE_JAVA_DETECTED, String.format(INCOMPATIBLE_JAVA_VERSION_NOTICE, RUNTIME_JAVA_VERSION)); | ||
throw new StartException(ERROR_CODE_INCOMPATIBLE_JAVA_DETECTED, | ||
String.format(INCOMPATIBLE_JAVA_VERSION_NOTICE, RUNTIME_JAVA_VERSION.orElse("UKNOWN"))); | ||
} | ||
|
||
// version is compatible | ||
|
@@ -131,22 +146,22 @@ | |
/* @Nullable */ final Integer lessThanMinor; | ||
/* @Nullable */ final Integer lessThanPatch; | ||
|
||
private IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor, /* @Nullable */ Integer lessThanPatch) { | ||
private IncompatibleJavaVersion(final int major, /* @Nullable */ final Integer lessThanMinor, /* @Nullable */ final Integer lessThanPatch) { | ||
this.major = major; | ||
this.lessThanMinor = lessThanMinor; | ||
this.lessThanPatch = lessThanPatch; | ||
} | ||
|
||
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor, /* @Nullable */ Integer lessThanPatch) { | ||
public static IncompatibleJavaVersion create(final int major, /* @Nullable */ final Integer lessThanMinor, /* @Nullable */ final Integer lessThanPatch) { | ||
return new IncompatibleJavaVersion(major, lessThanMinor, lessThanPatch); | ||
} | ||
|
||
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor) { | ||
return IncompatibleJavaVersion(major, lessThanMinor, null); | ||
public static IncompatibleJavaVersion create(final int major, /* @Nullable */ final Integer lessThanMinor) { | ||
return new IncompatibleJavaVersion(major, lessThanMinor, null); | ||
} | ||
|
||
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major) { | ||
return IncompatibleJavaVersion(major, null, null); | ||
public static IncompatibleJavaVersion create(final int major) { | ||
return new IncompatibleJavaVersion(major, null, null); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG.error() can now be used