mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-21 10:06:55 -04:00
- Refactored WebDavMounter (using Guice)
- implemented warm start for windows mounts
This commit is contained in:
@@ -38,19 +38,18 @@ import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.ui.InitializeController.InitializationListener;
|
||||
import org.cryptomator.ui.MainModule.ControllerFactory;
|
||||
import org.cryptomator.ui.UnlockController.UnlockListener;
|
||||
import org.cryptomator.ui.UnlockedController.LockListener;
|
||||
import org.cryptomator.ui.controls.DirectoryListCell;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultFactory;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class MainController implements Initializable, InitializationListener, UnlockListener, LockListener {
|
||||
|
||||
@@ -78,16 +77,16 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
|
||||
private final ControllerFactory controllerFactory;
|
||||
private final Settings settings;
|
||||
private final Provider<Cryptor> cryptorProvider;
|
||||
private final VaultFactory vaultFactoy;
|
||||
|
||||
private ResourceBundle rb;
|
||||
|
||||
@Inject
|
||||
public MainController(ControllerFactory controllerFactory, Settings settings, Provider<Cryptor> cryptorProvider) {
|
||||
public MainController(ControllerFactory controllerFactory, Settings settings, VaultFactory vaultFactoy) {
|
||||
super();
|
||||
this.controllerFactory = controllerFactory;
|
||||
this.settings = settings;
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
this.vaultFactoy = vaultFactoy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,7 +166,7 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
return;
|
||||
}
|
||||
|
||||
final Vault vault = new Vault(vaultPath, cryptorProvider.get());
|
||||
final Vault vault = vaultFactoy.createVault(vaultPath);
|
||||
if (!directoryList.getItems().contains(vault)) {
|
||||
directoryList.getItems().add(vault);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@ import javax.inject.Singleton;
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.SamplingDecorator;
|
||||
import org.cryptomator.crypto.aes256.Aes256Cryptor;
|
||||
import org.cryptomator.ui.model.VaultFactory;
|
||||
import org.cryptomator.ui.model.VaultObjectMapperProvider;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.cryptomator.ui.settings.SettingsProvider;
|
||||
import org.cryptomator.ui.util.DeferredCloser;
|
||||
import org.cryptomator.ui.util.DeferredCloser.Closer;
|
||||
import org.cryptomator.ui.util.mount.WebDavMounter;
|
||||
import org.cryptomator.ui.util.mount.WebDavMounterProvider;
|
||||
import org.cryptomator.webdav.WebDavServer;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -44,6 +47,7 @@ public class MainModule extends AbstractModule {
|
||||
bind(DeferredCloser.class).toInstance(deferredCloser);
|
||||
bind(ObjectMapper.class).annotatedWith(Names.named("VaultJsonMapper")).toProvider(VaultObjectMapperProvider.class);
|
||||
bind(Settings.class).toProvider(SettingsProvider.class);
|
||||
bind(WebDavMounter.class).toProvider(WebDavMounterProvider.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -63,6 +67,11 @@ public class MainModule extends AbstractModule {
|
||||
return SamplingDecorator.decorate(new Aes256Cryptor());
|
||||
}
|
||||
|
||||
@Provides
|
||||
VaultFactory getVaultFactory(Cryptor cryptor, WebDavMounter mounter) {
|
||||
return new VaultFactory(cryptor, mounter);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
WebDavServer getServer() {
|
||||
|
||||
@@ -31,19 +31,24 @@ public class Vault implements Serializable {
|
||||
|
||||
public static final String VAULT_FILE_EXTENSION = ".cryptomator";
|
||||
|
||||
private final Cryptor cryptor;
|
||||
private final ObjectProperty<Boolean> unlocked = new SimpleObjectProperty<Boolean>(this, "unlocked", Boolean.FALSE);
|
||||
private final Path path;
|
||||
private final Cryptor cryptor;
|
||||
private final WebDavMounter mounter;
|
||||
private final ObjectProperty<Boolean> unlocked = new SimpleObjectProperty<Boolean>(this, "unlocked", Boolean.FALSE);
|
||||
private String mountName;
|
||||
private DeferredClosable<ServletLifeCycleAdapter> webDavServlet = DeferredClosable.empty();
|
||||
private DeferredClosable<WebDavMount> webDavMount = DeferredClosable.empty();
|
||||
|
||||
public Vault(final Path vaultDirectoryPath, final Cryptor cryptor) {
|
||||
/**
|
||||
* Package private constructor, use {@link VaultFactory}.
|
||||
*/
|
||||
Vault(final Path vaultDirectoryPath, final Cryptor cryptor, final WebDavMounter mounter) {
|
||||
if (!Files.isDirectory(vaultDirectoryPath) || !vaultDirectoryPath.getFileName().toString().endsWith(VAULT_FILE_EXTENSION)) {
|
||||
throw new IllegalArgumentException("Not a valid vault directory: " + vaultDirectoryPath);
|
||||
}
|
||||
this.path = vaultDirectoryPath;
|
||||
this.cryptor = cryptor;
|
||||
this.mounter = mounter;
|
||||
|
||||
try {
|
||||
setMountName(getName());
|
||||
@@ -81,7 +86,7 @@ public class Vault implements Serializable {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
webDavMount = closer.closeLater(WebDavMounter.mount(o.get().getServletUri(), getMountName()), WebDavMount::unmount);
|
||||
webDavMount = closer.closeLater(mounter.mount(o.get().getServletUri(), getMountName()), WebDavMount::unmount);
|
||||
return true;
|
||||
} catch (CommandFailedException e) {
|
||||
LOG.warn("mount failed", e);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.ui.util.mount.WebDavMounter;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class VaultFactory {
|
||||
|
||||
private final Cryptor cryptor;
|
||||
private final WebDavMounter mounter;
|
||||
|
||||
@Inject
|
||||
public VaultFactory(Cryptor cryptor, WebDavMounter mounter) {
|
||||
this.cryptor = cryptor;
|
||||
this.mounter = mounter;
|
||||
}
|
||||
|
||||
public Vault createVault(Path path) {
|
||||
return new Vault(path, cryptor, mounter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -22,11 +20,11 @@ import com.google.inject.Provider;
|
||||
|
||||
public class VaultObjectMapperProvider implements Provider<ObjectMapper> {
|
||||
|
||||
private final Provider<Cryptor> cryptorProvider;
|
||||
private final VaultFactory vaultFactoy;
|
||||
|
||||
@Inject
|
||||
public VaultObjectMapperProvider(final Provider<Cryptor> cryptorProvider) {
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
public VaultObjectMapperProvider(final VaultFactory vaultFactoy) {
|
||||
this.vaultFactoy = vaultFactoy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,11 +56,11 @@ public class VaultObjectMapperProvider implements Provider<ObjectMapper> {
|
||||
final JsonNode node = jp.readValueAsTree();
|
||||
final String pathStr = node.get("path").asText();
|
||||
final Path path = FileSystems.getDefault().getPath(pathStr);
|
||||
final Vault dir = new Vault(path, cryptorProvider.get());
|
||||
final Vault vault = vaultFactoy.createVault(path);
|
||||
if (node.has("mountName")) {
|
||||
dir.setMountName(node.get("mountName").asText());
|
||||
vault.setMountName(node.get("mountName").asText());
|
||||
}
|
||||
return dir;
|
||||
return vault;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ final class FallbackWebDavMounter implements WebDavMounterStrategy {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmUp(int serverPort) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebDavMount mount(URI uri, String name) {
|
||||
displayMountInstructions();
|
||||
|
||||
@@ -30,6 +30,11 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmUp(int serverPort) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebDavMount mount(URI uri, String name) throws CommandFailedException {
|
||||
|
||||
@@ -21,6 +21,11 @@ final class MacOsXWebDavMounter implements WebDavMounterStrategy {
|
||||
return SystemUtils.IS_OS_MAC_OSX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmUp(int serverPort) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebDavMount mount(URI uri, String name) throws CommandFailedException {
|
||||
final String path = "/Volumes/Cryptomator" + uri.getRawPath().replace('/', '_');
|
||||
|
||||
@@ -11,16 +11,7 @@ package org.cryptomator.ui.util.mount;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class WebDavMounter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebDavMounter.class);
|
||||
|
||||
private static final WebDavMounterStrategy[] STRATEGIES = {new WindowsWebDavMounter(), new MacOsXWebDavMounter(), new LinuxGvfsWebDavMounter()};
|
||||
|
||||
private static volatile WebDavMounterStrategy choosenStrategy;
|
||||
public interface WebDavMounter {
|
||||
|
||||
/**
|
||||
* Tries to mount a given webdav share.
|
||||
@@ -30,29 +21,6 @@ public final class WebDavMounter {
|
||||
* @return a {@link WebDavMount} representing the mounted share
|
||||
* @throws CommandFailedException if the mount operation fails
|
||||
*/
|
||||
public static WebDavMount mount(URI uri, String name) throws CommandFailedException {
|
||||
return chooseStrategy().mount(uri, name);
|
||||
}
|
||||
|
||||
private static WebDavMounterStrategy chooseStrategy() {
|
||||
if (choosenStrategy == null) {
|
||||
choosenStrategy = getStrategyWhichShouldWork();
|
||||
}
|
||||
return choosenStrategy;
|
||||
}
|
||||
|
||||
private static WebDavMounterStrategy getStrategyWhichShouldWork() {
|
||||
for (WebDavMounterStrategy strategy : STRATEGIES) {
|
||||
if (strategy.shouldWork()) {
|
||||
LOG.info("Using {}", strategy.getClass().getSimpleName());
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
return new FallbackWebDavMounter();
|
||||
}
|
||||
|
||||
private WebDavMounter() {
|
||||
throw new IllegalStateException("Class is not instantiable.");
|
||||
}
|
||||
WebDavMount mount(URI uri, String name) throws CommandFailedException;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 Sebastian Stenzel
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Markus Kreusch - Refactored to use strategy pattern
|
||||
* Sebastian Stenzel - Refactored to use Guice provider, added warmup-phase for windows mounts.
|
||||
******************************************************************************/
|
||||
package org.cryptomator.ui.util.mount;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.cryptomator.webdav.WebDavServer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class WebDavMounterProvider implements Provider<WebDavMounter> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebDavMounterProvider.class);
|
||||
private static final WebDavMounterStrategy[] STRATEGIES = {new WindowsWebDavMounter(), new MacOsXWebDavMounter(), new LinuxGvfsWebDavMounter()};
|
||||
private final WebDavMounterStrategy choosenStrategy;
|
||||
|
||||
@Inject
|
||||
public WebDavMounterProvider(WebDavServer server) {
|
||||
this.choosenStrategy = getStrategyWhichShouldWork();
|
||||
this.choosenStrategy.warmUp(server.getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebDavMounterStrategy get() {
|
||||
return this.choosenStrategy;
|
||||
}
|
||||
|
||||
private static WebDavMounterStrategy getStrategyWhichShouldWork() {
|
||||
for (WebDavMounterStrategy strategy : STRATEGIES) {
|
||||
if (strategy.shouldWork()) {
|
||||
LOG.info("Using {}", strategy.getClass().getSimpleName());
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
return new FallbackWebDavMounter();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,14 +9,12 @@
|
||||
******************************************************************************/
|
||||
package org.cryptomator.ui.util.mount;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* A strategy able to mount a webdav share and display it to the user.
|
||||
*
|
||||
* @author Markus Kreusch
|
||||
*/
|
||||
interface WebDavMounterStrategy {
|
||||
interface WebDavMounterStrategy extends WebDavMounter {
|
||||
|
||||
/**
|
||||
* @return {@code false} if this {@code WebDavMounterStrategy} can not work on the local machine, {@code true} if it could work
|
||||
@@ -24,13 +22,9 @@ interface WebDavMounterStrategy {
|
||||
boolean shouldWork();
|
||||
|
||||
/**
|
||||
* Tries to mount a given webdav share.
|
||||
*
|
||||
* @param uri URI of the webdav share
|
||||
* @param name the name under which the folder is to be mounted. This might be ignored.
|
||||
* @return a {@link WebDavMount} representing the mounted share
|
||||
* @throws CommandFailedException if the mount operation fails
|
||||
* Invoked when mounting strategy gets chosen. On some operating systems (we don't want to tell names here) mounting might be faster,
|
||||
* when certain things are prepared before the actual mount attempt.
|
||||
*/
|
||||
WebDavMount mount(URI uri, String name) throws CommandFailedException;
|
||||
void warmUp(int serverPort);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,16 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
|
||||
return SystemUtils.IS_OS_WINDOWS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmUp(int serverPort) {
|
||||
final URI warmUpUri = URI.create("http://0--1.ipv6-literal.net:" + serverPort + "/bill-gates-mom-uses-goto");
|
||||
try {
|
||||
this.mount(warmUpUri, "WarmUpMount");
|
||||
} catch (CommandFailedException e) {
|
||||
// will most certainly throw an exception, because this is a fake WebDav path. But now windows has some DNS things cached :)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebDavMount mount(URI uri, String name) throws CommandFailedException {
|
||||
final Script mountScript = fromLines("net use * http://0--1.ipv6-literal.net:%PORT%%DAV_PATH% /persistent:no")
|
||||
|
||||
Reference in New Issue
Block a user