Browse Source

webdav mounting on windows

Sebastian Stenzel 10 years ago
parent
commit
6830861346

+ 16 - 1
main/core/src/main/java/org/cryptomator/webdav/WebDAVServer.java

@@ -8,6 +8,9 @@
  ******************************************************************************/
 package org.cryptomator.webdav;
 
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
 import org.cryptomator.crypto.Cryptor;
 import org.cryptomator.webdav.jackrabbit.WebDavServlet;
 import org.eclipse.jetty.server.Connector;
@@ -15,6 +18,8 @@ import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.util.thread.ThreadPool;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -22,7 +27,17 @@ public final class WebDAVServer {
 
 	private static final Logger LOG = LoggerFactory.getLogger(WebDAVServer.class);
 	private static final String LOCALHOST = "127.0.0.1";
-	private final Server server = new Server();
+	private static final int MAX_PENDING_REQUESTS = 200;
+	private static final int MAX_THREADS = 4;
+	private static final int MIN_THREADS = 2;
+	private static final int THREAD_IDLE_SECONDS = 20;
+	private final Server server;
+	
+	public WebDAVServer() {
+		final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS);
+		final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue);
+		server = new Server(tp);
+	}
 
 	/**
 	 * @param workDir Path of encrypted folder.

+ 8 - 11
main/ui/src/main/java/org/cryptomator/ui/AccessController.java

@@ -15,7 +15,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.util.ResourceBundle;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
@@ -39,12 +38,11 @@ import org.slf4j.LoggerFactory;
 public class AccessController implements Initializable {
 
 	private static final Logger LOG = LoggerFactory.getLogger(AccessController.class);
-	private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
 
 	private final Aes256Cryptor cryptor = new Aes256Cryptor();
 	private final WebDAVServer server = new WebDAVServer();
-	private final int id = ID_GENERATOR.getAndIncrement();
 	private ResourceBundle rb;
+	private String unmountCmd;
 
 	@FXML
 	private GridPane rootPane;
@@ -91,7 +89,7 @@ public class AccessController implements Initializable {
 		final int webdavPort = server.start(settings.getWebdavWorkDir(), cryptor);
 		if (webdavPort > 0) {
 			try {
-				WebDavMounter.mount(webdavPort, id);
+				unmountCmd = WebDavMounter.mount(webdavPort);
 				MainApplication.addShutdownTask(this::tryStop);
 			} catch (CommandFailedException e) {
 				messageLabel.setText(String.format(rb.getString("access.messageLabel.mountFailed"), webdavPort));
@@ -101,14 +99,13 @@ public class AccessController implements Initializable {
 	}
 
 	public void tryStop() {
-		try {
-			if (server != null && server.isRunning()) {
-				WebDavMounter.unmount(id, 5);
-				server.stop();
+		if (server != null && server.isRunning()) {
+			try {
+				WebDavMounter.unmount(unmountCmd);
+			} catch (CommandFailedException e) {
+				LOG.warn("Unmounting WebDAV share failed.", e);
 			}
-		} catch (CommandFailedException e) {
-			LOG.warn("Unmounting WebDAV share failed.", e);
-		} finally {
+			server.stop();
 			cryptor.swipeSensitiveData();
 		}
 	}

+ 32 - 11
main/ui/src/main/java/org/cryptomator/ui/util/WebDavMounter.java

@@ -10,6 +10,8 @@ package org.cryptomator.ui.util;
 
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.SystemUtils;
@@ -19,35 +21,54 @@ import org.slf4j.LoggerFactory;
 public final class WebDavMounter {
 
 	private static final Logger LOG = LoggerFactory.getLogger(WebDavMounter.class);
-	private static final int CMD_DEFAULT_TIMEOUT = 1;
+	private static final int CMD_DEFAULT_TIMEOUT = 3;
+	private static final Pattern WIN_MOUNT_DRIVELETTER_PATTERN = Pattern.compile("\\s*[A-Z]:\\s*");
 
 	private WebDavMounter() {
 		throw new IllegalStateException("not instantiable.");
 	}
-
-	public static synchronized void mount(int localPort, int uniqueId) throws CommandFailedException {
+	
+	/**
+	 * @return Unmount Command
+	 */
+	public static synchronized String mount(int localPort) throws CommandFailedException {
 		if (SystemUtils.IS_OS_MAC_OSX) {
-			exec("mkdir /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
-			exec("mount_webdav -S -v Cryptomator localhost:" + localPort + " /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
-			exec("open /Volumes/Cryptomator" + uniqueId, CMD_DEFAULT_TIMEOUT);
+			exec("mkdir /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
+			exec("mount_webdav -S -v Cryptomator localhost:" + localPort + " /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
+			exec("open /Volumes/Cryptomator" + localPort, CMD_DEFAULT_TIMEOUT);
+			return "umount /Volumes/Cryptomator" + localPort;
+		} else if (SystemUtils.IS_OS_WINDOWS) {
+			final String result = exec("net use * http://127.0.0.1:" + localPort + " /persistent:no", CMD_DEFAULT_TIMEOUT);
+			final Matcher matcher = WIN_MOUNT_DRIVELETTER_PATTERN.matcher(result);
+			if (matcher.find()) {
+				final String driveLetter = matcher.group();
+				return "net use " + driveLetter + " /delete";
+			}
 		}
+		return null;
 	}
 
-	public static synchronized void unmount(int uniqueId, int timeout) throws CommandFailedException {
-		if (SystemUtils.IS_OS_MAC_OSX) {
-			exec("umount /Volumes/Cryptomator" + uniqueId, timeout);
+	public static void unmount(String command) throws CommandFailedException {
+		if (command != null) {
+			exec(command, CMD_DEFAULT_TIMEOUT);
 		}
 	}
 
-	private static void exec(String cmd, int timoutSeconds) throws CommandFailedException {
+	private static String exec(String cmd, int timoutSeconds) throws CommandFailedException {
 		try {
-			final Process proc = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd});
+			final Process proc;
+			if (SystemUtils.IS_OS_WINDOWS) {
+				proc = Runtime.getRuntime().exec(new String[]{"cmd", "/C", cmd});
+			} else {
+				proc = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd});
+			}
 			if (proc.waitFor(timoutSeconds, TimeUnit.SECONDS)) {
 				proc.destroy();
 			}
 			if (proc.exitValue() != 0) {
 				throw new CommandFailedException(IOUtils.toString(proc.getErrorStream()));
 			}
+			return  IOUtils.toString(proc.getInputStream());
 		} catch (IOException | InterruptedException | IllegalThreadStateException e) {
 			LOG.error("Command execution failed.", e);
 			throw new CommandFailedException(e);