new filesystem-aware WebDAV LocatorFactory

This commit is contained in:
Sebastian Stenzel
2016-01-01 22:48:16 +01:00
parent 4e7f3503d9
commit a9744167c1
13 changed files with 396 additions and 266 deletions

View File

@@ -23,11 +23,14 @@
</properties>
<dependencies>
<!-- Filesystem -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- Jackrabbit -->
<dependency>
@@ -48,6 +51,10 @@
</dependency>
<!-- Test -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>

View File

@@ -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 DelegatingFile<DelegatingReadableFile, DelegatingWritableFile, FolderLocator>implements FileSystemResourceLocator {
private final DavLocatorFactory factory;
private final String prefix;
private final AtomicReference<String> 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<String> getResourcePathRef() {
return resourcePath;
}
@Override
public String computeResourcePath() {
assert parent().isPresent();
return parent().get().getResourcePath() + name();
}
}

View File

@@ -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 "/";
}
}

View File

@@ -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<String> getResourcePathRef();
String computeResourcePath();
@Override
Optional<FolderLocator> 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();
}
}

View File

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

View File

@@ -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 DelegatingFolder<DelegatingReadableFile, DelegatingWritableFile, FolderLocator, FileLocator>implements FileSystemResourceLocator {
private final DavLocatorFactory factory;
private final String prefix;
private final AtomicReference<String> 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<String> getResourcePathRef() {
return resourcePath;
}
@Override
public String computeResourcePath() {
assert parent().isPresent();
return parent().get().getResourcePath() + name() + "/";
}
}

View File

@@ -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<File> {
class DavFile extends DavNode<FileLocator> {
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

View File

@@ -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<Folder> {
class DavFolder extends DavNode<FolderLocator> {
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<Integer>(DavPropertyName.ISCOLLECTION, 1));
}
@@ -89,14 +90,12 @@ class DavFolder extends DavNode<Folder> {
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<Folder> {
*/
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);
});
}

View File

@@ -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<T extends Node> implements DavResource {
abstract class DavNode<T extends FileSystemResourceLocator> 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<T extends Node> 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<T extends Node> 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<T extends Node> 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) {

View File

@@ -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 <code>true</code> if the path ends on "/".
*/
public boolean isDirectory() {
return absPath.endsWith("/");
}
/**
* @return Parent DavPath or <code>null</code> 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;
}
}
}
}

View File

@@ -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 = Folder.class;
private static final Class<File> 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 extends Node> T resolve(String path, Class<T> 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 extends Node> T resolve(Folder parent, Iterator<String> pathIterator, Class<T> 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);
}
}

View File

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

View File

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