From a2b74b8e783fd71f5e2c454b06199e83cb6634da Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 8 Aug 2018 10:02:34 +0800 Subject: [PATCH] Fix getImplementationVersion returning null on Java 9. --- .../java/org/jackhuang/hmcl/Metadata.java | 4 +- .../hmcl/upgrade/LocalRepository.java | 24 +++---- .../jackhuang/hmcl/upgrade/LocalVersion.java | 41 ++--------- .../org/jackhuang/hmcl/game/GameVersion.java | 22 +++--- .../org/jackhuang/hmcl/launch/StreamPump.java | 18 +++-- .../org/jackhuang/hmcl/util/JarUtils.java | 72 +++++++++++++++++++ .../jackhuang/hmcl/util/ToStringBuilder.java | 17 +++++ 7 files changed, 123 insertions(+), 75 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/JarUtils.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java b/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java index 4ece46b5c..b9ce083ea 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl; -import java.util.Optional; +import org.jackhuang.hmcl.util.JarUtils; /** * Stores metadata about this application. @@ -25,7 +25,7 @@ import java.util.Optional; public final class Metadata { private Metadata() {} - public static final String VERSION = System.getProperty("hmcl.version.override", Optional.ofNullable(Metadata.class.getPackage().getImplementationVersion()).orElse("@develop@")); + public static final String VERSION = System.getProperty("hmcl.version.override", JarUtils.thisJar().flatMap(JarUtils::getImplementationVersion).orElse("@develop@")); public static final String NAME = "HMCL"; public static final String TITLE = NAME + " " + VERSION; 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 19616cb2a..9c8080ec6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalRepository.java @@ -17,7 +17,11 @@ */ package org.jackhuang.hmcl.upgrade; -import static org.jackhuang.hmcl.util.Logging.LOG; +import org.jackhuang.hmcl.Launcher; +import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.util.JarUtils; +import org.tukaani.xz.XZInputStream; + import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -25,15 +29,11 @@ import java.nio.file.Files; import java.nio.file.Path; 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 org.jackhuang.hmcl.Launcher; -import org.jackhuang.hmcl.task.FileDownloadTask; -import org.tukaani.xz.XZInputStream; +import static org.jackhuang.hmcl.util.Logging.LOG; /** * A class used to manage the local HMCL repository. @@ -52,15 +52,9 @@ final class LocalRepository { if (!Files.isRegularFile(localStorage)) { return Optional.empty(); } - try (JarFile jar = new JarFile(localStorage.toFile())) { - Attributes attributes = jar.getManifest().getMainAttributes(); - String version = Optional.ofNullable(attributes.getValue("Implementation-Version")) - .orElseThrow(() -> new IOException("Missing Implementation-Version")); - return Optional.of(new LocalVersion(version, localStorage)); - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to read HMCL jar: " + localStorage, e); - return Optional.empty(); - } + return Optional.of(localStorage) + .flatMap(JarUtils::getImplementationVersion) + .map(version -> new LocalVersion(version, localStorage)); } private static void writeToStorage(Path source, boolean checkHeaders) throws IOException { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalVersion.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalVersion.java index b1f613742..ada1acff8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalVersion.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/LocalVersion.java @@ -17,47 +17,16 @@ */ package org.jackhuang.hmcl.upgrade; -import static org.jackhuang.hmcl.util.Logging.LOG; - -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.CodeSource; -import java.util.Optional; -import java.util.logging.Level; - -import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.Metadata; +import org.jackhuang.hmcl.util.JarUtils; + +import java.nio.file.Path; +import java.util.Optional; class LocalVersion { public static Optional current() { - CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource(); - if (codeSource == null) { - return Optional.empty(); - } - - URL url = codeSource.getLocation(); - if (url == null) { - return Optional.empty(); - } - - Path path; - try { - path = Paths.get(url.toURI()); - } catch (FileSystemNotFoundException | IllegalArgumentException | URISyntaxException e) { - LOG.log(Level.WARNING, "Invalid path: " + url, e); - return Optional.empty(); - } - - if (!Files.isRegularFile(path)) { - return Optional.empty(); - } - - return Optional.of(new LocalVersion(Metadata.VERSION, path)); + return JarUtils.thisJar().map(path -> new LocalVersion(Metadata.VERSION, path)); } private String version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java index ea73afbf5..3329e67d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java @@ -73,19 +73,17 @@ public final class GameVersion { if (file == null || !file.exists() || !file.isFile() || !file.canRead()) return Optional.empty(); - try { - try (FileSystem gameJar = CompressingUtils.createReadOnlyZipFileSystem(file.toPath())) { - Path minecraft = gameJar.getPath("net/minecraft/client/Minecraft.class"); - if (Files.exists(minecraft)) { - Optional result = getVersionOfClassMinecraft(Files.readAllBytes(minecraft)); - if (result.isPresent()) - return result; - } - Path minecraftServer = gameJar.getPath("net/minecraft/server/MinecraftServer.class"); - if (Files.exists(minecraftServer)) - return getVersionFromClassMinecraftServer(Files.readAllBytes(minecraftServer)); - return Optional.empty(); + try (FileSystem gameJar = CompressingUtils.createReadOnlyZipFileSystem(file.toPath())) { + Path minecraft = gameJar.getPath("net/minecraft/client/Minecraft.class"); + if (Files.exists(minecraft)) { + Optional result = getVersionOfClassMinecraft(Files.readAllBytes(minecraft)); + if (result.isPresent()) + return result; } + Path minecraftServer = gameJar.getPath("net/minecraft/server/MinecraftServer.class"); + if (Files.exists(minecraftServer)) + return getVersionFromClassMinecraftServer(Files.readAllBytes(minecraftServer)); + return Optional.empty(); } catch (IOException e) { return Optional.empty(); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/StreamPump.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/StreamPump.java index ed193b7e2..be692dca1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/StreamPump.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/StreamPump.java @@ -49,17 +49,15 @@ final class StreamPump implements Runnable { @Override public void run() { - try { - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Constants.SYSTEM_CHARSET))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - if (Thread.currentThread().isInterrupted()) { - Thread.currentThread().interrupt(); - break; - } - - callback.accept(line); + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Constants.SYSTEM_CHARSET))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + if (Thread.currentThread().isInterrupted()) { + Thread.currentThread().interrupt(); + break; } + + callback.accept(line); } } catch (IOException e) { Logging.LOG.log(Level.SEVERE, "An error occurred when reading stream", e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/JarUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/JarUtils.java new file mode 100644 index 000000000..3147c39be --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/JarUtils.java @@ -0,0 +1,72 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * 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 {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.util; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.FileSystemNotFoundException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.CodeSource; +import java.util.Optional; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public final class JarUtils { + + public static Optional thisJar() { + CodeSource codeSource = FileUtils.class.getProtectionDomain().getCodeSource(); + if (codeSource == null) { + return Optional.empty(); + } + + URL url = codeSource.getLocation(); + if (url == null) { + return Optional.empty(); + } + + Path path; + try { + path = Paths.get(url.toURI()); + } catch (FileSystemNotFoundException | IllegalArgumentException | URISyntaxException e) { + return Optional.empty(); + } + + if (!Files.isRegularFile(path)) { + return Optional.empty(); + } + + return Optional.of(path); + } + + public static Optional getManifest(Path jar) { + try (JarFile file = new JarFile(jar.toFile())) { + return Optional.ofNullable(file.getManifest()); + } catch (IOException e) { + return Optional.empty(); + } + } + + public static Optional getImplementationVersion(Path jar) { + return Optional.of(jar).flatMap(JarUtils::getManifest) + .flatMap(manifest -> Optional.ofNullable(manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION))); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ToStringBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ToStringBuilder.java index 335a45d67..a9b923739 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ToStringBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ToStringBuilder.java @@ -1,3 +1,20 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * 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 {http://www.gnu.org/licenses/}. + */ package org.jackhuang.hmcl.util; public class ToStringBuilder {