diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java index 19c8147ad..494e9b649 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.mod.MinecraftInstanceTask; @@ -67,8 +66,7 @@ public final class HMCLModpackInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(Modpack.class)); if (!HMCLModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a HMCL modpack. Cannot update this version."); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index c07676597..78b96db50 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -18,7 +18,6 @@ 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.CurseModpackProvider; @@ -141,8 +140,7 @@ public final class ModpackHelper { throw new FileNotFoundException(file.getPath()); else try { - return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>() { - }.getType()); + return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class); } catch (JsonParseException e) { throw new IOException("Malformed modpack configuration"); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java index 974ed92cd..856b2a719 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.java; import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; @@ -29,6 +28,8 @@ import java.lang.reflect.Type; import java.util.Map; import java.util.Optional; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; + /** * @author Glavo */ @@ -63,8 +64,7 @@ public final class JavaManifest { public static final class Serializer implements JsonSerializer, JsonDeserializer { - private static final Type LOCAL_FILES_TYPE = new TypeToken>() { - }.getType(); + private static final Type LOCAL_FILES_TYPE = mapTypeOf(String.class, JavaLocalFiles.Local.class).getType(); @Override public JsonElement serialize(JavaManifest src, Type typeOfSrc, JsonSerializationContext context) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index 6223c6da8..009cf6b40 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.setting; -import com.google.gson.reflect.TypeToken; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.property.ObjectProperty; @@ -55,6 +54,8 @@ import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; import static org.jackhuang.hmcl.util.Lang.immutableListOf; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -171,14 +172,11 @@ public final class Accounts { config().getAccountStorages().setAll(portable); } - @SuppressWarnings("unchecked") private static void loadGlobalAccountStorages() { Path globalAccountsFile = Metadata.HMCL_DIRECTORY.resolve("accounts.json"); if (Files.exists(globalAccountsFile)) { try (Reader reader = Files.newBufferedReader(globalAccountsFile)) { - globalAccountStorages.setAll((List>) - Config.CONFIG_GSON.fromJson(reader, new TypeToken>>() { - }.getType())); + globalAccountStorages.setAll(Config.CONFIG_GSON.fromJson(reader, listTypeOf(mapTypeOf(Object.class, Object.class)))); } catch (Throwable e) { LOG.warning("Failed to load global accounts", e); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java index 33f7935e3..75223967c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.main; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import javafx.geometry.Insets; import javafx.scene.control.ScrollPane; import javafx.scene.layout.VBox; @@ -34,6 +33,7 @@ import org.jackhuang.hmcl.util.io.HttpRequest; import java.util.Collections; import java.util.List; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class HelpPage extends SpinnerPane { @@ -63,8 +63,7 @@ public class HelpPage extends SpinnerPane { private void loadHelp() { showSpinner(); - Task.>supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(new TypeToken>() { - }.getType())) + Task.supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(listTypeOf(HelpCategory.class))) .thenAcceptAsync(Schedulers.javafx(), helpCategories -> { for (HelpCategory category : helpCategories) { ComponentList categoryPane = new ComponentList(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java index 79d21fbb4..82ccd9fc3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.util; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -34,6 +33,7 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** @@ -51,9 +51,7 @@ public final class NativePatcher { return natives.computeIfAbsent(platform, p -> { //noinspection ConstantConditions try (Reader reader = new InputStreamReader(NativePatcher.class.getResourceAsStream("/assets/natives.json"), StandardCharsets.UTF_8)) { - Map> natives = JsonUtils.GSON.fromJson(reader, new TypeToken>>() { - }.getType()); - + Map> natives = JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, mapTypeOf(String.class, Library.class))); return natives.getOrDefault(p.toString(), Collections.emptyMap()); } catch (IOException e) { LOG.warning("Failed to load native library list", e); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java index cde4fcda0..79efb3848 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java @@ -41,10 +41,9 @@ */ package org.jackhuang.hmcl.util; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.ui.SwingUtils; +import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.ChecksumMismatchException; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.JarUtils; @@ -68,6 +67,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toSet; import static org.jackhuang.hmcl.Metadata.HMCL_DIRECTORY; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -104,11 +105,11 @@ public final class SelfDependencyPatcher { private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies").resolve(Platform.getPlatform().toString()).resolve("openjfx"); static List readDependencies() { - ArrayList dependencies; + List dependencies; //noinspection ConstantConditions try (Reader reader = new InputStreamReader(SelfDependencyPatcher.class.getResourceAsStream(DEPENDENCIES_LIST_FILE), UTF_8)) { - Map> allDependencies = - new Gson().fromJson(reader, new TypeToken>>(){}.getType()); + Map> allDependencies = + JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, listTypeOf(DependencyDescriptor.class))); dependencies = allDependencies.get(Platform.getPlatform().toString()); } catch (IOException e) { throw new UncheckedIOException(e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java index f3deed3d4..7e722fa6b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.auth.offline; -import com.google.gson.reflect.TypeToken; import org.glavo.png.javafx.PNGJavaFXUtils; import org.jackhuang.hmcl.auth.yggdrasil.GameProfile; import org.jackhuang.hmcl.auth.yggdrasil.TextureModel; @@ -38,6 +37,7 @@ import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public class YggdrasilServer extends HttpServer { @@ -81,8 +81,7 @@ public class YggdrasilServer extends HttpServer { } private Response profiles(Request request) throws IOException { - List names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), new TypeToken>() { - }.getType()); + List names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), listTypeOf(String.class)); return ok(names.stream().distinct() .map(this::findCharacterByName) .flatMap(Lang::toStream) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java index 9837bc679..8440f70b7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.download.fabric; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -25,13 +24,13 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class FabricVersionList extends VersionList { private final DownloadProvider downloadProvider; @@ -69,8 +68,8 @@ public final class FabricVersionList extends VersionList { private List getGameVersions(String metaUrl) throws IOException { String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); - return JsonUtils.GSON.>fromJson(json, new TypeToken>() { - }.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList()); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::getVersion).collect(Collectors.toList()); } private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index ef37315ee..c0d0fdc8b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.forge; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Lang; @@ -40,6 +39,7 @@ import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public final class ForgeBMCLVersionList extends VersionList { @@ -87,11 +87,9 @@ public final class ForgeBMCLVersionList extends VersionList String lookupVersion = toLookupVersion(gameVersion); return CompletableFuture.completedFuture(null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).>getJson(new TypeToken>() { - }.getType()))) + .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).getJson(listTypeOf(ForgeVersion.class)))) .thenAcceptAsync(forgeVersions -> { lock.writeLock().lock(); - try { versions.clear(gameVersion); if (forgeVersions == null) return; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java index e54966467..cd1cf741c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.download.java.mojang; import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.game.DownloadInfo; import org.jackhuang.hmcl.util.Immutable; @@ -27,6 +26,9 @@ import java.lang.reflect.Type; import java.util.List; import java.util.Map; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; + @JsonAdapter(MojangJavaDownloads.Adapter.class) public class MojangJavaDownloads { @@ -49,8 +51,7 @@ public class MojangJavaDownloads { @Override public MojangJavaDownloads deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return new MojangJavaDownloads(context.deserialize(json, new TypeToken>>>() { - }.getType())); + return new MojangJavaDownloads(context.deserialize(json, mapTypeOf(String.class, mapTypeOf(String.class, listTypeOf(JavaDownload.class))).getType())); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java index d1d8c8340..a00f2eaeb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java @@ -19,18 +19,17 @@ package org.jackhuang.hmcl.download.neoforge; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.io.HttpRequest; import java.util.Collections; -import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class NeoForgeBMCLVersionList extends VersionList { private final String apiRoot; @@ -68,8 +67,7 @@ public final class NeoForgeBMCLVersionList extends VersionList refreshAsync(String gameVersion) { return CompletableFuture.completedFuture((Void) null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).>getJson(new TypeToken>() { - }.getType()))) + .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).getJson(listTypeOf(NeoForgeVersion.class)))) .thenAcceptAsync(neoForgeVersions -> { lock.writeLock().lock(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java index af5f8b754..5e9c36823 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.optifine; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.HttpRequest; @@ -26,10 +25,11 @@ import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * @author huangyuhui */ @@ -72,8 +72,7 @@ public final class OptiFineBMCLVersionList extends VersionList refreshAsync() { - return HttpRequest.GET(apiRoot + "/optifine/versionlist").>getJsonAsync(new TypeToken>() { - }.getType()).thenAcceptAsync(root -> { + return HttpRequest.GET(apiRoot + "/optifine/versionlist").getJsonAsync(listTypeOf(OptiFineVersion.class)).thenAcceptAsync(root -> { lock.writeLock().lock(); try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java index bc7bf8804..f7d6a2e6b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.download.quilt; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -25,13 +24,13 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class QuiltVersionList extends VersionList { private final DownloadProvider downloadProvider; @@ -69,8 +68,8 @@ public final class QuiltVersionList extends VersionList { private List getGameVersions(String metaUrl) throws IOException { String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); - return JsonUtils.GSON.>fromJson(json, new TypeToken>() { - }.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList()); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::getVersion).collect(Collectors.toList()); } private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index 115b79c33..21c63c60e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.VersionJsonSaveTask; import org.jackhuang.hmcl.event.*; @@ -499,18 +498,16 @@ public class DefaultGameRepository implements GameRepository { * read modpack configuration for a version. * * @param version version installed as modpack - * @param manifest type of ModpackConfiguration * @return modpack configuration object, or null if this version is not a modpack. * @throws VersionNotFoundException if version does not exist. * @throws IOException if an i/o error occurs. */ @Nullable - public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { + public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { if (!hasVersion(version)) throw new VersionNotFoundException(version); File file = getModpackConfiguration(version); if (!file.exists()) return null; - return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>() { - }.getType()); + return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class); } public boolean isModpack(String version) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java index d812258c0..b55937f15 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java @@ -19,13 +19,14 @@ package org.jackhuang.hmcl.game; import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.Immutable; import java.lang.reflect.Type; import java.util.*; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * * @author huangyuhui @@ -86,8 +87,7 @@ public class RuledArgument implements Argument { public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject obj = json.getAsJsonObject(); - List rules = context.deserialize(obj.get("rules"), new TypeToken>() { - }.getType()); + List rules = context.deserialize(obj.get("rules"), listTypeOf(CompatibilityRule.class).getType()); JsonElement valuesElement; if (obj.has("values")) { @@ -102,8 +102,7 @@ public class RuledArgument implements Argument { if (valuesElement.isJsonPrimitive()) { values = Collections.singletonList(valuesElement.getAsString()); } else { - values = context.deserialize(valuesElement, new TypeToken>() { - }.getType()); + values = context.deserialize(valuesElement, listTypeOf(String.class).getType()); } return new RuledArgument(rules, values); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java index e936db80d..743f93045 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.mod; import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; import org.jetbrains.annotations.Nullable; @@ -29,6 +30,11 @@ import java.util.List; @Immutable public final class ModpackConfiguration implements Validation { + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class clazz) { + return (TypeToken>) TypeToken.getParameterized(ModpackConfiguration.class, clazz); + } + private final T manifest; private final String type; private final String name; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java index 5bda19051..3913ef7f0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java @@ -38,6 +38,7 @@ import java.util.stream.Stream; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class CurseForgeRemoteModRepository implements RemoteModRepository { @@ -113,8 +114,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository pair("index", Integer.toString(pageOffset * pageSize)), pair("pageSize", Integer.toString(pageSize))) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.class))); if (searchFilter.isEmpty()) { return new SearchResult(response.getData().stream().map(CurseAddon::toMod), calculateTotalPages(response, pageSize)); } @@ -163,8 +163,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository Response response = HttpRequest.POST(PREFIX + "/v1/fingerprints/432") .json(mapOf(pair("fingerprints", Collections.singletonList(hash)))) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(FingerprintMatchesResult.class)); if (response.getData().getExactMatches() == null || response.getData().getExactMatches().isEmpty()) { return Optional.empty(); @@ -177,8 +176,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository public RemoteMod getModById(String id) throws IOException { Response response = HttpRequest.GET(PREFIX + "/v1/mods/" + id) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(CurseAddon.class)); return response.data.toMod(); } @@ -186,8 +184,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository public RemoteMod.File getModFile(String modId, String fileId) throws IOException { Response response = HttpRequest.GET(String.format("%s/v1/mods/%s/files/%s", PREFIX, modId, fileId)) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(CurseAddon.LatestFile.class)); return response.getData().toVersion().getFile(); } @@ -196,16 +193,14 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository Response> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id + "/files", pair("pageSize", "10000")) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.LatestFile.class))); return response.getData().stream().map(CurseAddon.LatestFile::toVersion); } public List getCategoriesImpl() throws IOException { Response> categories = HttpRequest.GET(PREFIX + "/v1/categories", pair("gameId", "432")) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.Category.class))); return reorganizeCategories(categories.getData(), section); } @@ -284,6 +279,17 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository } public static class Response { + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType); + } + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(TypeToken responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType.getType()); + } + private final T data; private final Pagination pagination; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java index 6796cf330..b40618c68 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.curse; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -99,8 +98,7 @@ public final class CurseInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(CurseManifest.class)); if (!CurseModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java index 93be7eb00..1df44c1ea 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.mod.ModManager; @@ -88,8 +87,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask { if (configuration == null) { // Load configuration from disk try { - configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), new TypeToken>() { - }.getType()); + configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); } catch (IOException | JsonParseException e) { throw new IOException("Malformed modpack configuration"); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java index 3cee33c60..7bd81ae52 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -80,8 +79,7 @@ public class McbbsModpackLocalInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!McbbsModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java index 2deaf7233..6a7ab0728 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.jackhuang.hmcl.download.DefaultDependencyManager; @@ -56,8 +55,7 @@ public final class McbbsModpackProvider implements ModpackProvider { @Override public void injectLaunchOptions(String modpackConfigurationJson, LaunchOptions.Builder builder) { - ModpackConfiguration config = JsonUtils.GSON.fromJson(modpackConfigurationJson, new TypeToken>() { - }.getType()); + ModpackConfiguration config = JsonUtils.GSON.fromJson(modpackConfigurationJson, ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!getName().equals(config.getType())) { throw new IllegalArgumentException("Incorrect manifest type, actual=" + config.getType() + ", expected=" + getName()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java index 3e970980e..4550273d8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -66,8 +65,7 @@ public class McbbsModpackRemoteInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!MODPACK_TYPE.equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java index 067c5b8c2..78b673ece 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.mod.modinfo; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.mod.LocalModFile; import org.jackhuang.hmcl.mod.ModLoaderType; import org.jackhuang.hmcl.mod.ModManager; @@ -34,6 +33,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * * @author huangyuhui @@ -125,9 +126,7 @@ public final class ForgeOldModMetadata { Path mcmod = fs.getPath("mcmod.info"); if (Files.notExists(mcmod)) throw new IOException("File " + modFile + " is not a Forge mod."); - List modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), - new TypeToken>() { - }.getType()); + List modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), listTypeOf(ForgeOldModMetadata.class)); if (modList == null || modList.isEmpty()) throw new IOException("Mod " + modFile + " `mcmod.info` is malformed.."); ForgeOldModMetadata metadata = modList.get(0); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java index 64ccc7c2f..b796413d4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java @@ -18,12 +18,10 @@ package org.jackhuang.hmcl.mod.modrinth; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.mod.*; -import org.jackhuang.hmcl.mod.curse.CurseManifest; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -95,8 +93,7 @@ public class ModrinthInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ModrinthManifest.class)); if (!ModrinthModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Modrinth modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java index d20a542ac..c257a3881 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java @@ -39,6 +39,7 @@ import java.util.stream.Stream; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class ModrinthRemoteModRepository implements RemoteModRepository { public static final ModrinthRemoteModRepository MODS = new ModrinthRemoteModRepository("mod"); @@ -93,8 +94,7 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository { pair("index", convertSortType(sort)) ); Response response = HttpRequest.GET(NetworkUtils.withQuery(PREFIX + "/v2/search", query)) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(ProjectSearchResult.class)); return new SearchResult(response.getHits().stream().map(ProjectSearchResult::toMod), (int) Math.ceil((double) response.totalHits / pageSize)); } @@ -132,13 +132,12 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository { public Stream getRemoteVersionsById(String id) throws IOException { id = StringUtils.removePrefix(id, "local-"); List versions = HttpRequest.GET(PREFIX + "/v2/project/" + id + "/version") - .getJson(new TypeToken>() { - }.getType()); + .getJson(listTypeOf(ProjectVersion.class)); return versions.stream().map(ProjectVersion::toVersion).flatMap(Lang::toStream); } public List getCategoriesImpl() throws IOException { - List categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(new TypeToken>() {}.getType()); + List categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(listTypeOf(Category.class)); return categories.stream().filter(category -> category.getProjectType().equals(projectType)).collect(Collectors.toList()); } @@ -696,6 +695,12 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository { } public static class Response { + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType); + } + private final int offset; private final int limit; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 017f72244..973da7726 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.multimc; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.Arguments; @@ -128,8 +127,7 @@ public final class MultiMCModpackInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(MultiMCInstanceConfiguration.class)); if (!MultiMCModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a MultiMC modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java index 9f7ddfb95..3130f24e0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -66,8 +65,7 @@ public class ServerModpackCompletionTask extends Task { try { File manifestFile = repository.getModpackConfiguration(version); if (manifestFile.exists()) { - this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), new TypeToken>() { - }.getType()); + this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), ModpackConfiguration.typeOf(ServerModpackManifest.class)); } } catch (Exception e) { LOG.warning("Unable to read Server modpack manifest.json", e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java index b23753f30..fec92572d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -72,8 +71,7 @@ public class ServerModpackLocalInstallTask extends Task { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class)); if (!ServerModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java index eddafb81a..e6bb9b556 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -63,11 +62,10 @@ public class ServerModpackRemoteInstallTask extends Task { repository.removeVersionFromDisk(name); }); - ModpackConfiguration config = null; + ModpackConfiguration config; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class)); if (!MODPACK_TYPE.equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java index 89082d4cc..223ff4d63 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java @@ -19,9 +19,7 @@ package org.jackhuang.hmcl.util; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; -import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; @@ -46,6 +44,7 @@ import java.util.function.BiFunction; import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.jackhuang.hmcl.util.gson.JsonUtils.*; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public class CacheRepository { @@ -68,7 +67,7 @@ public class CacheRepository { } if (Files.isRegularFile(indexFile)) { - ETagIndex raw = JsonUtils.GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class); + ETagIndex raw = GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class); if (raw == null) index = new HashMap<>(); else @@ -289,10 +288,10 @@ public class CacheRepository { try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)) { FileLock lock = channel.lock(); try { - ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class); + ETagIndex indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class); Map newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values()); channel.truncate(0); - ByteBuffer writeTo = ByteBuffer.wrap(JsonUtils.GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8)); + ByteBuffer writeTo = ByteBuffer.wrap(GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8)); while (writeTo.hasRemaining()) { if (channel.write(writeTo) == 0) { throw new IOException("No value is written"); @@ -412,8 +411,7 @@ public class CacheRepository { try { indexFile = cacheDirectory.resolve(name + ".json"); if (Files.isRegularFile(indexFile)) { - joinEntries(JsonUtils.fromNonNullJson(FileUtils.readText(indexFile), new TypeToken>() { - }.getType())); + joinEntries(fromNonNullJson(FileUtils.readText(indexFile), mapTypeOf(String.class, Object.class))); } } catch (IOException | JsonParseException e) { LOG.warning("Unable to read storage {" + name + "} file"); @@ -426,12 +424,11 @@ public class CacheRepository { try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.READ, StandardOpenOption.WRITE)) { FileLock lock = channel.lock(); try { - Map indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), new TypeToken>() { - }.getType()); + Map indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), mapTypeOf(String.class, Object.class)); if (indexOnDisk == null) indexOnDisk = new HashMap<>(); indexOnDisk.putAll(storage); channel.truncate(0); - channel.write(ByteBuffer.wrap(JsonUtils.GSON.toJson(storage).getBytes(UTF_8))); + channel.write(ByteBuffer.wrap(GSON.toJson(storage).getBytes(UTF_8))); this.storage = indexOnDisk; } finally { lock.release(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java index bddf8d3f4..bfd07080a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java @@ -27,14 +27,16 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.util.List; +import java.util.Map; import java.util.UUID; /** * @author yushijinhun */ +@SuppressWarnings("unchecked") public final class JsonUtils { public static final Gson GSON = defaultGsonBuilder().create(); @@ -48,13 +50,29 @@ public final class JsonUtils { private JsonUtils() { } + public static TypeToken> listTypeOf(Class elementType) { + return (TypeToken>) TypeToken.getParameterized(List.class, elementType); + } + + public static TypeToken> listTypeOf(TypeToken elementType) { + return (TypeToken>) TypeToken.getParameterized(List.class, elementType.getType()); + } + + public static TypeToken> mapTypeOf(Class keyType, Class valueType) { + return (TypeToken>) TypeToken.getParameterized(Map.class, keyType, valueType); + } + + public static TypeToken> mapTypeOf(Class keyType, TypeToken valueType) { + return (TypeToken>) TypeToken.getParameterized(Map.class, keyType, valueType.getType()); + } + public static T fromJsonFully(InputStream json, Class classOfT) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { return GSON.fromJson(reader, classOfT); } } - public static T fromJsonFully(InputStream json, Type type) throws IOException, JsonParseException { + public static T fromJsonFully(InputStream json, TypeToken type) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { return GSON.fromJson(reader, type); } @@ -67,13 +85,6 @@ public final class JsonUtils { return parsed; } - public static T fromNonNullJson(String json, Type type) throws JsonParseException { - T parsed = GSON.fromJson(json, type); - if (parsed == null) - throw new JsonParseException("Json object cannot be null."); - return parsed; - } - public static T fromNonNullJson(String json, TypeToken type) throws JsonParseException { T parsed = GSON.fromJson(json, type); if (parsed == null) @@ -90,7 +101,7 @@ public final class JsonUtils { } } - public static T fromNonNullJsonFully(InputStream json, Type type) throws IOException, JsonParseException { + public static T fromNonNullJsonFully(InputStream json, TypeToken type) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { T parsed = GSON.fromJson(reader, type); if (parsed == null) @@ -107,7 +118,7 @@ public final class JsonUtils { } } - public static T fromMaybeMalformedJson(String json, Type type) throws JsonParseException { + public static T fromMaybeMalformedJson(String json, TypeToken type) throws JsonParseException { try { return GSON.fromJson(json, type); } catch (JsonSyntaxException e) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java index 29dd6d504..4fb0fead5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.util.io; import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.function.ExceptionalBiConsumer; @@ -26,7 +27,6 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import java.io.IOException; import java.io.OutputStream; -import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -101,7 +101,7 @@ public abstract class HttpRequest { return JsonUtils.fromNonNullJson(getString(), typeOfT); } - public T getJson(Type type) throws IOException, JsonParseException { + public T getJson(TypeToken type) throws IOException, JsonParseException { return JsonUtils.fromNonNullJson(getString(), type); } @@ -109,7 +109,7 @@ public abstract class HttpRequest { return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, typeOfT)); } - public CompletableFuture getJsonAsync(Type type) { + public CompletableFuture getJsonAsync(TypeToken type) { return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type)); } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java new file mode 100644 index 000000000..a3f0aaeed --- /dev/null +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java @@ -0,0 +1,42 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.util.gson; + +import com.google.gson.reflect.TypeToken; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Glavo + */ +public class JsonUtilsTest { + + @Test + public void testGetTypeToken() { + assertEquals(new TypeToken>(){}, listTypeOf(Object.class)); + assertEquals(new TypeToken>(){}, listTypeOf(String.class)); + assertEquals(new TypeToken>>(){}, listTypeOf(mapTypeOf(String.class, Integer.class))); + assertEquals(new TypeToken>>>(){}, listTypeOf(mapTypeOf(String.class, listTypeOf(Integer.class)))); + } +}