webdav mounting on windows

This commit is contained in:
Sebastian Stenzel
2014-12-05 14:40:28 +01:00
parent 696b3412f2
commit 6830861346
3 changed files with 59 additions and 26 deletions

View File

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

View File

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

View File

@@ -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 void unmount(String command) throws CommandFailedException {
if (command != null) {
exec(command, CMD_DEFAULT_TIMEOUT);
}
}
public static synchronized void unmount(int uniqueId, int timeout) throws CommandFailedException {
if (SystemUtils.IS_OS_MAC_OSX) {
exec("umount /Volumes/Cryptomator" + uniqueId, 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);