Fix getImplementationVersion returning null on Java 9.

This commit is contained in:
huanghongxun
2018-08-08 10:02:34 +08:00
parent 09730d74e0
commit a2b74b8e78
7 changed files with 123 additions and 75 deletions

View File

@@ -17,7 +17,7 @@
*/ */
package org.jackhuang.hmcl; package org.jackhuang.hmcl;
import java.util.Optional; import org.jackhuang.hmcl.util.JarUtils;
/** /**
* Stores metadata about this application. * Stores metadata about this application.
@@ -25,7 +25,7 @@ import java.util.Optional;
public final class Metadata { public final class Metadata {
private 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 NAME = "HMCL";
public static final String TITLE = NAME + " " + VERSION; public static final String TITLE = NAME + " " + VERSION;

View File

@@ -17,7 +17,11 @@
*/ */
package org.jackhuang.hmcl.upgrade; 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.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
@@ -25,15 +29,11 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.Optional; import java.util.Optional;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import java.util.jar.Pack200; import java.util.jar.Pack200;
import java.util.logging.Level; import java.util.logging.Level;
import org.jackhuang.hmcl.Launcher; import static org.jackhuang.hmcl.util.Logging.LOG;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.tukaani.xz.XZInputStream;
/** /**
* A class used to manage the local HMCL repository. * A class used to manage the local HMCL repository.
@@ -52,15 +52,9 @@ final class LocalRepository {
if (!Files.isRegularFile(localStorage)) { if (!Files.isRegularFile(localStorage)) {
return Optional.empty(); return Optional.empty();
} }
try (JarFile jar = new JarFile(localStorage.toFile())) { return Optional.of(localStorage)
Attributes attributes = jar.getManifest().getMainAttributes(); .flatMap(JarUtils::getImplementationVersion)
String version = Optional.ofNullable(attributes.getValue("Implementation-Version")) .map(version -> new LocalVersion(version, localStorage));
.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();
}
} }
private static void writeToStorage(Path source, boolean checkHeaders) throws IOException { private static void writeToStorage(Path source, boolean checkHeaders) throws IOException {

View File

@@ -17,47 +17,16 @@
*/ */
package org.jackhuang.hmcl.upgrade; 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.Metadata;
import org.jackhuang.hmcl.util.JarUtils;
import java.nio.file.Path;
import java.util.Optional;
class LocalVersion { class LocalVersion {
public static Optional<LocalVersion> current() { public static Optional<LocalVersion> current() {
CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource(); return JarUtils.thisJar().map(path -> new LocalVersion(Metadata.VERSION, path));
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));
} }
private String version; private String version;

View File

@@ -73,19 +73,17 @@ public final class GameVersion {
if (file == null || !file.exists() || !file.isFile() || !file.canRead()) if (file == null || !file.exists() || !file.isFile() || !file.canRead())
return Optional.empty(); return Optional.empty();
try { try (FileSystem gameJar = CompressingUtils.createReadOnlyZipFileSystem(file.toPath())) {
try (FileSystem gameJar = CompressingUtils.createReadOnlyZipFileSystem(file.toPath())) { Path minecraft = gameJar.getPath("net/minecraft/client/Minecraft.class");
Path minecraft = gameJar.getPath("net/minecraft/client/Minecraft.class"); if (Files.exists(minecraft)) {
if (Files.exists(minecraft)) { Optional<String> result = getVersionOfClassMinecraft(Files.readAllBytes(minecraft));
Optional<String> result = getVersionOfClassMinecraft(Files.readAllBytes(minecraft)); if (result.isPresent())
if (result.isPresent()) return result;
return result;
}
Path minecraftServer = gameJar.getPath("net/minecraft/server/MinecraftServer.class");
if (Files.exists(minecraftServer))
return getVersionFromClassMinecraftServer(Files.readAllBytes(minecraftServer));
return Optional.empty();
} }
Path minecraftServer = gameJar.getPath("net/minecraft/server/MinecraftServer.class");
if (Files.exists(minecraftServer))
return getVersionFromClassMinecraftServer(Files.readAllBytes(minecraftServer));
return Optional.empty();
} catch (IOException e) { } catch (IOException e) {
return Optional.empty(); return Optional.empty();
} }

View File

@@ -49,17 +49,15 @@ final class StreamPump implements Runnable {
@Override @Override
public void run() { public void run() {
try { try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Constants.SYSTEM_CHARSET))) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Constants.SYSTEM_CHARSET))) { String line;
String line; while ((line = bufferedReader.readLine()) != null) {
while ((line = bufferedReader.readLine()) != null) { if (Thread.currentThread().isInterrupted()) {
if (Thread.currentThread().isInterrupted()) { Thread.currentThread().interrupt();
Thread.currentThread().interrupt(); break;
break;
}
callback.accept(line);
} }
callback.accept(line);
} }
} catch (IOException e) { } catch (IOException e) {
Logging.LOG.log(Level.SEVERE, "An error occurred when reading stream", e); Logging.LOG.log(Level.SEVERE, "An error occurred when reading stream", e);

View File

@@ -0,0 +1,72 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* 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<Path> 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<Manifest> getManifest(Path jar) {
try (JarFile file = new JarFile(jar.toFile())) {
return Optional.ofNullable(file.getManifest());
} catch (IOException e) {
return Optional.empty();
}
}
public static Optional<String> getImplementationVersion(Path jar) {
return Optional.of(jar).flatMap(JarUtils::getManifest)
.flatMap(manifest -> Optional.ofNullable(manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION)));
}
}

View File

@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* 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; package org.jackhuang.hmcl.util;
public class ToStringBuilder { public class ToStringBuilder {