From 5df9f35065d386f460af842f533bbdfe76a958c6 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 22 Feb 2016 13:06:56 +0100 Subject: [PATCH] Locking unmapped URLs results in creation of that resource now, as specified in http://www.webdav.org/specs/rfc4918.html#rfc.section.9.10.4 --- .../webdav/jackrabbitservlet/DavFile.java | 11 +++++ .../webdav/jackrabbitservlet/DavFolder.java | 1 + .../jackrabbitservlet/NullInputContext.java | 45 +++++++++++++++++++ .../frontend/webdav/WebDavServerTest.java | 38 ++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/NullInputContext.java diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFile.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFile.java index f431ba335..951476555 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFile.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFile.java @@ -21,6 +21,8 @@ import org.apache.jackrabbit.webdav.DavServletResponse; 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.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; import org.apache.jackrabbit.webdav.lock.LockManager; import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyName; @@ -166,4 +168,13 @@ class DavFile extends DavNode { } } + @Override + public ActiveLock lock(LockInfo reqLockInfo) throws DavException { + ActiveLock lock = super.lock(reqLockInfo); + if (!exists()) { + getCollection().addMember(this, new NullInputContext()); + } + return lock; + } + } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java index 4992967cd..1d3cbf313 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java @@ -61,6 +61,7 @@ class DavFolder extends DavNode { if (resource instanceof DavFolder) { addMemberFolder((DavFolder) resource); } else if (resource instanceof DavFile) { + assert inputContext.hasStream(); addMemberFile((DavFile) resource, inputContext.getInputStream()); } else { throw new IllegalArgumentException("Unsupported resource type: " + resource.getClass().getName()); diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/NullInputContext.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/NullInputContext.java new file mode 100644 index 000000000..058421dcf --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/NullInputContext.java @@ -0,0 +1,45 @@ +package org.cryptomator.frontend.webdav.jackrabbitservlet; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.apache.jackrabbit.webdav.io.InputContext; + +public class NullInputContext implements InputContext { + + @Override + public boolean hasStream() { + return true; + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(new byte[0]); + } + + @Override + public long getModificationTime() { + return 0; + } + + @Override + public String getContentLanguage() { + return null; + } + + @Override + public long getContentLength() { + return 0; + } + + @Override + public String getContentType() { + return null; + } + + @Override + public String getProperty(String propertyName) { + return null; + } + +} diff --git a/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java index 0db482309..0255df9d5 100644 --- a/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java +++ b/main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WebDavServerTest.java @@ -45,9 +45,13 @@ import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.client.methods.CopyMethod; import org.apache.jackrabbit.webdav.client.methods.DavMethodBase; +import org.apache.jackrabbit.webdav.client.methods.LockMethod; import org.apache.jackrabbit.webdav.client.methods.MkColMethod; import org.apache.jackrabbit.webdav.client.methods.MoveMethod; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.ReadableFile; import org.cryptomator.filesystem.WritableFile; @@ -173,6 +177,40 @@ public class WebDavServerTest { Assert.assertTrue(CollectionUtils.containsAll(hrefs, Arrays.asList(servletRoot + "/folder1/", servletRoot + "/folder2/", servletRoot + "/file1"))); } + /* LOCK */ + + @Test + public void testLockExisting() throws IOException, DavException { + final HttpClient client = new HttpClient(); + + // create file: + try (WritableFile writable = fs.file("foo.txt").openWritable()) { + writable.write(ByteBuffer.allocate(0)); + } + + // lock existing file: + LockInfo lockInfo = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "le me", 3600, false); + final DavMethodBase lockMethod = new LockMethod(servletRoot + "/foo.txt", lockInfo); + final int lockResponse = client.executeMethod(lockMethod); + Assert.assertEquals(200, lockResponse); + + lockMethod.releaseConnection(); + } + + @Test + public void testLockNonExisting() throws IOException, DavException { + final HttpClient client = new HttpClient(); + + // lock nonexisting file: + LockInfo lockInfo = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "le me", 3600, false); + final DavMethodBase lockMethod = new LockMethod(servletRoot + "/foo.txt", lockInfo); + final int lockResponse = client.executeMethod(lockMethod); + Assert.assertEquals(201, lockResponse); + Assert.assertTrue(fs.file("foo.txt").exists()); + + lockMethod.releaseConnection(); + } + /* MOVE */ @Test