修复 Java 下载相关问题 (#1874)

* fix #1561: Replace existing files when downloading Java
close #1756

* close #1755: Download Java using mirror

* Skip existing files
This commit is contained in:
Glavo 2022-11-25 22:34:26 +08:00 committed by GitHub
parent a94bb407e5
commit f5d83095cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -25,6 +25,7 @@ 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.ChecksumMismatchException;
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.OperatingSystem; import org.jackhuang.hmcl.util.platform.OperatingSystem;
@ -37,9 +38,13 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.jackhuang.hmcl.util.Logging.LOG;
public class JavaDownloadTask extends Task<Void> { public class JavaDownloadTask extends Task<Void> {
private final GameJavaVersion javaVersion; private final GameJavaVersion javaVersion;
private final Path rootDir; private final Path rootDir;
@ -47,10 +52,12 @@ public class JavaDownloadTask extends Task<Void> {
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<>();
private final DownloadProvider downloadProvider;
public JavaDownloadTask(GameJavaVersion 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.downloadProvider = downloadProvider;
this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL( this.javaDownloadsTask = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(
"https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"))) "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json")))
.thenComposeAsync(javaDownloadsJson -> { .thenComposeAsync(javaDownloadsJson -> {
@ -62,7 +69,7 @@ public class JavaDownloadTask extends Task<Void> {
for (JavaDownloads.JavaDownload download : candidates) { for (JavaDownloads.JavaDownload download : candidates) {
if (VersionNumber.VERSION_COMPARATOR.compare(download.getVersion().getName(), Integer.toString(javaVersion.getMajorVersion())) >= 0) { if (VersionNumber.VERSION_COMPARATOR.compare(download.getVersion().getName(), Integer.toString(javaVersion.getMajorVersion())) >= 0) {
this.download = download; this.download = download;
return new GetTask(NetworkUtils.toURL(download.getManifest().getUrl())); return new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(download.getManifest().getUrl())));
} }
} }
throw new UnsupportedPlatformException(); throw new UnsupportedPlatformException();
@ -92,14 +99,29 @@ public class JavaDownloadTask extends Task<Void> {
Path dest = jvmDir.resolve(entry.getKey()); Path dest = jvmDir.resolve(entry.getKey());
if (entry.getValue() instanceof RemoteFiles.RemoteFile) { if (entry.getValue() instanceof RemoteFiles.RemoteFile) {
RemoteFiles.RemoteFile file = ((RemoteFiles.RemoteFile) entry.getValue()); RemoteFiles.RemoteFile file = ((RemoteFiles.RemoteFile) entry.getValue());
// Use local file if it already exists
try {
BasicFileAttributes localFileAttributes = Files.readAttributes(dest, BasicFileAttributes.class);
if (localFileAttributes.isRegularFile() && file.getDownloads().containsKey("raw")) {
DownloadInfo downloadInfo = file.getDownloads().get("raw");
if (localFileAttributes.size() == downloadInfo.getSize()) {
ChecksumMismatchException.verifyChecksum(dest, "SHA-1", downloadInfo.getSha1());
LOG.info("Skip existing file: " + dest);
continue;
}
}
} catch (IOException ignored) {
}
if (file.getDownloads().containsKey("lzma")) { if (file.getDownloads().containsKey("lzma")) {
DownloadInfo download = file.getDownloads().get("lzma"); DownloadInfo download = file.getDownloads().get("lzma");
File tempFile = jvmDir.resolve(entry.getKey() + ".lzma").toFile(); File tempFile = jvmDir.resolve(entry.getKey() + ".lzma").toFile();
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(download.getUrl()), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1())); FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(downloadProvider.injectURL(download.getUrl())), tempFile, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
task.setName(entry.getKey()); task.setName(entry.getKey());
dependencies.add(task.thenRunAsync(() -> { dependencies.add(task.thenRunAsync(() -> {
try (LZMAInputStream input = new LZMAInputStream(new FileInputStream(tempFile))) { try (LZMAInputStream input = new LZMAInputStream(new FileInputStream(tempFile))) {
Files.copy(input, dest); Files.copy(input, dest, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) { } catch (IOException e) {
throw new ArtifactMalformedException("File " + entry.getKey() + " is malformed", e); throw new ArtifactMalformedException("File " + entry.getKey() + " is malformed", e);
} }
@ -110,7 +132,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(downloadProvider.injectURL(download.getUrl())), dest.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
task.setName(entry.getKey()); task.setName(entry.getKey());
if (file.isExecutable()) { if (file.isExecutable()) {
dependencies.add(task.thenRunAsync(() -> dest.toFile().setExecutable(true))); dependencies.add(task.thenRunAsync(() -> dest.toFile().setExecutable(true)));