From 9052e7995fc171952e6840332586bb945fb8f47b Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 25 Jan 2016 16:13:21 +0100 Subject: [PATCH] added WebDavServer class to webdav frontend --- main/frontend-webdav/pom.xml | 11 +++ .../jackrabbitservlet/WebDavServlet.java | 2 +- .../webdav/server/WebDavComponent.java | 13 +++ .../webdav/server/WebDavServer.java | 98 +++++++++++++++++++ .../WebDavServletContextFactory.java | 19 ++-- .../FileSystemBasedWebDavServer.java | 65 ------------ .../InMemoryWebDavServer.java | 18 +++- .../NioWebDavServer.java | 18 +++- 8 files changed, 161 insertions(+), 83 deletions(-) create mode 100644 main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java create mode 100644 main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java rename main/frontend-webdav/src/main/java/org/cryptomator/webdav/{jackrabbitservlet => server}/WebDavServletContextFactory.java (86%) delete mode 100644 main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/FileSystemBasedWebDavServer.java rename main/frontend-webdav/src/test/java/org/cryptomator/webdav/{jackrabbitservlet => server}/InMemoryWebDavServer.java (72%) rename main/frontend-webdav/src/test/java/org/cryptomator/webdav/{jackrabbitservlet => server}/NioWebDavServer.java (80%) diff --git a/main/frontend-webdav/pom.xml b/main/frontend-webdav/pom.xml index cd3facb6a..f936103ed 100644 --- a/main/frontend-webdav/pom.xml +++ b/main/frontend-webdav/pom.xml @@ -66,6 +66,17 @@ commons-io commons-io + + + + com.google.dagger + dagger + + + com.google.dagger + dagger-compiler + provided + diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java index 26171d509..93e605f07 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java @@ -19,7 +19,7 @@ import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.jackrabbit.FileSystemResourceLocatorFactory; -class WebDavServlet extends AbstractWebdavServlet { +public class WebDavServlet extends AbstractWebdavServlet { private static final long serialVersionUID = -6632687979352625020L; diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java new file mode 100644 index 000000000..3be099a07 --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavComponent.java @@ -0,0 +1,13 @@ +package org.cryptomator.webdav.server; + +import javax.inject.Singleton; + +import dagger.Component; + +@Singleton +@Component +public interface WebDavComponent { + + WebDavServer getServer(); + +} \ No newline at end of file diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java new file mode 100644 index 000000000..b995f6ba6 --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServer.java @@ -0,0 +1,98 @@ +package org.cryptomator.webdav.server; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.apache.commons.lang3.SystemUtils; +import org.cryptomator.filesystem.Folder; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.util.thread.ThreadPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class WebDavServer { + + private static final Logger LOG = LoggerFactory.getLogger(WebDavServer.class); + private static final String LOCALHOST = SystemUtils.IS_OS_WINDOWS ? "::1" : "localhost"; + private static final int MAX_PENDING_REQUESTS = 200; + private static final int MAX_THREADS = 200; + private static final int MIN_THREADS = 4; + private static final int THREAD_IDLE_SECONDS = 20; + + private final Server server; + private final ServerConnector localConnector; + private final ContextHandlerCollection servletCollection; + private final WebDavServletContextFactory servletContextFactory; + + @Inject + public WebDavServer(WebDavServletContextFactory servletContextFactory) { + final BlockingQueue queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS); + final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue); + this.server = new Server(tp); + this.localConnector = new ServerConnector(server); + this.servletCollection = new ContextHandlerCollection(); + this.servletContextFactory = servletContextFactory; + + localConnector.setHost(LOCALHOST); + server.setConnectors(new Connector[] {localConnector}); + server.setHandler(servletCollection); + } + + public void setPort(int port) { + if (server.isStopped()) { + localConnector.setPort(port); + } else { + throw new IllegalStateException("Cannot change port of running server."); + } + } + + public int getPort() { + return localConnector.getLocalPort(); + } + + public synchronized void start() { + try { + server.start(); + LOG.info("Cryptomator is running on port {}", getPort()); + } catch (Exception ex) { + throw new RuntimeException("Server couldn't be started", ex); + } + } + + public boolean isRunning() { + return server.isRunning(); + } + + public synchronized void stop() { + try { + server.stop(); + } catch (Exception ex) { + LOG.error("Server couldn't be stopped", ex); + } + } + + public ServletContextHandler addServlet(Folder root, String contextPath) { + final URI uri; + try { + uri = new URI("http", null, LOCALHOST, getPort(), contextPath, null, null); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + ServletContextHandler handler = servletContextFactory.create(uri, root); + servletCollection.addHandler(handler); + servletCollection.mapContexts(); + return handler; + } + +} diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServletContextFactory.java b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java similarity index 86% rename from main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServletContextFactory.java rename to main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java index 3268db86a..1cce68a1a 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServletContextFactory.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/webdav/server/WebDavServletContextFactory.java @@ -6,33 +6,37 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.jackrabbitservlet; +package org.cryptomator.webdav.server; import java.net.URI; import java.util.EnumSet; +import javax.inject.Inject; +import javax.inject.Singleton; import javax.servlet.DispatcherType; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.filesystem.Folder; import org.cryptomator.webdav.filters.AcceptRangeFilter; -import org.cryptomator.webdav.filters.LoggingHttpFilter; import org.cryptomator.webdav.filters.MacChunkedPutCompatibilityFilter; import org.cryptomator.webdav.filters.UriNormalizationFilter; import org.cryptomator.webdav.filters.UriNormalizationFilter.ResourceTypeChecker; import org.cryptomator.webdav.filters.UriNormalizationFilter.ResourceTypeChecker.ResourceType; +import org.cryptomator.webdav.jackrabbitservlet.WebDavServlet; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class WebDavServletContextFactory { +@Singleton +class WebDavServletContextFactory { - private static final Logger LOG = LoggerFactory.getLogger(WebDavServletContextFactory.class); private static final String WILDCARD = "/*"; + @Inject + public WebDavServletContextFactory() { + } + /** * Creates a new Jetty ServletContextHandler, that can be be added to a servletCollection as follows: * @@ -65,9 +69,6 @@ public class WebDavServletContextFactory { if (SystemUtils.IS_OS_MAC_OSX) { servletContext.addFilter(MacChunkedPutCompatibilityFilter.class, WILDCARD, EnumSet.of(DispatcherType.REQUEST)); } - if (LOG.isDebugEnabled()) { - servletContext.addFilter(LoggingHttpFilter.class, WILDCARD, EnumSet.of(DispatcherType.REQUEST)); - } return servletContext; } diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/FileSystemBasedWebDavServer.java b/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/FileSystemBasedWebDavServer.java deleted file mode 100644 index cffba5c19..000000000 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/FileSystemBasedWebDavServer.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 Sebastian Stenzel and others. - * This file is licensed under the terms of the MIT license. - * See the LICENSE.txt file for more info. - * - * Contributors: - * Sebastian Stenzel - initial API and implementation - *******************************************************************************/ -package org.cryptomator.webdav.jackrabbitservlet; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import org.cryptomator.filesystem.FileSystem; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.util.thread.ThreadPool; - -class FileSystemBasedWebDavServer { - - private final Server server; - private final ServerConnector localConnector; - private final ContextHandlerCollection servletCollection; - - public FileSystemBasedWebDavServer(FileSystem fileSystem) { - final BlockingQueue queue = new LinkedBlockingQueue<>(10); - final ThreadPool tp = new QueuedThreadPool(4, 1, 1, queue); - server = new Server(tp); - localConnector = new ServerConnector(server); - localConnector.setHost("localhost"); - localConnector.setPort(8080); - servletCollection = new ContextHandlerCollection(); - - final URI servletContextRoot1; - final URI servletContextRoot2; - try { - servletContextRoot1 = new URI("http", null, "localhost", 8080, "/foo/", null, null); - servletContextRoot2 = new URI("http", null, "localhost", 8080, "/bar/", null, null); - } catch (URISyntaxException e) { - throw new IllegalStateException(e); - } - - final WebDavServletContextFactory servletContextFactory = new WebDavServletContextFactory(); - servletCollection.addHandler(servletContextFactory.create(servletContextRoot1, fileSystem)); - servletCollection.addHandler(servletContextFactory.create(servletContextRoot2, fileSystem)); - servletCollection.mapContexts(); - - server.setConnectors(new Connector[] {localConnector}); - server.setHandler(servletCollection); - } - - public void start() throws Exception { - server.start(); - } - - public void stop() throws Exception { - server.stop(); - } - -} diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/InMemoryWebDavServer.java b/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java similarity index 72% rename from main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/InMemoryWebDavServer.java rename to main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java index 5adaf2c9b..6bbe43d1f 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/InMemoryWebDavServer.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/InMemoryWebDavServer.java @@ -6,21 +6,31 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.jackrabbitservlet; +package org.cryptomator.webdav.server; import java.nio.ByteBuffer; +import java.util.EnumSet; + +import javax.servlet.DispatcherType; import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.WritableFile; import org.cryptomator.filesystem.inmem.InMemoryFileSystem; +import org.cryptomator.webdav.filters.LoggingHttpFilter; +import org.eclipse.jetty.servlet.ServletContextHandler; public class InMemoryWebDavServer { public static void main(String[] args) throws Exception { - FileSystem fileSystem = setupFilesystem(); - FileSystemBasedWebDavServer server = new FileSystemBasedWebDavServer(fileSystem); - + WebDavServer server = DaggerWebDavComponent.create().getServer(); + server.setPort(8080); server.start(); + + FileSystem fileSystem = setupFilesystem(); + ServletContextHandler servlet = server.addServlet(fileSystem, "/foo"); + servlet.addFilter(LoggingHttpFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + servlet.start(); + System.out.println("Server started. Press any key to stop it..."); System.in.read(); server.stop(); diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/NioWebDavServer.java b/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java similarity index 80% rename from main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/NioWebDavServer.java rename to main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java index afc1e6632..0f0227938 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/webdav/jackrabbitservlet/NioWebDavServer.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/webdav/server/NioWebDavServer.java @@ -6,7 +6,7 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.webdav.jackrabbitservlet; +package org.cryptomator.webdav.server; import java.io.BufferedReader; import java.io.IOException; @@ -16,20 +16,30 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.EnumSet; import java.util.Optional; +import javax.servlet.DispatcherType; + import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.nio.NioFileSystem; +import org.cryptomator.webdav.filters.LoggingHttpFilter; +import org.eclipse.jetty.servlet.ServletContextHandler; public class NioWebDavServer { private static final String PATH_TO_SERVE_PROPERTY = "pathToServe"; public static void main(String[] args) throws Exception { - FileSystem fileSystem = setupFilesystem(); - FileSystemBasedWebDavServer server = new FileSystemBasedWebDavServer(fileSystem); - + WebDavServer server = DaggerWebDavComponent.create().getServer(); + server.setPort(8080); server.start(); + + FileSystem fileSystem = setupFilesystem(); + ServletContextHandler servlet = server.addServlet(fileSystem, "/foo"); + servlet.addFilter(LoggingHttpFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + servlet.start(); + System.out.println("Server started. Press any key to stop it..."); System.in.read(); server.stop();