Skip to content

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

Draft
wants to merge 18 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.SystemProperties;
import org.exist.start.Classpath;
import org.exist.start.EXistClassLoader;
import org.exist.start.classloader.Classpath;
import org.exist.start.classloader.EXistClassLoader;
import org.exist.storage.BrokerPool;
import org.exist.storage.BrokerPoolService;
import org.expath.pkg.repo.FileSystemStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.EXistException;
import org.exist.start.Classpath;
import org.exist.start.EXistClassLoader;
import org.exist.start.classloader.Classpath;
import org.exist.start.classloader.EXistClassLoader;
import org.exist.storage.BrokerPool;
import org.exist.storage.journal.Journal;
import org.exist.util.Configuration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.start.LatestFileResolver;
import org.exist.util.FileUtils;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);

Expand All @@ -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) {
Expand All @@ -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);
Copy link
Member Author

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

}
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();
}
}
2 changes: 1 addition & 1 deletion exist-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@
<identifier>org.exist.start.Main</identifier>
<mainClassName>org.exist.start.Main</mainClassName>
<executableName>eXist-JavaAppLauncher</executableName>
<jvmRequired>1.8</jvmRequired>
<jvmRequired>21</jvmRequired>
<minimumSystemVersion>10.9</minimumSystemVersion>
<version>${project.version}</version>
<shortVersion>${project.version}</shortVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ public void start() throws Exception {
runArgs[0] = MODE_JETTY;
System.arraycopy(args, 0, runArgs, 1, args.length);

this.main.runEx(runArgs);
this.main.startExistdb(runArgs);
}

@Override
public void stop() throws Exception {
this.main.shutdownEx();
this.main.shutdownExistdb();
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions exist-start/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@
-->
<excludes>
<exclude>Mortbay-APACHE-2-license.template.txt</exclude>
<exclude>src/main/java/org/exist/start/Classpath.java</exclude>
<exclude>src/main/java/org/exist/start/classloader/Classpath.java</exclude>
<exclude>src/main/java/org/exist/start/Main.java</exclude>
<exclude>src/main/java/org/exist/start/Version.java</exclude>
</excludes>

</licenseSet>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,46 @@
import static org.exist.start.CompatibleJavaVersionCheck.IncompatibleJavaVersion.IncompatibleJavaVersion;
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<a href=" 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)
IncompatibleJavaVersion(15, 0, 2),
};

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"));

Expand All @@ -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
Expand All @@ -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
Expand All @@ -131,17 +146,17 @@
/* @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 IncompatibleJavaVersion(final int major, /* @Nullable */ final Integer lessThanMinor, /* @Nullable */ final Integer lessThanPatch) {

Check warning on line 155 in exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

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

Classes should not have non-constructor methods with the same name as the class

Check notice on line 155 in exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

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

The static method name 'IncompatibleJavaVersion' doesn't match '[a-z][a-zA-Z0-9]*'
return new IncompatibleJavaVersion(major, lessThanMinor, lessThanPatch);
}

public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ Integer lessThanMinor) {
public static IncompatibleJavaVersion IncompatibleJavaVersion(final int major, /* @Nullable */ final Integer lessThanMinor) {

Check warning on line 159 in exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

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

Classes should not have non-constructor methods with the same name as the class

Check notice on line 159 in exist-start/src/main/java/org/exist/start/CompatibleJavaVersionCheck.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

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

The static method name 'IncompatibleJavaVersion' doesn't match '[a-z][a-zA-Z0-9]*'
return IncompatibleJavaVersion(major, lessThanMinor, null);
}

Expand Down
Loading
Loading