diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 6c8d0bd5e..68f2be8d8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ public class AddAuthlibInjectorServerPane extends StackPane implements DialogAwa Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> { + }).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); @@ -118,7 +118,6 @@ public class AddAuthlibInjectorServerPane extends StackPane implements DialogAwa transitionHandler.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT.getAnimationProducer()); } else { - Exception exception = variables.get("lastException"); LOG.log(Level.WARNING, "Failed to resolve auth server: " + url, exception); lblCreationWarning.setText(resolveFetchExceptionMessage(exception)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 9a3e6bcbf..087e8cae3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().finalized((a, b, c) -> profile.getRepository().refreshVersions()) .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 13b4d9c56..e7d64e8b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -128,7 +128,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((variables, isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); @@ -147,7 +147,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres } }); } else { - LOG.log(Level.WARNING, "Failed to fetch versions list", (Throwable) variables.get("lastException")); + LOG.log(Level.WARNING, "Failed to fetch versions list", exception); Platform.runLater(() -> { transitionHandler.setContent(failedPane, ContainerAnimations.FADE.getAnimationProducer()); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 3b7a80001..904b9801a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -92,7 +92,7 @@ public final class ModListPage extends Control { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded) -> { + }).finalizedResult(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 304eafaa9..b7592469e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -52,7 +52,7 @@ public class WorldListPage extends ListPage { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded) -> { + .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java index 55dde966f..3e66cf84e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java @@ -121,8 +121,7 @@ public final class UpdateHandler { } } else { - Throwable e = task.getLastException(); - LOG.log(Level.WARNING, "Failed to update to " + version, e); + LOG.log(Level.WARNING, "Failed to update to " + version, executor.getLastException()); Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE)); } }); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java index 5ed67f757..19045d5ac 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -69,7 +69,7 @@ public class DefaultGameBuilder extends GameBuilder { result = result.then(dependencyManager.installLibraryAsync(remoteVersion)); return result; - }).finalized((variables, isDependentsSucceeded) -> { + }).finalized((variables, isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java index 3de732d9c..539b6f11d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java @@ -20,5 +20,5 @@ package org.jackhuang.hmcl.task; import org.jackhuang.hmcl.util.AutoTypingMap; public interface FinalizedCallback { - void execute(AutoTypingMap variables, boolean isDependentsSucceeded) throws Exception; + void execute(AutoTypingMap variables, boolean isDependentsSucceeded, Exception exception) throws Exception; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java index 1a7691474..d0b6caef4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java @@ -27,7 +27,7 @@ import java.util.Collections; */ final class FinalizedTask extends Task { - private final Collection dependents; + private final Task pred; private final FinalizedCallback callback; private final Scheduler scheduler; @@ -38,7 +38,7 @@ final class FinalizedTask extends Task { * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. */ public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback, String name) { - this.dependents = Collections.singleton(pred); + this.pred = pred; this.scheduler = scheduler; this.callback = callback; @@ -53,7 +53,7 @@ final class FinalizedTask extends Task { @Override public void execute() throws Exception { - callback.execute(getVariables(), isDependentsSucceeded()); + callback.execute(getVariables(), isDependentsSucceeded(), pred.getLastException()); if (!isDependentsSucceeded()) throw new SilentException(); @@ -61,7 +61,7 @@ final class FinalizedTask extends Task { @Override public Collection getDependents() { - return dependents; + return Collections.singleton(pred); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java index 3938dac5e..631c8ae55 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -68,13 +68,13 @@ public abstract class Task { this.state = state; } - private Throwable lastException = null; + private Exception lastException; - public Throwable getLastException() { + public Exception getLastException() { return lastException; } - void setLastException(Throwable e) { + void setLastException(Exception e) { lastException = e; } @@ -321,7 +321,7 @@ public abstract class Task { } public final Task finalized(Scheduler scheduler, ExceptionalConsumer, T> success, ExceptionalConsumer failure) { - return finalized(scheduler, (variables, isDependentsSucceeded) -> { + return finalized(scheduler, (variables, isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { if (success != null) try { @@ -331,10 +331,9 @@ public abstract class Task { if (failure != null) failure.accept(e); } - } - else { + } else { if (failure != null) - failure.accept(variables.get(TaskExecutor.LAST_EXCEPTION_ID)); + failure.accept(exception); } }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java index 257c14e49..68bda2a5d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -234,7 +234,6 @@ public final class TaskExecutor { } catch (Exception e) { task.setLastException(e); lastException = e; - variables.set(LAST_EXCEPTION_ID, e); if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); } @@ -279,6 +278,4 @@ public final class TaskExecutor { } } - - public static final String LAST_EXCEPTION_ID = "lastException"; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index e9d6fecf8..533fead55 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -61,7 +61,7 @@ public abstract class TaskResult extends Task { public Task finalizedResult(Scheduler scheduler, FinalizedCallback callback) { return new FinalizedTask(this, scheduler, - (variables, isDependentsSucceeded) -> callback.execute(getResult(), isDependentsSucceeded), + (variables, isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception), ReflectionHelper.getCaller().toString()); } @@ -98,6 +98,6 @@ public abstract class TaskResult extends Task { } public interface FinalizedCallback { - void execute(V result, boolean isDependentsSucceeded) throws Exception; + void execute(V result, boolean isDependentsSucceeded, Exception exception) throws Exception; } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java index b987f8a38..b51220da7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/Validation.java @@ -35,6 +35,7 @@ public interface Validation { * Throw an exception when values are malformed. * * @throws JsonParseException if fields are filled in wrong format or wrong type. + * @throws TolerableValidationException if we want to replace this object with null (i.e. the object does not fulfill the constraints). */ void validate() throws JsonParseException, TolerableValidationException; }