diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/AcceptRangeFilter.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/AcceptRangeFilter.java
new file mode 100644
index 000000000..34dff9d18
--- /dev/null
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/AcceptRangeFilter.java
@@ -0,0 +1,38 @@
+package org.cryptomator.webdav.filters;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Adds an Accept-Range: bytes header to all GET requests.
+ */
+public class AcceptRangeFilter implements HttpFilter {
+
+ private static final String METHOD_GET = "GET";
+ private static final String HEADER_ACCEPT_RANGES = "Accept-Ranges";
+ private static final String HEADER_ACCEPT_RANGE_VALUE = "bytes";
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // no-op
+ }
+
+ @Override
+ public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+ if (METHOD_GET.equalsIgnoreCase(request.getMethod())) {
+ response.addHeader(HEADER_ACCEPT_RANGES, HEADER_ACCEPT_RANGE_VALUE);
+ }
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ // no-op
+ }
+
+}
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/HttpFilter.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/HttpFilter.java
new file mode 100644
index 000000000..9f1d0797c
--- /dev/null
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/HttpFilter.java
@@ -0,0 +1,26 @@
+package org.cryptomator.webdav.filters;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+interface HttpFilter extends Filter {
+
+ @Override
+ default void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
+ doFilterHttp((HttpServletRequest) request, (HttpServletResponse) response, chain);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException;
+
+}
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/UriNormalizationFilter.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/UriNormalizationFilter.java
new file mode 100644
index 000000000..785e8f1bf
--- /dev/null
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/filters/UriNormalizationFilter.java
@@ -0,0 +1,77 @@
+package org.cryptomator.webdav.filters;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Depending on the HTTP method a "/" is added to or removed from the end of an URI.
+ * For example MKCOL creates a directory (ending on "/"), while PUT creates a file (not ending on "/").
+ */
+public class UriNormalizationFilter implements HttpFilter {
+
+ private static final String[] FILE_METHODS = {"PUT"};
+ private static final String[] DIRECTORY_METHODS = {"MKCOL"};
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // no-op
+ }
+
+ @Override
+ public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+ if (ArrayUtils.contains(FILE_METHODS, request.getMethod().toUpperCase())) {
+ chain.doFilter(new FileUriRequest(request), response);
+ } else if (ArrayUtils.contains(DIRECTORY_METHODS, request.getMethod().toUpperCase())) {
+ chain.doFilter(new DirectoryUriRequest(request), response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ // no-op
+ }
+
+ /**
+ * HTTP request, whose URI never ends on "/".
+ */
+ private static class FileUriRequest extends HttpServletRequestWrapper {
+
+ public FileUriRequest(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public String getRequestURI() {
+ return StringUtils.removeEnd(super.getRequestURI(), "/");
+ }
+
+ }
+
+ /**
+ * HTTP request, whose URI always ends on "/".
+ */
+ private static class DirectoryUriRequest extends HttpServletRequestWrapper {
+
+ public DirectoryUriRequest(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public String getRequestURI() {
+ return StringUtils.appendIfMissing(super.getRequestURI(), "/");
+ }
+
+ }
+
+}
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFile.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFile.java
index 3eb96adfa..12cbb1857 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFile.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFile.java
@@ -17,7 +17,6 @@ import java.time.Instant;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceIterator;
-import org.apache.jackrabbit.webdav.DavResourceLocator;
import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.io.InputContext;
import org.apache.jackrabbit.webdav.io.OutputContext;
@@ -25,11 +24,12 @@ import org.apache.jackrabbit.webdav.lock.LockManager;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
+import org.cryptomator.webdav.jackrabbit.DavPathFactory.DavPath;
class DavFile extends DavNode {
- public DavFile(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavResourceLocator locator, File node) {
- super(factory, lockManager, session, locator, node);
+ public DavFile(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, File node) {
+ super(factory, lockManager, session, path, node);
}
@Override
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFolder.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFolder.java
index 132092699..29c0d5f61 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFolder.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavFolder.java
@@ -9,6 +9,11 @@
package org.cryptomator.webdav.jackrabbit;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
import java.time.Instant;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -17,7 +22,6 @@ import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceIterator;
import org.apache.jackrabbit.webdav.DavResourceIteratorImpl;
-import org.apache.jackrabbit.webdav.DavResourceLocator;
import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.io.InputContext;
import org.apache.jackrabbit.webdav.io.OutputContext;
@@ -27,11 +31,14 @@ import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
import org.apache.jackrabbit.webdav.property.ResourceType;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
+import org.cryptomator.filesystem.FolderCreateMode;
+import org.cryptomator.filesystem.WritableFile;
+import org.cryptomator.webdav.jackrabbit.DavPathFactory.DavPath;
class DavFolder extends DavNode {
- public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavResourceLocator locator, Folder folder) {
- super(factory, lockManager, session, locator, folder);
+ public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, Folder folder) {
+ super(factory, lockManager, session, path, folder);
properties.add(new ResourceType(ResourceType.COLLECTION));
properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, 1));
}
@@ -48,8 +55,30 @@ class DavFolder extends DavNode {
@Override
public void addMember(DavResource resource, InputContext inputContext) throws DavException {
- // TODO Auto-generated method stub
+ if (resource instanceof DavFolder) {
+ addMemberFolder((DavFolder) resource);
+ } else if (resource instanceof DavFile) {
+ addMemberFile((DavFile) resource, inputContext.getInputStream());
+ } else {
+ throw new IllegalArgumentException("Unsupported resource type: " + resource.getClass().getName());
+ }
+ }
+ private void addMemberFolder(DavFolder memberFolder) {
+ node.folder(memberFolder.getDisplayName()).create(FolderCreateMode.FAIL_IF_PARENT_IS_MISSING);
+ }
+
+ private void addMemberFile(DavFile memberFile, InputStream inputStream) {
+ try (ReadableByteChannel src = Channels.newChannel(inputStream); WritableFile dst = node.file(memberFile.getDisplayName()).openWritable()) {
+ ByteBuffer buf = ByteBuffer.allocate(1337);
+ while (src.read(buf) != -1) {
+ buf.flip();
+ dst.write(buf);
+ buf.clear();
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
@Override
@@ -60,14 +89,12 @@ class DavFolder extends DavNode {
}
private DavFolder getMemberFolder(Folder memberFolder) {
- final String subFolderResourcePath = locator.getResourcePath() + memberFolder.name() + '/';
- final DavResourceLocator subFolderLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), subFolderResourcePath);
+ final DavPath subFolderLocator = path.getChild(memberFolder.name() + '/');
return factory.createFolder(memberFolder, subFolderLocator, session);
}
private DavFile getMemberFile(File memberFile) {
- final String subFolderResourcePath = locator.getResourcePath() + memberFile.name();
- final DavResourceLocator subFolderLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), subFolderResourcePath);
+ final DavPath subFolderLocator = path.getChild(memberFile.name());
return factory.createFile(memberFile, subFolderLocator, session);
}
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavNode.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavNode.java
index 340f0654d..3a1179e9d 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavNode.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavNode.java
@@ -14,7 +14,6 @@ import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
-import org.apache.commons.io.FilenameUtils;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceLocator;
@@ -31,6 +30,7 @@ import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.property.DavPropertySet;
import org.apache.jackrabbit.webdav.property.PropEntry;
import org.cryptomator.filesystem.Node;
+import org.cryptomator.webdav.jackrabbit.DavPathFactory.DavPath;
abstract class DavNode implements DavResource {
@@ -41,15 +41,15 @@ abstract class DavNode implements DavResource {
protected final FilesystemResourceFactory factory;
protected final LockManager lockManager;
protected final DavSession session;
- protected final DavResourceLocator locator;
+ protected final DavPath path;
protected final T node;
protected final DavPropertySet properties;
- public DavNode(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavResourceLocator locator, T node) {
+ public DavNode(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, T node) {
this.factory = factory;
this.lockManager = lockManager;
this.session = session;
- this.locator = locator;
+ this.path = path;
this.node = node;
this.properties = new DavPropertySet();
}
@@ -76,17 +76,17 @@ abstract class DavNode implements DavResource {
@Override
public DavResourceLocator getLocator() {
- return locator;
+ return path;
}
@Override
public String getResourcePath() {
- return locator.getResourcePath();
+ return path.getResourcePath();
}
@Override
public String getHref() {
- return locator.getHref(this.isCollection());
+ return path.getHref();
}
@Override
@@ -157,16 +157,15 @@ abstract class DavNode implements DavResource {
@Override
public DavResource getCollection() {
- if (locator.isRootLocation()) {
+ if (path.isRootLocation()) {
return null;
}
- final String parentResource = FilenameUtils.getPathNoEndSeparator(locator.getResourcePath());
- final DavResourceLocator parentLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), parentResource);
+ final DavPath parentPath = path.getParent();
try {
- return factory.createResource(parentLocator, session);
+ return factory.createResource(parentPath, session);
} catch (DavException e) {
- throw new IllegalStateException("Unable to get parent resource with path " + parentLocator.getResourcePath(), e);
+ throw new IllegalStateException("Unable to get parent resource with path " + parentPath, e);
}
}
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/IdentityLocatorFactory.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavPathFactory.java
similarity index 57%
rename from main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/IdentityLocatorFactory.java
rename to main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavPathFactory.java
index ca0895db6..86fc03709 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/IdentityLocatorFactory.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/DavPathFactory.java
@@ -19,45 +19,78 @@ import org.apache.jackrabbit.webdav.util.EncodeUtil;
/**
* A LocatorFactory constructing Locators, whose {@link DavResourceLocator#getResourcePath() resourcePath} and {@link DavResourceLocator#getRepositoryPath() repositoryPath} are equal.
* These paths will be plain, case-sensitive, absolute, unencoded Strings with Unix-style path separators.
+ *
+ * Paths ending on "/" are treated as directory paths and all others as file paths.
*/
-class IdentityLocatorFactory implements DavLocatorFactory {
+class DavPathFactory implements DavLocatorFactory {
private final String pathPrefix;
- public IdentityLocatorFactory(URI contextRootUri) {
+ public DavPathFactory(URI contextRootUri) {
this.pathPrefix = StringUtils.removeEnd(contextRootUri.toString(), "/");
}
@Override
- public DavResourceLocator createResourceLocator(String prefix, String href) {
+ public DavPath createResourceLocator(String prefix, String href) {
final String fullPrefix = StringUtils.removeEnd(prefix, "/");
final String remainingHref = StringUtils.removeStart(href, fullPrefix);
final String unencodedRemaingingHref = EncodeUtil.unescape(remainingHref);
- assert unencodedRemaingingHref.startsWith("/");
- return new IdentityLocator(unencodedRemaingingHref);
+ return new DavPath(unencodedRemaingingHref);
}
@Override
- public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
- assert resourcePath.startsWith("/");
- return new IdentityLocator(resourcePath);
+ public DavPath createResourceLocator(String prefix, String workspacePath, String resourcePath) {
+ return createResourceLocator(prefix, workspacePath, resourcePath, true);
}
@Override
- public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
- assert path.startsWith("/");
- return new IdentityLocator(path);
+ public DavPath createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
+ return new DavPath(path);
}
- private class IdentityLocator implements DavResourceLocator {
+ public class DavPath implements DavResourceLocator {
private final String absPath;
- private IdentityLocator(String absPath) {
+ private DavPath(String absPath) {
assert absPath.startsWith("/");
this.absPath = FilenameUtils.normalize(absPath, true);
}
+ /**
+ * @return true if the path ends on "/".
+ */
+ public boolean isDirectory() {
+ return absPath.endsWith("/");
+ }
+
+ /**
+ * @return Parent DavPath or null if this is the root node.
+ */
+ public DavPath getParent() {
+ if (isRootLocation()) {
+ return null;
+ } else {
+ final String parentPath = FilenameUtils.getFullPath(FilenameUtils.normalizeNoEndSeparator(absPath, true));
+ return createResourceLocator(getPrefix(), getWorkspacePath(), parentPath);
+ }
+ }
+
+ /**
+ * Get the path of a child resource, consisting of curren path + child path.
+ * If the child path ends on "/", the returned DavPath will be a directory path.
+ *
+ * @return Child path
+ */
+ public DavPath getChild(String relativeChildPath) {
+ if (isDirectory()) {
+ final String absChildPath = absPath + StringUtils.removeStart(relativeChildPath, "/");
+ return createResourceLocator(getPrefix(), getWorkspacePath(), absChildPath);
+ } else {
+ throw new UnsupportedOperationException("Can only resolve subpaths of a path representing a directory");
+ }
+ }
+
@Override
public String getPrefix() {
return pathPrefix;
@@ -88,13 +121,20 @@ class IdentityLocatorFactory implements DavLocatorFactory {
return false;
}
+ /**
+ * @see #getHref(boolean)
+ */
+ public String getHref() {
+ return getHref(isDirectory());
+ }
+
@Override
public String getHref(boolean isCollection) {
final String encodedResourcePath = EncodeUtil.escapePath(absPath);
if (isRootLocation()) {
return pathPrefix + "/";
} else {
- assert isCollection ? encodedResourcePath.endsWith("/") : true;
+ assert isCollection ? isDirectory() : true;
return pathPrefix + encodedResourcePath;
}
}
@@ -105,8 +145,8 @@ class IdentityLocatorFactory implements DavLocatorFactory {
}
@Override
- public DavLocatorFactory getFactory() {
- return IdentityLocatorFactory.this;
+ public DavPathFactory getFactory() {
+ return DavPathFactory.this;
}
@Override
@@ -116,7 +156,7 @@ class IdentityLocatorFactory implements DavLocatorFactory {
@Override
public String toString() {
- return "Locator: " + absPath + " (Prefix: " + pathPrefix + ")";
+ return "[" + pathPrefix + "]" + absPath;
}
@Override
@@ -126,8 +166,8 @@ class IdentityLocatorFactory implements DavLocatorFactory {
@Override
public boolean equals(Object obj) {
- if (obj instanceof IdentityLocator) {
- final IdentityLocator other = (IdentityLocator) obj;
+ if (obj instanceof DavPath) {
+ final DavPath other = (DavPath) obj;
final boolean samePrefix = this.getPrefix() == null && other.getPrefix() == null || this.getPrefix().equals(other.getPrefix());
final boolean sameRelativeCleartextPath = this.absPath == null && other.absPath == null || this.absPath.equals(other.absPath);
return samePrefix && sameRelativeCleartextPath;
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/FilesystemResourceFactory.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/FilesystemResourceFactory.java
index 5811264e2..c1869c98e 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/FilesystemResourceFactory.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/FilesystemResourceFactory.java
@@ -26,6 +26,7 @@ import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
+import org.cryptomator.webdav.jackrabbit.DavPathFactory.DavPath;
class FilesystemResourceFactory implements DavResourceFactory {
@@ -47,22 +48,29 @@ class FilesystemResourceFactory implements DavResourceFactory {
@Override
public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException {
- final String path = locator.getResourcePath();
- if (path.endsWith("/")) {
- Folder folder = this.resolve(path, FOLDER);
- return createFolder(folder, locator, session);
+ if (locator instanceof DavPath) {
+ return createResource((DavPath) locator, session);
} else {
- File file = this.resolve(path, FILE);
- return createFile(file, locator, session);
+ throw new IllegalArgumentException("Unsupported locator type " + locator.getClass().getName());
}
}
- DavFolder createFolder(Folder folder, DavResourceLocator locator, DavSession session) {
- return new DavFolder(this, lockManager, session, locator, folder);
+ private DavResource createResource(DavPath path, DavSession session) throws DavException {
+ if (path.isDirectory()) {
+ Folder folder = this.resolve(path.getResourcePath(), FOLDER);
+ return createFolder(folder, path, session);
+ } else {
+ File file = this.resolve(path.getResourcePath(), FILE);
+ return createFile(file, path, session);
+ }
}
- public DavFile createFile(File file, DavResourceLocator locator, DavSession session) {
- return new DavFile(this, lockManager, session, locator, file);
+ DavFolder createFolder(Folder folder, DavPath path, DavSession session) {
+ return new DavFolder(this, lockManager, session, path, folder);
+ }
+
+ DavFile createFile(File file, DavPath path, DavSession session) {
+ return new DavFile(this, lockManager, session, path, file);
}
private T resolve(String path, Class expectedNodeType) {
diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/WebDavServlet.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/WebDavServlet.java
index 533479601..2dc991484 100644
--- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/WebDavServlet.java
+++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbit/WebDavServlet.java
@@ -28,7 +28,7 @@ public class WebDavServlet extends AbstractWebdavServlet {
public WebDavServlet(URI contextRootUri, FileSystem filesystem) {
davSessionProvider = new DavSessionProviderImpl();
- davLocatorFactory = new IdentityLocatorFactory(contextRootUri);
+ davLocatorFactory = new DavPathFactory(contextRootUri);
davResourceFactory = new FilesystemResourceFactory(filesystem);
}
diff --git a/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/webdav/jackrabbit/InMemoryWebDavServer.java b/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/webdav/jackrabbit/InMemoryWebDavServer.java
index 9d27c643b..2e5397540 100644
--- a/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/webdav/jackrabbit/InMemoryWebDavServer.java
+++ b/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/webdav/jackrabbit/InMemoryWebDavServer.java
@@ -11,13 +11,18 @@ package org.cryptomator.webdav.jackrabbit;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
+import java.util.EnumSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
+import javax.servlet.DispatcherType;
+
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.FolderCreateMode;
import org.cryptomator.filesystem.WritableFile;
import org.cryptomator.filesystem.inmem.InMemoryFileSystem;
+import org.cryptomator.webdav.filters.AcceptRangeFilter;
+import org.cryptomator.webdav.filters.UriNormalizationFilter;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
@@ -52,6 +57,8 @@ public class InMemoryWebDavServer {
final ServletContextHandler servletContext = new ServletContextHandler(servletCollection, "/", ServletContextHandler.SESSIONS);
final ServletHolder servletHolder = new ServletHolder("InMemory-WebDAV-Servlet", new WebDavServlet(servletContextRootUri, inMemoryFileSystem));
servletContext.addServlet(servletHolder, "/*");
+ servletContext.addFilter(AcceptRangeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
+ servletContext.addFilter(UriNormalizationFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
servletCollection.mapContexts();
server.setConnectors(new Connector[] {localConnector});