From 04553c2c5688cfa260edc54c866f97f3ee53ad74 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sat, 4 Aug 2018 22:04:59 +0800 Subject: [PATCH] Support packed update archive --- .../hmcl/upgrade/LocalRepository.java | 20 +++++++++++--- .../jackhuang/hmcl/upgrade/RemoteVersion.java | 26 ++++++++++++++++--- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java index 03358beda..dd873d820 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java @@ -26,7 +26,10 @@ import java.nio.file.StandardCopyOption; import java.util.Optional; import java.util.jar.Attributes; import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Pack200; import java.util.logging.Level; +import java.util.zip.GZIPInputStream; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; @@ -63,17 +66,26 @@ final class LocalRepository { * Creates a task that downloads the given version to local repository. */ public static FileDownloadTask downloadFromRemote(RemoteVersion version) throws IOException { - Path stage = Files.createTempFile("hmcl-update-", ".jar"); + Path stage = Files.createTempFile("hmcl-update-", ""); return new FileDownloadTask(new URL(version.getUrl()), stage.toFile(), version.getIntegrityCheck()) { @Override public void execute() throws Exception { + Path jar = stage; try { super.execute(); - IntegrityChecker.requireVerifiedJar(stage); + if (version.getType() == RemoteVersion.Type.PACK) { + Path unpacked = Files.createTempFile("hmcl-update-", ".jar"); + try (GZIPInputStream stream = new GZIPInputStream(Files.newInputStream(jar)); + JarOutputStream out = new JarOutputStream(Files.newOutputStream(unpacked))) { + Pack200.newUnpacker().unpack(stream, out); + } + jar = unpacked; + } + IntegrityChecker.requireVerifiedJar(jar); Files.createDirectories(localStorage.getParent()); - Files.copy(stage, localStorage, StandardCopyOption.REPLACE_EXISTING); + Files.copy(jar, localStorage, StandardCopyOption.REPLACE_EXISTING); } finally { - Files.deleteIfExists(stage); + Files.deleteIfExists(jar); } } }; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java index 0f5c6e14f..33fda5f62 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java @@ -34,9 +34,16 @@ public class RemoteVersion { try { JsonObject response = JsonUtils.fromNonNullJson(NetworkUtils.doGet(NetworkUtils.toURL(url)), JsonObject.class); String version = Optional.ofNullable(response.get("version")).map(JsonElement::getAsString).orElseThrow(() -> new IOException("version is missing")); - String downloadUrl = Optional.ofNullable(response.get("jar")).map(JsonElement::getAsString).orElseThrow(() -> new IOException("jar is missing")); - String sha1 = Optional.ofNullable(response.get("jarsha1")).map(JsonElement::getAsString).orElseThrow(() -> new IOException("jarsha1 is missing")); - return new RemoteVersion(version, downloadUrl, new IntegrityCheck("SHA-1", sha1)); + String jarUrl = Optional.ofNullable(response.get("jar")).map(JsonElement::getAsString).orElse(null); + String jarHash = Optional.ofNullable(response.get("jarsha1")).map(JsonElement::getAsString).orElse(null); + String packUrl = Optional.ofNullable(response.get("pack")).map(JsonElement::getAsString).orElse(null); + String packHash = Optional.ofNullable(response.get("packsha1")).map(JsonElement::getAsString).orElse(null); + if (packUrl != null && packHash != null) + return new RemoteVersion(version, packUrl, Type.PACK, new IntegrityCheck("SHA-1", packHash)); + else if (jarUrl != null && jarHash != null) + return new RemoteVersion(version, jarUrl, Type.JAR, new IntegrityCheck("SHA-1", jarHash)); + else + throw new IOException("Missing both jar and pack download URL"); } catch (JsonParseException e) { throw new IOException("Malformed response", e); } @@ -44,11 +51,13 @@ public class RemoteVersion { private String version; private String url; + private Type type; private IntegrityCheck integrityCheck; - public RemoteVersion(String version, String url, IntegrityCheck integrityCheck) { + public RemoteVersion(String version, String url, Type type, IntegrityCheck integrityCheck) { this.version = version; this.url = url; + this.type = type; this.integrityCheck = integrityCheck; } @@ -60,6 +69,10 @@ public class RemoteVersion { return url; } + public Type getType() { + return type; + } + public IntegrityCheck getIntegrityCheck() { return integrityCheck; } @@ -68,4 +81,9 @@ public class RemoteVersion { public String toString() { return "[" + version + " from " + url + "]"; } + + public enum Type { + PACK, + JAR + } }