Allow specifying authlib-injector path

This commit is contained in:
yushijinhun 2018-11-24 20:32:22 +08:00
parent bb0c11fa12
commit ea5b31d537
No known key found for this signature in database
GPG Key ID: 5BC167F73EA558E4
8 changed files with 130 additions and 36 deletions

View File

@ -29,8 +29,10 @@ import org.jackhuang.hmcl.auth.AccountFactory;
import org.jackhuang.hmcl.auth.AuthenticationException;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccountFactory;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorArtifactProvider;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloader;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.authlibinjector.SimpleAuthlibInjectorArtifactProvider;
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory;
import org.jackhuang.hmcl.auth.yggdrasil.MojangYggdrasilProvider;
@ -39,6 +41,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory;
import org.jackhuang.hmcl.task.Schedulers;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@ -61,9 +64,7 @@ public final class Accounts {
public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE;
public static final YggdrasilAccountFactory FACTORY_YGGDRASIL = new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE);
public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(
new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider),
Accounts::getOrCreateAuthlibInjectorServer);
public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(createAuthlibInjectorArtifactProvider(), Accounts::getOrCreateAuthlibInjectorServer);
// ==== login type / account factory mapping ====
private static final Map<String, AccountFactory<?>> type2factory = new HashMap<>();
@ -240,6 +241,16 @@ public final class Accounts {
}
// ==== authlib-injector ====
private static AuthlibInjectorArtifactProvider createAuthlibInjectorArtifactProvider() {
String authlibinjectorLocation = System.getProperty("hmcl.authlibinjector.location");
if (authlibinjectorLocation == null) {
return new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider);
} else {
LOG.info("Using specified authlib-injector: " + authlibinjectorLocation);
return new SimpleAuthlibInjectorArtifactProvider(Paths.get(authlibinjectorLocation));
}
}
private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) {
return config().getAuthlibInjectorServers().stream()
.filter(server -> url.equals(server.getUrl()))

View File

@ -36,9 +36,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
public class AuthlibInjectorAccount extends YggdrasilAccount {
private AuthlibInjectorServer server;
private AuthlibInjectorDownloader downloader;
private AuthlibInjectorArtifactProvider downloader;
protected AuthlibInjectorAccount(YggdrasilService service, AuthlibInjectorServer server, AuthlibInjectorDownloader downloader, String username, UUID characterUUID, YggdrasilSession session) {
protected AuthlibInjectorAccount(YggdrasilService service, AuthlibInjectorServer server, AuthlibInjectorArtifactProvider downloader, String username, UUID characterUUID, YggdrasilSession session) {
super(service, username, characterUUID, session);
this.downloader = downloader;

View File

@ -29,13 +29,13 @@ import java.util.function.Function;
import static org.jackhuang.hmcl.util.Lang.tryCast;
public class AuthlibInjectorAccountFactory extends AccountFactory<AuthlibInjectorAccount> {
private AuthlibInjectorDownloader downloader;
private AuthlibInjectorArtifactProvider downloader;
private Function<String, AuthlibInjectorServer> serverLookup;
/**
* @param serverLookup a function that looks up {@link AuthlibInjectorServer} by url
*/
public AuthlibInjectorAccountFactory(AuthlibInjectorDownloader downloader, Function<String, AuthlibInjectorServer> serverLookup) {
public AuthlibInjectorAccountFactory(AuthlibInjectorArtifactProvider downloader, Function<String, AuthlibInjectorServer> serverLookup) {
this.downloader = downloader;
this.serverLookup = serverLookup;
}

View File

@ -17,10 +17,39 @@
*/
package org.jackhuang.hmcl.auth.authlibinjector;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
public class AuthlibInjectorArtifactInfo {
public static AuthlibInjectorArtifactInfo from(Path location) throws IOException {
try (JarFile jarFile = new JarFile(location.toFile())) {
Attributes attributes = jarFile.getManifest().getMainAttributes();
String title = Optional.ofNullable(attributes.getValue("Implementation-Title"))
.orElseThrow(() -> new IOException("Missing Implementation-Title"));
if (!"authlib-injector".equals(title)) {
throw new IOException("Bad Implementation-Title");
}
String version = Optional.ofNullable(attributes.getValue("Implementation-Version"))
.orElseThrow(() -> new IOException("Missing Implementation-Version"));
int buildNumber;
try {
buildNumber = Optional.ofNullable(attributes.getValue("Build-Number"))
.map(Integer::parseInt)
.orElseThrow(() -> new IOException("Missing Build-Number"));
} catch (NumberFormatException e) {
throw new IOException("Bad Build-Number", e);
}
return new AuthlibInjectorArtifactInfo(buildNumber, version, location.toAbsolutePath());
}
}
private int buildNumber;
private String version;
private Path location;

View File

@ -0,0 +1,29 @@
/*
* 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.auth.authlibinjector;
import java.io.IOException;
import java.util.Optional;
public interface AuthlibInjectorArtifactProvider {
AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException;
Optional<AuthlibInjectorArtifactInfo> getArtifactInfoImmediately();
}

View File

@ -32,13 +32,11 @@ import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.logging.Level;
import static org.jackhuang.hmcl.util.Logging.LOG;
public class AuthlibInjectorDownloader {
public class AuthlibInjectorDownloader implements AuthlibInjectorArtifactProvider {
private static final String LATEST_BUILD_URL = "https://authlib-injector.yushi.moe/artifact/latest.json";
@ -58,6 +56,7 @@ public class AuthlibInjectorDownloader {
this.downloadProvider = downloadProvider;
}
@Override
public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException {
synchronized (artifactLocation) {
Optional<AuthlibInjectorArtifactInfo> local = getLocalArtifact();
@ -79,6 +78,7 @@ public class AuthlibInjectorDownloader {
}
}
@Override
public Optional<AuthlibInjectorArtifactInfo> getArtifactInfoImmediately() {
return getLocalArtifact();
}
@ -120,38 +120,13 @@ public class AuthlibInjectorDownloader {
return Optional.empty();
}
try {
return Optional.of(readArtifactInfo(artifactLocation));
return Optional.of(AuthlibInjectorArtifactInfo.from(artifactLocation));
} catch (IOException e) {
LOG.log(Level.WARNING, "Bad authlib-injector artifact", e);
return Optional.empty();
}
}
private static AuthlibInjectorArtifactInfo readArtifactInfo(Path location) throws IOException {
try (JarFile jarFile = new JarFile(location.toFile())) {
Attributes attributes = jarFile.getManifest().getMainAttributes();
String title = Optional.ofNullable(attributes.getValue("Implementation-Title"))
.orElseThrow(() -> new IOException("Missing Implementation-Title"));
if (!"authlib-injector".equals(title)) {
throw new IOException("Bad Implementation-Title");
}
String version = Optional.ofNullable(attributes.getValue("Implementation-Version"))
.orElseThrow(() -> new IOException("Missing Implementation-Version"));
int buildNumber;
try {
buildNumber = Optional.ofNullable(attributes.getValue("Build-Number"))
.map(Integer::parseInt)
.orElseThrow(() -> new IOException("Missing Build-Number"));
} catch (NumberFormatException e) {
throw new IOException("Bad Build-Number", e);
}
return new AuthlibInjectorArtifactInfo(buildNumber, version, location.toAbsolutePath());
}
}
private class AuthlibInjectorVersionInfo {
@SerializedName("build_number")
public int buildNumber;

View File

@ -0,0 +1,49 @@
/*
* 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.auth.authlibinjector;
import static org.jackhuang.hmcl.util.Logging.LOG;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.logging.Level;
public class SimpleAuthlibInjectorArtifactProvider implements AuthlibInjectorArtifactProvider {
private Path location;
public SimpleAuthlibInjectorArtifactProvider(Path location) {
this.location = location;
}
@Override
public AuthlibInjectorArtifactInfo getArtifactInfo() throws IOException {
return AuthlibInjectorArtifactInfo.from(location);
}
@Override
public Optional<AuthlibInjectorArtifactInfo> getArtifactInfoImmediately() {
try {
return Optional.of(getArtifactInfo());
} catch (IOException e) {
LOG.log(Level.WARNING, "Bad authlib-injector artifact", e);
return Optional.empty();
}
}
}

View File

@ -118,3 +118,4 @@ No plugin API.
|`-Dhmcl.self_integrity_check.disable=true`|Bypass the self integrity check when checking for update.|
|`-Dhmcl.version.override=<version>`|Override the version number.|
|`-Dhmcl.update_source.override=<url>`|Override the update source.|
|`-Dhmcl.authlibinjector.location=<path>`|Use specified authlib-injector (instead of downloading one).|