From 7cb435e517c29099ff0df38702cf521ef4fdf88f Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 23 Feb 2016 18:13:19 +0100 Subject: [PATCH] support for RFC 4331: DAV:quota-available-bytes and DAV:quota-used-bytes references #97; quota calculation in NIO filesystem still missing --- .../cryptomator/filesystem/FileSystem.java | 4 +++ .../delegating/DelegatingFileSystem.java | 22 +++++++++++++ .../delegating/DelegatingFileSystemTest.java | 32 +++++++++++++++++++ .../delegating/TestDelegatingFileSystem.java | 8 +++-- .../blockaligned/BlockAlignedFileSystem.java | 9 ++++-- .../filesystem/crypto/CryptoFileSystem.java | 10 ++++++ .../filesystem/inmem/InMemoryFileSystem.java | 12 +++++++ .../blacklisting/BlacklistingFileSystem.java | 9 ++++-- .../shortening/ShorteningFileSystem.java | 9 ++++-- .../filesystem/nio/NioFileSystem.java | 12 +++++++ .../filesystem/stats/StatsFileSystem.java | 9 ++++-- .../jackrabbit/FileSystemLocator.java | 9 ++++-- .../webdav/jackrabbitservlet/DavFolder.java | 23 ++++++++++++- .../webdav/jackrabbitservlet/DavNode.java | 5 +-- 14 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java create mode 100644 main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileSystemTest.java diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java index 563b1f068..138fcb95e 100644 --- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java +++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java @@ -23,4 +23,8 @@ public interface FileSystem extends Folder { return Optional.empty(); } + Optional quotaUsedBytes(); + + Optional quotaAvailableBytes(); + } diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java new file mode 100644 index 000000000..ee3702cef --- /dev/null +++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java @@ -0,0 +1,22 @@ +package org.cryptomator.filesystem.delegating; + +import java.util.Optional; + +import org.cryptomator.filesystem.FileSystem; +import org.cryptomator.filesystem.Folder; + +public interface DelegatingFileSystem extends FileSystem { + + Folder getDelegate(); + + @Override + default Optional quotaUsedBytes() { + return getDelegate().fileSystem().quotaUsedBytes(); + } + + @Override + default Optional quotaAvailableBytes() { + return getDelegate().fileSystem().quotaAvailableBytes(); + } + +} diff --git a/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileSystemTest.java b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileSystemTest.java new file mode 100644 index 000000000..8c4ff82c6 --- /dev/null +++ b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileSystemTest.java @@ -0,0 +1,32 @@ +package org.cryptomator.filesystem.delegating; + +import java.util.Optional; + +import org.cryptomator.filesystem.FileSystem; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class DelegatingFileSystemTest { + + @Test + public void testQuotaAvailableBytes() { + FileSystem mockFs = Mockito.mock(FileSystem.class); + Mockito.when(mockFs.fileSystem()).thenReturn(mockFs); + Mockito.when(mockFs.quotaAvailableBytes()).thenReturn(Optional.of(42l)); + + DelegatingFileSystem delegatingFs = TestDelegatingFileSystem.withRoot(mockFs); + Assert.assertEquals(mockFs.quotaAvailableBytes(), delegatingFs.quotaAvailableBytes()); + } + + @Test + public void testQuotaUsedBytes() { + FileSystem mockFs = Mockito.mock(FileSystem.class); + Mockito.when(mockFs.fileSystem()).thenReturn(mockFs); + Mockito.when(mockFs.quotaUsedBytes()).thenReturn(Optional.of(23l)); + + DelegatingFileSystem delegatingFs = TestDelegatingFileSystem.withRoot(mockFs); + Assert.assertEquals(mockFs.quotaUsedBytes(), delegatingFs.quotaUsedBytes()); + } + +} diff --git a/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/TestDelegatingFileSystem.java b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/TestDelegatingFileSystem.java index e3d8b379e..2a2ef3f6e 100644 --- a/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/TestDelegatingFileSystem.java +++ b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/TestDelegatingFileSystem.java @@ -1,9 +1,8 @@ package org.cryptomator.filesystem.delegating; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; -class TestDelegatingFileSystem extends TestDelegatingFolder implements FileSystem { +class TestDelegatingFileSystem extends TestDelegatingFolder implements DelegatingFileSystem { private TestDelegatingFileSystem(Folder delegate) { super(null, delegate); @@ -13,4 +12,9 @@ class TestDelegatingFileSystem extends TestDelegatingFolder implements FileSyste return new TestDelegatingFileSystem(delegate); } + @Override + public Folder getDelegate() { + return delegate; + } + } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java index e703566c9..391287ab4 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java @@ -8,13 +8,18 @@ *******************************************************************************/ package org.cryptomator.filesystem.blockaligned; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; -class BlockAlignedFileSystem extends BlockAlignedFolder implements FileSystem { +class BlockAlignedFileSystem extends BlockAlignedFolder implements DelegatingFileSystem { public BlockAlignedFileSystem(Folder delegate, int blockSize) { super(null, delegate, blockSize); } + @Override + public Folder getDelegate() { + return delegate; + } + } diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java index 47eab1834..25007a197 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java @@ -55,6 +55,16 @@ class CryptoFileSystem extends CryptoFolder implements FileSystem { return physicalRoot.folder(DATA_ROOT_DIR); } + @Override + public Optional quotaUsedBytes() { + return physicalRoot.fileSystem().quotaUsedBytes(); + } + + @Override + public Optional quotaAvailableBytes() { + return physicalRoot.fileSystem().quotaAvailableBytes(); + } + @Override public Optional parent() { return Optional.empty(); diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFileSystem.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFileSystem.java index 42ff5dc0b..492d834c2 100644 --- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFileSystem.java +++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFileSystem.java @@ -39,4 +39,16 @@ public class InMemoryFileSystem extends InMemoryFolder implements FileSystem { return "/"; } + @Override + public Optional quotaUsedBytes() { + long used = Runtime.getRuntime().totalMemory(); + return Optional.of(used); + } + + @Override + public Optional quotaAvailableBytes() { + long available = Runtime.getRuntime().freeMemory(); + return Optional.of(available); + } + } diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java index 283965d87..b0b9460f3 100644 --- a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java @@ -10,14 +10,19 @@ package org.cryptomator.filesystem.blacklisting; import java.util.function.Predicate; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; import org.cryptomator.filesystem.Node; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; -class BlacklistingFileSystem extends BlacklistingFolder implements FileSystem { +class BlacklistingFileSystem extends BlacklistingFolder implements DelegatingFileSystem { public BlacklistingFileSystem(Folder root, Predicate hiddenNodes) { super(null, root, hiddenNodes); } + @Override + public Folder getDelegate() { + return delegate; + } + } diff --git a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java index 7d6407b0a..047fdb028 100644 --- a/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java +++ b/main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java @@ -8,14 +8,19 @@ *******************************************************************************/ package org.cryptomator.filesystem.shortening; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; -public class ShorteningFileSystem extends ShorteningFolder implements FileSystem { +public class ShorteningFileSystem extends ShorteningFolder implements DelegatingFileSystem { public ShorteningFileSystem(Folder root, Folder metadataRoot, int threshold) { super(null, root, "", new FilenameShortener(metadataRoot, threshold)); create(); } + @Override + public Folder getDelegate() { + return delegate; + } + } diff --git a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFileSystem.java b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFileSystem.java index 827c75ec5..ff84bd8e3 100644 --- a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFileSystem.java +++ b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFileSystem.java @@ -16,4 +16,16 @@ public class NioFileSystem extends NioFolder implements FileSystem { create(); } + @Override + public Optional quotaUsedBytes() { + // TODO du -sh + return Optional.empty(); + } + + @Override + public Optional quotaAvailableBytes() { + // TODO df -lh + return Optional.empty(); + } + } diff --git a/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java b/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java index 991a3da05..9a215a370 100644 --- a/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java +++ b/main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java @@ -10,10 +10,10 @@ package org.cryptomator.filesystem.stats; import java.util.concurrent.atomic.LongAdder; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; -public class StatsFileSystem extends StatsFolder implements FileSystem { +public class StatsFileSystem extends StatsFolder implements DelegatingFileSystem { private final LongAdder read; private final LongAdder written; @@ -36,4 +36,9 @@ public class StatsFileSystem extends StatsFolder implements FileSystem { return written.sumThenReset(); } + @Override + public Folder getDelegate() { + return delegate; + } + } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java b/main/frontend-webdav/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java index 4f390da15..a407889fc 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java @@ -9,10 +9,10 @@ package org.cryptomator.filesystem.jackrabbit; import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.cryptomator.filesystem.FileSystem; import org.cryptomator.filesystem.Folder; +import org.cryptomator.filesystem.delegating.DelegatingFileSystem; -class FileSystemLocator extends FolderLocator implements FileSystem { +class FileSystemLocator extends FolderLocator implements DelegatingFileSystem { public FileSystemLocator(DavLocatorFactory factory, String prefix, Folder delegate) { super(factory, prefix, null, delegate); @@ -28,4 +28,9 @@ class FileSystemLocator extends FolderLocator implements FileSystem { return "/"; } + @Override + public Folder getDelegate() { + return delegate; + } + } 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 ed0b9b9b3..861e8ffd9 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 @@ -17,6 +17,7 @@ import java.time.Instant; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.lang3.ArrayUtils; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; import org.apache.jackrabbit.webdav.DavResourceIterator; @@ -26,6 +27,7 @@ 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.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import org.apache.jackrabbit.webdav.property.ResourceType; @@ -39,6 +41,9 @@ import com.google.common.io.ByteStreams; class DavFolder extends DavNode { + private static final DavPropertyName PROPERTY_QUOTA_AVAILABLE = DavPropertyName.create("quota-available-bytes"); + private static final DavPropertyName PROPERTY_QUOTA_USED = DavPropertyName.create("quota-used-bytes"); + public DavFolder(FilesystemResourceFactory factory, LockManager lockManager, DavSession session, FolderLocator folder) { super(factory, lockManager, session, folder); properties.add(new ResourceType(ResourceType.COLLECTION)); @@ -173,7 +178,7 @@ class DavFolder extends DavNode { @Override protected void setModificationTime(Instant instant) { - // TODO Auto-generated method stub + node.setLastModified(instant); } @Override @@ -181,4 +186,20 @@ class DavFolder extends DavNode { node.setCreationTime(instant); } + @Override + public DavPropertyName[] getPropertyNames() { + return ArrayUtils.addAll(super.getPropertyNames(), PROPERTY_QUOTA_AVAILABLE, PROPERTY_QUOTA_USED); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + if (PROPERTY_QUOTA_AVAILABLE.equals(name)) { + return node.fileSystem().quotaAvailableBytes().map(numBytes -> new DefaultDavProperty(name, numBytes)).orElse(null); + } else if (PROPERTY_QUOTA_USED.equals(name)) { + return node.fileSystem().quotaUsedBytes().map(numBytes -> new DefaultDavProperty(name, numBytes)).orElse(null); + } else { + return super.getProperty(name); + } + } + } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavNode.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavNode.java index 354edb6f8..5fb6ef51c 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavNode.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavNode.java @@ -20,6 +20,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; +import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; import org.apache.jackrabbit.webdav.DavSession; @@ -40,8 +41,8 @@ import org.cryptomator.filesystem.jackrabbit.FileSystemResourceLocator; 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"}; - private static final String[] DAV_MODIFIEDDATE_PROPNAMES = {DavPropertyName.GETLASTMODIFIED.getName(), "Win32LastModifiedTime"}; + private static final String[] DAV_CREATIONDATE_PROPNAMES = {DavConstants.PROPERTY_CREATIONDATE, "Win32CreationTime"}; + private static final String[] DAV_MODIFIEDDATE_PROPNAMES = {DavConstants.PROPERTY_GETLASTMODIFIED, "Win32LastModifiedTime"}; protected final FilesystemResourceFactory factory; protected final LockManager lockManager;