Refactor Task
This commit is contained in:
@@ -30,7 +30,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Export the game to a mod pack file.
|
* Export the game to a mod pack file.
|
||||||
*/
|
*/
|
||||||
public class HMCLModpackExportTask extends Task {
|
public class HMCLModpackExportTask extends Task<Void> {
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
private final String version;
|
private final String version;
|
||||||
private final List<String> whitelist;
|
private final List<String> whitelist;
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ import java.io.IOException;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class HMCLModpackInstallTask extends Task {
|
public final class HMCLModpackInstallTask extends Task<Void> {
|
||||||
private final File zipFile;
|
private final File zipFile;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final HMCLGameRepository repository;
|
private final HMCLGameRepository repository;
|
||||||
private final Modpack modpack;
|
private final Modpack modpack;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
|
|
||||||
public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, String name) {
|
public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, String name) {
|
||||||
DependencyManager dependency = profile.getDependency();
|
DependencyManager dependency = profile.getDependency();
|
||||||
@@ -77,12 +77,12 @@ public final class HMCLModpackInstallTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public List<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependents() {
|
public List<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,15 +121,15 @@ public final class LauncherHelper {
|
|||||||
Version version = MaintainTask.maintain(repository.getResolvedVersion(selectedVersion));
|
Version version = MaintainTask.maintain(repository.getResolvedVersion(selectedVersion));
|
||||||
Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
|
Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
|
||||||
|
|
||||||
TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))
|
TaskExecutor executor = Task.runAsync(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))
|
||||||
.then(() -> {
|
.thenCompose(() -> {
|
||||||
if (setting.isNotCheckGame())
|
if (setting.isNotCheckGame())
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
return dependencyManager.checkGameCompletionAsync(version);
|
return dependencyManager.checkGameCompletionAsync(version);
|
||||||
})
|
})
|
||||||
.then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS)))
|
.thenRun(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS))
|
||||||
.then(() -> {
|
.thenCompose(() -> {
|
||||||
try {
|
try {
|
||||||
ModpackConfiguration<?> configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion));
|
ModpackConfiguration<?> configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion));
|
||||||
if ("Curse".equals(configuration.getType()))
|
if ("Curse".equals(configuration.getType()))
|
||||||
@@ -140,8 +140,8 @@ public final class LauncherHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN)))
|
.thenRun(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))
|
||||||
.thenCompose(() -> Task.ofResult(i18n("account.methods"), () -> {
|
.thenSupply(i18n("account.methods"), () -> {
|
||||||
try {
|
try {
|
||||||
return account.logIn();
|
return account.logIn();
|
||||||
} catch (CredentialExpiredException e) {
|
} catch (CredentialExpiredException e) {
|
||||||
@@ -151,7 +151,7 @@ public final class LauncherHelper {
|
|||||||
LOG.warning("Authentication failed, try playing offline: " + e);
|
LOG.warning("Authentication failed, try playing offline: " + e);
|
||||||
return account.playOffline().orElseThrow(() -> e);
|
return account.playOffline().orElseThrow(() -> e);
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
.thenApply(Schedulers.javafx(), authInfo -> {
|
.thenApply(Schedulers.javafx(), authInfo -> {
|
||||||
emitStatus(LoadingState.LAUNCHING);
|
emitStatus(LoadingState.LAUNCHING);
|
||||||
return authInfo;
|
return authInfo;
|
||||||
@@ -199,7 +199,7 @@ public final class LauncherHelper {
|
|||||||
final AtomicInteger finished = new AtomicInteger(0);
|
final AtomicInteger finished = new AtomicInteger(0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinished(Task task) {
|
public void onFinished(Task<?> task) {
|
||||||
finished.incrementAndGet();
|
finished.incrementAndGet();
|
||||||
int runningTasks = executor.getRunningTasks();
|
int runningTasks = executor.getRunningTasks();
|
||||||
Platform.runLater(() -> launchingStepsPane.setProgress(1.0 * finished.get() / runningTasks));
|
Platform.runLater(() -> launchingStepsPane.setProgress(1.0 * finished.get() / runningTasks));
|
||||||
@@ -416,7 +416,7 @@ public final class LauncherHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LaunchTask<T> extends TaskResult<T> {
|
private static class LaunchTask<T> extends Task<T> {
|
||||||
private final ExceptionalSupplier<T, Exception> supplier;
|
private final ExceptionalSupplier<T, Exception> supplier;
|
||||||
|
|
||||||
public LaunchTask(ExceptionalSupplier<T, Exception> supplier) {
|
public LaunchTask(ExceptionalSupplier<T, Exception> supplier) {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public final class ModpackHelper {
|
|||||||
throw new UnsupportedModpackException();
|
throw new UnsupportedModpackException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) {
|
public static Task<Void> getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) {
|
||||||
profile.getRepository().markVersionAsModpack(name);
|
profile.getRepository().markVersionAsModpack(name);
|
||||||
|
|
||||||
ExceptionalRunnable<?> success = () -> {
|
ExceptionalRunnable<?> success = () -> {
|
||||||
@@ -117,11 +117,11 @@ public final class ModpackHelper {
|
|||||||
else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration)
|
else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration)
|
||||||
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
|
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
|
||||||
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
||||||
.then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
|
.thenCompose(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
|
||||||
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
|
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException {
|
public static Task<Void> getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException {
|
||||||
Modpack modpack = ModpackHelper.readModpackManifest(zipFile.toPath(), charset);
|
Modpack modpack = ModpackHelper.readModpackManifest(zipFile.toPath(), charset);
|
||||||
|
|
||||||
switch (configuration.getType()) {
|
switch (configuration.getType()) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class MultiMCInstallVersionSettingTask extends Task {
|
public final class MultiMCInstallVersionSettingTask extends Task<Void> {
|
||||||
private final Profile profile;
|
private final Profile profile;
|
||||||
private final MultiMCInstanceConfiguration manifest;
|
private final MultiMCInstanceConfiguration manifest;
|
||||||
private final String version;
|
private final String version;
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ public final class Controllers {
|
|||||||
dialog(i18n("launcher.cache_directory.invalid"));
|
dialog(i18n("launcher.cache_directory.invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.of(JavaVersion::initialize).start();
|
Task.runAsync(JavaVersion::initialize).start();
|
||||||
|
|
||||||
scene = new Scene(decorator.getDecorator(), 800, 519);
|
scene = new Scene(decorator.getDecorator(), 800, 519);
|
||||||
scene.getStylesheets().setAll(config().getTheme().getStylesheets());
|
scene.getStylesheets().setAll(config().getTheme().getStylesheets());
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ public final class FXUtils {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static void bindEnum(JFXComboBox<?> comboBox, Property<? extends Enum> property) {
|
public static void bindEnum(JFXComboBox<?> comboBox, Property<? extends Enum<?>> property) {
|
||||||
unbindEnum(comboBox);
|
unbindEnum(comboBox);
|
||||||
ChangeListener<Number> listener = (a, b, newValue) ->
|
ChangeListener<Number> listener = (a, b, newValue) ->
|
||||||
((Property) property).setValue(property.getValue().getClass().getEnumConstants()[newValue.intValue()]);
|
((Property) property).setValue(property.getValue().getClass().getEnumConstants()[newValue.intValue()]);
|
||||||
|
|||||||
@@ -118,12 +118,12 @@ public final class LeftPaneController extends AdvancedListBox {
|
|||||||
if (repository.getVersionCount() == 0) {
|
if (repository.getVersionCount() == 0) {
|
||||||
File modpackFile = new File("modpack.zip").getAbsoluteFile();
|
File modpackFile = new File("modpack.zip").getAbsoluteFile();
|
||||||
if (modpackFile.exists()) {
|
if (modpackFile.exists()) {
|
||||||
Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath()))
|
Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath()))
|
||||||
.thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
|
.thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
|
||||||
.thenAccept(modpack -> {
|
.thenAccept(modpack -> {
|
||||||
AtomicReference<Region> region = new AtomicReference<>();
|
AtomicReference<Region> region = new AtomicReference<>();
|
||||||
TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
|
TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
|
||||||
.with(Task.of(Schedulers.javafx(), this::checkAccount)).executor();
|
.withRun(Schedulers.javafx(), this::checkAccount).executor();
|
||||||
region.set(Controllers.taskDialog(executor, i18n("modpack.installing")));
|
region.set(Controllers.taskDialog(executor, i18n("modpack.installing")));
|
||||||
executor.start();
|
executor.start();
|
||||||
}).start();
|
}).start();
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class AccountLoginPane extends StackPane {
|
|||||||
String password = txtPassword.getText();
|
String password = txtPassword.getText();
|
||||||
progressBar.setVisible(true);
|
progressBar.setVisible(true);
|
||||||
lblCreationWarning.setText("");
|
lblCreationWarning.setText("");
|
||||||
Task.ofResult(() -> oldAccount.logInWithPassword(password))
|
Task.supplyAsync(() -> oldAccount.logInWithPassword(password))
|
||||||
.whenComplete(Schedulers.javafx(), authInfo -> {
|
.whenComplete(Schedulers.javafx(), authInfo -> {
|
||||||
success.accept(authInfo);
|
success.accept(authInfo);
|
||||||
fireEvent(new DialogCloseEvent());
|
fireEvent(new DialogCloseEvent());
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ public class AddAccountPane extends StackPane {
|
|||||||
AccountFactory<?> factory = cboType.getSelectionModel().getSelectedItem();
|
AccountFactory<?> factory = cboType.getSelectionModel().getSelectedItem();
|
||||||
Object additionalData = getAuthAdditionalData();
|
Object additionalData = getAuthAdditionalData();
|
||||||
|
|
||||||
Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData))
|
Task.supplyAsync(() -> factory.create(new Selector(), username, password, additionalData))
|
||||||
.whenComplete(Schedulers.javafx(), account -> {
|
.whenComplete(Schedulers.javafx(), account -> {
|
||||||
int oldIndex = Accounts.getAccounts().indexOf(account);
|
int oldIndex = Accounts.getAccounts().indexOf(account);
|
||||||
if (oldIndex == -1) {
|
if (oldIndex == -1) {
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class AddAuthlibInjectorServerPane extends StackPane implements DialogAwa
|
|||||||
nextPane.showSpinner();
|
nextPane.showSpinner();
|
||||||
addServerPane.setDisable(true);
|
addServerPane.setDisable(true);
|
||||||
|
|
||||||
Task.of(() -> {
|
Task.runAsync(() -> {
|
||||||
serverBeingAdded = AuthlibInjectorServer.locateServer(url);
|
serverBeingAdded = AuthlibInjectorServer.locateServer(url);
|
||||||
}).whenComplete(Schedulers.javafx(), (isDependentSucceeded, exception) -> {
|
}).whenComplete(Schedulers.javafx(), (isDependentSucceeded, exception) -> {
|
||||||
addServerPane.setDisable(false);
|
addServerPane.setDisable(false);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
|
|
||||||
public final class TaskListPane extends StackPane {
|
public final class TaskListPane extends StackPane {
|
||||||
private final AdvancedListBox listBox = new AdvancedListBox();
|
private final AdvancedListBox listBox = new AdvancedListBox();
|
||||||
private final Map<Task, ProgressListNode> nodes = new HashMap<>();
|
private final Map<Task<?>, ProgressListNode> nodes = new HashMap<>();
|
||||||
private final ReadOnlyIntegerWrapper finishedTasks = new ReadOnlyIntegerWrapper();
|
private final ReadOnlyIntegerWrapper finishedTasks = new ReadOnlyIntegerWrapper();
|
||||||
private final ReadOnlyIntegerWrapper totTasks = new ReadOnlyIntegerWrapper();
|
private final ReadOnlyIntegerWrapper totTasks = new ReadOnlyIntegerWrapper();
|
||||||
|
|
||||||
@@ -72,12 +72,12 @@ public final class TaskListPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReady(Task task) {
|
public void onReady(Task<?> task) {
|
||||||
Platform.runLater(() -> totTasks.set(totTasks.getValue() + 1));
|
Platform.runLater(() -> totTasks.set(totTasks.getValue() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRunning(Task task) {
|
public void onRunning(Task<?> task) {
|
||||||
if (!task.getSignificance().shouldShow())
|
if (!task.getSignificance().shouldShow())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ public final class TaskListPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinished(Task task) {
|
public void onFinished(Task<?> task) {
|
||||||
ProgressListNode node = nodes.remove(task);
|
ProgressListNode node = nodes.remove(task);
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return;
|
return;
|
||||||
@@ -125,7 +125,7 @@ public final class TaskListPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed(Task task, Throwable throwable) {
|
public void onFailed(Task<?> task, Throwable throwable) {
|
||||||
ProgressListNode node = nodes.remove(task);
|
ProgressListNode node = nodes.remove(task);
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return;
|
return;
|
||||||
@@ -142,7 +142,7 @@ public final class TaskListPane extends StackPane {
|
|||||||
private final Label title = new Label();
|
private final Label title = new Label();
|
||||||
private final Label state = new Label();
|
private final Label state = new Label();
|
||||||
|
|
||||||
public ProgressListNode(Task task) {
|
public ProgressListNode(Task<?> task) {
|
||||||
bar.progressProperty().bind(task.progressProperty());
|
bar.progressProperty().bind(task.progressProperty());
|
||||||
title.setText(task.getName());
|
title.setText(task.getName());
|
||||||
state.textProperty().bind(task.messageProperty());
|
state.textProperty().bind(task.messageProperty());
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import org.jackhuang.hmcl.game.Version;
|
|||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.task.DownloadException;
|
import org.jackhuang.hmcl.task.DownloadException;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
@@ -90,7 +89,7 @@ public final class InstallerWizardProvider implements WizardProvider {
|
|||||||
settings.put("success_message", i18n("install.success"));
|
settings.put("success_message", i18n("install.success"));
|
||||||
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
||||||
|
|
||||||
TaskResult<Version> ret = Task.ofResult(() -> version);
|
Task<Version> ret = Task.supplyAsync(() -> version);
|
||||||
|
|
||||||
if (settings.containsKey("forge"))
|
if (settings.containsKey("forge"))
|
||||||
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge")));
|
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge")));
|
||||||
@@ -101,7 +100,7 @@ public final class InstallerWizardProvider implements WizardProvider {
|
|||||||
if (settings.containsKey("optifine"))
|
if (settings.containsKey("optifine"))
|
||||||
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine")));
|
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine")));
|
||||||
|
|
||||||
return ret.then(profile.getRepository().refreshVersionsAsync());
|
return ret.thenCompose(profile.getRepository().refreshVersionsAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
settings.put(PROFILE, profile);
|
settings.put(PROFILE, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task finishModpackInstallingAsync(Map<String, Object> settings) {
|
private Task<Void> finishModpackInstallingAsync(Map<String, Object> settings) {
|
||||||
if (!settings.containsKey(ModpackPage.MODPACK_FILE))
|
if (!settings.containsKey(ModpackPage.MODPACK_FILE))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
|
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
|
||||||
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
|
.thenRun(Schedulers.javafx(), () -> profile.setSelectedVersion(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public final class ModpackPage extends StackPane implements WizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spinnerPane.showSpinner();
|
spinnerPane.showSpinner();
|
||||||
Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath()))
|
Task.supplyAsync(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath()))
|
||||||
.thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding))
|
.thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding))
|
||||||
.whenComplete(Schedulers.javafx(), manifest -> {
|
.whenComplete(Schedulers.javafx(), manifest -> {
|
||||||
spinnerPane.hideSpinner();
|
spinnerPane.hideSpinner();
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider {
|
|||||||
settings.put(PROFILE, profile);
|
settings.put(PROFILE, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task finishVersionDownloadingAsync(Map<String, Object> settings) {
|
private Task<Void> finishVersionDownloadingAsync(Map<String, Object> settings) {
|
||||||
GameBuilder builder = profile.getDependency().gameBuilder();
|
GameBuilder builder = profile.getDependency().gameBuilder();
|
||||||
|
|
||||||
String name = (String) settings.get("name");
|
String name = (String) settings.get("name");
|
||||||
@@ -60,7 +60,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider {
|
|||||||
builder.version((RemoteVersion) settings.get("optifine"));
|
builder.version((RemoteVersion) settings.get("optifine"));
|
||||||
|
|
||||||
return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions())
|
return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions())
|
||||||
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
|
.thenRun(Schedulers.javafx(), () -> profile.setSelectedVersion(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ public final class ExportWizardProvider implements WizardProvider {
|
|||||||
List<File> launcherJar = Launcher.getCurrentJarFiles();
|
List<File> launcherJar = Launcher.getCurrentJarFiles();
|
||||||
boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null;
|
boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null;
|
||||||
|
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
Task dependency = null;
|
Task<?> dependency = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws Exception {
|
public void execute() throws Exception {
|
||||||
@@ -80,7 +80,7 @@ public final class ExportWizardProvider implements WizardProvider {
|
|||||||
), tempModpack);
|
), tempModpack);
|
||||||
|
|
||||||
if (includeLauncher) {
|
if (includeLauncher) {
|
||||||
dependency = dependency.then(Task.of(() -> {
|
dependency = dependency.thenRun(() -> {
|
||||||
try (Zipper zip = new Zipper(modpackFile.toPath())) {
|
try (Zipper zip = new Zipper(modpackFile.toPath())) {
|
||||||
Config exported = new Config();
|
Config exported = new Config();
|
||||||
|
|
||||||
@@ -109,12 +109,12 @@ public final class ExportWizardProvider implements WizardProvider {
|
|||||||
for (File jar : launcherJar)
|
for (File jar : launcherJar)
|
||||||
zip.putFile(jar, jar.getName());
|
zip.putFile(jar, jar.getName());
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return Collections.singleton(dependency);
|
return Collections.singleton(dependency);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ public class InstallerListPage extends ListPage<InstallerItem> {
|
|||||||
LinkedList<Library> newList = new LinkedList<>(version.getLibraries());
|
LinkedList<Library> newList = new LinkedList<>(version.getLibraries());
|
||||||
newList.remove(library);
|
newList.remove(library);
|
||||||
new MaintainTask(version.setLibraries(newList))
|
new MaintainTask(version.setLibraries(newList))
|
||||||
.then(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion))
|
.thenCompose(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion))
|
||||||
.with(profile.getRepository().refreshVersionsAsync())
|
.withCompose(profile.getRepository().refreshVersionsAsync())
|
||||||
.with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId)))
|
.withRun(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))
|
||||||
.start();
|
.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public final class ModListPage extends Control {
|
|||||||
|
|
||||||
public void loadMods(ModManager modManager) {
|
public void loadMods(ModManager modManager) {
|
||||||
this.modManager = modManager;
|
this.modManager = modManager;
|
||||||
Task.ofResult(() -> {
|
Task.supplyAsync(() -> {
|
||||||
synchronized (ModListPage.this) {
|
synchronized (ModListPage.this) {
|
||||||
JFXUtilities.runInFX(() -> loadingProperty().set(true));
|
JFXUtilities.runInFX(() -> loadingProperty().set(true));
|
||||||
modManager.refreshMods();
|
modManager.refreshMods();
|
||||||
@@ -111,7 +111,7 @@ public final class ModListPage extends Control {
|
|||||||
List<String> succeeded = new LinkedList<>();
|
List<String> succeeded = new LinkedList<>();
|
||||||
List<String> failed = new LinkedList<>();
|
List<String> failed = new LinkedList<>();
|
||||||
if (res == null) return;
|
if (res == null) return;
|
||||||
Task.of(() -> {
|
Task.runAsync(() -> {
|
||||||
for (File file : res) {
|
for (File file : res) {
|
||||||
try {
|
try {
|
||||||
modManager.addMod(file);
|
modManager.addMod(file);
|
||||||
@@ -123,7 +123,7 @@ public final class ModListPage extends Control {
|
|||||||
// Actually addMod will not throw exceptions because FileChooser has already filtered files.
|
// Actually addMod will not throw exceptions because FileChooser has already filtered files.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).with(Task.of(Schedulers.javafx(), () -> {
|
}).withRun(Schedulers.javafx(), () -> {
|
||||||
List<String> prompt = new LinkedList<>();
|
List<String> prompt = new LinkedList<>();
|
||||||
if (!succeeded.isEmpty())
|
if (!succeeded.isEmpty())
|
||||||
prompt.add(i18n("mods.add.success", String.join(", ", succeeded)));
|
prompt.add(i18n("mods.add.success", String.join(", ", succeeded)));
|
||||||
@@ -131,7 +131,7 @@ public final class ModListPage extends Control {
|
|||||||
prompt.add(i18n("mods.add.failed", String.join(", ", failed)));
|
prompt.add(i18n("mods.add.failed", String.join(", ", failed)));
|
||||||
Controllers.dialog(String.join("\n", prompt), i18n("mods.add"));
|
Controllers.dialog(String.join("\n", prompt), i18n("mods.add"));
|
||||||
loadMods(modManager);
|
loadMods(modManager);
|
||||||
})).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParentTab(JFXTabPane parentTab) {
|
public void setParentTab(JFXTabPane parentTab) {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
|
|
||||||
FXUtils.smoothScrolling(scroll);
|
FXUtils.smoothScrolling(scroll);
|
||||||
|
|
||||||
Task.ofResult(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> {
|
Task.supplyAsync(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> {
|
||||||
javaItem.loadChildren(list.stream()
|
javaItem.loadChildren(list.stream()
|
||||||
.map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
|
.map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
|
||||||
javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion))
|
javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion))
|
||||||
@@ -273,7 +273,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
VersionSetting versionSetting = lastVersionSetting;
|
VersionSetting versionSetting = lastVersionSetting;
|
||||||
if (versionSetting == null)
|
if (versionSetting == null)
|
||||||
return;
|
return;
|
||||||
Task.ofResult(versionSetting::getJavaVersion)
|
Task.supplyAsync(versionSetting::getJavaVersion)
|
||||||
.thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion)
|
.thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion)
|
||||||
.map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path")))
|
.map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path")))
|
||||||
.start();
|
.start();
|
||||||
|
|||||||
@@ -74,6 +74,6 @@ public class WorldExportPage extends WizardSinglePage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object finish() {
|
protected Object finish() {
|
||||||
return Task.of(i18n("world.export.wizard", worldName.get()), () -> world.export(Paths.get(path.get()), worldName.get()));
|
return Task.runAsync(i18n("world.export.wizard", worldName.get()), () -> world.export(Paths.get(path.get()), worldName.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class WorldListPage extends ListPage<WorldListItem> {
|
|||||||
this.savesDir = profile.getRepository().getRunDirectory(id).toPath().resolve("saves");
|
this.savesDir = profile.getRepository().getRunDirectory(id).toPath().resolve("saves");
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList()))
|
Task.supplyAsync(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList()))
|
||||||
.whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> {
|
.whenComplete(Schedulers.javafx(), (result, isDependentSucceeded, exception) -> {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
if (isDependentSucceeded)
|
if (isDependentSucceeded)
|
||||||
@@ -72,10 +72,10 @@ public class WorldListPage extends ListPage<WorldListItem> {
|
|||||||
private void installWorld(File zipFile) {
|
private void installWorld(File zipFile) {
|
||||||
// Only accept one world file because user is required to confirm the new world name
|
// Only accept one world file because user is required to confirm the new world name
|
||||||
// Or too many input dialogs are popped.
|
// Or too many input dialogs are popped.
|
||||||
Task.ofResult(() -> new World(zipFile.toPath()))
|
Task.supplyAsync(() -> new World(zipFile.toPath()))
|
||||||
.whenComplete(Schedulers.javafx(), world -> {
|
.whenComplete(Schedulers.javafx(), world -> {
|
||||||
Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> {
|
Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> {
|
||||||
Task.of(() -> world.install(savesDir, name))
|
Task.runAsync(() -> world.install(savesDir, name))
|
||||||
.whenComplete(Schedulers.javafx(), () -> {
|
.whenComplete(Schedulers.javafx(), () -> {
|
||||||
itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name))));
|
itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name))));
|
||||||
resolve.run();
|
resolve.run();
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ public interface AbstractWizardDisplayer extends WizardDisplayer {
|
|||||||
Queue<Object> getCancelQueue();
|
Queue<Object> getCancelQueue();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void handleTask(Map<String, Object> settings, Task task) {
|
default void handleTask(Map<String, Object> settings, Task<?> task) {
|
||||||
TaskExecutor executor = task.with(Task.of(Schedulers.javafx(), this::navigateToSuccess)).executor();
|
TaskExecutor executor = task.withRun(Schedulers.javafx(), this::navigateToSuccess).executor();
|
||||||
TaskListPane pane = new TaskListPane();
|
TaskListPane pane = new TaskListPane();
|
||||||
pane.setExecutor(executor);
|
pane.setExecutor(executor);
|
||||||
navigateTo(pane, Navigation.NavigationDirection.FINISH);
|
navigateTo(pane, Navigation.NavigationDirection.FINISH);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer {
|
public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void handleTask(Map<String, Object> settings, Task task) {
|
default void handleTask(Map<String, Object> settings, Task<?> task) {
|
||||||
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> {
|
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> {
|
||||||
it.fireEvent(new DialogCloseEvent());
|
it.fireEvent(new DialogCloseEvent());
|
||||||
onEnd();
|
onEnd();
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class WizardController implements Navigation {
|
|||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
Object result = provider.finish(settings);
|
Object result = provider.finish(settings);
|
||||||
if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT);
|
if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT);
|
||||||
else if (result instanceof Task) displayer.handleTask(settings, ((Task) result));
|
else if (result instanceof Task<?>) displayer.handleTask(settings, ((Task<?>) result));
|
||||||
else if (result != null) throw new IllegalStateException("Unrecognized wizard result: " + result);
|
else if (result != null) throw new IllegalStateException("Unrecognized wizard result: " + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,5 +27,5 @@ public interface WizardDisplayer {
|
|||||||
void onEnd();
|
void onEnd();
|
||||||
void onCancel();
|
void onCancel();
|
||||||
void navigateTo(Node page, Navigation.NavigationDirection nav);
|
void navigateTo(Node page, Navigation.NavigationDirection nav);
|
||||||
void handleTask(Map<String, Object> settings, Task task);
|
void handleTask(Map<String, Object> settings, Task<?> task);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public final class UpdateHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task task = new HMCLDownloadTask(version, downloaded);
|
Task<?> task = new HMCLDownloadTask(version, downloaded);
|
||||||
|
|
||||||
TaskExecutor executor = task.executor();
|
TaskExecutor executor = task.executor();
|
||||||
Controllers.taskDialog(executor, i18n("message.downloading"));
|
Controllers.taskDialog(executor, i18n("message.downloading"));
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask;
|
|||||||
import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion;
|
import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.ParallelTask;
|
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,9 +67,9 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task checkGameCompletionAsync(Version version) {
|
public Task<?> checkGameCompletionAsync(Version version) {
|
||||||
return new ParallelTask(
|
return Task.allOf(
|
||||||
Task.ofThen(() -> {
|
Task.composeAsync(() -> {
|
||||||
if (!repository.getVersionJar(version).exists())
|
if (!repository.getVersionJar(version).exists())
|
||||||
return new GameDownloadTask(this, null, version);
|
return new GameDownloadTask(this, null, version);
|
||||||
else
|
else
|
||||||
@@ -83,12 +81,12 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task checkLibraryCompletionAsync(Version version) {
|
public Task<?> checkLibraryCompletionAsync(Version version) {
|
||||||
return new GameLibrariesTask(this, version);
|
return new GameLibrariesTask(this, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskResult<Version> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) {
|
public Task<Version> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) {
|
||||||
VersionList<?> versionList = getVersionList(libraryId);
|
VersionList<?> versionList = getVersionList(libraryId);
|
||||||
return versionList.loadAsync(gameVersion, getDownloadProvider())
|
return versionList.loadAsync(gameVersion, getDownloadProvider())
|
||||||
.thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion)
|
.thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion)
|
||||||
@@ -96,8 +94,8 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskResult<Version> installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) {
|
public Task<Version> installLibraryAsync(Version oldVersion, RemoteVersion libraryVersion) {
|
||||||
TaskResult<Version> task;
|
Task<Version> task;
|
||||||
if (libraryVersion instanceof ForgeRemoteVersion)
|
if (libraryVersion instanceof ForgeRemoteVersion)
|
||||||
task = new ForgeInstallTask(this, oldVersion, (ForgeRemoteVersion) libraryVersion);
|
task = new ForgeInstallTask(this, oldVersion, (ForgeRemoteVersion) libraryVersion);
|
||||||
else if (libraryVersion instanceof LiteLoaderRemoteVersion)
|
else if (libraryVersion instanceof LiteLoaderRemoteVersion)
|
||||||
@@ -113,7 +111,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ExceptionalFunction<Version, TaskResult<Version>, ?> installLibraryAsync(RemoteVersion libraryVersion) {
|
public ExceptionalFunction<Version, Task<Version>, ?> installLibraryAsync(RemoteVersion libraryVersion) {
|
||||||
return version -> installLibraryAsync(version, libraryVersion);
|
return version -> installLibraryAsync(version, libraryVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ package org.jackhuang.hmcl.download;
|
|||||||
|
|
||||||
import org.jackhuang.hmcl.download.game.*;
|
import org.jackhuang.hmcl.download.game.*;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.ParallelTask;
|
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
|
|
||||||
@@ -48,16 +46,16 @@ public class DefaultGameBuilder extends GameBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task buildAsync() {
|
public Task<?> buildAsync() {
|
||||||
return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> {
|
return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> {
|
||||||
Version original = JsonUtils.GSON.fromJson(rawJson, Version.class);
|
Version original = JsonUtils.GSON.fromJson(rawJson, Version.class);
|
||||||
Version version = original.setId(name).setJar(null);
|
Version version = original.setId(name).setJar(null);
|
||||||
Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask(
|
Task<?> vanillaTask = downloadGameAsync(gameVersion, version).thenCompose(Task.allOf(
|
||||||
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY),
|
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY),
|
||||||
new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||||
).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant.
|
).withCompose(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant.
|
||||||
|
|
||||||
TaskResult<Version> libraryTask = vanillaTask.thenSupply(() -> version);
|
Task<Version> libraryTask = vanillaTask.thenSupply(() -> version);
|
||||||
|
|
||||||
if (toolVersions.containsKey("forge"))
|
if (toolVersions.containsKey("forge"))
|
||||||
libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge"));
|
libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge"));
|
||||||
@@ -76,11 +74,11 @@ public class DefaultGameBuilder extends GameBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExceptionalFunction<Version, TaskResult<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId) {
|
private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId) {
|
||||||
return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, toolVersions.get(libraryId));
|
return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, toolVersions.get(libraryId));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Task downloadGameAsync(String gameVersion, Version version) {
|
protected Task<Void> downloadGameAsync(String gameVersion, Version version) {
|
||||||
return new GameDownloadTask(dependencyManager, gameVersion, version);
|
return new GameDownloadTask(dependencyManager, gameVersion, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public interface DependencyManager {
|
|||||||
*
|
*
|
||||||
* @return the task to check game completion.
|
* @return the task to check game completion.
|
||||||
*/
|
*/
|
||||||
Task checkGameCompletionAsync(Version version);
|
Task<?> checkGameCompletionAsync(Version version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the game is complete.
|
* Check if the game is complete.
|
||||||
@@ -54,7 +54,7 @@ public interface DependencyManager {
|
|||||||
*
|
*
|
||||||
* @return the task to check game completion.
|
* @return the task to check game completion.
|
||||||
*/
|
*/
|
||||||
Task checkLibraryCompletionAsync(Version version);
|
Task<?> checkLibraryCompletionAsync(Version version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine.
|
* The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine.
|
||||||
@@ -71,7 +71,7 @@ public interface DependencyManager {
|
|||||||
* @param libraryVersion the version of being installed library.
|
* @param libraryVersion the version of being installed library.
|
||||||
* @return the task to install the specific library.
|
* @return the task to install the specific library.
|
||||||
*/
|
*/
|
||||||
Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion);
|
Task<?> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a library to a version.
|
* Install a library to a version.
|
||||||
@@ -81,7 +81,7 @@ public interface DependencyManager {
|
|||||||
* @param libraryVersion the remote version of being installed library.
|
* @param libraryVersion the remote version of being installed library.
|
||||||
* @return the task to install the specific library.
|
* @return the task to install the specific library.
|
||||||
*/
|
*/
|
||||||
Task installLibraryAsync(Version version, RemoteVersion libraryVersion);
|
Task<?> installLibraryAsync(Version version, RemoteVersion libraryVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get registered version list.
|
* Get registered version list.
|
||||||
|
|||||||
@@ -72,5 +72,5 @@ public abstract class GameBuilder {
|
|||||||
/**
|
/**
|
||||||
* @return the task that can build thw whole Minecraft environment
|
* @return the task that can build thw whole Minecraft environment
|
||||||
*/
|
*/
|
||||||
public abstract Task buildAsync();
|
public abstract Task<?> buildAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
package org.jackhuang.hmcl.download;
|
package org.jackhuang.hmcl.download;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.game.*;
|
import org.jackhuang.hmcl.game.*;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
|
||||||
public class MaintainTask extends TaskResult<Version> {
|
public class MaintainTask extends Task<Version> {
|
||||||
|
|
||||||
private final Version version;
|
private final Version version;
|
||||||
|
|
||||||
|
|||||||
@@ -62,19 +62,19 @@ public abstract class VersionList<T extends RemoteVersion> {
|
|||||||
* @param downloadProvider DownloadProvider
|
* @param downloadProvider DownloadProvider
|
||||||
* @return the task to reload the remote version list.
|
* @return the task to reload the remote version list.
|
||||||
*/
|
*/
|
||||||
public abstract Task refreshAsync(DownloadProvider downloadProvider);
|
public abstract Task<?> refreshAsync(DownloadProvider downloadProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gameVersion the remote version depends on
|
* @param gameVersion the remote version depends on
|
||||||
* @param downloadProvider DownloadProvider
|
* @param downloadProvider DownloadProvider
|
||||||
* @return the task to reload the remote version list.
|
* @return the task to reload the remote version list.
|
||||||
*/
|
*/
|
||||||
public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(String gameVersion, DownloadProvider downloadProvider) {
|
||||||
return refreshAsync(downloadProvider);
|
return refreshAsync(downloadProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task loadAsync(DownloadProvider downloadProvider) {
|
public Task<?> loadAsync(DownloadProvider downloadProvider) {
|
||||||
return Task.ofThen(() -> {
|
return Task.composeAsync(() -> {
|
||||||
lock.readLock().lock();
|
lock.readLock().lock();
|
||||||
boolean loaded;
|
boolean loaded;
|
||||||
|
|
||||||
@@ -87,8 +87,8 @@ public abstract class VersionList<T extends RemoteVersion> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task loadAsync(String gameVersion, DownloadProvider downloadProvider) {
|
public Task<?> loadAsync(String gameVersion, DownloadProvider downloadProvider) {
|
||||||
return Task.ofThen(() -> {
|
return Task.composeAsync(() -> {
|
||||||
lock.readLock().lock();
|
lock.readLock().lock();
|
||||||
boolean loaded;
|
boolean loaded;
|
||||||
|
|
||||||
|
|||||||
@@ -46,21 +46,21 @@ public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task loadAsync(DownloadProvider downloadProvider) {
|
public Task<?> loadAsync(DownloadProvider downloadProvider) {
|
||||||
throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list.");
|
throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list.");
|
throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(String gameVersion, DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(String gameVersion, DownloadProvider downloadProvider) {
|
||||||
final GetTask task = new GetTask(NetworkUtils.toURL("https://bmclapi2.bangbang93.com/forge/minecraft/" + gameVersion));
|
final GetTask task = new GetTask(NetworkUtils.toURL("https://bmclapi2.bangbang93.com/forge/minecraft/" + gameVersion));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
|||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||||
|
|
||||||
@@ -34,14 +33,14 @@ import java.util.Collections;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class ForgeInstallTask extends TaskResult<Version> {
|
public final class ForgeInstallTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private Path installer;
|
private Path installer;
|
||||||
private final ForgeRemoteVersion remote;
|
private final ForgeRemoteVersion remote;
|
||||||
private Task dependent;
|
private Task<Void> dependent;
|
||||||
private TaskResult<Version> dependency;
|
private Task<Version> dependency;
|
||||||
|
|
||||||
public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) {
|
public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
@@ -73,20 +72,15 @@ public final class ForgeInstallTask extends TaskResult<Version> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(dependent);
|
return Collections.singleton(dependent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return Collections.singleton(dependency);
|
return Collections.singleton(dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRelyingOnDependencies() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0)
|
if (VersionNumber.VERSION_COMPARATOR.compare("1.13", remote.getGameVersion()) <= 0)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
|||||||
import org.jackhuang.hmcl.download.game.GameLibrariesTask;
|
import org.jackhuang.hmcl.download.game.GameLibrariesTask;
|
||||||
import org.jackhuang.hmcl.game.*;
|
import org.jackhuang.hmcl.game.*;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
@@ -49,19 +48,19 @@ import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
|||||||
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
||||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
|
|
||||||
public class ForgeNewInstallTask extends TaskResult<Version> {
|
public class ForgeNewInstallTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final DefaultGameRepository gameRepository;
|
private final DefaultGameRepository gameRepository;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final Path installer;
|
private final Path installer;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
private ForgeNewInstallProfile profile;
|
private ForgeNewInstallProfile profile;
|
||||||
private Version forgeVersion;
|
private Version forgeVersion;
|
||||||
|
|
||||||
public ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) {
|
ForgeNewInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
this.gameRepository = dependencyManager.getGameRepository();
|
this.gameRepository = dependencyManager.getGameRepository();
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@@ -80,12 +79,12 @@ public class ForgeNewInstallTask extends TaskResult<Version> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package org.jackhuang.hmcl.download.forge;
|
|||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.game.*;
|
import org.jackhuang.hmcl.game.*;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||||
@@ -31,21 +30,21 @@ import java.util.*;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class ForgeOldInstallTask extends TaskResult<Version> {
|
public class ForgeOldInstallTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final Path installer;
|
private final Path installer;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
public ForgeOldInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) {
|
ForgeOldInstallTask(DefaultDependencyManager dependencyManager, Version version, Path installer) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public List<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ public final class ForgeVersionList extends VersionList<ForgeRemoteVersion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
final GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(FORGE_LIST)));
|
final GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(FORGE_LIST)));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class GameAssetDownloadTask extends Task {
|
public final class GameAssetDownloadTask extends Task<Void> {
|
||||||
|
|
||||||
private final AbstractDependencyManager dependencyManager;
|
private final AbstractDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final AssetIndexInfo assetIndexInfo;
|
private final AssetIndexInfo assetIndexInfo;
|
||||||
private final File assetIndexFile;
|
private final File assetIndexFile;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -64,12 +64,12 @@ public final class GameAssetDownloadTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.jackhuang.hmcl.game.AssetIndexInfo;
|
|||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.util.CacheRepository;
|
|
||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -34,11 +33,11 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class GameAssetIndexDownloadTask extends Task {
|
public final class GameAssetIndexDownloadTask extends Task<Void> {
|
||||||
|
|
||||||
private final AbstractDependencyManager dependencyManager;
|
private final AbstractDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -53,7 +52,7 @@ public final class GameAssetIndexDownloadTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public List<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jackhuang.hmcl.util.CacheRepository;
|
|||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -33,11 +34,11 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class GameDownloadTask extends Task {
|
public final class GameDownloadTask extends Task<Void> {
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final String gameVersion;
|
private final String gameVersion;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
public GameDownloadTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version) {
|
public GameDownloadTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
@@ -48,7 +49,7 @@ public final class GameDownloadTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class GameLibrariesTask extends Task {
|
public final class GameLibrariesTask extends Task<Void> {
|
||||||
|
|
||||||
private final AbstractDependencyManager dependencyManager;
|
private final AbstractDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final List<Library> libraries;
|
private final List<Library> libraries;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -64,7 +64,7 @@ public final class GameLibrariesTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public List<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ public final class GameVersionList extends VersionList<GameRemoteVersion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.getVersionListURL()));
|
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.getVersionListURL()));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ package org.jackhuang.hmcl.download.game;
|
|||||||
import org.jackhuang.hmcl.game.CompatibilityRule;
|
import org.jackhuang.hmcl.game.CompatibilityRule;
|
||||||
import org.jackhuang.hmcl.game.Library;
|
import org.jackhuang.hmcl.game.Library;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.util.SimpleMultimap;
|
import org.jackhuang.hmcl.util.SimpleMultimap;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||||
@@ -31,7 +31,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class LibrariesUniqueTask extends TaskResult<Version> {
|
public class LibrariesUniqueTask extends Task<Version> {
|
||||||
private final Version version;
|
private final Version version;
|
||||||
|
|
||||||
public LibrariesUniqueTask(Version version) {
|
public LibrariesUniqueTask(Version version) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import java.util.logging.Level;
|
|||||||
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
||||||
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
||||||
|
|
||||||
public class LibraryDownloadTask extends Task {
|
public class LibraryDownloadTask extends Task<Void> {
|
||||||
private FileDownloadTask task;
|
private FileDownloadTask task;
|
||||||
protected final File jar;
|
protected final File jar;
|
||||||
protected final DefaultCacheRepository cacheRepository;
|
protected final DefaultCacheRepository cacheRepository;
|
||||||
@@ -74,7 +74,7 @@ public class LibraryDownloadTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
if (cached) return Collections.emptyList();
|
if (cached) return Collections.emptyList();
|
||||||
else return Collections.singleton(task);
|
else return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.jackhuang.hmcl.download.RemoteVersion;
|
|||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.task.GetTask;
|
import org.jackhuang.hmcl.task.GetTask;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -33,11 +32,11 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class VersionJsonDownloadTask extends TaskResult<String> {
|
public final class VersionJsonDownloadTask extends Task<String> {
|
||||||
private final String gameVersion;
|
private final String gameVersion;
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
private final VersionList<?> gameVersionList;
|
private final VersionList<?> gameVersionList;
|
||||||
|
|
||||||
public VersionJsonDownloadTask(String gameVersion, DefaultDependencyManager dependencyManager) {
|
public VersionJsonDownloadTask(String gameVersion, DefaultDependencyManager dependencyManager) {
|
||||||
@@ -52,12 +51,12 @@ public final class VersionJsonDownloadTask extends TaskResult<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jackhuang.hmcl.download.game;
|
|||||||
|
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ import java.io.File;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class VersionJsonSaveTask extends TaskResult<Version> {
|
public final class VersionJsonSaveTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -52,11 +51,11 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST)));
|
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST)));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import org.jackhuang.hmcl.game.Library;
|
|||||||
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -36,13 +35,13 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class LiteLoaderInstallTask extends TaskResult<Version> {
|
public final class LiteLoaderInstallTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final LiteLoaderRemoteVersion remote;
|
private final LiteLoaderRemoteVersion remote;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, Version version, LiteLoaderRemoteVersion remoteVersion) {
|
public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, Version version, LiteLoaderRemoteVersion remoteVersion) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
@@ -51,12 +50,12 @@ public final class LiteLoaderInstallTask extends TaskResult<Version> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -52,11 +51,11 @@ public final class LiteLoaderVersionList extends VersionList<LiteLoaderRemoteVer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST)));
|
GetTask task = new GetTask(NetworkUtils.toURL(downloadProvider.injectURL(LITELOADER_LIST)));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task refreshAsync(DownloadProvider downloadProvider) {
|
public Task<?> refreshAsync(DownloadProvider downloadProvider) {
|
||||||
GetTask task = new GetTask(NetworkUtils.toURL("http://bmclapi2.bangbang93.com/optifine/versionlist"));
|
GetTask task = new GetTask(NetworkUtils.toURL("http://bmclapi2.bangbang93.com/optifine/versionlist"));
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(task);
|
return Collections.singleton(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import org.jackhuang.hmcl.game.Library;
|
|||||||
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -35,13 +34,13 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class OptiFineInstallTask extends TaskResult<Version> {
|
public final class OptiFineInstallTask extends Task<Version> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final OptiFineRemoteVersion remote;
|
private final OptiFineRemoteVersion remote;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) {
|
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
@@ -50,12 +49,12 @@ public final class OptiFineInstallTask extends TaskResult<Version> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ public interface GameRepository extends VersionProvider {
|
|||||||
*/
|
*/
|
||||||
void refreshVersions();
|
void refreshVersions();
|
||||||
|
|
||||||
default Task refreshVersionsAsync() {
|
default Task<Void> refreshVersionsAsync() {
|
||||||
return Task.of(this::refreshVersions);
|
return Task.runAsync(this::refreshVersions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ import java.util.stream.Collectors;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class CurseCompletionTask extends Task {
|
public final class CurseCompletionTask extends Task<Void> {
|
||||||
|
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
private final ModManager modManager;
|
private final ModManager modManager;
|
||||||
private final String version;
|
private final String version;
|
||||||
private CurseManifest manifest = null;
|
private CurseManifest manifest = null;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -86,12 +86,12 @@ public final class CurseCompletionTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ public final class CurseCompletionTask extends Task {
|
|||||||
// Let this task fail if the curse manifest has not been completed.
|
// Let this task fail if the curse manifest has not been completed.
|
||||||
// But continue other downloads.
|
// But continue other downloads.
|
||||||
if (!flag.get() || notFound.get())
|
if (!flag.get() || notFound.get())
|
||||||
dependencies.add(Task.of(() -> {
|
dependencies.add(Task.runAsync(() -> {
|
||||||
if (notFound.get())
|
if (notFound.get())
|
||||||
throw new CurseCompletionException(new FileNotFoundException());
|
throw new CurseCompletionException(new FileNotFoundException());
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class CurseInstallTask extends Task {
|
public final class CurseInstallTask extends Task<Void> {
|
||||||
|
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
@@ -48,8 +48,8 @@ public final class CurseInstallTask extends Task {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final File run;
|
private final File run;
|
||||||
private final ModpackConfiguration<CurseManifest> config;
|
private final ModpackConfiguration<CurseManifest> config;
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -99,12 +99,12 @@ public final class CurseInstallTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import java.util.List;
|
|||||||
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
||||||
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
||||||
|
|
||||||
public final class MinecraftInstanceTask<T> extends Task {
|
public final class MinecraftInstanceTask<T> extends Task<Void> {
|
||||||
|
|
||||||
private final File zipFile;
|
private final File zipFile;
|
||||||
private final Charset encoding;
|
private final Charset encoding;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import java.util.function.Predicate;
|
|||||||
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
import static org.jackhuang.hmcl.util.DigestUtils.digest;
|
||||||
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
import static org.jackhuang.hmcl.util.Hex.encodeHex;
|
||||||
|
|
||||||
public class ModpackInstallTask<T> extends Task {
|
public class ModpackInstallTask<T> extends Task<Void> {
|
||||||
|
|
||||||
private final File modpackFile;
|
private final File modpackFile;
|
||||||
private final File dest;
|
private final File dest;
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ import java.nio.file.Path;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public class ModpackUpdateTask extends Task {
|
public class ModpackUpdateTask extends Task<Void> {
|
||||||
|
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
private final String id;
|
private final String id;
|
||||||
private final Task updateTask;
|
private final Task<?> updateTask;
|
||||||
private final Path backupFolder;
|
private final Path backupFolder;
|
||||||
|
|
||||||
public ModpackUpdateTask(DefaultGameRepository repository, String id, Task updateTask) {
|
public ModpackUpdateTask(DefaultGameRepository repository, String id, Task<?> updateTask) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.updateTask = updateTask;
|
this.updateTask = updateTask;
|
||||||
@@ -49,7 +49,7 @@ public class ModpackUpdateTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return Collections.singleton(updateTask);
|
return Collections.singleton(updateTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,15 +46,15 @@ import java.util.Optional;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class MultiMCModpackInstallTask extends Task {
|
public final class MultiMCModpackInstallTask extends Task<Void> {
|
||||||
|
|
||||||
private final File zipFile;
|
private final File zipFile;
|
||||||
private final Modpack modpack;
|
private final Modpack modpack;
|
||||||
private final MultiMCInstanceConfiguration manifest;
|
private final MultiMCInstanceConfiguration manifest;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final DefaultGameRepository repository;
|
private final DefaultGameRepository repository;
|
||||||
private final List<Task> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
private final List<Task> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
|
|
||||||
public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, MultiMCInstanceConfiguration manifest, String name) {
|
public MultiMCModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, MultiMCInstanceConfiguration manifest, String name) {
|
||||||
this.zipFile = zipFile;
|
this.zipFile = zipFile;
|
||||||
@@ -91,7 +91,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependencies() {
|
public List<Task<?>> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getDependents() {
|
public List<Task<?>> getDependents() {
|
||||||
return dependents;
|
return dependents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher
|
|
||||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.task;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.AutoTypingMap;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A task that combines two tasks and make sure [pred] runs before succ.
|
|
||||||
*
|
|
||||||
* @author huangyuhui
|
|
||||||
*/
|
|
||||||
final class CoupleTask extends Task {
|
|
||||||
|
|
||||||
private final boolean relyingOnDependents;
|
|
||||||
private final Task pred;
|
|
||||||
private Task succ;
|
|
||||||
private final ExceptionalSupplier<Task, ?> supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A task that combines two tasks and make sure pred runs before succ.
|
|
||||||
*
|
|
||||||
* @param pred the task that runs before supplier.
|
|
||||||
* @param supplier 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.
|
|
||||||
* @param relyingOnDependents true if this task chain will be broken when task pred fails.
|
|
||||||
*/
|
|
||||||
CoupleTask(Task pred, ExceptionalSupplier<Task, ?> supplier, boolean relyingOnDependents) {
|
|
||||||
this.pred = pred;
|
|
||||||
this.supplier = supplier;
|
|
||||||
this.relyingOnDependents = relyingOnDependents;
|
|
||||||
|
|
||||||
setSignificance(TaskSignificance.MODERATE);
|
|
||||||
setName(supplier.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
setName(supplier.toString());
|
|
||||||
succ = supplier.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Task> getDependents() {
|
|
||||||
return pred == null ? Collections.emptySet() : Collections.singleton(pred);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Task> getDependencies() {
|
|
||||||
return succ == null ? Collections.emptySet() : Collections.singleton(succ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRelyingOnDependents() {
|
|
||||||
return relyingOnDependents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,7 @@ import static org.jackhuang.hmcl.util.DigestUtils.getDigest;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public class FileDownloadTask extends Task {
|
public class FileDownloadTask extends Task<Void> {
|
||||||
|
|
||||||
public static class IntegrityCheck {
|
public static class IntegrityCheck {
|
||||||
private String algorithm;
|
private String algorithm;
|
||||||
|
|||||||
@@ -36,33 +36,27 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huang
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class GetTask extends TaskResult<String> {
|
public final class GetTask extends Task<String> {
|
||||||
|
|
||||||
private final URL url;
|
private final URL url;
|
||||||
private final Charset charset;
|
private final Charset charset;
|
||||||
private final int retry;
|
private final int retry;
|
||||||
private final String id;
|
|
||||||
private CacheRepository repository = CacheRepository.getInstance();
|
private CacheRepository repository = CacheRepository.getInstance();
|
||||||
|
|
||||||
public GetTask(URL url) {
|
public GetTask(URL url) {
|
||||||
this(url, ID);
|
this(url, UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetTask(URL url, String id) {
|
public GetTask(URL url, Charset charset) {
|
||||||
this(url, id, UTF_8);
|
this(url, charset, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetTask(URL url, String id, Charset charset) {
|
public GetTask(URL url, Charset charset, int retry) {
|
||||||
this(url, id, charset, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetTask(URL url, String id, Charset charset, int retry) {
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
this.retry = retry;
|
this.retry = retry;
|
||||||
this.id = id;
|
|
||||||
|
|
||||||
setName(url.toString());
|
setName(url.toString());
|
||||||
}
|
}
|
||||||
@@ -138,9 +132,4 @@ public final class GetTask extends TaskResult<String> {
|
|||||||
throw new DownloadException(url, exception);
|
throw new DownloadException(url, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The default task result ID.
|
|
||||||
*/
|
|
||||||
public static final String ID = "http_get";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher
|
|
||||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.task;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The tasks that provides a way to execute tasks parallelly.
|
|
||||||
* Fails when some of {@link #tasks} failed.
|
|
||||||
*
|
|
||||||
* @author huangyuhui
|
|
||||||
*/
|
|
||||||
public final class ParallelTask extends Task {
|
|
||||||
|
|
||||||
private final Collection<Task> tasks;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param tasks the tasks that can be executed parallelly.
|
|
||||||
*/
|
|
||||||
public ParallelTask(Task... tasks) {
|
|
||||||
this.tasks = Arrays.asList(tasks);
|
|
||||||
setSignificance(TaskSignificance.MINOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParallelTask(Collection<Task> tasks) {
|
|
||||||
this.tasks = tasks;
|
|
||||||
setSignificance(TaskSignificance.MINOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Task> getDependents() {
|
|
||||||
return tasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher
|
|
||||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.task;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author huangyuhui
|
|
||||||
*/
|
|
||||||
class SimpleTask extends Task {
|
|
||||||
|
|
||||||
private final ExceptionalRunnable<?> closure;
|
|
||||||
private final Scheduler scheduler;
|
|
||||||
|
|
||||||
public SimpleTask(String name, ExceptionalRunnable<?> closure, Scheduler scheduler) {
|
|
||||||
this.closure = closure;
|
|
||||||
this.scheduler = scheduler;
|
|
||||||
|
|
||||||
if (name == null) {
|
|
||||||
setSignificance(TaskSignificance.MINOR);
|
|
||||||
setName(closure.toString());
|
|
||||||
} else {
|
|
||||||
setName(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scheduler getScheduler() {
|
|
||||||
return scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
closure.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher
|
|
||||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.task;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.AutoTypingMap;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author huangyuhui
|
|
||||||
*/
|
|
||||||
class SimpleTaskResult<V> extends TaskResult<V> {
|
|
||||||
|
|
||||||
private final Callable<V> callable;
|
|
||||||
|
|
||||||
public SimpleTaskResult(Callable<V> callable) {
|
|
||||||
this.callable = callable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTaskResult(ExceptionalSupplier<V, ?> supplier) {
|
|
||||||
this.callable = supplier.toCallable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
setResult(callable.call());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,13 +27,16 @@ import org.jackhuang.hmcl.util.InvocationDispatcher;
|
|||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
import org.jackhuang.hmcl.util.ReflectionHelper;
|
import org.jackhuang.hmcl.util.ReflectionHelper;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
|
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
|
||||||
|
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
|
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,15 +44,15 @@ import java.util.logging.Level;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public abstract class Task {
|
public abstract class Task<T> {
|
||||||
|
|
||||||
private final EventManager<TaskEvent> onDone = new EventManager<>();
|
private final EventManager<TaskEvent> onDone = new EventManager<>();
|
||||||
|
|
||||||
private TaskSignificance significance = TaskSignificance.MAJOR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if not logging when executing this task.
|
* True if not logging when executing this task.
|
||||||
*/
|
*/
|
||||||
|
private TaskSignificance significance = TaskSignificance.MAJOR;
|
||||||
|
|
||||||
public final TaskSignificance getSignificance() {
|
public final TaskSignificance getSignificance() {
|
||||||
return significance;
|
return significance;
|
||||||
}
|
}
|
||||||
@@ -58,6 +61,7 @@ public abstract class Task {
|
|||||||
this.significance = significance;
|
this.significance = significance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// state
|
||||||
private TaskState state = TaskState.READY;
|
private TaskState state = TaskState.READY;
|
||||||
|
|
||||||
public TaskState getState() {
|
public TaskState getState() {
|
||||||
@@ -68,6 +72,7 @@ public abstract class Task {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// last exception
|
||||||
private Exception lastException;
|
private Exception lastException;
|
||||||
|
|
||||||
public Exception getLastException() {
|
public Exception getLastException() {
|
||||||
@@ -85,6 +90,7 @@ public abstract class Task {
|
|||||||
return Schedulers.defaultScheduler();
|
return Schedulers.defaultScheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dependents succeeded
|
||||||
private boolean dependentsSucceeded = false;
|
private boolean dependentsSucceeded = false;
|
||||||
|
|
||||||
public boolean isDependentsSucceeded() {
|
public boolean isDependentsSucceeded() {
|
||||||
@@ -95,6 +101,7 @@ public abstract class Task {
|
|||||||
dependentsSucceeded = true;
|
dependentsSucceeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dependencies succeeded
|
||||||
private boolean dependenciesSucceeded = false;
|
private boolean dependenciesSucceeded = false;
|
||||||
|
|
||||||
public boolean isDependenciesSucceeded() {
|
public boolean isDependenciesSucceeded() {
|
||||||
@@ -123,17 +130,49 @@ public abstract class Task {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// name
|
||||||
private String name = getClass().getName();
|
private String name = getClass().getName();
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task setName(String name) {
|
public Task<T> setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// result
|
||||||
|
private T result;
|
||||||
|
private Consumer<T> resultConsumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the result of this task.
|
||||||
|
*
|
||||||
|
* The result will be generated only if the execution is completed.
|
||||||
|
*/
|
||||||
|
public T getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setResult(T result) {
|
||||||
|
this.result = result;
|
||||||
|
if (resultConsumer != null)
|
||||||
|
resultConsumer.accept(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync the result of this task by given action.
|
||||||
|
*
|
||||||
|
* @param action the action to perform when result of this task changed
|
||||||
|
* @return this Task
|
||||||
|
*/
|
||||||
|
public Task<T> storeTo(Consumer<T> action) {
|
||||||
|
this.resultConsumer = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// execution
|
||||||
public boolean doPreExecute() {
|
public boolean doPreExecute() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -171,7 +210,7 @@ public abstract class Task {
|
|||||||
/**
|
/**
|
||||||
* The collection of sub-tasks that should execute **before** this task running.
|
* The collection of sub-tasks that should execute **before** this task running.
|
||||||
*/
|
*/
|
||||||
public Collection<? extends Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +218,7 @@ public abstract class Task {
|
|||||||
* The collection of sub-tasks that should execute **after** this task running.
|
* The collection of sub-tasks that should execute **after** this task running.
|
||||||
* Will not be executed if execution fails.
|
* Will not be executed if execution fails.
|
||||||
*/
|
*/
|
||||||
public Collection<? extends Task> getDependencies() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,15 +271,15 @@ public abstract class Task {
|
|||||||
if (getSignificance().shouldLog())
|
if (getSignificance().shouldLog())
|
||||||
Logging.LOG.log(Level.FINE, "Executing task: " + getName());
|
Logging.LOG.log(Level.FINE, "Executing task: " + getName());
|
||||||
|
|
||||||
for (Task task : getDependents())
|
for (Task<?> task : getDependents())
|
||||||
doSubTask(task);
|
doSubTask(task);
|
||||||
execute();
|
execute();
|
||||||
for (Task task : getDependencies())
|
for (Task<?> task : getDependencies())
|
||||||
doSubTask(task);
|
doSubTask(task);
|
||||||
onDone.fireEvent(new TaskEvent(this, this, false));
|
onDone.fireEvent(new TaskEvent(this, this, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSubTask(Task task) throws Exception {
|
private void doSubTask(Task<?> task) throws Exception {
|
||||||
message.bind(task.message);
|
message.bind(task.message);
|
||||||
progress.bind(task.progress);
|
progress.bind(task.progress);
|
||||||
task.run();
|
task.run();
|
||||||
@@ -273,61 +312,240 @@ public abstract class Task {
|
|||||||
return executor().test();
|
return executor().test();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Task then(Task b) {
|
/**
|
||||||
return then(convert(b));
|
* Returns a new Task that, when this task completes
|
||||||
}
|
* normally, is executed using the default Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied function.
|
||||||
public final Task then(ExceptionalSupplier<Task, ?> b) {
|
*
|
||||||
return new CoupleTask(this, b, true);
|
* @param fn the function to use to compute the value of the returned Task
|
||||||
|
* @param <U> the function's return type
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <U, E extends Exception> Task<U> thenApply(ExceptionalFunction<T, U, E> fn) {
|
||||||
|
return thenApply(Schedulers.defaultScheduler(), fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new TaskResult that, when this task completes
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the supplied Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied function.
|
||||||
|
*
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @param fn the function to use to compute the value of the returned Task
|
||||||
|
* @param <U> the function's return type
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <U, E extends Exception> Task<U> thenApply(Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
||||||
|
return thenApply(getCaller(), scheduler, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the supplied Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied function.
|
||||||
|
*
|
||||||
|
* @param name the name of this new Task for displaying
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @param fn the function to use to compute the value of the returned Task
|
||||||
|
* @param <U> the function's return type
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <U, E extends Exception> Task<U> thenApply(String name, Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
||||||
|
return new UniApply<>(name, scheduler, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the default Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied action.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenAccept(ExceptionalConsumer<T, E> action) {
|
||||||
|
return thenAccept(Schedulers.defaultScheduler(), action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the supplied Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied action.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenAccept(Scheduler scheduler, ExceptionalConsumer<T, E> action) {
|
||||||
|
return thenAccept(getCaller(), scheduler, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the supplied Scheduler, with this
|
||||||
|
* task's result as the argument to the supplied action.
|
||||||
|
*
|
||||||
|
* @param name the name of this new Task for displaying
|
||||||
|
* @param action the action to perform before completing the returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenAccept(String name, Scheduler scheduler, ExceptionalConsumer<T, E> action) {
|
||||||
|
return thenApply(name, scheduler, result -> {
|
||||||
|
action.accept(result);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the default Scheduler.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenRun(ExceptionalRunnable<E> action) {
|
||||||
|
return thenRun(Schedulers.defaultScheduler(), action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the supplied Scheduler.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenRun(Scheduler scheduler, ExceptionalRunnable<E> action) {
|
||||||
|
return thenRun(getCaller(), scheduler, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the supplied Scheduler.
|
||||||
|
*
|
||||||
|
* @param name the name of this new Task for displaying
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> thenRun(String name, Scheduler scheduler, ExceptionalRunnable<E> action) {
|
||||||
|
return thenApply(name, scheduler, ignore -> {
|
||||||
|
action.run();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
* normally, is executed using the default Scheduler.
|
* normally, is executed using the default Scheduler.
|
||||||
*
|
*
|
||||||
* @param fn the function to use to compute the value of the returned TaskResult
|
* @param fn the function to use to compute the value of the returned Task
|
||||||
* @param <U> the function's return type
|
* @param <U> the function's return type
|
||||||
* @return the new TaskResult
|
* @return the new Task
|
||||||
*/
|
*/
|
||||||
public final <U> TaskResult<U> thenSupply(Callable<U> fn) {
|
public final <U> Task<U> thenSupply(Callable<U> fn) {
|
||||||
return thenCompose(() -> Task.ofResult(fn));
|
return thenCompose(() -> Task.supplyAsync(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new TaskResult that, when this task completes
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, is executed using the default Scheduler.
|
||||||
|
*
|
||||||
|
* @param name the name of this new Task for displaying
|
||||||
|
* @param fn the function to use to compute the value of the returned Task
|
||||||
|
* @param <U> the function's return type
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public final <U> Task<U> thenSupply(String name, Callable<U> fn) {
|
||||||
|
return thenCompose(() -> Task.supplyAsync(name, fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
* normally, is executed.
|
* normally, is executed.
|
||||||
*
|
*
|
||||||
* @param fn the function returning a new TaskResult
|
* @param other the another Task
|
||||||
* @param <U> the type of the returned TaskResult's result
|
* @param <U> the type of the returned Task's result
|
||||||
* @return the TaskResult
|
* @return the Task
|
||||||
*/
|
*/
|
||||||
public final <U> TaskResult<U> thenCompose(ExceptionalSupplier<TaskResult<U>, ?> fn) {
|
public final <U> Task<U> thenCompose(Task<U> other) {
|
||||||
return new TaskResult<U>() {
|
return thenCompose(() -> other);
|
||||||
TaskResult<U> then;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends Task> getDependents() {
|
|
||||||
return Collections.singleton(Task.this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void execute() throws Exception {
|
* Returns a new Task that, when this task completes
|
||||||
then = fn.get().storeTo(this::setResult);
|
* normally, is executed.
|
||||||
|
*
|
||||||
|
* @param fn the function returning a new Task
|
||||||
|
* @param <U> the type of the returned Task's result
|
||||||
|
* @return the Task
|
||||||
|
*/
|
||||||
|
public final <U> Task<U> thenCompose(ExceptionalSupplier<Task<U>, ?> fn) {
|
||||||
|
return new UniCompose<>(fn, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public Collection<? extends Task> getDependencies() {
|
* Returns a new Task that, when this task completes
|
||||||
return then == null ? Collections.emptyList() : Collections.singleton(then);
|
* normally, is executed with result of this task as the argument
|
||||||
}
|
* to the supplied function.
|
||||||
};
|
*
|
||||||
|
* @param fn the function returning a new Task
|
||||||
|
* @param <U> the type of the returned Task's result
|
||||||
|
* @return the Task
|
||||||
|
*/
|
||||||
|
public <U, E extends Exception> Task<U> thenCompose(ExceptionalFunction<T, Task<U>, E> fn) {
|
||||||
|
return new UniCompose<>(fn, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Task with(Task b) {
|
public final <U> Task<U> withCompose(Task<U> other) {
|
||||||
return with(convert(b));
|
return withCompose(() -> other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final <E extends Exception> Task with(ExceptionalSupplier<Task, E> b) {
|
public final <U, E extends Exception> Task<U> withCompose(ExceptionalSupplier<Task<U>, E> fn) {
|
||||||
return new CoupleTask(this, b, false);
|
return new UniCompose<>(fn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the default Scheduler.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> withRun(ExceptionalRunnable<E> action) {
|
||||||
|
return withRun(Schedulers.defaultScheduler(), action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the supplied Scheduler.
|
||||||
|
*
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> withRun(Scheduler scheduler, ExceptionalRunnable<E> action) {
|
||||||
|
return withRun(getCaller(), scheduler, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that, when this task completes
|
||||||
|
* normally, executes the given action using the supplied Scheduler.
|
||||||
|
*
|
||||||
|
* @param name the name of this new Task for displaying
|
||||||
|
* @param action the action to perform before completing the
|
||||||
|
* returned Task
|
||||||
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E extends Exception> Task<Void> withRun(String name, Scheduler scheduler, ExceptionalRunnable<E> action) {
|
||||||
|
return new UniCompose<>(() -> Task.runAsync(name, scheduler, action), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,7 +562,7 @@ public abstract class Task {
|
|||||||
* @param action the action to perform
|
* @param action the action to perform
|
||||||
* @return the new Task
|
* @return the new Task
|
||||||
*/
|
*/
|
||||||
public final Task whenComplete(FinalizedCallback action) {
|
public final Task<Void> whenComplete(FinalizedCallback action) {
|
||||||
return whenComplete(Schedulers.defaultScheduler(), action);
|
return whenComplete(Schedulers.defaultScheduler(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +582,8 @@ public abstract class Task {
|
|||||||
* @param scheduler the executor to use for asynchronous execution
|
* @param scheduler the executor to use for asynchronous execution
|
||||||
* @return the new Task
|
* @return the new Task
|
||||||
*/
|
*/
|
||||||
public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) {
|
public final Task<Void> whenComplete(Scheduler scheduler, FinalizedCallback action) {
|
||||||
return new Task() {
|
return new Task<Void>() {
|
||||||
{
|
{
|
||||||
setSignificance(TaskSignificance.MODERATE);
|
setSignificance(TaskSignificance.MODERATE);
|
||||||
}
|
}
|
||||||
@@ -389,7 +607,7 @@ public abstract class Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Task> getDependents() {
|
public Collection<Task<?>> getDependents() {
|
||||||
return Collections.singleton(Task.this);
|
return Collections.singleton(Task.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,6 +618,25 @@ public abstract class Task {
|
|||||||
}.setName(getCaller());
|
}.setName(getCaller());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task with the same exception as this task, that executes
|
||||||
|
* the given action when this task completes.
|
||||||
|
*
|
||||||
|
* <p>When this task is complete, the given action is invoked with the
|
||||||
|
* result (or {@code null} if none), a boolean value represents the
|
||||||
|
* execution status of this task, and the exception (or {@code null}
|
||||||
|
* if none) of this task as arguments. The returned task is completed
|
||||||
|
* when the action returns. If the supplied action itself encounters an
|
||||||
|
* exception, then the returned task exceptionally completes with this
|
||||||
|
* exception unless this task also completed exceptionally.
|
||||||
|
*
|
||||||
|
* @param action the action to perform
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public Task<Void> whenComplete(Scheduler scheduler, FinalizedCallbackWithResult<T> action) {
|
||||||
|
return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Task with the same exception as this task, that executes
|
* Returns a new Task with the same exception as this task, that executes
|
||||||
* the given actions when this task completes.
|
* the given actions when this task completes.
|
||||||
@@ -415,7 +652,7 @@ public abstract class Task {
|
|||||||
* @param failure the action to perform when this task exceptionally returned
|
* @param failure the action to perform when this task exceptionally returned
|
||||||
* @return the new Task
|
* @return the new Task
|
||||||
*/
|
*/
|
||||||
public final <E1 extends Exception, E2 extends Exception> Task whenComplete(Scheduler scheduler, ExceptionalRunnable<E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
public final <E1 extends Exception, E2 extends Exception> Task<Void> whenComplete(Scheduler scheduler, ExceptionalRunnable<E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
||||||
return whenComplete(scheduler, (isDependentSucceeded, exception) -> {
|
return whenComplete(scheduler, (isDependentSucceeded, exception) -> {
|
||||||
if (isDependentSucceeded) {
|
if (isDependentSucceeded) {
|
||||||
if (success != null)
|
if (success != null)
|
||||||
@@ -433,44 +670,114 @@ public abstract class Task {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task of(ExceptionalRunnable<?> closure) {
|
/**
|
||||||
return of(Schedulers.defaultScheduler(), closure);
|
* Returns a new Task with the same exception as this task, that executes
|
||||||
|
* the given actions when this task completes.
|
||||||
|
*
|
||||||
|
* <p>When this task is complete, the given success action is invoked with
|
||||||
|
* the result, the given failure action is invoked with the exception of
|
||||||
|
* this task. The returned task is completed when the action returns. If
|
||||||
|
* the supplied action itself encounters an exception, then the returned
|
||||||
|
* task exceptionally completes with this exception unless this task also
|
||||||
|
* completed exceptionally.
|
||||||
|
*
|
||||||
|
* @param success the action to perform when this task successfully completed
|
||||||
|
* @param failure the action to perform when this task exceptionally returned
|
||||||
|
* @return the new Task
|
||||||
|
*/
|
||||||
|
public <E1 extends Exception, E2 extends Exception> Task<Void> whenComplete(Scheduler scheduler, ExceptionalConsumer<T, E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
||||||
|
return whenComplete(scheduler, () -> success.accept(getResult()), failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task of(String name, ExceptionalRunnable<?> closure) {
|
public static Task<Void> runAsync(ExceptionalRunnable<?> closure) {
|
||||||
return of(name, Schedulers.defaultScheduler(), closure);
|
return runAsync(Schedulers.defaultScheduler(), closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task of(Scheduler scheduler, ExceptionalRunnable<?> closure) {
|
public static Task<Void> runAsync(String name, ExceptionalRunnable<?> closure) {
|
||||||
return of(getCaller(), scheduler, closure);
|
return runAsync(name, Schedulers.defaultScheduler(), closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task of(String name, Scheduler scheduler, ExceptionalRunnable<?> closure) {
|
public static Task<Void> runAsync(Scheduler scheduler, ExceptionalRunnable<?> closure) {
|
||||||
return new SimpleTask(name, closure, scheduler);
|
return runAsync(getCaller(), scheduler, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task ofThen(ExceptionalSupplier<Task, ?> b) {
|
public static Task<Void> runAsync(String name, Scheduler scheduler, ExceptionalRunnable<?> closure) {
|
||||||
return new CoupleTask(null, b, true);
|
return new SimpleTask<>(closure.toCallable(), scheduler).setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> TaskResult<V> ofResult(Callable<V> callable) {
|
public static <T> Task<T> composeAsync(ExceptionalSupplier<Task<T>, ?> fn) {
|
||||||
return ofResult(getCaller(), callable);
|
return new Task<T>() {
|
||||||
}
|
Task<T> then;
|
||||||
|
|
||||||
public static <V> TaskResult<V> ofResult(String name, Callable<V> callable) {
|
|
||||||
return new SimpleTaskResult<>(callable).setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ExceptionalSupplier<Task, ?> convert(Task t) {
|
|
||||||
return new ExceptionalSupplier<Task, Exception>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Task get() {
|
public void execute() throws Exception {
|
||||||
return t;
|
then = fn.get();
|
||||||
|
if (then != null)
|
||||||
|
then.storeTo(this::setResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public Collection<Task<?>> getDependencies() {
|
||||||
return t.getName();
|
return then == null ? Collections.emptySet() : Collections.singleton(then);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Task<V> supplyAsync(Callable<V> callable) {
|
||||||
|
return supplyAsync(getCaller(), callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Task<V> supplyAsync(Scheduler scheduler, Callable<V> callable) {
|
||||||
|
return supplyAsync(getCaller(), scheduler, callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Task<V> supplyAsync(String name, Callable<V> callable) {
|
||||||
|
return supplyAsync(name, Schedulers.defaultScheduler(), callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Task<V> supplyAsync(String name, Scheduler scheduler, Callable<V> callable) {
|
||||||
|
return new SimpleTask<>(callable, scheduler).setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that is completed when all of the given Tasks
|
||||||
|
* complete. If any of the given Tasks complete exceptionally,
|
||||||
|
* then the returned Task also does so. Otherwise, the results, if
|
||||||
|
* any, of the given Tasks are not reflected in the returned Task,
|
||||||
|
* but may be obtained by inspecting them individually. If no Tasks
|
||||||
|
* are provided, returns a Task completed with the value {@code null}.
|
||||||
|
*
|
||||||
|
* @param tasks the Tasks
|
||||||
|
* @return a new Task that is completed when all of the given Tasks complete
|
||||||
|
*/
|
||||||
|
public static Task<Void> allOf(Task<?>... tasks) {
|
||||||
|
return allOf(Arrays.asList(tasks));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that is completed when all of the given Tasks
|
||||||
|
* complete. If any of the given Tasks complete exceptionally,
|
||||||
|
* then the returned Task also does so. Otherwise, the results, if
|
||||||
|
* any, of the given Tasks are not reflected in the returned Task,
|
||||||
|
* but may be obtained by inspecting them individually. If no Tasks
|
||||||
|
* are provided, returns a Task completed with the value {@code null}.
|
||||||
|
*
|
||||||
|
* @param tasks the Tasks
|
||||||
|
* @return a new Task that is completed when all of the given Tasks complete
|
||||||
|
*/
|
||||||
|
public static Task<Void> allOf(Collection<Task<?>> tasks) {
|
||||||
|
return new Task<Void>() {
|
||||||
|
{
|
||||||
|
setSignificance(TaskSignificance.MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Task<?>> getDependents() {
|
||||||
|
return tasks;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -501,7 +808,118 @@ public abstract class Task {
|
|||||||
void execute(boolean isDependentSucceeded, Exception exception) throws Exception;
|
void execute(boolean isDependentSucceeded, Exception exception) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getCaller() {
|
public interface FinalizedCallbackWithResult<T> {
|
||||||
|
void execute(T result, boolean isDependentSucceeded, Exception exception) throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getCaller() {
|
||||||
return ReflectionHelper.getCaller(packageName -> !"org.jackhuang.hmcl.task".equals(packageName)).toString();
|
return ReflectionHelper.getCaller(packageName -> !"org.jackhuang.hmcl.task".equals(packageName)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SimpleTask<T> extends Task<T> {
|
||||||
|
|
||||||
|
private final Callable<T> callable;
|
||||||
|
private final Scheduler scheduler;
|
||||||
|
|
||||||
|
SimpleTask(Callable<T> callable, Scheduler scheduler) {
|
||||||
|
this.callable = callable;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scheduler getScheduler() {
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
setResult(callable.call());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UniApply<R> extends Task<R> {
|
||||||
|
private final Scheduler scheduler;
|
||||||
|
private final ExceptionalFunction<T, R, ?> callable;
|
||||||
|
|
||||||
|
UniApply(String name, Scheduler scheduler, ExceptionalFunction<T, R, ?> callable) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
this.callable = callable;
|
||||||
|
|
||||||
|
setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Task<?>> getDependents() {
|
||||||
|
return Collections.singleton(Task.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scheduler getScheduler() {
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
setResult(callable.apply(Task.this.getResult()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that combines two tasks and make sure [pred] runs before succ.
|
||||||
|
*
|
||||||
|
* @author huangyuhui
|
||||||
|
*/
|
||||||
|
private final class UniCompose<U> extends Task<U> {
|
||||||
|
|
||||||
|
private final boolean relyingOnDependents;
|
||||||
|
private Task<U> succ;
|
||||||
|
private final ExceptionalFunction<T, Task<U>, ?> fn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that combines two tasks and make sure pred runs before succ.
|
||||||
|
*
|
||||||
|
* @param fn 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.
|
||||||
|
* @param relyingOnDependents true if this task chain will be broken when task pred fails.
|
||||||
|
*/
|
||||||
|
UniCompose(ExceptionalSupplier<Task<U>, ?> fn, boolean relyingOnDependents) {
|
||||||
|
this(result -> fn.get(), relyingOnDependents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that combines two tasks and make sure pred runs before succ.
|
||||||
|
*
|
||||||
|
* @param fn 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.
|
||||||
|
* @param relyingOnDependents true if this task chain will be broken when task pred fails.
|
||||||
|
*/
|
||||||
|
UniCompose(ExceptionalFunction<T, Task<U>, ?> fn, boolean relyingOnDependents) {
|
||||||
|
this.fn = fn;
|
||||||
|
this.relyingOnDependents = relyingOnDependents;
|
||||||
|
|
||||||
|
setSignificance(TaskSignificance.MODERATE);
|
||||||
|
setName(fn.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
setName(fn.toString());
|
||||||
|
succ = fn.apply(Task.this.getResult());
|
||||||
|
if (succ != null)
|
||||||
|
succ.storeTo(this::setResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Task<?>> getDependents() {
|
||||||
|
return Collections.singleton(Task.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Task<?>> getDependencies() {
|
||||||
|
return succ == null ? Collections.emptySet() : Collections.singleton(succ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRelyingOnDependents() {
|
||||||
|
return relyingOnDependents;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,16 @@ import org.jackhuang.hmcl.event.Event;
|
|||||||
*/
|
*/
|
||||||
public class TaskEvent extends Event {
|
public class TaskEvent extends Event {
|
||||||
|
|
||||||
private final Task task;
|
private final Task<?> task;
|
||||||
private final boolean failed;
|
private final boolean failed;
|
||||||
|
|
||||||
public TaskEvent(Object source, Task task, boolean failed) {
|
public TaskEvent(Object source, Task<?> task, boolean failed) {
|
||||||
super(source);
|
super(source);
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.failed = failed;
|
this.failed = failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task getTask() {
|
public Task<?> getTask() {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
@@ -32,15 +31,13 @@ import java.util.logging.Level;
|
|||||||
*/
|
*/
|
||||||
public final class TaskExecutor {
|
public final class TaskExecutor {
|
||||||
|
|
||||||
private final Task firstTask;
|
private final Task<?> firstTask;
|
||||||
private final List<TaskListener> taskListeners = new LinkedList<>();
|
private final List<TaskListener> taskListeners = new LinkedList<>();
|
||||||
private boolean canceled = false;
|
|
||||||
private Exception lastException;
|
private Exception lastException;
|
||||||
private final AtomicInteger totTask = new AtomicInteger(0);
|
private final AtomicInteger totTask = new AtomicInteger(0);
|
||||||
private final ConcurrentLinkedQueue<Future<?>> workerQueue = new ConcurrentLinkedQueue<>();
|
private CompletableFuture<Boolean> future;
|
||||||
private Scheduler scheduler = Schedulers.newThread();
|
|
||||||
|
|
||||||
public TaskExecutor(Task task) {
|
public TaskExecutor(Task<?> task) {
|
||||||
this.firstTask = task;
|
this.firstTask = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,95 +45,93 @@ public final class TaskExecutor {
|
|||||||
taskListeners.add(taskListener);
|
taskListeners.add(taskListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCanceled() {
|
|
||||||
return canceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Exception getLastException() {
|
public Exception getLastException() {
|
||||||
return lastException;
|
return lastException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScheduler(Scheduler scheduler) {
|
|
||||||
this.scheduler = Objects.requireNonNull(scheduler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TaskExecutor start() {
|
public TaskExecutor start() {
|
||||||
taskListeners.forEach(TaskListener::onStart);
|
taskListeners.forEach(TaskListener::onStart);
|
||||||
workerQueue.add(scheduler.schedule(() -> {
|
future = executeTasks(Collections.singleton(firstTask))
|
||||||
boolean flag = executeTasks(Collections.singleton(firstTask));
|
.thenApplyAsync(exception -> {
|
||||||
taskListeners.forEach(it -> it.onStop(flag, this));
|
boolean success = exception == null;
|
||||||
}));
|
taskListeners.forEach(it -> it.onStop(success, this));
|
||||||
|
return success;
|
||||||
|
})
|
||||||
|
.exceptionally(e -> {
|
||||||
|
Lang.handleUncaughtException(e instanceof UncheckedThrowable ? e.getCause() : e);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean test() {
|
public boolean test() {
|
||||||
taskListeners.forEach(TaskListener::onStart);
|
start();
|
||||||
AtomicBoolean flag = new AtomicBoolean(true);
|
|
||||||
Future<?> future = scheduler.schedule(() -> {
|
|
||||||
flag.set(executeTasks(Collections.singleton(firstTask)));
|
|
||||||
taskListeners.forEach(it -> it.onStop(flag.get(), this));
|
|
||||||
});
|
|
||||||
workerQueue.add(future);
|
|
||||||
try {
|
try {
|
||||||
future.get();
|
return future.get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} catch (ExecutionException | CancellationException e) {
|
} catch (ExecutionException | CancellationException e) {
|
||||||
}
|
}
|
||||||
return flag.get();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the subscription ant interrupt all tasks.
|
* Cancel the subscription ant interrupt all tasks.
|
||||||
*/
|
*/
|
||||||
public synchronized void cancel() {
|
public synchronized void cancel() {
|
||||||
canceled = true;
|
if (future == null) {
|
||||||
|
throw new IllegalStateException("Cannot cancel a not started TaskExecutor");
|
||||||
|
}
|
||||||
|
|
||||||
while (!workerQueue.isEmpty()) {
|
|
||||||
Future<?> future = workerQueue.poll();
|
|
||||||
if (future != null)
|
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean executeTasks(Collection<? extends Task> tasks) throws InterruptedException {
|
private CompletableFuture<Exception> executeTasks(Collection<Task<?>> tasks) {
|
||||||
if (tasks.isEmpty())
|
if (tasks == null || tasks.isEmpty())
|
||||||
return true;
|
return CompletableFuture.completedFuture(null);
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(null)
|
||||||
|
.thenComposeAsync(unused -> {
|
||||||
totTask.addAndGet(tasks.size());
|
totTask.addAndGet(tasks.size());
|
||||||
AtomicBoolean success = new AtomicBoolean(true);
|
|
||||||
CountDownLatch latch = new CountDownLatch(tasks.size());
|
return CompletableFuture.allOf(tasks.stream()
|
||||||
for (Task task : tasks) {
|
.map(task -> CompletableFuture.completedFuture(null)
|
||||||
if (canceled)
|
.thenComposeAsync(unused2 -> executeTask(task))
|
||||||
return false;
|
).toArray(CompletableFuture<?>[]::new));
|
||||||
Invoker invoker = new Invoker(task, latch, success);
|
})
|
||||||
try {
|
.thenApplyAsync(unused -> (Exception) null)
|
||||||
Future<?> future = scheduler.schedule(invoker);
|
.exceptionally(throwable -> {
|
||||||
if (future != null)
|
if (throwable instanceof Exception) {
|
||||||
workerQueue.add(future);
|
return (Exception) throwable;
|
||||||
} catch (RejectedExecutionException e) {
|
} else {
|
||||||
throw new InterruptedException();
|
// If an error occurred, we just rethrow it.
|
||||||
|
throw new UncheckedThrowable(throwable);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canceled)
|
private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable<?> runnable) {
|
||||||
return false;
|
scheduleTo(scheduler, runnable, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void scheduleTo(Scheduler scheduler, ExceptionalRunnable<?> runnable, Runnable finalize) {
|
||||||
try {
|
try {
|
||||||
latch.await();
|
scheduler.schedule(runnable).get();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
if (e.getCause() instanceof Exception)
|
||||||
|
rethrow(e.getCause());
|
||||||
|
else
|
||||||
|
throw new UncheckedException(e);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return false;
|
throw new UncheckedException(e);
|
||||||
|
} finally {
|
||||||
|
if (finalize != null)
|
||||||
|
finalize.run();
|
||||||
}
|
}
|
||||||
return success.get() && !canceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean executeTask(Task task) {
|
|
||||||
if (canceled) {
|
|
||||||
task.setState(Task.TaskState.FAILED);
|
|
||||||
task.setLastException(new CancellationException());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<Object> executeTask(Task<?> task) {
|
||||||
|
return CompletableFuture.completedFuture(null).thenComposeAsync(unused -> {
|
||||||
task.setState(Task.TaskState.READY);
|
task.setState(Task.TaskState.READY);
|
||||||
|
|
||||||
if (task.getSignificance().shouldLog())
|
if (task.getSignificance().shouldLog())
|
||||||
@@ -144,88 +139,70 @@ public final class TaskExecutor {
|
|||||||
|
|
||||||
taskListeners.forEach(it -> it.onReady(task));
|
taskListeners.forEach(it -> it.onReady(task));
|
||||||
|
|
||||||
boolean flag = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (task.doPreExecute()) {
|
if (task.doPreExecute()) {
|
||||||
try {
|
scheduleTo(task.getScheduler(), task::preExecute);
|
||||||
task.getScheduler().schedule(task::preExecute).get();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof Exception)
|
|
||||||
throw (Exception) e.getCause();
|
|
||||||
else
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<? extends Task> dependents = task.getDependents();
|
return executeTasks(task.getDependents());
|
||||||
boolean doDependentsSucceeded = executeTasks(dependents);
|
}).thenComposeAsync(dependentsException -> {
|
||||||
Exception dependentsException = dependents.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null);
|
boolean isDependentsSucceeded = dependentsException == null;
|
||||||
if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) {
|
|
||||||
|
if (!isDependentsSucceeded && task.isRelyingOnDependents()) {
|
||||||
task.setLastException(dependentsException);
|
task.setLastException(dependentsException);
|
||||||
throw new CancellationException();
|
rethrow(dependentsException);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doDependentsSucceeded)
|
if (isDependentsSucceeded)
|
||||||
task.setDependentsSucceeded();
|
task.setDependentsSucceeded();
|
||||||
|
|
||||||
try {
|
scheduleTo(task.getScheduler(), () -> {
|
||||||
task.getScheduler().schedule(() -> {
|
|
||||||
task.setState(Task.TaskState.RUNNING);
|
task.setState(Task.TaskState.RUNNING);
|
||||||
taskListeners.forEach(it -> it.onRunning(task));
|
taskListeners.forEach(it -> it.onRunning(task));
|
||||||
task.execute();
|
task.execute();
|
||||||
}).get();
|
}, () -> task.setState(Task.TaskState.EXECUTED));
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof Exception)
|
|
||||||
throw (Exception) e.getCause();
|
|
||||||
else
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
task.setState(Task.TaskState.EXECUTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<? extends Task> dependencies = task.getDependencies();
|
return executeTasks(task.getDependencies());
|
||||||
boolean doDependenciesSucceeded = executeTasks(dependencies);
|
}).thenApplyAsync(dependenciesException -> {
|
||||||
Exception dependenciesException = dependencies.stream().map(Task::getLastException).filter(Objects::nonNull).findAny().orElse(null);
|
boolean isDependenciesSucceeded = dependenciesException == null;
|
||||||
|
|
||||||
if (doDependenciesSucceeded)
|
if (isDependenciesSucceeded)
|
||||||
task.setDependenciesSucceeded();
|
task.setDependenciesSucceeded();
|
||||||
|
|
||||||
if (task.doPostExecute()) {
|
if (task.doPostExecute()) {
|
||||||
try {
|
scheduleTo(task.getScheduler(), task::postExecute);
|
||||||
task.getScheduler().schedule(task::postExecute).get();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof Exception)
|
|
||||||
throw (Exception) e.getCause();
|
|
||||||
else
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doDependenciesSucceeded && task.isRelyingOnDependencies()) {
|
if (!isDependenciesSucceeded && task.isRelyingOnDependencies()) {
|
||||||
Logging.LOG.severe("Subtasks failed for " + task.getName());
|
Logging.LOG.severe("Subtasks failed for " + task.getName());
|
||||||
task.setLastException(dependenciesException);
|
task.setLastException(dependenciesException);
|
||||||
throw new CancellationException();
|
rethrow(dependenciesException);
|
||||||
}
|
}
|
||||||
|
|
||||||
flag = true;
|
|
||||||
if (task.getSignificance().shouldLog()) {
|
if (task.getSignificance().shouldLog()) {
|
||||||
Logging.LOG.log(Level.FINER, "Task finished: " + task.getName());
|
Logging.LOG.log(Level.FINER, "Task finished: " + task.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
task.onDone().fireEvent(new TaskEvent(this, task, false));
|
task.onDone().fireEvent(new TaskEvent(this, task, false));
|
||||||
taskListeners.forEach(it -> it.onFinished(task));
|
taskListeners.forEach(it -> it.onFinished(task));
|
||||||
} catch (InterruptedException e) {
|
|
||||||
|
task.setState(Task.TaskState.SUCCEEDED);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
if (!(throwable instanceof Exception))
|
||||||
|
throw new UncheckedThrowable(throwable);
|
||||||
|
Exception e = throwable instanceof UncheckedException ? (Exception) throwable.getCause() : (Exception) throwable;
|
||||||
|
if (e instanceof InterruptedException) {
|
||||||
task.setLastException(e);
|
task.setLastException(e);
|
||||||
if (task.getSignificance().shouldLog()) {
|
if (task.getSignificance().shouldLog()) {
|
||||||
Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName());
|
Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName());
|
||||||
}
|
}
|
||||||
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
||||||
taskListeners.forEach(it -> it.onFailed(task, e));
|
taskListeners.forEach(it -> it.onFailed(task, e));
|
||||||
} catch (CancellationException | RejectedExecutionException e) {
|
} else if (e instanceof CancellationException || e instanceof RejectedExecutionException) {
|
||||||
if (task.getLastException() == null)
|
if (task.getLastException() == null)
|
||||||
task.setLastException(e);
|
task.setLastException(e);
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
task.setLastException(e);
|
task.setLastException(e);
|
||||||
lastException = e;
|
lastException = e;
|
||||||
if (task.getSignificance().shouldLog()) {
|
if (task.getSignificance().shouldLog()) {
|
||||||
@@ -234,36 +211,38 @@ public final class TaskExecutor {
|
|||||||
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
||||||
taskListeners.forEach(it -> it.onFailed(task, e));
|
taskListeners.forEach(it -> it.onFailed(task, e));
|
||||||
}
|
}
|
||||||
task.setState(flag ? Task.TaskState.SUCCEEDED : Task.TaskState.FAILED);
|
|
||||||
return flag;
|
task.setState(Task.TaskState.FAILED);
|
||||||
|
|
||||||
|
throw new UncheckedException(e);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRunningTasks() {
|
public int getRunningTasks() {
|
||||||
return totTask.get();
|
return totTask.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Invoker implements ExceptionalRunnable<Exception> {
|
private static class UncheckedException extends RuntimeException {
|
||||||
|
|
||||||
private final Task task;
|
UncheckedException(Exception exception) {
|
||||||
private final CountDownLatch latch;
|
super(exception);
|
||||||
private final AtomicBoolean success;
|
|
||||||
|
|
||||||
public Invoker(Task task, CountDownLatch latch, AtomicBoolean success) {
|
|
||||||
this.task = task;
|
|
||||||
this.latch = latch;
|
|
||||||
this.success = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
Thread.currentThread().setName(task.getName());
|
|
||||||
if (!executeTask(task))
|
|
||||||
success.set(false);
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class UncheckedThrowable extends RuntimeException {
|
||||||
|
|
||||||
|
UncheckedThrowable(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void rethrow(Throwable e) {
|
||||||
|
if (e instanceof RuntimeException) { // including UncheckedException and UncheckedThrowable
|
||||||
|
throw (RuntimeException) e;
|
||||||
|
} else if (e instanceof Exception) {
|
||||||
|
throw new UncheckedException((Exception) e);
|
||||||
|
} else {
|
||||||
|
throw new UncheckedThrowable(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,16 +28,16 @@ public abstract class TaskListener implements EventListener {
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onReady(Task task) {
|
public void onReady(Task<?> task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRunning(Task task) {
|
public void onRunning(Task<?> task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onFinished(Task task) {
|
public void onFinished(Task<?> task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onFailed(Task task, Throwable throwable) {
|
public void onFailed(Task<?> task, Throwable throwable) {
|
||||||
onFinished(task);
|
onFinished(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher
|
|
||||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.task;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A task that has a result.
|
|
||||||
*
|
|
||||||
* @author huangyuhui
|
|
||||||
*/
|
|
||||||
public abstract class TaskResult<T> extends Task {
|
|
||||||
|
|
||||||
private T result;
|
|
||||||
private Consumer<T> resultConsumer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TaskResult<T> setName(String name) {
|
|
||||||
super.setName(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the result of this task.
|
|
||||||
*
|
|
||||||
* The result will be generated only if the execution is completed.
|
|
||||||
*/
|
|
||||||
public T getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setResult(T result) {
|
|
||||||
this.result = result;
|
|
||||||
if (resultConsumer != null)
|
|
||||||
resultConsumer.accept(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sync the result of this task by given action.
|
|
||||||
*
|
|
||||||
* @param action the action to perform when result of this task changed
|
|
||||||
* @return this TaskResult
|
|
||||||
*/
|
|
||||||
public TaskResult<T> storeTo(Consumer<T> action) {
|
|
||||||
this.resultConsumer = action;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new TaskResult that, when this task completes
|
|
||||||
* normally, is executed with result of this task as the argument
|
|
||||||
* to the supplied function.
|
|
||||||
*
|
|
||||||
* @param fn the function returning a new TaskResult
|
|
||||||
* @param <U> the type of the returned TaskResult's result
|
|
||||||
* @return the TaskResult
|
|
||||||
*/
|
|
||||||
public <U, E extends Exception> TaskResult<U> thenCompose(ExceptionalFunction<T, TaskResult<U>, E> fn) {
|
|
||||||
return new TaskResult<U>() {
|
|
||||||
TaskResult<U> then;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends Task> getDependents() {
|
|
||||||
return Collections.singleton(TaskResult.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
then = fn.apply(TaskResult.this.getResult()).storeTo(this::setResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends Task> getDependencies() {
|
|
||||||
return then == null ? Collections.emptyList() : Collections.singleton(then);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new Task that, when this task completes
|
|
||||||
* normally, is executed with this task as the argument
|
|
||||||
* to the supplied function.
|
|
||||||
*
|
|
||||||
* @param fn the function returning a new Task
|
|
||||||
* @return the Task
|
|
||||||
*/
|
|
||||||
public <E extends Exception> Task then(ExceptionalFunction<T, Task, E> fn) {
|
|
||||||
return new CoupleTask(this, () -> fn.apply(getResult()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new TaskResult that, when this task completes
|
|
||||||
* normally, is executed using the default Scheduler, with this
|
|
||||||
* task's result as the argument to the supplied function.
|
|
||||||
*
|
|
||||||
* @param fn the function to use to compute the value of the returned TaskResult
|
|
||||||
* @param <U> the function's return type
|
|
||||||
* @return the new TaskResult
|
|
||||||
*/
|
|
||||||
public <U, E extends Exception> TaskResult<U> thenApply(ExceptionalFunction<T, U, E> fn) {
|
|
||||||
return thenApply(Schedulers.defaultScheduler(), fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new TaskResult that, when this task completes
|
|
||||||
* normally, is executed using the supplied Scheduler, with this
|
|
||||||
* task's result as the argument to the supplied function.
|
|
||||||
*
|
|
||||||
* @param scheduler the executor to use for asynchronous execution
|
|
||||||
* @param fn the function to use to compute the value of the returned TaskResult
|
|
||||||
* @param <U> the function's return type
|
|
||||||
* @return the new TaskResult
|
|
||||||
*/
|
|
||||||
public <U, E extends Exception> TaskResult<U> thenApply(Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
|
||||||
return thenApply(getCaller(), scheduler, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new TaskResult that, when this task completes
|
|
||||||
* normally, is executed using the supplied Scheduler, with this
|
|
||||||
* task's result as the argument to the supplied function.
|
|
||||||
*
|
|
||||||
* @param name the name of this new TaskResult for displaying
|
|
||||||
* @param scheduler the executor to use for asynchronous execution
|
|
||||||
* @param fn the function to use to compute the value of the returned TaskResult
|
|
||||||
* @param <U> the function's return type
|
|
||||||
* @return the new TaskResult
|
|
||||||
*/
|
|
||||||
public <U, E extends Exception> TaskResult<U> thenApply(String name, Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
|
||||||
return new Subtask<>(name, scheduler, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new Task that, when this task completes
|
|
||||||
* normally, is executed using the default Scheduler, with this
|
|
||||||
* task's result as the argument to the supplied action.
|
|
||||||
*
|
|
||||||
* @param action the action to perform before completing the
|
|
||||||
* returned Task
|
|
||||||
* @return the new Task
|
|
||||||
*/
|
|
||||||
public <E extends Exception> Task thenAccept(ExceptionalConsumer<T, E> action) {
|
|
||||||
return thenAccept(Schedulers.defaultScheduler(), action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new Task that, when this task completes
|
|
||||||
* normally, is executed using the supplied Scheduler, with this
|
|
||||||
* task's result as the argument to the supplied action.
|
|
||||||
*
|
|
||||||
* @param action the action to perform before completing the returned Task
|
|
||||||
* @param scheduler the executor to use for asynchronous execution
|
|
||||||
* @return the new Task
|
|
||||||
*/
|
|
||||||
public <E extends Exception> Task thenAccept(Scheduler scheduler, ExceptionalConsumer<T, E> action) {
|
|
||||||
return new CoupleTask(this, () -> Task.of(scheduler, () -> action.accept(getResult())), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new Task with the same exception as this task, that executes
|
|
||||||
* the given actions when this task completes.
|
|
||||||
*
|
|
||||||
* <p>When this task is complete, the given success action is invoked with
|
|
||||||
* the result, the given failure action is invoked with the exception of
|
|
||||||
* this task. The returned task is completed when the action returns. If
|
|
||||||
* the supplied action itself encounters an exception, then the returned
|
|
||||||
* task exceptionally completes with this exception unless this task also
|
|
||||||
* completed exceptionally.
|
|
||||||
*
|
|
||||||
* @param success the action to perform when this task successfully completed
|
|
||||||
* @param failure the action to perform when this task exceptionally returned
|
|
||||||
* @return the new Task
|
|
||||||
*/
|
|
||||||
public <E1 extends Exception, E2 extends Exception> Task whenComplete(Scheduler scheduler, ExceptionalConsumer<T, E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
|
||||||
return whenComplete(scheduler, () -> success.accept(getResult()), failure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new Task with the same exception as this task, that executes
|
|
||||||
* the given action when this task completes.
|
|
||||||
*
|
|
||||||
* <p>When this task is complete, the given action is invoked with the
|
|
||||||
* result (or {@code null} if none), a boolean value represents the
|
|
||||||
* execution status of this task, and the exception (or {@code null}
|
|
||||||
* if none) of this task as arguments. The returned task is completed
|
|
||||||
* when the action returns. If the supplied action itself encounters an
|
|
||||||
* exception, then the returned task exceptionally completes with this
|
|
||||||
* exception unless this task also completed exceptionally.
|
|
||||||
*
|
|
||||||
* @param action the action to perform
|
|
||||||
* @return the new Task
|
|
||||||
*/
|
|
||||||
public Task whenComplete(Scheduler scheduler, FinalizedCallback<T> action) {
|
|
||||||
return whenComplete(scheduler, ((isDependentSucceeded, exception) -> action.execute(getResult(), isDependentSucceeded, exception)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Subtask<R> extends TaskResult<R> {
|
|
||||||
private final Scheduler scheduler;
|
|
||||||
private final ExceptionalFunction<T, R, ?> callable;
|
|
||||||
|
|
||||||
public Subtask(String name, Scheduler scheduler, ExceptionalFunction<T, R, ?> callable) {
|
|
||||||
this.scheduler = scheduler;
|
|
||||||
this.callable = callable;
|
|
||||||
|
|
||||||
setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends Task> getDependents() {
|
|
||||||
return Collections.singleton(TaskResult.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scheduler getScheduler() {
|
|
||||||
return scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
setResult(callable.apply(TaskResult.this.getResult()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FinalizedCallback<V> {
|
|
||||||
void execute(V result, boolean isDependentSucceeded, Exception exception) throws Exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,15 +27,11 @@ public interface ExceptionalRunnable<E extends Exception> {
|
|||||||
|
|
||||||
void run() throws E;
|
void run() throws E;
|
||||||
|
|
||||||
default Callable<?> toCallable() {
|
default Callable<Void> toCallable() {
|
||||||
return () -> {
|
return () -> {
|
||||||
run();
|
run();
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExceptionalRunnable<?> fromRunnable(Runnable r) {
|
|
||||||
return r::run;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
18
HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java
Normal file
18
HMCLCore/src/test/java/org/jackhuang/hmcl/util/TaskTest.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TaskTest {
|
||||||
|
@Test
|
||||||
|
public void testWhenComplete() {
|
||||||
|
Task.composeAsync(() -> Task.allOf(
|
||||||
|
Task.allOf(Task.runAsync(() -> {
|
||||||
|
throw new Exception();
|
||||||
|
}))
|
||||||
|
)).whenComplete(((isDependentSucceeded, exception) -> {
|
||||||
|
Assert.assertFalse(isDependentSucceeded);
|
||||||
|
})).test();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user