Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 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,62 +19,61 @@
* 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 org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.exist.util.FileUtils.fileName;

/**
* 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 (exist@benschmaus.com)
* @version $Revision$
* @see org.exist.webstart.LatestFileResolver#getResolvedFileName(String)
*/
public class LatestFileResolver {

private static final Logger LOGGER = LogManager.getLogger();

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

// 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 Pattern LATEST_VERSION_PATTERN = Pattern.compile("(%latest%)");

/**
* 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) {
final Matcher matches = latestVersionPattern.matcher(filename);
final Matcher matches = LATEST_VERSION_PATTERN.matcher(filename);
if (!matches.find()) {
return filename;
}

final String[] fileinfo = filename.split("%latest%");
// Path of file up to the beginning of the %latest% token.
final String uptoToken = fileinfo[0];

// Dir that should contain our jar.
final String containerDirName = uptoToken.substring(
0, uptoToken.lastIndexOf(File.separatorChar)
);
// Directory that should contain our jar.
final String containerDirName = uptoToken.substring(0, uptoToken.lastIndexOf(File.separatorChar));

final Path containerDir = Paths.get(containerDirName);

Expand All @@ -84,35 +83,25 @@ public String getResolvedFileName(final String filename) {
final Pattern pattern = Pattern.compile(patternString);
final Matcher matcher = pattern.matcher("");

List<Path> jars;
try {
jars = Main.list(containerDir, p -> {
matcher.reset(Main.fileName(p));
final List<Path> jars = FileUtils.list(containerDir, p -> {
matcher.reset(fileName(p));
return matcher.find();
});
} catch (final IOException e) {
System.err.println("ERROR: No jars found in " + containerDir.toAbsolutePath());
e.printStackTrace();
jars = Collections.emptyList();
}

if (!jars.isEmpty()) {
final String actualFileName = jars.getFirst().toAbsolutePath().toString();
if (_debug) {
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 + "'"
);
if (jars.isEmpty()) {
LOGGER.warn("WARN: No latest version found for JAR file: '{}'", filename);

} else {
final String actualFileName = jars.getFirst().toAbsolutePath().toString();
LOGGER.debug("Found match: {} for jar file pattern: {}", actualFileName, filename);
return actualFileName;
}

} catch (final IOException e) {
LOGGER.error("No jars found in {}. Reason: {}", containerDir.toAbsolutePath(), e.getMessage(), e);
}

return filename;
}
}
}
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>
Comment thread
dizzzz marked this conversation as resolved.
<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 @@ -36,7 +36,7 @@ public class ExistDbDaemon implements Daemon {
private String[] args = null;

private void init(final String args[]) {
this.main = new Main("jetty");
this.main = new Main(Main.MODE_JETTY);
this.args = args;
}

Expand Down 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
8 changes: 2 additions & 6 deletions exist-start/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@
-->
<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/Main.java</exclude>
<exclude>src/main/java/org/exist/start/Version.java</exclude>
<exclude>src/main/java/org/exist/start/classloader/Classpath.java</exclude>
</excludes>

</licenseSet>
Expand All @@ -95,9 +93,7 @@ The original license statement is also included below.]]></preamble>
</multi>
<excludes />
<includes>
<include>src/main/java/org/exist/start/Classpath.java</include>
<include>src/main/java/org/exist/start/Main.java</include>
<include>src/main/java/org/exist/start/Version.java</include>
<include>src/main/java/org/exist/start/classloader/Classpath.java</include>
</includes>
</licenseSet>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment thread
dizzzz marked this conversation as resolved.
Outdated
* 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),
Comment thread
dizzzz marked this conversation as resolved.
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

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

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

Unnecessary use of fully qualified name 'IncompatibleJavaVersion.create' due to existing static import 'org.exist.start.CompatibleJavaVersionCheck.IncompatibleJavaVersion.create'
};

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,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);
}
}
}
Loading
Loading