|
@@ -8,6 +8,10 @@
|
|
|
******************************************************************************/
|
|
|
package org.cryptomator.webdav;
|
|
|
|
|
|
+import java.net.URI;
|
|
|
+import java.net.URISyntaxException;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.util.UUID;
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
|
|
@@ -18,6 +22,7 @@ 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.component.LifeCycle;
|
|
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|
|
import org.eclipse.jetty.util.thread.ThreadPool;
|
|
|
import org.slf4j.Logger;
|
|
@@ -31,40 +36,33 @@ public final class WebDavServer {
|
|
|
private static final int MAX_THREADS = 200;
|
|
|
private static final int MIN_THREADS = 4;
|
|
|
private static final int THREAD_IDLE_SECONDS = 20;
|
|
|
+ private static final WebDavServer INSTANCE = new WebDavServer();
|
|
|
private final Server server;
|
|
|
- private int port;
|
|
|
+ private final ServerConnector localConnector;
|
|
|
+ private final ServletContextHandler servletContext;
|
|
|
|
|
|
- public WebDavServer() {
|
|
|
+ public static WebDavServer getInstance() {
|
|
|
+ return INSTANCE;
|
|
|
+ }
|
|
|
+
|
|
|
+ private 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);
|
|
|
+ localConnector = new ServerConnector(server);
|
|
|
+ localConnector.setHost(LOCALHOST);
|
|
|
+ servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
|
|
+ servletContext.setContextPath("/");
|
|
|
+ server.setConnectors(new Connector[] {localConnector});
|
|
|
+ server.setHandler(servletContext);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * @param workDir Path of encrypted folder.
|
|
|
- * @param cryptor A fully initialized cryptor instance ready to en- or decrypt streams.
|
|
|
- * @return <code>true</code> upon success
|
|
|
- */
|
|
|
- public synchronized boolean start(final String workDir, final boolean checkFileIntegrity, final Cryptor cryptor) {
|
|
|
- final ServerConnector connector = new ServerConnector(server);
|
|
|
- connector.setHost(LOCALHOST);
|
|
|
-
|
|
|
- final String contextPath = "/";
|
|
|
- final String servletPathSpec = "/*";
|
|
|
-
|
|
|
- final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
|
|
- context.addServlet(getWebDavServletHolder(workDir, contextPath, checkFileIntegrity, cryptor), servletPathSpec);
|
|
|
- context.setContextPath(contextPath);
|
|
|
- server.setHandler(context);
|
|
|
-
|
|
|
+ public synchronized void start() {
|
|
|
try {
|
|
|
- server.setConnectors(new Connector[] {connector});
|
|
|
server.start();
|
|
|
- port = connector.getLocalPort();
|
|
|
- return true;
|
|
|
+ LOG.info("Cryptomator is running on port {}", getPort());
|
|
|
} catch (Exception ex) {
|
|
|
- LOG.error("Server couldn't be started", ex);
|
|
|
- return false;
|
|
|
+ throw new RuntimeException("Server couldn't be started", ex);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -72,14 +70,33 @@ public final class WebDavServer {
|
|
|
return server.isRunning();
|
|
|
}
|
|
|
|
|
|
- public synchronized boolean stop() {
|
|
|
+ public synchronized void stop() {
|
|
|
try {
|
|
|
server.stop();
|
|
|
- port = 0;
|
|
|
} catch (Exception ex) {
|
|
|
LOG.error("Server couldn't be stopped", ex);
|
|
|
}
|
|
|
- return server.isStopped();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param workDir Path of encrypted folder.
|
|
|
+ * @param cryptor A fully initialized cryptor instance ready to en- or decrypt streams.
|
|
|
+ * @return servlet
|
|
|
+ */
|
|
|
+ public ServletLifeCycleAdapter createServlet(final Path workDir, final boolean checkFileIntegrity, final Cryptor cryptor) {
|
|
|
+ try {
|
|
|
+ final URI uri = new URI(null, null, localConnector.getHost(), localConnector.getLocalPort(), "/" + UUID.randomUUID().toString(), null, null);
|
|
|
+
|
|
|
+ final String pathPrefix = uri.getRawPath() + "/";
|
|
|
+ final String pathSpec = pathPrefix + "*";
|
|
|
+ final ServletHolder servlet = getWebDavServletHolder(workDir.toString(), pathPrefix, checkFileIntegrity, cryptor);
|
|
|
+ servletContext.addServlet(servlet, pathSpec);
|
|
|
+
|
|
|
+ LOG.info("{} available on http://{}", workDir, uri.getRawSchemeSpecificPart());
|
|
|
+ return new ServletLifeCycleAdapter(servlet, uri);
|
|
|
+ } catch (URISyntaxException e) {
|
|
|
+ throw new IllegalArgumentException("Can't create URI from given workDir", e);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private ServletHolder getWebDavServletHolder(final String workDir, final String contextPath, final boolean checkFileIntegrity, final Cryptor cryptor) {
|
|
@@ -91,7 +108,50 @@ public final class WebDavServer {
|
|
|
}
|
|
|
|
|
|
public int getPort() {
|
|
|
- return port;
|
|
|
+ return localConnector.getLocalPort();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Exposes implementation-specific methods to other modules.
|
|
|
+ */
|
|
|
+ public class ServletLifeCycleAdapter {
|
|
|
+
|
|
|
+ private final LifeCycle lifecycle;
|
|
|
+ private final URI servletUri;
|
|
|
+
|
|
|
+ private ServletLifeCycleAdapter(LifeCycle lifecycle, URI servletUri) {
|
|
|
+ this.lifecycle = lifecycle;
|
|
|
+ this.servletUri = servletUri;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isRunning() {
|
|
|
+ return lifecycle.isRunning();
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean start() {
|
|
|
+ try {
|
|
|
+ lifecycle.start();
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.error("Failed to start", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean stop() {
|
|
|
+ try {
|
|
|
+ lifecycle.stop();
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.error("Failed to stop", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public URI getServletUri() {
|
|
|
+ return servletUri;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|