mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-22 10:43:57 -04:00
清理 org.jackhuang.hmcl.download.game (#4495)
1. 将 `java.io.File` 迁移至 NIO; 2. 将部分类迁移至 record。
This commit is contained in:
parent
fc1cce5e5a
commit
6a497df0d1
@ -173,7 +173,7 @@ public final class LauncherHelper {
|
||||
String agent = file.getAbsolutePath() + "=" + renderer.name().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (GameLibrariesTask.shouldDownloadLibrary(repository, version.get(), lib, integrityCheck)) {
|
||||
return new LibraryDownloadTask(dependencyManager, file, lib)
|
||||
return new LibraryDownloadTask(dependencyManager, file.toPath(), lib)
|
||||
.thenRunAsync(() -> javaAgents.add(agent));
|
||||
} else {
|
||||
javaAgents.add(agent);
|
||||
|
@ -104,7 +104,7 @@ public class DefaultCacheRepository extends CacheRepository {
|
||||
if (hash.equalsIgnoreCase(checksum))
|
||||
cacheLibrary(library, jar, false);
|
||||
} else if (library.getChecksums() != null && !library.getChecksums().isEmpty()) {
|
||||
if (LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums()))
|
||||
if (LibraryDownloadTask.checksumValid(jar, library.getChecksums()))
|
||||
cacheLibrary(library, jar, true);
|
||||
} else {
|
||||
// or we will not cache the library
|
||||
@ -139,7 +139,7 @@ public class DefaultCacheRepository extends CacheRepository {
|
||||
if (fileExists(SHA1, libIndex.getHash())) {
|
||||
Path file = getFile(SHA1, libIndex.getHash());
|
||||
if (libIndex.getType().equalsIgnoreCase(LibraryIndex.TYPE_FORGE)) {
|
||||
if (LibraryDownloadTask.checksumValid(file.toFile(), library.getChecksums()))
|
||||
if (LibraryDownloadTask.checksumValid(file, library.getChecksums()))
|
||||
return Optional.of(file);
|
||||
}
|
||||
}
|
||||
@ -157,7 +157,7 @@ public class DefaultCacheRepository extends CacheRepository {
|
||||
if (hash.equalsIgnoreCase(checksum))
|
||||
return Optional.of(restore(jar, () -> cacheLibrary(library, jar, false)));
|
||||
} else if (library.getChecksums() != null && !library.getChecksums().isEmpty()) {
|
||||
if (LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums()))
|
||||
if (LibraryDownloadTask.checksumValid(jar, library.getChecksums()))
|
||||
return Optional.of(restore(jar, () -> cacheLibrary(library, jar, true)));
|
||||
} else {
|
||||
return Optional.of(jar);
|
||||
|
@ -32,7 +32,6 @@ import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
@ -89,30 +88,29 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
}
|
||||
|
||||
public static boolean shouldDownloadLibrary(GameRepository gameRepository, Version version, Library library, boolean integrityCheck) {
|
||||
File file = gameRepository.getLibraryFile(version, library);
|
||||
Path jar = file.toPath();
|
||||
if (!file.isFile()) return true;
|
||||
Path file = gameRepository.getLibraryFile(version, library).toPath();
|
||||
if (!Files.isRegularFile(file)) return true;
|
||||
|
||||
if (!integrityCheck) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (!library.getDownload().validateChecksum(jar, true)) {
|
||||
if (!library.getDownload().validateChecksum(file, true)) {
|
||||
return true;
|
||||
}
|
||||
if (library.getChecksums() != null && !library.getChecksums().isEmpty() && !LibraryDownloadTask.checksumValid(file, library.getChecksums())) {
|
||||
return true;
|
||||
}
|
||||
if (FileUtils.getExtension(file.getName()).equals("jar")) {
|
||||
if (FileUtils.getExtension(file).equals("jar")) {
|
||||
try {
|
||||
FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(jar, jar);
|
||||
FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(file, file);
|
||||
} catch (IOException ignored) {
|
||||
// the Jar file is malformed, so re-download it.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Unable to calc hash value of file " + jar, e);
|
||||
LOG.warning("Unable to calc hash value of file " + file, e);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -160,13 +158,13 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
}
|
||||
}
|
||||
|
||||
File file = gameRepository.getLibraryFile(version, library);
|
||||
if ("optifine".equals(library.getGroupId()) && file.exists() && GameVersionNumber.asGameVersion(gameRepository.getGameVersion(version)).compareTo("1.20.4") == 0) {
|
||||
Path file = gameRepository.getLibraryFile(version, library).toPath();
|
||||
if ("optifine".equals(library.getGroupId()) && Files.exists(file) && GameVersionNumber.asGameVersion(gameRepository.getGameVersion(version)).compareTo("1.20.4") == 0) {
|
||||
String forgeVersion = LibraryAnalyzer.analyze(version, "1.20.4")
|
||||
.getVersion(LibraryAnalyzer.LibraryType.FORGE)
|
||||
.orElse(null);
|
||||
if (forgeVersion != null && LibraryAnalyzer.FORGE_OPTIFINE_BROKEN_RANGE.contains(VersionNumber.asVersion(forgeVersion))) {
|
||||
try (FileSystem fs2 = CompressingUtils.createWritableZipFileSystem(file.toPath())) {
|
||||
try (FileSystem fs2 = CompressingUtils.createWritableZipFileSystem(file)) {
|
||||
Files.deleteIfExists(fs2.getPath("/META-INF/mods.toml"));
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Cannot fix optifine", e);
|
||||
@ -176,7 +174,7 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
if (shouldDownloadLibrary(gameRepository, version, library, integrityCheck) && (library.hasDownloadURL() || !"optifine".equals(library.getGroupId()))) {
|
||||
dependencies.add(new LibraryDownloadTask(dependencyManager, file, library).withCounter("hmcl.install.libraries"));
|
||||
} else {
|
||||
dependencyManager.getCacheRepository().tryCacheLibrary(library, file.toPath());
|
||||
dependencyManager.getCacheRepository().tryCacheLibrary(library, file);
|
||||
}
|
||||
|
||||
updateProgress(++progress, libraries.size());
|
||||
|
@ -19,34 +19,14 @@ package org.jackhuang.hmcl.download.game;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.gson.JsonSerializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
@Immutable
|
||||
public final class GameRemoteLatestVersions {
|
||||
|
||||
@SerializedName("snapshot")
|
||||
private final String snapshot;
|
||||
|
||||
@SerializedName("release")
|
||||
private final String release;
|
||||
|
||||
public GameRemoteLatestVersions() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public GameRemoteLatestVersions(String snapshot, String release) {
|
||||
this.snapshot = snapshot;
|
||||
this.release = release;
|
||||
}
|
||||
|
||||
public String getRelease() {
|
||||
return release;
|
||||
}
|
||||
|
||||
public String getSnapshot() {
|
||||
return snapshot;
|
||||
}
|
||||
@JsonSerializable
|
||||
public record GameRemoteLatestVersions(
|
||||
@SerializedName("snapshot") String snapshot,
|
||||
@SerializedName("release") String release) {
|
||||
}
|
||||
|
@ -68,17 +68,12 @@ public final class GameRemoteVersion extends RemoteVersion {
|
||||
|
||||
private static Type getReleaseType(ReleaseType type) {
|
||||
if (type == null) return Type.UNCATEGORIZED;
|
||||
switch (type) {
|
||||
case RELEASE:
|
||||
return Type.RELEASE;
|
||||
case SNAPSHOT:
|
||||
return Type.SNAPSHOT;
|
||||
case UNKNOWN:
|
||||
return Type.UNCATEGORIZED;
|
||||
case PENDING:
|
||||
return Type.PENDING;
|
||||
default:
|
||||
return Type.OLD;
|
||||
}
|
||||
return switch (type) {
|
||||
case RELEASE -> Type.RELEASE;
|
||||
case SNAPSHOT -> Type.SNAPSHOT;
|
||||
case UNKNOWN -> Type.UNCATEGORIZED;
|
||||
case PENDING -> Type.PENDING;
|
||||
default -> Type.OLD;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ package org.jackhuang.hmcl.download.game;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.jackhuang.hmcl.game.ReleaseType;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.gson.JsonSerializable;
|
||||
import org.jackhuang.hmcl.util.gson.Validation;
|
||||
|
||||
import java.time.Instant;
|
||||
@ -30,58 +30,13 @@ import java.time.Instant;
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public final class GameRemoteVersionInfo implements Validation {
|
||||
|
||||
@SerializedName("id")
|
||||
private final String gameVersion;
|
||||
|
||||
@SerializedName("time")
|
||||
private final Instant time;
|
||||
|
||||
@SerializedName("releaseTime")
|
||||
private final Instant releaseTime;
|
||||
|
||||
@SerializedName("type")
|
||||
private final ReleaseType type;
|
||||
|
||||
@SerializedName("url")
|
||||
private final String url;
|
||||
|
||||
public GameRemoteVersionInfo() {
|
||||
this("", Instant.now(), Instant.now(), ReleaseType.UNKNOWN);
|
||||
}
|
||||
|
||||
public GameRemoteVersionInfo(String gameVersion, Instant time, Instant releaseTime, ReleaseType type) {
|
||||
this(gameVersion, time, releaseTime, type, Constants.DEFAULT_LIBRARY_URL + gameVersion + "/" + gameVersion + ".json");
|
||||
}
|
||||
|
||||
public GameRemoteVersionInfo(String gameVersion, Instant time, Instant releaseTime, ReleaseType type, String url) {
|
||||
this.gameVersion = gameVersion;
|
||||
this.time = time;
|
||||
this.releaseTime = releaseTime;
|
||||
this.type = type;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getGameVersion() {
|
||||
return gameVersion;
|
||||
}
|
||||
|
||||
public Instant getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Instant getReleaseTime() {
|
||||
return releaseTime;
|
||||
}
|
||||
|
||||
public ReleaseType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
@JsonSerializable
|
||||
public record GameRemoteVersionInfo(
|
||||
@SerializedName("id") String gameVersion,
|
||||
@SerializedName("time") Instant time,
|
||||
@SerializedName("releaseTime") Instant releaseTime,
|
||||
@SerializedName("type") ReleaseType type,
|
||||
@SerializedName("url") String url) implements Validation {
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
|
@ -20,9 +20,9 @@ package org.jackhuang.hmcl.download.game;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.gson.JsonSerializable;
|
||||
import org.jackhuang.hmcl.util.gson.Validation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -30,34 +30,10 @@ import java.util.List;
|
||||
* @author huangyuhui
|
||||
*/
|
||||
@Immutable
|
||||
public final class GameRemoteVersions implements Validation {
|
||||
|
||||
@SerializedName("versions")
|
||||
private final List<GameRemoteVersionInfo> versions;
|
||||
|
||||
@SerializedName("latest")
|
||||
private final GameRemoteLatestVersions latest;
|
||||
|
||||
/**
|
||||
* No-arg constructor for Gson.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public GameRemoteVersions() {
|
||||
this(Collections.emptyList(), null);
|
||||
}
|
||||
|
||||
public GameRemoteVersions(List<GameRemoteVersionInfo> versions, GameRemoteLatestVersions latest) {
|
||||
this.versions = versions;
|
||||
this.latest = latest;
|
||||
}
|
||||
|
||||
public GameRemoteLatestVersions getLatest() {
|
||||
return latest;
|
||||
}
|
||||
|
||||
public List<GameRemoteVersionInfo> getVersions() {
|
||||
return versions;
|
||||
}
|
||||
@JsonSerializable
|
||||
public record GameRemoteVersions(
|
||||
@SerializedName("versions") List<GameRemoteVersionInfo> versions,
|
||||
@SerializedName("latest") GameRemoteLatestVersions latest) implements Validation {
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
|
@ -24,11 +24,11 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -62,11 +62,11 @@ public final class GameVerificationFixTask extends Task<Void> {
|
||||
|
||||
@Override
|
||||
public void execute() throws IOException {
|
||||
File jar = dependencyManager.getGameRepository().getVersionJar(version);
|
||||
Path jar = dependencyManager.getGameRepository().getVersionJar(version).toPath();
|
||||
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version, gameVersion);
|
||||
|
||||
if (jar.exists() && GameVersionNumber.compare(gameVersion, "1.6") < 0 && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) {
|
||||
try (FileSystem fs = CompressingUtils.createWritableZipFileSystem(jar.toPath(), StandardCharsets.UTF_8)) {
|
||||
if (Files.exists(jar) && GameVersionNumber.compare(gameVersion, "1.6") < 0 && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) {
|
||||
try (FileSystem fs = CompressingUtils.createWritableZipFileSystem(jar, StandardCharsets.UTF_8)) {
|
||||
Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.DSA"));
|
||||
Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.SF"));
|
||||
}
|
||||
|
@ -70,21 +70,21 @@ public final class GameVersionList extends VersionList<GameRemoteVersion> {
|
||||
versions.clear();
|
||||
|
||||
if (unlistedVersions != null) {
|
||||
for (GameRemoteVersionInfo unlistedVersion : unlistedVersions.getVersions()) {
|
||||
versions.put(unlistedVersion.getGameVersion(), new GameRemoteVersion(
|
||||
unlistedVersion.getGameVersion(),
|
||||
unlistedVersion.getGameVersion(),
|
||||
Collections.singletonList(unlistedVersion.getUrl()),
|
||||
unlistedVersion.getType(), unlistedVersion.getReleaseTime()));
|
||||
for (GameRemoteVersionInfo unlistedVersion : unlistedVersions.versions()) {
|
||||
versions.put(unlistedVersion.gameVersion(), new GameRemoteVersion(
|
||||
unlistedVersion.gameVersion(),
|
||||
unlistedVersion.gameVersion(),
|
||||
Collections.singletonList(unlistedVersion.url()),
|
||||
unlistedVersion.type(), unlistedVersion.releaseTime()));
|
||||
}
|
||||
}
|
||||
|
||||
for (GameRemoteVersionInfo remoteVersion : root.getVersions()) {
|
||||
versions.put(remoteVersion.getGameVersion(), new GameRemoteVersion(
|
||||
remoteVersion.getGameVersion(),
|
||||
remoteVersion.getGameVersion(),
|
||||
Collections.singletonList(remoteVersion.getUrl()),
|
||||
remoteVersion.getType(), remoteVersion.getReleaseTime()));
|
||||
for (GameRemoteVersionInfo remoteVersion : root.versions()) {
|
||||
versions.put(remoteVersion.gameVersion(), new GameRemoteVersion(
|
||||
remoteVersion.gameVersion(),
|
||||
remoteVersion.gameVersion(),
|
||||
Collections.singletonList(remoteVersion.url()),
|
||||
remoteVersion.type(), remoteVersion.releaseTime()));
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
|
@ -28,7 +28,6 @@ import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -43,7 +42,7 @@ import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
|
||||
public class LibraryDownloadTask extends Task<Void> {
|
||||
private FileDownloadTask task;
|
||||
protected final File jar;
|
||||
protected final Path jar;
|
||||
protected final DefaultCacheRepository cacheRepository;
|
||||
protected final AbstractDependencyManager dependencyManager;
|
||||
protected final Library library;
|
||||
@ -51,7 +50,7 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
private final Library originalLibrary;
|
||||
private boolean cached = false;
|
||||
|
||||
public LibraryDownloadTask(AbstractDependencyManager dependencyManager, File file, Library library) {
|
||||
public LibraryDownloadTask(AbstractDependencyManager dependencyManager, Path file, Library library) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
this.originalLibrary = library;
|
||||
|
||||
@ -105,7 +104,7 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
Optional<Path> libPath = cacheRepository.getLibrary(originalLibrary);
|
||||
if (libPath.isPresent()) {
|
||||
try {
|
||||
FileUtils.copyFile(libPath.get(), jar.toPath());
|
||||
FileUtils.copyFile(libPath.get(), jar);
|
||||
cached = true;
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
@ -117,7 +116,7 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
|
||||
|
||||
List<URI> uris = dependencyManager.getDownloadProvider().injectURLWithCandidates(url);
|
||||
task = new FileDownloadTask(uris, jar.toPath(),
|
||||
task = new FileDownloadTask(uris, jar,
|
||||
library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null);
|
||||
task.setCacheRepository(cacheRepository);
|
||||
task.setCaching(true);
|
||||
@ -133,26 +132,26 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
public void postExecute() throws Exception {
|
||||
if (!cached) {
|
||||
try {
|
||||
cacheRepository.cacheLibrary(library, jar.toPath(), false);
|
||||
cacheRepository.cacheLibrary(library, jar, false);
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Failed to cache downloaded library " + library, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checksumValid(File libPath, List<String> checksums) {
|
||||
public static boolean checksumValid(Path libPath, List<String> checksums) {
|
||||
try {
|
||||
if (checksums == null || checksums.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
byte[] fileData = Files.readAllBytes(libPath.toPath());
|
||||
byte[] fileData = Files.readAllBytes(libPath);
|
||||
boolean valid = checksums.contains(DigestUtils.digestToString("SHA-1", fileData));
|
||||
if (!valid && libPath.getName().endsWith(".jar")) {
|
||||
if (!valid && FileUtils.getName(libPath).endsWith(".jar")) {
|
||||
valid = validateJar(fileData, checksums);
|
||||
}
|
||||
return valid;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
LOG.warning("Failed to validate " + libPath, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -177,7 +176,7 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
boolean failed = !checksums.contains(files.get("checksums.sha1"));
|
||||
if (!failed) {
|
||||
for (String hash : hashes) {
|
||||
if ((!hash.trim().equals("")) && (hash.contains(" "))) {
|
||||
if (!hash.trim().isEmpty() && hash.contains(" ")) {
|
||||
String[] e = hash.split(" ");
|
||||
String validChecksum = e[0];
|
||||
String target = hash.substring(validChecksum.length() + 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user