mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2024-11-27 06:10:08 +08:00
Use Commons Compress to readModpackManifest
This commit is contained in:
parent
0f22c9e31a
commit
17ad6362c3
@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
@ -28,7 +29,6 @@ import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
@ -46,10 +46,10 @@ public final class HMCLModpackManager {
|
||||
* @throws IOException if the file is not a valid zip file.
|
||||
* @throws JsonParseException if the manifest.json is missing or malformed.
|
||||
*/
|
||||
public static Modpack readHMCLModpackManifest(Path file, Charset encoding) throws IOException, JsonParseException {
|
||||
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json", encoding);
|
||||
public static Modpack readHMCLModpackManifest(ZipFile file, Charset encoding) throws IOException, JsonParseException {
|
||||
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json");
|
||||
Modpack manifest = JsonUtils.fromNonNullJson(manifestJson, HMCLModpack.class).setEncoding(encoding);
|
||||
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json", encoding);
|
||||
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json");
|
||||
Version game = JsonUtils.fromNonNullJson(gameJson, Version.class);
|
||||
if (game.getJar() == null)
|
||||
if (StringUtils.isBlank(manifest.getVersion()))
|
||||
|
@ -19,6 +19,7 @@ package org.jackhuang.hmcl.game;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.mod.*;
|
||||
import org.jackhuang.hmcl.mod.curse.CurseCompletionException;
|
||||
import org.jackhuang.hmcl.mod.curse.CurseInstallTask;
|
||||
@ -61,34 +62,38 @@ public final class ModpackHelper {
|
||||
private ModpackHelper() {}
|
||||
|
||||
public static Modpack readModpackManifest(Path file, Charset charset) throws UnsupportedModpackException, ManuallyCreatedModpackException {
|
||||
try {
|
||||
return McbbsModpackManifest.readManifest(file, charset);
|
||||
} catch (Exception ignored) {
|
||||
// ignore it, not a valid MCBBS modpack.
|
||||
}
|
||||
try (ZipFile zipFile = CompressingUtils.openZipFile(file, charset)) {
|
||||
try {
|
||||
return McbbsModpackManifest.readManifest(zipFile, charset);
|
||||
} catch (Exception ignored) {
|
||||
// ignore it, not a valid MCBBS modpack.
|
||||
}
|
||||
|
||||
try {
|
||||
return CurseManifest.readCurseForgeModpackManifest(file, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid CurseForge modpack.
|
||||
}
|
||||
try {
|
||||
return CurseManifest.readCurseForgeModpackManifest(zipFile, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid CurseForge modpack.
|
||||
}
|
||||
|
||||
try {
|
||||
return HMCLModpackManager.readHMCLModpackManifest(file, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid HMCL modpack.
|
||||
}
|
||||
try {
|
||||
return HMCLModpackManager.readHMCLModpackManifest(zipFile, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid HMCL modpack.
|
||||
}
|
||||
|
||||
try {
|
||||
return MultiMCInstanceConfiguration.readMultiMCModpackManifest(file, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid MultiMC modpack.
|
||||
}
|
||||
try {
|
||||
return MultiMCInstanceConfiguration.readMultiMCModpackManifest(zipFile, file, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid MultiMC modpack.
|
||||
}
|
||||
|
||||
try {
|
||||
return ServerModpackManifest.readManifest(file, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid Server modpack.
|
||||
try {
|
||||
return ServerModpackManifest.readManifest(zipFile, charset);
|
||||
} catch (Exception e) {
|
||||
// ignore it, not a valid Server modpack.
|
||||
}
|
||||
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(file, charset)) {
|
||||
|
@ -19,17 +19,19 @@ package org.jackhuang.hmcl.mod.curse;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ -121,11 +123,17 @@ public final class CurseManifest {
|
||||
* @throws JsonParseException if the manifest.json is missing or malformed.
|
||||
* @return the manifest.
|
||||
*/
|
||||
public static Modpack readCurseForgeModpackManifest(Path zip, Charset encoding) throws IOException, JsonParseException {
|
||||
String json = CompressingUtils.readTextZipEntry(zip, "manifest.json", encoding);
|
||||
CurseManifest manifest = JsonUtils.fromNonNullJson(json, CurseManifest.class);
|
||||
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(),
|
||||
CompressingUtils.readTextZipEntryQuietly(zip, "modlist.html", encoding).orElse( "No description"), encoding, manifest) {
|
||||
public static Modpack readCurseForgeModpackManifest(ZipFile zip, Charset encoding) throws IOException, JsonParseException {
|
||||
CurseManifest manifest = JsonUtils.fromNonNullJson(CompressingUtils.readTextZipEntry(zip, "manifest.json"), CurseManifest.class);
|
||||
String description = "No description";
|
||||
try {
|
||||
ZipArchiveEntry modlist = zip.getEntry("modlist.html");
|
||||
if (modlist != null)
|
||||
description = IOUtils.readFullyAsString(zip.getInputStream(modlist));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(), description, encoding, manifest) {
|
||||
@Override
|
||||
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
|
||||
return new CurseInstallTask(dependencyManager, zipFile, this, manifest, name);
|
||||
|
@ -19,24 +19,21 @@ package org.jackhuang.hmcl.mod.mcbbs;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.game.LaunchOptions;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.gson.*;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -434,8 +431,7 @@ public class McbbsModpackManifest implements Validation {
|
||||
launchOptions.getJavaArguments().addAll(launchInfo.getJavaArguments());
|
||||
}
|
||||
|
||||
private static Modpack fromManifestFile(Path manifestFile, Charset encoding) throws IOException, JsonParseException {
|
||||
String json = FileUtils.readText(manifestFile, StandardCharsets.UTF_8);
|
||||
private static Modpack fromManifestFile(String json, Charset encoding) throws IOException, JsonParseException {
|
||||
McbbsModpackManifest manifest = JsonUtils.fromNonNullJson(json, McbbsModpackManifest.class);
|
||||
return manifest.toModpack(encoding);
|
||||
}
|
||||
@ -447,17 +443,15 @@ public class McbbsModpackManifest implements Validation {
|
||||
* @throws JsonParseException if the server-manifest.json is missing or malformed.
|
||||
* @return the manifest.
|
||||
*/
|
||||
public static Modpack readManifest(Path zip, Charset encoding) throws IOException, JsonParseException {
|
||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(zip, encoding)) {
|
||||
Path mcbbsPackMeta = fs.getPath("mcbbs.packmeta");
|
||||
if (Files.exists(mcbbsPackMeta)) {
|
||||
return fromManifestFile(mcbbsPackMeta, encoding);
|
||||
}
|
||||
Path manifestJson = fs.getPath("manifest.json");
|
||||
if (Files.exists(manifestJson)) {
|
||||
return fromManifestFile(manifestJson, encoding);
|
||||
}
|
||||
throw new IOException("`mcbbs.packmeta` or `manifest.json` cannot be found");
|
||||
public static Modpack readManifest(ZipFile zip, Charset encoding) throws IOException, JsonParseException {
|
||||
ZipArchiveEntry mcbbsPackMeta = zip.getEntry("mcbbs.packmeta");
|
||||
if (mcbbsPackMeta != null) {
|
||||
return fromManifestFile(IOUtils.readFullyAsString(zip.getInputStream(mcbbsPackMeta)), encoding);
|
||||
}
|
||||
ZipArchiveEntry manifestJson = zip.getEntry("manifest.json");
|
||||
if (manifestJson != null) {
|
||||
return fromManifestFile(IOUtils.readFullyAsString(zip.getInputStream(manifestJson)), encoding);
|
||||
}
|
||||
throw new IOException("`mcbbs.packmeta` or `manifest.json` cannot be found");
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,12 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod.multimc;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
@ -30,9 +31,9 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Stream;
|
||||
@ -348,24 +349,44 @@ public final class MultiMCInstanceConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
public static Modpack readMultiMCModpackManifest(Path modpackFile, Charset encoding) throws IOException {
|
||||
try (FileSystem fs = CompressingUtils.readonly(modpackFile).setEncoding(encoding).build()) {
|
||||
Path root = getRootPath(fs.getPath("/"));
|
||||
MultiMCManifest manifest = MultiMCManifest.readMultiMCModpackManifest(root);
|
||||
String name = FileUtils.getName(root, FileUtils.getNameWithoutExtension(modpackFile));
|
||||
public static String getRootEntryName(ZipFile file) throws IOException {
|
||||
final String instanceFileName = "instance.cfg";
|
||||
|
||||
Path instancePath = root.resolve("instance.cfg");
|
||||
if (Files.notExists(instancePath))
|
||||
throw new IOException("`instance.cfg` not found, " + modpackFile + " is not a valid MultiMC modpack.");
|
||||
try (InputStream instanceStream = Files.newInputStream(instancePath)) {
|
||||
MultiMCInstanceConfiguration cfg = new MultiMCInstanceConfiguration(name, instanceStream, manifest);
|
||||
return new Modpack(cfg.getName(), "", "", cfg.getGameVersion(), cfg.getNotes(), encoding, cfg) {
|
||||
@Override
|
||||
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
|
||||
return new MultiMCModpackInstallTask(dependencyManager, zipFile, this, cfg, name);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (file.getEntry(instanceFileName) != null) return "";
|
||||
|
||||
Enumeration<ZipArchiveEntry> entries = file.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
String entryName = entry.getName();
|
||||
|
||||
int idx = entryName.indexOf('/');
|
||||
if (idx >= 0
|
||||
&& entryName.length() == idx + instanceFileName.length() + 1
|
||||
&& entryName.startsWith(instanceFileName, idx + 1))
|
||||
return entryName.substring(0, idx + 1);
|
||||
}
|
||||
|
||||
throw new IOException("Not a valid MultiMC modpack");
|
||||
}
|
||||
|
||||
public static Modpack readMultiMCModpackManifest(ZipFile modpackFile, Path modpackPath, Charset encoding) throws IOException {
|
||||
String rootEntryName = getRootEntryName(modpackFile);
|
||||
MultiMCManifest manifest = MultiMCManifest.readMultiMCModpackManifest(modpackFile, rootEntryName);
|
||||
|
||||
String name = rootEntryName.isEmpty() ? FileUtils.getNameWithoutExtension(modpackPath) : rootEntryName.substring(0, rootEntryName.length() - 1);
|
||||
ZipArchiveEntry instanceEntry = modpackFile.getEntry(rootEntryName + "instance.cfg");
|
||||
|
||||
if (instanceEntry == null)
|
||||
throw new IOException("`instance.cfg` not found, " + modpackFile + " is not a valid MultiMC modpack.");
|
||||
try (InputStream instanceStream = modpackFile.getInputStream(instanceEntry)) {
|
||||
MultiMCInstanceConfiguration cfg = new MultiMCInstanceConfiguration(name, instanceStream, manifest);
|
||||
return new Modpack(cfg.getName(), "", "", cfg.getGameVersion(), cfg.getNotes(), encoding, cfg) {
|
||||
@Override
|
||||
public Task<?> getInstallTask(DefaultDependencyManager dependencyManager, File zipFile, String name) {
|
||||
return new MultiMCModpackInstallTask(dependencyManager, zipFile, this, cfg, name);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,13 +18,13 @@
|
||||
package org.jackhuang.hmcl.mod.multimc;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
@Immutable
|
||||
@ -51,18 +51,17 @@ public final class MultiMCManifest {
|
||||
|
||||
/**
|
||||
* Read MultiMC modpack manifest from zip file
|
||||
* @param root root path in zip file (Path root is a path of ZipFileSystem)
|
||||
* @param zipFile the zip file
|
||||
* @return the MultiMC modpack manifest.
|
||||
* @throws IOException if zip file is malformed
|
||||
* @throws com.google.gson.JsonParseException if manifest is malformed.
|
||||
*/
|
||||
public static MultiMCManifest readMultiMCModpackManifest(Path root) throws IOException {
|
||||
Path mmcPack = root.resolve("mmc-pack.json");
|
||||
if (Files.notExists(mmcPack))
|
||||
public static MultiMCManifest readMultiMCModpackManifest(ZipFile zipFile, String rootEntryName) throws IOException {
|
||||
ZipArchiveEntry mmcPack = zipFile.getEntry(rootEntryName + "mmc-pack.json");
|
||||
if (mmcPack == null)
|
||||
return null;
|
||||
String json = FileUtils.readText(mmcPack);
|
||||
String json = IOUtils.readFullyAsString(zipFile.getInputStream(mmcPack));
|
||||
MultiMCManifest manifest = JsonUtils.fromNonNullJson(json, MultiMCManifest.class);
|
||||
|
||||
if (manifest.getComponents() == null)
|
||||
throw new IOException("mmc-pack.json malformed.");
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.mod.server;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.mod.ModpackConfiguration;
|
||||
@ -30,7 +31,6 @@ import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ -134,8 +134,8 @@ public class ServerModpackManifest implements Validation {
|
||||
* @throws JsonParseException if the server-manifest.json is missing or malformed.
|
||||
* @return the manifest.
|
||||
*/
|
||||
public static Modpack readManifest(Path zip, Charset encoding) throws IOException, JsonParseException {
|
||||
String json = CompressingUtils.readTextZipEntry(zip, "server-manifest.json", encoding);
|
||||
public static Modpack readManifest(ZipFile zip, Charset encoding) throws IOException, JsonParseException {
|
||||
String json = CompressingUtils.readTextZipEntry(zip, "server-manifest.json");
|
||||
ServerModpackManifest manifest = JsonUtils.fromNonNullJson(json, ServerModpackManifest.class);
|
||||
return manifest.toModpack(encoding);
|
||||
}
|
||||
|
@ -217,10 +217,22 @@ public final class CompressingUtils {
|
||||
*/
|
||||
public static String readTextZipEntry(File zipFile, String name) throws IOException {
|
||||
try (ZipFile s = new ZipFile(zipFile)) {
|
||||
return IOUtils.readFullyAsString(s.getInputStream(s.getEntry(name)), StandardCharsets.UTF_8);
|
||||
return readTextZipEntry(s, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the text content of a file in zip.
|
||||
*
|
||||
* @param zipFile the zip file
|
||||
* @param name the location of the text in zip file, something like A/B/C/D.txt
|
||||
* @throws IOException if the file is not a valid zip file.
|
||||
* @return the plain text content of given file.
|
||||
*/
|
||||
public static String readTextZipEntry(ZipFile zipFile, String name) throws IOException {
|
||||
return IOUtils.readFullyAsString(zipFile.getInputStream(zipFile.getEntry(name)), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the text content of a file in zip.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user