From 0906abdea9929f55ca18d79896b2bd01412635f1 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 11 May 2017 17:14:23 +0200 Subject: [PATCH] fixes #499 --- .../org/cryptomator/common/Optionals.java | 13 ++++++ .../java/org/cryptomator/ui/ExitUtil.java | 10 +---- .../ui/controllers/MainController.java | 7 +++- .../java/org/cryptomator/ui/model/Vault.java | 40 +++++++++++++++---- 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/Optionals.java b/main/commons/src/main/java/org/cryptomator/common/Optionals.java index d7c510bea..c2abb9206 100644 --- a/main/commons/src/main/java/org/cryptomator/common/Optionals.java +++ b/main/commons/src/main/java/org/cryptomator/common/Optionals.java @@ -1,6 +1,7 @@ package org.cryptomator.common; import java.util.Optional; +import java.util.function.Function; public final class Optionals { @@ -14,4 +15,16 @@ public final class Optionals { } } + /** + * Returns a function that is equivalent to the input function but immediately gets the value of the returned optional when invoked. + * + * @param the type of the input to the function + * @param the type of the result of the function + * @param optionalFunction An input function {@code Function>} + * @return A {@code Function}, that may throw an NoSuchElementException, if the original function returns an empty optional. + */ + public static Function unwrap(Function> optionalFunction) { + return t -> optionalFunction.apply(t).get(); + } + } diff --git a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java index 0aebd795f..64db2ac4c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java +++ b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java @@ -62,15 +62,7 @@ public class ExitUtil { this.macFunctions = macFunctions; } - public void initExitHandler() { - initExitHandler(ExitUtil::platformExitOnMainThread); - } - - private static void platformExitOnMainThread() { - Platform.runLater(Platform::exit); - } - - private void initExitHandler(Runnable exitCommand) { + public void initExitHandler(Runnable exitCommand) { if (SystemUtils.IS_OS_LINUX) { initMinimizeExitHandler(exitCommand); } else { diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index 1546f02a8..22b0964b9 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -189,10 +189,15 @@ public class MainController implements ViewController { stage.getIcons().add(new Image(getClass().getResourceAsStream("/window_icon.png"))); Application.setUserAgentStylesheet(getClass().getResource("/css/win_theme.css").toString()); } - exitUtil.initExitHandler(); + exitUtil.initExitHandler(this::gracefulShutdown); listenToFileOpenRequests(stage); } + private void gracefulShutdown() { + vaults.filtered(Vault::isUnlocked).forEach(Vault::prepareForShutdown); + Platform.runLater(Platform::exit); + } + private void loadFont(String resourcePath) { try (InputStream in = getClass().getResourceAsStream(resourcePath)) { Font.loadFont(in, 12.0); diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index c33db3492..63a93c1c3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -18,13 +18,14 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.ConsumerThrowingException; import org.cryptomator.common.LazyInitializer; +import org.cryptomator.common.Optionals; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.cryptofs.CryptoFileSystem; @@ -36,6 +37,7 @@ import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.frontend.webdav.mount.MountParams; import org.cryptomator.frontend.webdav.mount.Mounter.CommandFailedException; import org.cryptomator.frontend.webdav.mount.Mounter.Mount; +import org.cryptomator.frontend.webdav.mount.Mounter.UnmountOperation; import org.cryptomator.frontend.webdav.servlet.WebDavServletController; import org.cryptomator.ui.model.VaultModule.PerVault; import org.cryptomator.ui.util.DeferredCloser; @@ -143,17 +145,17 @@ public class Vault { }); } - public synchronized void unmount() throws Exception { - unmount(mount -> mount.unmount()); + public synchronized void unmount() throws CommandFailedException { + unmount(Function.identity()); } - public synchronized void unmountForced() throws Exception { - unmount(mount -> mount.forced().get().unmount()); + public synchronized void unmountForced() throws CommandFailedException { + unmount(Optionals.unwrap(Mount::forced)); } - private synchronized void unmount(ConsumerThrowingException command) throws CommandFailedException { + private synchronized void unmount(Function unmountOperationChooser) throws CommandFailedException { if (mount != null) { - command.accept(mount); + unmountOperationChooser.apply(mount).unmount(); } Platform.runLater(() -> { mounted.set(false); @@ -177,6 +179,30 @@ public class Vault { }); } + /** + * Ejects any mounted drives and locks this vault. no-op if this vault is currently locked. + */ + public void prepareForShutdown() { + try { + unmount(); + } catch (CommandFailedException e) { + if (supportsForcedUnmount()) { + try { + unmountForced(); + } catch (CommandFailedException e1) { + LOG.warn("Failed to force unmount vault."); + } + } else { + LOG.warn("Failed to gracefully unmount vault."); + } + } + try { + lock(); + } catch (Exception e) { + LOG.warn("Failed to lock vault."); + } + } + public void reveal() throws CommandFailedException { if (mount != null) { mount.reveal();