From d11e22026c3ab408647574ad01fa3b8f90b071c7 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Nov 2022 21:43:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=81=97=E7=95=99=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#1875)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Check the sha1 file of java in the minecraft runtime dir * Fix download Java on macOS * misc * Verify Java at startup * Find the Java installed by official launcher on osx-arm64 * Extract the downloaded file to a temporary file * Rollback JavaRepository.getSystemJavaPlatform --- .../jackhuang/hmcl/game/LauncherHelper.java | 2 +- .../hmcl/download/java/JavaDownloadTask.java | 5 +- .../hmcl/download/java/JavaRepository.java | 79 ++++++++++++++----- 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index cf8f6c7cc..55e53c6ea 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -822,7 +822,7 @@ public final class LauncherHelper { if (exitType != ExitType.NORMAL) { ArrayList> pairs = new ArrayList<>(logs.size()); Lang.forEachZipped(logs, levels, - (log, l) -> pairs.add(pair(log, l instanceof Log4jLevel ? ((Log4jLevel) l) : Log4jLevel.guessLevel(log)))); + (log, l) -> pairs.add(pair(log, l instanceof Log4jLevel ? ((Log4jLevel) l) : Optional.ofNullable(Log4jLevel.guessLevel(log)).orElse(Log4jLevel.INFO)))); repository.markVersionLaunchedAbnormally(version.getId()); Platform.runLater(() -> new GameCrashWindow(process, exitType, repository, version, launchOptions, pairs).show()); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDownloadTask.java index a83eb0cdc..f32baf403 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDownloadTask.java @@ -120,12 +120,15 @@ public class JavaDownloadTask extends Task { FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(downloadProvider.injectURL(download.getUrl())), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); task.setName(entry.getKey()); dependencies.add(task.thenRunAsync(() -> { + Path decompressed = jvmDir.resolve(entry.getKey() + ".tmp"); try (LZMAInputStream input = new LZMAInputStream(new FileInputStream(tempFile))) { - Files.copy(input, dest, StandardCopyOption.REPLACE_EXISTING); + Files.copy(input, decompressed, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new ArtifactMalformedException("File " + entry.getKey() + " is malformed", e); } + tempFile.delete(); + Files.move(decompressed, dest, StandardCopyOption.REPLACE_EXISTING); if (file.isExecutable()) { dest.toFile().setExecutable(true); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaRepository.java index 694ee4bb8..0601fa09c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaRepository.java @@ -8,14 +8,15 @@ import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.Platform; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; +import java.nio.file.*; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Stream; @@ -58,8 +59,7 @@ public final class JavaRepository { case LINUX: return Stream.of(FileUtils.tryGetPath(System.getProperty("user.home", ".minecraft/runtime"))); case OSX: - return Stream.of(FileUtils.tryGetPath("/Library/Application Support/minecraft/runtime"), - FileUtils.tryGetPath(System.getProperty("user.home"), "Library/Application Support/minecraft/runtime")); + return Stream.of(FileUtils.tryGetPath(System.getProperty("user.home"), "Library/Application Support/minecraft/runtime")); default: return Stream.empty(); } @@ -71,25 +71,63 @@ public final class JavaRepository { // Examples: // $HOME/Library/Application Support/minecraft/runtime/java-runtime-beta/mac-os/java-runtime-beta/jre.bundle/Contents/Home // $HOME/.minecraft/runtime/java-runtime-beta/linux/java-runtime-beta - Optional platformOptional = getSystemJavaPlatform(); - if (!platformOptional.isPresent()) return Stream.empty(); - String platform = platformOptional.get(); List javaHomes = new ArrayList<>(); - try (DirectoryStream dir = Files.newDirectoryStream(runtimeDir)) { - // component can be jre-legacy, java-runtime-alpha, java-runtime-beta, java-runtime-gamma or any other being added in the future. - for (Path component : dir) { - Path javaHome = component.resolve(platform).resolve(component.getFileName()); - if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { - javaHomes.add(javaHome.resolve("jre.bundle/Contents/Home")); + Consumer action = platform -> { + try (DirectoryStream dir = Files.newDirectoryStream(runtimeDir)) { + // component can be jre-legacy, java-runtime-alpha, java-runtime-beta, java-runtime-gamma or any other being added in the future. + for (Path component : dir) { + findJavaHomeInComponentDir(platform, component).ifPresent(javaHomes::add); } - javaHomes.add(javaHome); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to list java-runtime directory " + runtimeDir, e); } - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to list java-runtime directory " + runtimeDir, e); - } + }; + getSystemJavaPlatform().ifPresent(action); + + // Workaround, which will be removed in the future + if (Platform.SYSTEM_PLATFORM == Platform.OSX_ARM64) + action.accept("mac-os-arm64"); + return javaHomes.stream(); } + private static Optional findJavaHomeInComponentDir(String platform, Path component) { + Path sha1File = component.resolve(platform).resolve(component.getFileName() + ".sha1"); + if (!Files.isRegularFile(sha1File)) + return Optional.empty(); + Path dir = component.resolve(platform).resolve(component.getFileName()); + + try (BufferedReader reader = Files.newBufferedReader(sha1File)) { + String line; + while ((line = reader.readLine()) != null) { + if (line.isEmpty()) continue; + + int idx = line.indexOf(" /#//"); + if (idx <= 0) + throw new IOException("Illegal line: " + line); + + Path file = dir.resolve(line.substring(0, idx)); + + // Should we check the sha1 of files? This will take a lot of time. + if (Files.notExists(file)) + throw new NoSuchFileException(file.toAbsolutePath().toString()); + } + + if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { + Path macPath = dir.resolve("jre.bundle/Contents/Home"); + if (Files.exists(macPath)) + return Optional.of(macPath); + else + LOG.warning("The Java is not in 'jre.bundle/Contents/Home'"); + } + + return Optional.of(dir); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to verify Java in " + component, e); + return Optional.empty(); + } + } + public static Optional getSystemJavaPlatform() { if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) { if (Architecture.SYSTEM_ARCH == Architecture.X86) { @@ -122,6 +160,9 @@ public final class JavaRepository { } public static Path getJavaHome(GameJavaVersion javaVersion, String platform) { - return getJavaStoragePath().resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent()); + Path javaHome = getJavaStoragePath().resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent()); + if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) + javaHome = javaHome.resolve("jre.bundle/Contents/Home"); + return javaHome; } }