From a9744167c16793a25bbaf43746e8f54eceff1879 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Fri, 1 Jan 2016 22:48:16 +0100 Subject: [PATCH] new filesystem-aware WebDAV LocatorFactory --- main/jackrabbit-filesystem-adapter/pom.xml | 9 +- .../filesystem/jackrabbit/FileLocator.java | 60 ++++++ .../jackrabbit/FileSystemLocator.java | 23 +++ .../jackrabbit/FileSystemResourceLocator.java | 61 ++++++ .../FileSystemResourceLocatorFactory.java | 55 ++++++ .../filesystem/jackrabbit/FolderLocator.java | 71 +++++++ .../webdav/jackrabbitservlet/DavFile.java | 9 +- .../webdav/jackrabbitservlet/DavFolder.java | 21 +- .../webdav/jackrabbitservlet/DavNode.java | 20 +- .../jackrabbitservlet/DavPathFactory.java | 180 ------------------ .../FilesystemResourceFactory.java | 69 ++----- .../jackrabbitservlet/WebDavServlet.java | 5 +- .../FileSystemResourceLocatorFactoryTest.java | 79 ++++++++ 13 files changed, 396 insertions(+), 266 deletions(-) create mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileLocator.java create mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java create mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocator.java create mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactory.java create mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FolderLocator.java delete mode 100644 main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavPathFactory.java create mode 100644 main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactoryTest.java diff --git a/main/jackrabbit-filesystem-adapter/pom.xml b/main/jackrabbit-filesystem-adapter/pom.xml index d54f2073a..e361a17fc 100644 --- a/main/jackrabbit-filesystem-adapter/pom.xml +++ b/main/jackrabbit-filesystem-adapter/pom.xml @@ -23,11 +23,14 @@ - org.cryptomator filesystem-api + + org.cryptomator + commons + @@ -48,6 +51,10 @@ + + org.cryptomator + commons-test + org.eclipse.jetty jetty-server diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileLocator.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileLocator.java new file mode 100644 index 000000000..297fd466e --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileLocator.java @@ -0,0 +1,60 @@ +package org.cryptomator.filesystem.jackrabbit; + +import java.io.UncheckedIOException; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.delegating.DelegatingFile; +import org.cryptomator.filesystem.delegating.DelegatingReadableFile; +import org.cryptomator.filesystem.delegating.DelegatingWritableFile; + +public class FileLocator extends DelegatingFileimplements FileSystemResourceLocator { + + private final DavLocatorFactory factory; + private final String prefix; + private final AtomicReference resourcePath = new AtomicReference<>(); + + public FileLocator(DavLocatorFactory factory, String prefix, FolderLocator parent, File delegate) { + super(parent, delegate); + this.factory = factory; + this.prefix = prefix; + } + + @Override + public DelegatingReadableFile openReadable() throws UncheckedIOException { + return new DelegatingReadableFile(delegate.openReadable()); + } + + @Override + public DelegatingWritableFile openWritable() throws UncheckedIOException { + return new DelegatingWritableFile(delegate.openWritable()); + } + + @Override + public String getPrefix() { + return prefix; + } + + @Override + public boolean isRootLocation() { + return false; + } + + @Override + public DavLocatorFactory getFactory() { + return factory; + } + + @Override + public AtomicReference getResourcePathRef() { + return resourcePath; + } + + @Override + public String computeResourcePath() { + assert parent().isPresent(); + return parent().get().getResourcePath() + name(); + } + +} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java new file mode 100644 index 000000000..6bf9116e3 --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java @@ -0,0 +1,23 @@ +package org.cryptomator.filesystem.jackrabbit; + +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; + +class FileSystemLocator extends FolderLocator implements FileSystem { + + public FileSystemLocator(DavLocatorFactory factory, String prefix, Folder delegate) { + super(factory, prefix, null, delegate); + } + + @Override + public boolean isRootLocation() { + return true; + } + + @Override + public String getResourcePath() { + return "/"; + } + +} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocator.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocator.java new file mode 100644 index 000000000..c6717194c --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocator.java @@ -0,0 +1,61 @@ +package org.cryptomator.filesystem.jackrabbit; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.cryptomator.common.LazyInitializer; +import org.cryptomator.filesystem.Node; + +public interface FileSystemResourceLocator extends DavResourceLocator, Node { + + @Override + default String getResourcePath() { + return LazyInitializer.initializeLazily(getResourcePathRef(), this::computeResourcePath); + } + + AtomicReference getResourcePathRef(); + + String computeResourcePath(); + + @Override + Optional parent(); + + @Override + default String getWorkspacePath() { + return null; + } + + @Override + default String getWorkspaceName() { + return null; + } + + @Override + default boolean isSameWorkspace(DavResourceLocator locator) { + return false; + } + + @Override + default boolean isSameWorkspace(String workspaceName) { + return false; + } + + default String getHref() { + final boolean isCollection = getResourcePath().endsWith("/"); + return getHref(isCollection); + } + + @Override + default String getHref(boolean isCollection) { + final String encodedResourcePath = EncodeUtil.escapePath(getResourcePath()); + return getPrefix() + encodedResourcePath; + } + + @Override + default String getRepositoryPath() { + return getResourcePath(); + } + +} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactory.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactory.java new file mode 100644 index 000000000..ba1ca9d75 --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactory.java @@ -0,0 +1,55 @@ +package org.cryptomator.filesystem.jackrabbit; + +import java.net.URI; + +import org.apache.commons.lang3.StringUtils; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.cryptomator.filesystem.Folder; + +public class FileSystemResourceLocatorFactory implements DavLocatorFactory { + + private final FileSystemLocator fs; + + public FileSystemResourceLocatorFactory(URI contextRootUri, Folder root) { + String pathPrefix = StringUtils.removeEnd(contextRootUri.toString(), "/"); + this.fs = new FileSystemLocator(this, pathPrefix, root); + } + + @Override + public FileSystemResourceLocator createResourceLocator(String prefix, String href) { + final String fullPrefix = StringUtils.removeEnd(prefix, "/"); + final String remainingHref = StringUtils.removeStart(href, fullPrefix); + final String unencodedRemaingingHref = EncodeUtil.unescape(remainingHref); + return createResourceLocator(unencodedRemaingingHref); + } + + @Override + public FileSystemResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { + return createResourceLocator(resourcePath); + } + + @Override + public FileSystemResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + return createResourceLocator(path); + } + + private FileSystemResourceLocator createResourceLocator(String path) { + if (StringUtils.isEmpty(path) || "/".equals(path)) { + return fs; + } + final FolderLocator folder = fs.resolveFolder(path); + final FileLocator file = fs.resolveFile(path); + if (folder.exists()) { + return folder; + } else if (file.exists()) { + return file; + } else if (path.endsWith("/")) { + return folder; + } else { + return file; + } + + } + +} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FolderLocator.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FolderLocator.java new file mode 100644 index 000000000..d1a99be05 --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/filesystem/jackrabbit/FolderLocator.java @@ -0,0 +1,71 @@ +package org.cryptomator.filesystem.jackrabbit; + +import java.io.UncheckedIOException; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.cryptomator.filesystem.File; +import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFolder; +import org.cryptomator.filesystem.delegating.DelegatingReadableFile; +import org.cryptomator.filesystem.delegating.DelegatingWritableFile; + +public class FolderLocator extends DelegatingFolderimplements FileSystemResourceLocator { + + private final DavLocatorFactory factory; + private final String prefix; + private final AtomicReference resourcePath = new AtomicReference<>(); + + public FolderLocator(DavLocatorFactory factory, String prefix, FolderLocator parent, Folder delegate) { + super(parent, delegate); + this.factory = factory; + this.prefix = prefix; + } + + @Override + protected FileLocator file(File delegate) { + return new FileLocator(factory, prefix, this, delegate); + } + + @Override + public FileLocator resolveFile(String relativePath) throws UncheckedIOException { + return (FileLocator) super.resolveFile(relativePath); + } + + @Override + protected FolderLocator folder(Folder delegate) { + return new FolderLocator(factory, prefix, this, delegate); + } + + @Override + public FolderLocator resolveFolder(String relativePath) throws UncheckedIOException { + return (FolderLocator) super.resolveFolder(relativePath); + } + + @Override + public String getPrefix() { + return prefix; + } + + @Override + public boolean isRootLocation() { + return false; + } + + @Override + public DavLocatorFactory getFactory() { + return factory; + } + + @Override + public AtomicReference getResourcePathRef() { + return resourcePath; + } + + @Override + public String computeResourcePath() { + assert parent().isPresent(); + return parent().get().getResourcePath() + name() + "/"; + } + +} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFile.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFile.java index db913a9da..7aa0a17d6 100644 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFile.java +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFile.java @@ -21,15 +21,14 @@ import org.apache.jackrabbit.webdav.DavSession; import org.apache.jackrabbit.webdav.io.InputContext; import org.apache.jackrabbit.webdav.io.OutputContext; 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.jackrabbitservlet.DavPathFactory.DavPath; +import org.cryptomator.filesystem.jackrabbit.FileLocator; -class DavFile extends DavNode { +class DavFile extends DavNode { - public DavFile(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, File node) { - super(factory, lockManager, session, path, node); + public DavFile(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, FileLocator node) { + super(factory, lockManager, session, node); } @Override diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFolder.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFolder.java index f4a506d2c..98969a353 100644 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFolder.java +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavFolder.java @@ -34,12 +34,13 @@ import org.cryptomator.filesystem.File; import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.Node; import org.cryptomator.filesystem.WritableFile; -import org.cryptomator.webdav.jackrabbitservlet.DavPathFactory.DavPath; +import org.cryptomator.filesystem.jackrabbit.FileLocator; +import org.cryptomator.filesystem.jackrabbit.FolderLocator; -class DavFolder extends DavNode { +class DavFolder extends DavNode { - public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, Folder folder) { - super(factory, lockManager, session, path, folder); + public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, FolderLocator folder) { + super(factory, lockManager, session, folder); properties.add(new ResourceType(ResourceType.COLLECTION)); properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, 1)); } @@ -89,14 +90,12 @@ class DavFolder extends DavNode { return new DavResourceIteratorImpl(Stream.concat(folders, files).collect(Collectors.toList())); } - private DavFolder folderToDavFolder(Folder memberFolder) { - final DavPath subFolderLocator = path.getChild(memberFolder.name() + '/'); - return factory.createFolder(memberFolder, subFolderLocator, session); + private DavFolder folderToDavFolder(FolderLocator memberFolder) { + return factory.createFolder(memberFolder, session); } - private DavFile fileToDavFile(File memberFile) { - final DavPath subFolderLocator = path.getChild(memberFile.name()); - return factory.createFile(memberFile, subFolderLocator, session); + private DavFile fileToDavFile(FileLocator memberFile) { + return factory.createFile(memberFile, session); } @Override @@ -121,7 +120,7 @@ class DavFolder extends DavNode { */ private Node getMemberNode(String name) throws DavException { return node.children().filter(c -> c.name().equals(name)).findAny().orElseThrow(() -> { - return new DavException(DavServletResponse.SC_NOT_FOUND, "No such file or directory: " + path + name); + return new DavException(DavServletResponse.SC_NOT_FOUND, "No such file or directory: " + node.getResourcePath() + name); }); } diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavNode.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavNode.java index 89c938899..9b5f107a2 100644 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavNode.java +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavNode.java @@ -29,10 +29,9 @@ import org.apache.jackrabbit.webdav.property.DavPropertyName; 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.jackrabbitservlet.DavPathFactory.DavPath; +import org.cryptomator.filesystem.jackrabbit.FileSystemResourceLocator; -abstract class DavNode implements DavResource { +abstract class DavNode implements DavResource { private static final String DAV_COMPLIANCE_CLASSES = "1, 2"; private static final String[] DAV_CREATIONDATE_PROPNAMES = {DavPropertyName.CREATIONDATE.getName(), "Win32CreationTime"}; @@ -41,15 +40,13 @@ abstract class DavNode implements DavResource { protected final FilesystemResourceFactory factory; protected final LockManager lockManager; protected final DavSession session; - protected final DavPath path; protected final T node; protected final DavPropertySet properties; - public DavNode(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, DavPath path, T node) { + public DavNode(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, T node) { this.factory = factory; this.lockManager = lockManager; this.session = session; - this.path = path; this.node = node; this.properties = new DavPropertySet(); } @@ -76,17 +73,17 @@ abstract class DavNode implements DavResource { @Override public DavResourceLocator getLocator() { - return path; + return node; } @Override public String getResourcePath() { - return path.getResourcePath(); + return node.getResourcePath(); } @Override public String getHref() { - return path.getHref(); + return node.getHref(); } @Override @@ -157,11 +154,12 @@ abstract class DavNode implements DavResource { @Override public DavResource getCollection() { - if (path.isRootLocation()) { + if (node.isRootLocation()) { return null; } - final DavPath parentPath = path.getParent(); + assert node.parent().isPresent() : "as my mom always sais: if it's not root, it has a parent"; + final FileSystemResourceLocator parentPath = node.parent().get(); try { return factory.createResource(parentPath, session); } catch (DavException e) { diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavPathFactory.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavPathFactory.java deleted file mode 100644 index 11076d714..000000000 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/DavPathFactory.java +++ /dev/null @@ -1,180 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 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 org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -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 DavPathFactory implements DavLocatorFactory { - - private final String pathPrefix; - - public DavPathFactory(URI contextRootUri) { - this.pathPrefix = StringUtils.removeEnd(contextRootUri.toString(), "/"); - } - - @Override - 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); - return new DavPath(unencodedRemaingingHref); - } - - @Override - public DavPath createResourceLocator(String prefix, String workspacePath, String resourcePath) { - return createResourceLocator(prefix, workspacePath, resourcePath, true); - } - - @Override - public DavPath createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { - return new DavPath(path); - } - - public class DavPath implements DavResourceLocator { - - private final 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; - } - - @Override - public String getResourcePath() { - return absPath; - } - - @Override - public String getWorkspacePath() { - return null; - } - - @Override - public String getWorkspaceName() { - return null; - } - - @Override - public boolean isSameWorkspace(DavResourceLocator locator) { - return false; - } - - @Override - public boolean isSameWorkspace(String workspaceName) { - 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 ? isDirectory() : true; - return pathPrefix + encodedResourcePath; - } - } - - @Override - public boolean isRootLocation() { - return "/".equals(absPath); - } - - @Override - public DavPathFactory getFactory() { - return DavPathFactory.this; - } - - @Override - public String getRepositoryPath() { - return absPath; - } - - @Override - public String toString() { - return "[" + pathPrefix + "]" + absPath; - } - - @Override - public int hashCode() { - return absPath.hashCode(); - } - - @Override - public boolean equals(Object 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; - } else { - return false; - } - } - } - -} diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/FilesystemResourceFactory.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/FilesystemResourceFactory.java index d734d793d..f169df87b 100644 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/FilesystemResourceFactory.java +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/FilesystemResourceFactory.java @@ -8,11 +8,6 @@ *******************************************************************************/ package org.cryptomator.webdav.jackrabbitservlet; -import java.util.Arrays; -import java.util.Iterator; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; import org.apache.jackrabbit.webdav.DavResourceFactory; @@ -22,22 +17,14 @@ import org.apache.jackrabbit.webdav.DavServletResponse; import org.apache.jackrabbit.webdav.DavSession; import org.apache.jackrabbit.webdav.lock.LockManager; import org.apache.jackrabbit.webdav.lock.SimpleLockManager; -import org.cryptomator.filesystem.File; -import org.cryptomator.filesystem.FileSystem; -import org.cryptomator.filesystem.Folder; -import org.cryptomator.filesystem.Node; -import org.cryptomator.webdav.jackrabbitservlet.DavPathFactory.DavPath; +import org.cryptomator.filesystem.jackrabbit.FileLocator; +import org.cryptomator.filesystem.jackrabbit.FolderLocator; class FilesystemResourceFactory implements DavResourceFactory { - private static final Class FOLDER = Folder.class; - private static final Class FILE = File.class; - - private final FileSystem filesystem; private final LockManager lockManager; - public FilesystemResourceFactory(FileSystem filesystem) { - this.filesystem = filesystem; + public FilesystemResourceFactory() { this.lockManager = new SimpleLockManager(); } @@ -48,53 +35,23 @@ class FilesystemResourceFactory implements DavResourceFactory { @Override public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { - if (locator instanceof DavPath) { - return createResource((DavPath) locator, session); + if (locator instanceof FolderLocator) { + FolderLocator folder = (FolderLocator) locator; + return createFolder(folder, session); + } else if (locator instanceof FileLocator) { + FileLocator file = (FileLocator) locator; + return createFile(file, session); } else { throw new IllegalArgumentException("Unsupported locator type " + locator.getClass().getName()); } } - 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); - } + DavFolder createFolder(FolderLocator folder, DavSession session) { + return new DavFolder(this, lockManager, session, folder); } - 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) { - final String[] pathFragments = StringUtils.split(path, '/'); - if (ArrayUtils.isEmpty(pathFragments)) { - assert expectedNodeType.isAssignableFrom(Folder.class); - return expectedNodeType.cast(filesystem); - } else { - return resolve(filesystem, Arrays.stream(pathFragments).iterator(), expectedNodeType); - } - } - - private T resolve(Folder parent, Iterator pathIterator, Class expectedNodeType) { - assert pathIterator.hasNext(); - final String childName = pathIterator.next(); - if (pathIterator.hasNext()) { - return resolve(parent.folder(childName), pathIterator, expectedNodeType); - } else if (expectedNodeType.isAssignableFrom(Folder.class)) { - return expectedNodeType.cast(parent.folder(childName)); - } else if (expectedNodeType.isAssignableFrom(File.class)) { - return expectedNodeType.cast(parent.file(childName)); - } else { - throw new IllegalArgumentException("Supported expectedNodeTypes are File or Folder."); - } + DavFile createFile(FileLocator file, DavSession session) { + return new DavFile(this, lockManager, session, file); } } diff --git a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java index 5e5d1d203..f883cef1d 100644 --- a/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java +++ b/main/jackrabbit-filesystem-adapter/src/main/java/org/cryptomator/webdav/jackrabbitservlet/WebDavServlet.java @@ -17,6 +17,7 @@ import org.apache.jackrabbit.webdav.DavSessionProvider; import org.apache.jackrabbit.webdav.WebdavRequest; import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.jackrabbit.FileSystemResourceLocatorFactory; public class WebDavServlet extends AbstractWebdavServlet { @@ -28,8 +29,8 @@ public class WebDavServlet extends AbstractWebdavServlet { public WebDavServlet(URI contextRootUri, FileSystem filesystem) { davSessionProvider = new DavSessionProviderImpl(); - davLocatorFactory = new DavPathFactory(contextRootUri); - davResourceFactory = new FilesystemResourceFactory(filesystem); + davLocatorFactory = new FileSystemResourceLocatorFactory(contextRootUri, filesystem); + davResourceFactory = new FilesystemResourceFactory(); } @Override diff --git a/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactoryTest.java b/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactoryTest.java new file mode 100644 index 000000000..ce3edf417 --- /dev/null +++ b/main/jackrabbit-filesystem-adapter/src/test/java/org/cryptomator/filesystem/jackrabbit/FileSystemResourceLocatorFactoryTest.java @@ -0,0 +1,79 @@ +package org.cryptomator.filesystem.jackrabbit; + +import java.net.URI; +import java.nio.ByteBuffer; + +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.WritableFile; +import org.cryptomator.filesystem.inmem.InMemoryFileSystem; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class FileSystemResourceLocatorFactoryTest { + + private FileSystemResourceLocatorFactory factory; + + @Before + public void setupLocatorFactory() { + final FileSystem fs = new InMemoryFileSystem(); + fs.folder("existingFolder").create(); + try (WritableFile writable = fs.file("existingFile").openWritable()) { + writable.write(ByteBuffer.allocate(0)); + } + factory = new FileSystemResourceLocatorFactory(URI.create("http://localhost/contextroot"), fs); + } + + @Test + public void testCreateFoldersEvenWhenRequestingFiles() { + FileSystemResourceLocator locator = factory.createResourceLocator(null, null, "/existingFolder"); + Assert.assertTrue(locator instanceof FolderLocator); + + locator = factory.createResourceLocator("http://localhost/contextroot", "http://localhost/contextroot/existingFolder"); + Assert.assertTrue(locator instanceof FolderLocator); + } + + @Test + public void testCreateFilesEvenWhenRequestingFolders() { + FileSystemResourceLocator locator = factory.createResourceLocator(null, null, "/existingFile/"); + Assert.assertTrue(locator instanceof FileLocator); + + locator = factory.createResourceLocator("http://localhost/contextroot", "http://localhost/contextroot/existingFile/"); + Assert.assertTrue(locator instanceof FileLocator); + } + + @Test + public void testCreateFolders() { + FileSystemResourceLocator locator = factory.createResourceLocator(null, null, "/foo/bar/"); + Assert.assertTrue(locator instanceof FolderLocator); + Assert.assertEquals("bar", locator.name()); + Assert.assertEquals("foo", locator.parent().get().name()); + Assert.assertEquals("", locator.parent().get().parent().get().name()); + Assert.assertFalse(locator.parent().get().parent().get().parent().isPresent()); + + locator = factory.createResourceLocator("http://localhost/contextroot", "http://localhost/contextroot/foo/bar/"); + Assert.assertTrue(locator instanceof FolderLocator); + Assert.assertEquals("bar", locator.name()); + Assert.assertEquals("foo", locator.parent().get().name()); + Assert.assertEquals("", locator.parent().get().parent().get().name()); + Assert.assertFalse(locator.parent().get().parent().get().parent().isPresent()); + } + + @Test + public void testCreateFiles() { + FileSystemResourceLocator locator = factory.createResourceLocator(null, null, "/foo/bar"); + Assert.assertTrue(locator instanceof FileLocator); + Assert.assertEquals("bar", locator.name()); + Assert.assertEquals("foo", locator.parent().get().name()); + Assert.assertEquals("", locator.parent().get().parent().get().name()); + Assert.assertFalse(locator.parent().get().parent().get().parent().isPresent()); + + locator = factory.createResourceLocator("http://localhost/contextroot", "http://localhost/contextroot/foo/bar"); + Assert.assertTrue(locator instanceof FileLocator); + Assert.assertEquals("bar", locator.name()); + Assert.assertEquals("foo", locator.parent().get().name()); + Assert.assertEquals("", locator.parent().get().parent().get().name()); + Assert.assertFalse(locator.parent().get().parent().get().parent().isPresent()); + } + +}