diff --git a/src/main/java/org/terasology/launcher/LauncherInitTask.java b/src/main/java/org/terasology/launcher/LauncherInitTask.java index 0ad1b054a..4fe820014 100644 --- a/src/main/java/org/terasology/launcher/LauncherInitTask.java +++ b/src/main/java/org/terasology/launcher/LauncherInitTask.java @@ -24,7 +24,7 @@ import org.terasology.launcher.util.LauncherDirectoryUtils; import org.terasology.launcher.util.LauncherManagedDirectory; import org.terasology.launcher.util.LauncherStartFailedException; -import org.terasology.launcher.util.Platform; +import org.terasology.launcher.platform.Platform; import java.io.IOException; import java.net.URI; diff --git a/src/main/java/org/terasology/launcher/game/GameStarter.java b/src/main/java/org/terasology/launcher/game/GameStarter.java index 00d2f5ebf..3476ddd0c 100644 --- a/src/main/java/org/terasology/launcher/game/GameStarter.java +++ b/src/main/java/org/terasology/launcher/game/GameStarter.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.event.Level; import org.terasology.launcher.util.JavaHeapSize; -import org.terasology.launcher.util.Platform; +import org.terasology.launcher.platform.Platform; import java.io.IOException; import java.nio.file.Path; diff --git a/src/main/java/org/terasology/launcher/jre/JREArtefact.java b/src/main/java/org/terasology/launcher/jre/JREArtefact.java new file mode 100644 index 000000000..ebcbfa097 --- /dev/null +++ b/src/main/java/org/terasology/launcher/jre/JREArtefact.java @@ -0,0 +1,22 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.jre; + +import org.terasology.launcher.platform.Platform; + +//TODO(Java17): make this a 'record' +public final class JREArtefact { + + public final String url; + public final String checksum; + public final Platform platform; + public final int version; + + public JREArtefact(int version, Platform platform,String url, String checksum) { + this.url = url; + this.checksum = checksum; + this.platform = platform; + this.version = version; + } +} diff --git a/src/main/java/org/terasology/launcher/jre/ManagedJRE.java b/src/main/java/org/terasology/launcher/jre/ManagedJRE.java new file mode 100644 index 000000000..7deeda1ef --- /dev/null +++ b/src/main/java/org/terasology/launcher/jre/ManagedJRE.java @@ -0,0 +1,88 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.jre; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.terasology.launcher.platform.Arch; +import org.terasology.launcher.platform.OS; +import org.terasology.launcher.platform.Platform; + +import java.util.HashSet; +import java.util.Set; + +public final class ManagedJRE { + + public static final Set SUPPORTED_JAVA_VERSIONS = Sets.newHashSet(8, 11, 17); + + private static final Set supportedJavaVersions; + + static { + supportedJavaVersions = new HashSet<>(); + + + supportedJavaVersions.addAll( + Lists.newArrayList( + // Linux + new JREArtefact(8, + new Platform(OS.LINUX, Arch.X64), + "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jre_x64_linux_hotspot_8u392b08.tar.gz", + "91d31027da0d985be3549714389593d9e0da3da5057d87e3831c7c538b9a2a0f" + ), + new JREArtefact(11, + new Platform(OS.LINUX, Arch.X64), + "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.21%2B9/OpenJDK11U-jre_x64_linux_hotspot_11.0.21_9.tar.gz", + "156861bb901ef18759e05f6f008595220c7d1318a46758531b957b0c950ef2c3" + ), + new JREArtefact(17, + new Platform(OS.LINUX, Arch.X64), + "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jre_x64_linux_hotspot_17.0.9_9.tar.gz", + "c37f729200b572884b8f8e157852c739be728d61d9a1da0f920104876d324733" + ), + // Mac + new JREArtefact(8, + new Platform(OS.MAC, Arch.X64), + "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jre_x64_mac_hotspot_8u392b08.tar.gz", + "f1f15920ed299e10c789aef6274d88d45eb21b72f9a7b0d246a352107e344e6a" + ), + new JREArtefact(11, + new Platform(OS.MAC, Arch.X64), + "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.21%2B9/OpenJDK11U-jre_x64_mac_hotspot_11.0.21_9.tar.gz", + "43d29affe994a09de31bf2fb6f8ab6d6792ba4267b9a2feacaa1f6e042481b9b" + ), + new JREArtefact(17, + new Platform(OS.MAC, Arch.X64), + "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jre_x64_mac_hotspot_17.0.9_9.tar.gz", + "c69b37ea72136df49ce54972408803584b49b2c91b0fbc876d7125e963c7db37" + ), + // Window + new JREArtefact(8, + new Platform(OS.WINDOWS, Arch.X64), + "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jre_x64_mac_hotspot_8u392b08.tar.gz", + "a6b7e671cc12f9fc16db59419bda8be00da037e14aaf5d5afb78042c145b76ed" + ), + new JREArtefact(11, + new Platform(OS.WINDOWS, Arch.X64), + "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.21%2B9/OpenJDK11U-jre_x64_windows_hotspot_11.0.21_9.zip", + "a93d8334a85f6cbb228694346aad0353a8cb9ff3c84b5dc3221daf2c54a11e54" + ), + new JREArtefact(17, + new Platform(OS.WINDOWS, Arch.X64), + "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jre_x64_windows_hotspot_17.0.9_9.zip", + "6c491d6f8c28c6f451f08110a30348696a04b009f8c58592191046e0fab1477b" + ) + )); + + for (var v : supportedJavaVersions) { + System.out.println(v.url); + } + } + + public static JREArtefact getJreFor(Platform platform, int version) throws UnsupportedJREException { + return supportedJavaVersions.stream() + .filter(jre -> jre.platform.equals(platform) && jre.version == version) + .findFirst() + .orElseThrow(() -> new UnsupportedJREException(platform, version)); + } +} diff --git a/src/main/java/org/terasology/launcher/jre/UnsupportedJREException.java b/src/main/java/org/terasology/launcher/jre/UnsupportedJREException.java new file mode 100644 index 000000000..f1bb62356 --- /dev/null +++ b/src/main/java/org/terasology/launcher/jre/UnsupportedJREException.java @@ -0,0 +1,21 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.jre; + +import org.terasology.launcher.platform.Platform; + +public class UnsupportedJREException extends Exception { + private Platform platform; + private int version; + + public UnsupportedJREException(Platform platform, int version) { + this.platform = platform; + this.version = version; + } + + @Override + public String getMessage() { + return "UnsupportedJre: No managed JRE supported for Java version " + version + " and platform " + platform; + } +} diff --git a/src/main/java/org/terasology/launcher/platform/Arch.java b/src/main/java/org/terasology/launcher/platform/Arch.java new file mode 100644 index 000000000..9740bc8e2 --- /dev/null +++ b/src/main/java/org/terasology/launcher/platform/Arch.java @@ -0,0 +1,9 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.platform; + +public enum Arch { + X64, + X86; +} diff --git a/src/main/java/org/terasology/launcher/platform/OS.java b/src/main/java/org/terasology/launcher/platform/OS.java new file mode 100644 index 000000000..8bc8c551b --- /dev/null +++ b/src/main/java/org/terasology/launcher/platform/OS.java @@ -0,0 +1,10 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.platform; + +public enum OS { + WINDOWS, + MAC, + LINUX; +} diff --git a/src/main/java/org/terasology/launcher/util/Platform.java b/src/main/java/org/terasology/launcher/platform/Platform.java similarity index 51% rename from src/main/java/org/terasology/launcher/util/Platform.java rename to src/main/java/org/terasology/launcher/platform/Platform.java index 33abfa100..44656a8dd 100644 --- a/src/main/java/org/terasology/launcher/util/Platform.java +++ b/src/main/java/org/terasology/launcher/platform/Platform.java @@ -1,70 +1,87 @@ -// Copyright 2020 The Terasology Foundation +// Copyright 2023 The Terasology Foundation // SPDX-License-Identifier: Apache-2.0 -package org.terasology.launcher.util; +package org.terasology.launcher.platform; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import java.util.List; +import java.util.Set; /** * A simplified representation of a computer platform as `os` and `arch` */ public final class Platform { + public static final Set SUPPORTED_PLATFORMS = Sets.newHashSet( + new Platform(OS.WINDOWS, Arch.X64), + new Platform(OS.LINUX, Arch.X64), + new Platform(OS.MAC, Arch.X64) + ); private static final Platform PLATFORM = new Platform(); - private String os; - private String arch; + private final OS os; + private final Arch arch; /** * Constructs platform information for the current host system. * Simplifies operating system name to one of `linux`, `mac`, `windows` if applicable. * Simplifies operating system architecture to one of `32` and `64` if applicable. */ - private Platform() { + private Platform() throws UnsupportedPlatformException{ final String platformOs = System.getProperty("os.name").toLowerCase(); // TODO: consider using regex if (platformOs.startsWith("linux")) { - os = "linux"; + os = OS.LINUX; } else if (platformOs.startsWith("mac os")) { - os = "mac"; + os = OS.MAC; } else if (platformOs.startsWith("windows")) { - os = "windows"; + os = OS.WINDOWS; } else { - os = platformOs; + throw new UnsupportedPlatformException(); } final String platformArch = System.getProperty("os.arch"); if (platformArch.equals("x86_64") || platformArch.equals("amd64")) { - arch = "64"; + arch = Arch.X64; } else if (platformArch.equals("x86") || platformArch.equals("i386")) { - arch = "32"; + arch = Arch.X86; } else { - arch = platformArch; + arch = Arch.X64; + //TODO: throw new UnsupportedPlatformException(); } } + public Platform(OS os, Arch arch) { + this.os = os; + this.arch = arch; + } + /** * @return the simplified operating system name as platform os */ public String getOs() { - return os; + return os.name().toLowerCase(); } /** * @return the simplified operating system architecture as platform arch */ public String getArch() { - return arch; + return arch.name().toLowerCase(); } public boolean isLinux() { - return os.equals("linux"); + return os.equals(OS.LINUX); } public boolean isMac() { - return os.equals("mac"); + return os.equals(OS.MAC); } public boolean isWindows() { - return os.equals("windows"); + return os.equals(OS.WINDOWS); } public String toString() { @@ -79,4 +96,22 @@ public String toString() { public static Platform getPlatform() { return PLATFORM; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Platform platform = (Platform) o; + + if (os != platform.os) return false; + return arch == platform.arch; + } + + @Override + public int hashCode() { + int result = os != null ? os.hashCode() : 0; + result = 31 * result + (arch != null ? arch.hashCode() : 0); + return result; + } } diff --git a/src/main/java/org/terasology/launcher/platform/UnsupportedPlatformException.java b/src/main/java/org/terasology/launcher/platform/UnsupportedPlatformException.java new file mode 100644 index 000000000..f88e0f701 --- /dev/null +++ b/src/main/java/org/terasology/launcher/platform/UnsupportedPlatformException.java @@ -0,0 +1,7 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.platform; + +public class UnsupportedPlatformException extends RuntimeException { +} diff --git a/src/main/java/org/terasology/launcher/util/LauncherDirectoryUtils.java b/src/main/java/org/terasology/launcher/util/LauncherDirectoryUtils.java index 9bd3e5acf..a12ee9921 100644 --- a/src/main/java/org/terasology/launcher/util/LauncherDirectoryUtils.java +++ b/src/main/java/org/terasology/launcher/util/LauncherDirectoryUtils.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.terasology.launcher.platform.Platform; import java.io.IOException; import java.net.URISyntaxException; diff --git a/src/test/java/org/terasology/launcher/jre/ManagedJRETest.java b/src/test/java/org/terasology/launcher/jre/ManagedJRETest.java new file mode 100644 index 000000000..8241e55ee --- /dev/null +++ b/src/test/java/org/terasology/launcher/jre/ManagedJRETest.java @@ -0,0 +1,26 @@ +// Copyright 2023 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.launcher.jre; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.terasology.launcher.platform.Platform; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class ManagedJRETest { + + @ParameterizedTest(name = "JRE in version {1} available for platform {0}") + @MethodSource("provideSupportedPlatforms") + void testJresForAllSupportedPlatforms(Platform platform, Integer javaVersion) { + assertDoesNotThrow(() -> ManagedJRE.getJreFor(platform, javaVersion)); + } + + private static Stream provideSupportedPlatforms() { + return Platform.SUPPORTED_PLATFORMS.stream().flatMap(p -> ManagedJRE.SUPPORTED_JAVA_VERSIONS.stream().map(v -> Arguments.of(p, v))); + } +} \ No newline at end of file