|
1 | 1 | package me.itzg.helpers.fabric;
|
2 | 2 |
|
3 |
| -import java.io.BufferedReader; |
4 | 3 | import java.io.IOException;
|
| 4 | +import java.io.InputStream; |
| 5 | +import java.nio.ByteBuffer; |
5 | 6 | import java.nio.file.Files;
|
6 | 7 | import java.nio.file.Path;
|
7 | 8 | import java.time.Duration;
|
|
16 | 17 | import me.itzg.helpers.http.FileDownloadStatusHandler;
|
17 | 18 | import me.itzg.helpers.http.SharedFetch;
|
18 | 19 | import me.itzg.helpers.http.UriBuilder;
|
| 20 | +import org.apache.commons.codec.binary.Hex; |
19 | 21 | import org.jetbrains.annotations.NotNull;
|
20 | 22 | import org.jetbrains.annotations.Nullable;
|
21 | 23 | import reactor.core.publisher.Mono;
|
@@ -155,52 +157,59 @@ public Mono<Path> downloadLauncher(
|
155 | 157 | .handleStatus(statusHandler)
|
156 | 158 | .assemble()
|
157 | 159 | .retryWhen(Retry.backoff(downloadRetryMaxAttempts, downloadRetryMinBackoff).filter(IOException.class::isInstance))
|
158 |
| - .flatMap(path -> skipValidation ? Mono.just(path) : validateLauncherJar(path)) |
159 |
| - .doOnError(InvalidContentException.class, e -> log.warn("Invalid launcher jar, will try again", e)) |
| 160 | + .flatMap(path -> skipValidation ? |
| 161 | + Mono.just(path) |
| 162 | + : validateLauncherJar(path).subscribeOn(Schedulers.boundedElastic()) |
| 163 | + ) |
| 164 | + .doOnError(InvalidContentException.class, e -> |
| 165 | + log.warn("Invalid launcher jar, will try again: {}", e.getMessage()) |
| 166 | + ) |
160 | 167 | .retryWhen(Retry.backoff(downloadRetryMaxAttempts, downloadRetryMinBackoff).filter(InvalidContentException.class::isInstance))
|
161 | 168 | .checkpoint("downloadLauncher");
|
162 | 169 | }
|
163 | 170 |
|
164 | 171 | private Mono<Path> validateLauncherJar(Path path) {
|
165 |
| - return Mono.fromCallable(() -> { |
166 |
| - log.debug("Validating Fabric launcher file {}", path); |
| 172 | + return Mono.create(sink -> { |
| 173 | + log.debug("Validating Fabric launcher file {}", path); |
167 | 174 |
|
168 |
| - if (!path.toFile().isFile()) { |
169 |
| - throw new InvalidContentException("Downloaded launcher jar is not a file"); |
170 |
| - } |
171 |
| - try { |
172 |
| - final Properties installProperties = IoStreams.readFileFromZip(path, "install.properties", in -> { |
173 |
| - Properties p = new Properties(); |
174 |
| - p.load(in); |
175 |
| - return p; |
176 |
| - } |
177 |
| - ); |
178 |
| - if (installProperties == null) { |
179 |
| - debugDownloadedContent(path); |
180 |
| - throw new InvalidContentException("Downloaded launcher jar does not contain an install.properties"); |
181 |
| - } |
182 |
| - if (!installProperties.containsKey("game-version")) { |
183 |
| - debugDownloadedContent(path); |
184 |
| - throw new InvalidContentException("Downloaded launcher jar does not contain a valid install.properties"); |
| 175 | + if (!path.toFile().isFile()) { |
| 176 | + sink.error(new InvalidContentException("Downloaded launcher jar is not a file")); |
| 177 | + } |
| 178 | + try { |
| 179 | + final Properties installProperties = IoStreams.readFileFromZip(path, "install.properties", in -> { |
| 180 | + Properties p = new Properties(); |
| 181 | + p.load(in); |
| 182 | + return p; |
185 | 183 | }
|
186 |
| - } catch (IOException e) { |
| 184 | + ); |
| 185 | + if (installProperties == null) { |
187 | 186 | debugDownloadedContent(path);
|
188 |
| - throw new InvalidContentException("Downloaded launcher jar could not be read as a jar/zip", e); |
| 187 | + sink.error(new InvalidContentException("Does not contain an install.properties")); |
189 | 188 | }
|
| 189 | + else if (!installProperties.containsKey("game-version")) { |
| 190 | + debugDownloadedContent(path); |
| 191 | + sink.error(new InvalidContentException("Does not contain a valid install.properties")); |
| 192 | + } |
| 193 | + } catch (IOException e) { |
| 194 | + debugDownloadedContent(path); |
| 195 | + sink.error(new InvalidContentException("Could not be read as a jar/zip", e)); |
| 196 | + } |
190 | 197 |
|
191 |
| - return path; |
192 |
| - }) |
193 |
| - .subscribeOn(Schedulers.boundedElastic()); |
| 198 | + sink.success(path); |
| 199 | + }); |
194 | 200 | }
|
195 | 201 |
|
196 | 202 | private static void debugDownloadedContent(Path path) {
|
197 | 203 | if (log.isDebugEnabled()) {
|
198 |
| - try (BufferedReader reader = Files.newBufferedReader(path)) { |
199 |
| - final char[] buf = new char[100]; |
200 |
| - final int amount = reader.read(buf); |
201 |
| - log.debug("Downloaded launcher jar content starts with: {}", new String(buf, 0, amount)); |
| 204 | + try (InputStream in = Files.newInputStream(path)) { |
| 205 | + final byte[] buf = new byte[100]; |
| 206 | + final int amount = in.read(buf); |
| 207 | + |
| 208 | + log.debug("Downloaded launcher jar content starts with: {}", |
| 209 | + Hex.encodeHexString(ByteBuffer.wrap(buf, 0, amount)) |
| 210 | + ); |
202 | 211 | } catch (IOException e) {
|
203 |
| - throw new GenericException("Failed to read downloaded launcher jar for debugging", e); |
| 212 | + log.warn("Failed to debug content of launcher jar", e); |
204 | 213 | }
|
205 | 214 | }
|
206 | 215 | }
|
|
0 commit comments