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 76c2e939f..ef2ea2b89 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -22,14 +22,13 @@ import javafx.stage.Stage; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException; -import org.jackhuang.hmcl.download.DefaultCacheRepository; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; import org.jackhuang.hmcl.download.game.GameVerificationFixTask; import org.jackhuang.hmcl.download.game.LibraryDownloadException; -import org.jackhuang.hmcl.download.java.JavaDownloadTask; +import org.jackhuang.hmcl.download.java.JavaRepository; import org.jackhuang.hmcl.launch.NotDecompressingNativesException; import org.jackhuang.hmcl.launch.PermissionException; import org.jackhuang.hmcl.launch.ProcessCreationException; @@ -57,7 +56,6 @@ import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jackhuang.hmcl.util.platform.*; -import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.io.File; @@ -463,13 +461,13 @@ public final class LauncherHelper { onAccept.run(); } - private static CompletableFuture downloadJava(org.jackhuang.hmcl.game.JavaVersion javaVersion, Profile profile) { + private static CompletableFuture downloadJava(GameJavaVersion javaVersion, Profile profile) { CompletableFuture future = new CompletableFuture<>(); - TaskExecutorDialogPane javaDownloadingPane = new TaskExecutorDialogPane(it -> {}); + TaskExecutorDialogPane javaDownloadingPane = new TaskExecutorDialogPane(it -> { + }); - TaskExecutor executor = new JavaDownloadTask(javaVersion, - DefaultCacheRepository.getInstance().getCacheDirectory().resolve("java"), + TaskExecutor executor = JavaRepository.downloadJava(javaVersion, profile.getDependency().getDownloadProvider()).executor(false); executor.addTaskListener(new TaskListener() { @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index 564294168..20d361998 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -27,6 +27,7 @@ import javafx.stage.Stage; import javafx.stage.StageStyle; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata; +import org.jackhuang.hmcl.download.java.JavaRepository; import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; @@ -125,7 +126,7 @@ public final class Controllers { dialog(i18n("launcher.cache_directory.invalid")); } - Task.runAsync(JavaVersion::initialize).start(); + Task.runAsync(JavaVersion::initialize).thenRunAsync(JavaRepository::initialize).start(); scene = new Scene(decorator.getDecorator()); scene.setFill(Color.TRANSPARENT); 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 8528fca62..5a6815c4b 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 @@ -20,13 +20,13 @@ package org.jackhuang.hmcl.download.java; import org.jackhuang.hmcl.download.ArtifactMalformedException; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.game.DownloadInfo; +import org.jackhuang.hmcl.game.GameJavaVersion; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; -import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.tukaani.xz.LZMAInputStream; @@ -41,14 +41,14 @@ import java.util.*; import java.util.stream.Collectors; public class JavaDownloadTask extends Task { - private final org.jackhuang.hmcl.game.JavaVersion javaVersion; + private final GameJavaVersion javaVersion; private final Path rootDir; private String platform; private final Task javaDownloadsTask; private JavaDownloads.JavaDownload download; private final List> dependencies = new ArrayList<>(); - public JavaDownloadTask(org.jackhuang.hmcl.game.JavaVersion javaVersion, Path rootDir, DownloadProvider downloadProvider) { + public JavaDownloadTask(GameJavaVersion javaVersion, Path rootDir, DownloadProvider downloadProvider) { this.javaVersion = javaVersion; this.rootDir = rootDir; this.javaDownloadsTask = new GetTask(NetworkUtils.toURL( @@ -77,7 +77,7 @@ public class JavaDownloadTask extends Task { @Override public void preExecute() throws Exception { - this.platform = getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new); + this.platform = JavaRepository.getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new); } @Override @@ -96,6 +96,7 @@ public class JavaDownloadTask extends Task { DownloadInfo download = file.getDownloads().get("lzma"); File tempFile = Files.createTempFile("hmcl", "tmp").toFile(); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); + task.setName(entry.getKey()); dependencies.add(task.thenRunAsync(() -> { try { Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest); @@ -106,6 +107,7 @@ public class JavaDownloadTask extends Task { } else if (file.getDownloads().containsKey("raw")) { DownloadInfo download = file.getDownloads().get("raw"); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); + task.setName(entry.getKey()); dependencies.add(task); } else { continue; @@ -142,26 +144,5 @@ public class JavaDownloadTask extends Task { .collect(Collectors.joining(OperatingSystem.LINE_SEPARATOR))); } - public static Optional getCurrentJavaPlatform() { - if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) { - if (Architecture.CURRENT == Architecture.X86) { - return Optional.of("linux-i386"); - } else if (Architecture.CURRENT == Architecture.X86_64) { - return Optional.of("linux"); - } - } else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { - if (Architecture.CURRENT == Architecture.X86_64) { - return Optional.of("mac-os"); - } - } else if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { - if (Architecture.CURRENT == Architecture.X86) { - return Optional.of("windows-x86"); - } else if (Architecture.CURRENT == Architecture.X86_64) { - return Optional.of("windows-x64"); - } - } - return Optional.empty(); - } - public static class UnsupportedPlatformException extends Exception {} } 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 new file mode 100644 index 000000000..f363fad63 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaRepository.java @@ -0,0 +1,83 @@ +package org.jackhuang.hmcl.download.java; + +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.game.GameJavaVersion; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.CacheRepository; +import org.jackhuang.hmcl.util.platform.Architecture; +import org.jackhuang.hmcl.util.platform.JavaVersion; +import org.jackhuang.hmcl.util.platform.OperatingSystem; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; +import java.util.logging.Level; + +import static org.jackhuang.hmcl.util.Logging.LOG; + +public final class JavaRepository { + + public static Task downloadJava(GameJavaVersion javaVersion, DownloadProvider downloadProvider) { + return new JavaDownloadTask(javaVersion, getJavaStoragePath(), downloadProvider) + .thenRunAsync(() -> { + Optional platform = getCurrentJavaPlatform(); + if (platform.isPresent()) { + addJava(getJavaHome(javaVersion, platform.get())); + } + }); + } + + public static void addJava(Path javaHome) throws InterruptedException, IOException { + if (Files.isDirectory(javaHome)) { + Path executable = JavaVersion.getExecutable(javaHome); + if (Files.isRegularFile(executable)) { + JavaVersion.getJavas().add(JavaVersion.fromExecutable(executable)); + } + } + } + + public static void initialize() throws IOException, InterruptedException { + Optional platformOptional = getCurrentJavaPlatform(); + if (platformOptional.isPresent()) { + String platform = platformOptional.get(); + for (Path component : Files.newDirectoryStream(getJavaStoragePath())) { + Path javaHome = component.resolve(platform).resolve(component.getFileName()); + try { + addJava(javaHome); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to determine Java at " + javaHome, e); + } + } + } + } + + public static Optional getCurrentJavaPlatform() { + if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) { + if (Architecture.CURRENT == Architecture.X86) { + return Optional.of("linux-i386"); + } else if (Architecture.CURRENT == Architecture.X86_64) { + return Optional.of("linux"); + } + } else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { + if (Architecture.CURRENT == Architecture.X86_64) { + return Optional.of("mac-os"); + } + } else if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { + if (Architecture.CURRENT == Architecture.X86) { + return Optional.of("windows-x86"); + } else if (Architecture.CURRENT == Architecture.X86_64) { + return Optional.of("windows-x64"); + } + } + return Optional.empty(); + } + + public static Path getJavaStoragePath() { + return CacheRepository.getInstance().getCacheDirectory().resolve("java"); + } + + public static Path getJavaHome(GameJavaVersion javaVersion, String platform) { + return getJavaStoragePath().resolve(javaVersion.getComponent()).resolve(platform).resolve(javaVersion.getComponent()); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java similarity index 89% rename from HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersion.java rename to HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java index 9dad08dd1..ea554bf93 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java @@ -17,15 +17,15 @@ */ package org.jackhuang.hmcl.game; -public class JavaVersion { +public class GameJavaVersion { private final String component; private final int majorVersion; - public JavaVersion() { + public GameJavaVersion() { this("", 0); } - public JavaVersion(String component, int majorVersion) { + public GameJavaVersion(String component, int majorVersion) { this.component = component; this.majorVersion = majorVersion; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java index e10ad11b2..bcc491533 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java @@ -60,7 +60,7 @@ public class Version implements Comparable, Validation { private final String assets; private final Integer complianceLevel; @Nullable - private final JavaVersion javaVersion; + private final GameJavaVersion javaVersion; private final List libraries; private final List compatibilityRules; private final JsonMap downloads; @@ -93,7 +93,7 @@ public class Version implements Comparable, Validation { this(false, id, version, priority, null, arguments, mainClass, null, null, null, null, null, null, libraries, null, null, null, null, null, null, null, null, null, null); } - public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, JavaVersion javaVersion, List libraries, List compatibilityRules, Map downloads, Map logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List patches) { + public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, GameJavaVersion javaVersion, List libraries, List compatibilityRules, Map downloads, Map logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List patches) { this.resolved = resolved; this.id = id; this.version = version; @@ -178,7 +178,7 @@ public class Version implements Comparable, Validation { return complianceLevel; } - public JavaVersion getJavaVersion() { + public GameJavaVersion getJavaVersion() { return javaVersion; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java index 6b3f44d18..0d089adad 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/JavaVersion.java @@ -28,9 +28,7 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; @@ -38,7 +36,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; -import static java.util.Collections.unmodifiableList; import static java.util.stream.Collectors.toList; import static org.jackhuang.hmcl.util.Logging.LOG; @@ -144,7 +141,7 @@ public final class JavaVersion { return javaVersion; } - private static Path getExecutable(Path javaHome) { + public static Path getExecutable(Path javaHome) { if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { return javaHome.resolve("bin").resolve("java.exe"); } else { @@ -171,10 +168,10 @@ public final class JavaVersion { Platform.PLATFORM); } - private static List JAVAS; + private static Collection JAVAS; private static final CountDownLatch LATCH = new CountDownLatch(1); - public static List getJavas() throws InterruptedException { + public static Collection getJavas() throws InterruptedException { if (JAVAS != null) return JAVAS; LATCH.await(); @@ -199,7 +196,8 @@ public final class JavaVersion { javaVersions.add(CURRENT_JAVA); } - JAVAS = unmodifiableList(javaVersions); + JAVAS = Collections.newSetFromMap(new ConcurrentHashMap<>()); + JAVAS.addAll(javaVersions); LATCH.countDown(); }