feat: load downloaded java installations.

This commit is contained in:
huanghongxun 2021-05-24 20:46:31 +08:00
parent e8a64f52f0
commit f2d3d24338
7 changed files with 108 additions and 47 deletions

View File

@ -22,14 +22,13 @@ import javafx.stage.Stage;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.auth.*;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
import org.jackhuang.hmcl.download.DefaultCacheRepository;
import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.MaintainTask;
import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask;
import org.jackhuang.hmcl.download.game.GameVerificationFixTask; import org.jackhuang.hmcl.download.game.GameVerificationFixTask;
import org.jackhuang.hmcl.download.game.LibraryDownloadException; 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.NotDecompressingNativesException;
import org.jackhuang.hmcl.launch.PermissionException; import org.jackhuang.hmcl.launch.PermissionException;
import org.jackhuang.hmcl.launch.ProcessCreationException; 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.i18n.I18n;
import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jackhuang.hmcl.util.io.ResponseCodeException;
import org.jackhuang.hmcl.util.platform.*; import org.jackhuang.hmcl.util.platform.*;
import org.jackhuang.hmcl.util.platform.JavaVersion;
import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.io.File; import java.io.File;
@ -463,13 +461,13 @@ public final class LauncherHelper {
onAccept.run(); onAccept.run();
} }
private static CompletableFuture<Void> downloadJava(org.jackhuang.hmcl.game.JavaVersion javaVersion, Profile profile) { private static CompletableFuture<Void> downloadJava(GameJavaVersion javaVersion, Profile profile) {
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
TaskExecutorDialogPane javaDownloadingPane = new TaskExecutorDialogPane(it -> {}); TaskExecutorDialogPane javaDownloadingPane = new TaskExecutorDialogPane(it -> {
});
TaskExecutor executor = new JavaDownloadTask(javaVersion, TaskExecutor executor = JavaRepository.downloadJava(javaVersion,
DefaultCacheRepository.getInstance().getCacheDirectory().resolve("java"),
profile.getDependency().getDownloadProvider()).executor(false); profile.getDependency().getDownloadProvider()).executor(false);
executor.addTaskListener(new TaskListener() { executor.addTaskListener(new TaskListener() {
@Override @Override

View File

@ -27,6 +27,7 @@ import javafx.stage.Stage;
import javafx.stage.StageStyle; import javafx.stage.StageStyle;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.download.java.JavaRepository;
import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.EnumCommonDirectory;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskExecutor;
@ -125,7 +126,7 @@ public final class Controllers {
dialog(i18n("launcher.cache_directory.invalid")); 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 = new Scene(decorator.getDecorator());
scene.setFill(Color.TRANSPARENT); scene.setFill(Color.TRANSPARENT);

View File

@ -20,13 +20,13 @@ package org.jackhuang.hmcl.download.java;
import org.jackhuang.hmcl.download.ArtifactMalformedException; import org.jackhuang.hmcl.download.ArtifactMalformedException;
import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.game.DownloadInfo; import org.jackhuang.hmcl.game.DownloadInfo;
import org.jackhuang.hmcl.game.GameJavaVersion;
import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.GetTask;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils; 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.platform.OperatingSystem;
import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber;
import org.tukaani.xz.LZMAInputStream; import org.tukaani.xz.LZMAInputStream;
@ -41,14 +41,14 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class JavaDownloadTask extends Task<Void> { public class JavaDownloadTask extends Task<Void> {
private final org.jackhuang.hmcl.game.JavaVersion javaVersion; private final GameJavaVersion javaVersion;
private final Path rootDir; private final Path rootDir;
private String platform; private String platform;
private final Task<RemoteFiles> javaDownloadsTask; private final Task<RemoteFiles> javaDownloadsTask;
private JavaDownloads.JavaDownload download; private JavaDownloads.JavaDownload download;
private final List<Task<?>> dependencies = new ArrayList<>(); private final List<Task<?>> 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.javaVersion = javaVersion;
this.rootDir = rootDir; this.rootDir = rootDir;
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL( this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(
@ -77,7 +77,7 @@ public class JavaDownloadTask extends Task<Void> {
@Override @Override
public void preExecute() throws Exception { public void preExecute() throws Exception {
this.platform = getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new); this.platform = JavaRepository.getCurrentJavaPlatform().orElseThrow(UnsupportedPlatformException::new);
} }
@Override @Override
@ -96,6 +96,7 @@ public class JavaDownloadTask extends Task<Void> {
DownloadInfo download = file.getDownloads().get("lzma"); DownloadInfo download = file.getDownloads().get("lzma");
File tempFile = Files.createTempFile("hmcl", "tmp").toFile(); File tempFile = Files.createTempFile("hmcl", "tmp").toFile();
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
task.setName(entry.getKey());
dependencies.add(task.thenRunAsync(() -> { dependencies.add(task.thenRunAsync(() -> {
try { try {
Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest); Files.copy(new LZMAInputStream(new FileInputStream(tempFile)), dest);
@ -106,6 +107,7 @@ public class JavaDownloadTask extends Task<Void> {
} else if (file.getDownloads().containsKey("raw")) { } else if (file.getDownloads().containsKey("raw")) {
DownloadInfo download = file.getDownloads().get("raw"); DownloadInfo download = file.getDownloads().get("raw");
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
task.setName(entry.getKey());
dependencies.add(task); dependencies.add(task);
} else { } else {
continue; continue;
@ -142,26 +144,5 @@ public class JavaDownloadTask extends Task<Void> {
.collect(Collectors.joining(OperatingSystem.LINE_SEPARATOR))); .collect(Collectors.joining(OperatingSystem.LINE_SEPARATOR)));
} }
public static Optional<String> 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 {} public static class UnsupportedPlatformException extends Exception {}
} }

View File

@ -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<String> 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<String> 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<String> 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());
}
}

View File

@ -17,15 +17,15 @@
*/ */
package org.jackhuang.hmcl.game; package org.jackhuang.hmcl.game;
public class JavaVersion { public class GameJavaVersion {
private final String component; private final String component;
private final int majorVersion; private final int majorVersion;
public JavaVersion() { public GameJavaVersion() {
this("", 0); this("", 0);
} }
public JavaVersion(String component, int majorVersion) { public GameJavaVersion(String component, int majorVersion) {
this.component = component; this.component = component;
this.majorVersion = majorVersion; this.majorVersion = majorVersion;
} }

View File

@ -60,7 +60,7 @@ public class Version implements Comparable<Version>, Validation {
private final String assets; private final String assets;
private final Integer complianceLevel; private final Integer complianceLevel;
@Nullable @Nullable
private final JavaVersion javaVersion; private final GameJavaVersion javaVersion;
private final List<Library> libraries; private final List<Library> libraries;
private final List<CompatibilityRule> compatibilityRules; private final List<CompatibilityRule> compatibilityRules;
private final JsonMap<DownloadType, DownloadInfo> downloads; private final JsonMap<DownloadType, DownloadInfo> downloads;
@ -93,7 +93,7 @@ public class Version implements Comparable<Version>, 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); 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<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List<Version> 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<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List<Version> patches) {
this.resolved = resolved; this.resolved = resolved;
this.id = id; this.id = id;
this.version = version; this.version = version;
@ -178,7 +178,7 @@ public class Version implements Comparable<Version>, Validation {
return complianceLevel; return complianceLevel;
} }
public JavaVersion getJavaVersion() { public GameJavaVersion getJavaVersion() {
return javaVersion; return javaVersion;
} }

View File

@ -28,9 +28,7 @@ import java.nio.file.Files;
import java.nio.file.InvalidPathException; import java.nio.file.InvalidPathException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.logging.Level; import java.util.logging.Level;
@ -38,7 +36,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Stream; import java.util.stream.Stream;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Logging.LOG;
@ -144,7 +141,7 @@ public final class JavaVersion {
return javaVersion; return javaVersion;
} }
private static Path getExecutable(Path javaHome) { public static Path getExecutable(Path javaHome) {
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
return javaHome.resolve("bin").resolve("java.exe"); return javaHome.resolve("bin").resolve("java.exe");
} else { } else {
@ -171,10 +168,10 @@ public final class JavaVersion {
Platform.PLATFORM); Platform.PLATFORM);
} }
private static List<JavaVersion> JAVAS; private static Collection<JavaVersion> JAVAS;
private static final CountDownLatch LATCH = new CountDownLatch(1); private static final CountDownLatch LATCH = new CountDownLatch(1);
public static List<JavaVersion> getJavas() throws InterruptedException { public static Collection<JavaVersion> getJavas() throws InterruptedException {
if (JAVAS != null) if (JAVAS != null)
return JAVAS; return JAVAS;
LATCH.await(); LATCH.await();
@ -199,7 +196,8 @@ public final class JavaVersion {
javaVersions.add(CURRENT_JAVA); javaVersions.add(CURRENT_JAVA);
} }
JAVAS = unmodifiableList(javaVersions); JAVAS = Collections.newSetFromMap(new ConcurrentHashMap<>());
JAVAS.addAll(javaVersions);
LATCH.countDown(); LATCH.countDown();
} }