diff --git a/src/main/java/me/itzg/helpers/fabric/FabricMetaClient.java b/src/main/java/me/itzg/helpers/fabric/FabricMetaClient.java index 1ecc23fb..60e797ae 100644 --- a/src/main/java/me/itzg/helpers/fabric/FabricMetaClient.java +++ b/src/main/java/me/itzg/helpers/fabric/FabricMetaClient.java @@ -1,7 +1,8 @@ package me.itzg.helpers.fabric; -import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; @@ -16,6 +17,7 @@ import me.itzg.helpers.http.FileDownloadStatusHandler; import me.itzg.helpers.http.SharedFetch; import me.itzg.helpers.http.UriBuilder; +import org.apache.commons.codec.binary.Hex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import reactor.core.publisher.Mono; @@ -155,52 +157,59 @@ public Mono downloadLauncher( .handleStatus(statusHandler) .assemble() .retryWhen(Retry.backoff(downloadRetryMaxAttempts, downloadRetryMinBackoff).filter(IOException.class::isInstance)) - .flatMap(path -> skipValidation ? Mono.just(path) : validateLauncherJar(path)) - .doOnError(InvalidContentException.class, e -> log.warn("Invalid launcher jar, will try again", e)) + .flatMap(path -> skipValidation ? + Mono.just(path) + : validateLauncherJar(path).subscribeOn(Schedulers.boundedElastic()) + ) + .doOnError(InvalidContentException.class, e -> + log.warn("Invalid launcher jar, will try again: {}", e.getMessage()) + ) .retryWhen(Retry.backoff(downloadRetryMaxAttempts, downloadRetryMinBackoff).filter(InvalidContentException.class::isInstance)) .checkpoint("downloadLauncher"); } private Mono validateLauncherJar(Path path) { - return Mono.fromCallable(() -> { - log.debug("Validating Fabric launcher file {}", path); + return Mono.create(sink -> { + log.debug("Validating Fabric launcher file {}", path); - if (!path.toFile().isFile()) { - throw new InvalidContentException("Downloaded launcher jar is not a file"); - } - try { - final Properties installProperties = IoStreams.readFileFromZip(path, "install.properties", in -> { - Properties p = new Properties(); - p.load(in); - return p; - } - ); - if (installProperties == null) { - debugDownloadedContent(path); - throw new InvalidContentException("Downloaded launcher jar does not contain an install.properties"); - } - if (!installProperties.containsKey("game-version")) { - debugDownloadedContent(path); - throw new InvalidContentException("Downloaded launcher jar does not contain a valid install.properties"); + if (!path.toFile().isFile()) { + sink.error(new InvalidContentException("Downloaded launcher jar is not a file")); + } + try { + final Properties installProperties = IoStreams.readFileFromZip(path, "install.properties", in -> { + Properties p = new Properties(); + p.load(in); + return p; } - } catch (IOException e) { + ); + if (installProperties == null) { debugDownloadedContent(path); - throw new InvalidContentException("Downloaded launcher jar could not be read as a jar/zip", e); + sink.error(new InvalidContentException("Does not contain an install.properties")); } + else if (!installProperties.containsKey("game-version")) { + debugDownloadedContent(path); + sink.error(new InvalidContentException("Does not contain a valid install.properties")); + } + } catch (IOException e) { + debugDownloadedContent(path); + sink.error(new InvalidContentException("Could not be read as a jar/zip", e)); + } - return path; - }) - .subscribeOn(Schedulers.boundedElastic()); + sink.success(path); + }); } private static void debugDownloadedContent(Path path) { if (log.isDebugEnabled()) { - try (BufferedReader reader = Files.newBufferedReader(path)) { - final char[] buf = new char[100]; - final int amount = reader.read(buf); - log.debug("Downloaded launcher jar content starts with: {}", new String(buf, 0, amount)); + try (InputStream in = Files.newInputStream(path)) { + final byte[] buf = new byte[100]; + final int amount = in.read(buf); + + log.debug("Downloaded launcher jar content starts with: {}", + Hex.encodeHexString(ByteBuffer.wrap(buf, 0, amount)) + ); } catch (IOException e) { - throw new GenericException("Failed to read downloaded launcher jar for debugging", e); + log.warn("Failed to debug content of launcher jar", e); } } }