Ver Fonte

- Refactored WebDavMounter (using Guice)
- implemented warm start for windows mounts

Sebastian Stenzel há 10 anos atrás
pai
commit
30dc8eecb1

+ 5 - 6
main/ui/src/main/java/org/cryptomator/ui/MainController.java

@@ -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);
 		}

+ 9 - 0
main/ui/src/main/java/org/cryptomator/ui/MainModule.java

@@ -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() {

+ 8 - 3
main/ui/src/main/java/org/cryptomator/ui/model/Vault.java

@@ -31,19 +31,24 @@ public class Vault implements Serializable {
 
 	public static final String VAULT_FILE_EXTENSION = ".cryptomator";
 
+	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 final Path path;
 	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);

+ 25 - 0
main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java

@@ -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
main/ui/src/main/java/org/cryptomator/ui/model/VaultObjectMapperProvider.java

@@ -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;
 		}
 
 	}

+ 5 - 0
main/ui/src/main/java/org/cryptomator/ui/util/mount/FallbackWebDavMounter.java

@@ -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();

+ 5 - 0
main/ui/src/main/java/org/cryptomator/ui/util/mount/LinuxGvfsWebDavMounter.java

@@ -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 {

+ 5 - 0
main/ui/src/main/java/org/cryptomator/ui/util/mount/MacOsXWebDavMounter.java

@@ -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('/', '_');

+ 2 - 34
main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounter.java

@@ -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;
 
 }

+ 47 - 0
main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterProvider.java

@@ -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();
+	}
+
+}

+ 4 - 10
main/ui/src/main/java/org/cryptomator/ui/util/mount/WebDavMounterStrategy.java

@@ -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);
 
 }

+ 10 - 0
main/ui/src/main/java/org/cryptomator/ui/util/mount/WindowsWebDavMounter.java

@@ -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")