Browse Source

support for RFC 4331: DAV:quota-available-bytes and DAV:quota-used-bytes
references #97; quota calculation in NIO filesystem still missing

Sebastian Stenzel 9 years ago
parent
commit
7cb435e517
14 changed files with 158 additions and 15 deletions
  1. 4 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java
  2. 22 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java
  3. 32 0
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileSystemTest.java
  4. 6 2
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/TestDelegatingFileSystem.java
  5. 7 2
      main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedFileSystem.java
  6. 10 0
      main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java
  7. 12 0
      main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFileSystem.java
  8. 7 2
      main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/blacklisting/BlacklistingFileSystem.java
  9. 7 2
      main/filesystem-nameshortening/src/main/java/org/cryptomator/filesystem/shortening/ShorteningFileSystem.java
  10. 12 0
      main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFileSystem.java
  11. 7 2
      main/filesystem-stats/src/main/java/org/cryptomator/filesystem/stats/StatsFileSystem.java
  12. 7 2
      main/frontend-webdav/src/main/java/org/cryptomator/filesystem/jackrabbit/FileSystemLocator.java
  13. 22 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java
  14. 3 2
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavNode.java

+ 4 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystem.java

@@ -23,4 +23,8 @@ public interface FileSystem extends Folder {
 		return Optional.empty();
 	}
 
+	Optional<Long> quotaUsedBytes();
+
+	Optional<Long> quotaAvailableBytes();
+
 }

+ 22 - 0
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<Long> quotaUsedBytes() {
+		return getDelegate().fileSystem().quotaUsedBytes();
+	}
+
+	@Override
+	default Optional<Long> quotaAvailableBytes() {
+		return getDelegate().fileSystem().quotaAvailableBytes();
+	}
+
+}

+ 32 - 0
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());
+	}
+
+}

+ 6 - 2
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;
+	}
+
 }

+ 7 - 2
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;
+	}
+
 }

+ 10 - 0
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<Long> quotaUsedBytes() {
+		return physicalRoot.fileSystem().quotaUsedBytes();
+	}
+
+	@Override
+	public Optional<Long> quotaAvailableBytes() {
+		return physicalRoot.fileSystem().quotaAvailableBytes();
+	}
+
 	@Override
 	public Optional<CryptoFolder> parent() {
 		return Optional.empty();

+ 12 - 0
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<Long> quotaUsedBytes() {
+		long used = Runtime.getRuntime().totalMemory();
+		return Optional.of(used);
+	}
+
+	@Override
+	public Optional<Long> quotaAvailableBytes() {
+		long available = Runtime.getRuntime().freeMemory();
+		return Optional.of(available);
+	}
+
 }

+ 7 - 2
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<Node> hiddenNodes) {
 		super(null, root, hiddenNodes);
 	}
 
+	@Override
+	public Folder getDelegate() {
+		return delegate;
+	}
+
 }

+ 7 - 2
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;
+	}
+
 }

+ 12 - 0
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<Long> quotaUsedBytes() {
+		// TODO du -sh
+		return Optional.empty();
+	}
+
+	@Override
+	public Optional<Long> quotaAvailableBytes() {
+		// TODO df -lh
+		return Optional.empty();
+	}
+
 }

+ 7 - 2
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;
+	}
+
 }

+ 7 - 2
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;
+	}
+
 }

+ 22 - 1
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<FolderLocator> {
 
+	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<FolderLocator> {
 
 	@Override
 	protected void setModificationTime(Instant instant) {
-		// TODO Auto-generated method stub
+		node.setLastModified(instant);
 	}
 
 	@Override
@@ -181,4 +186,20 @@ class DavFolder extends DavNode<FolderLocator> {
 		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<Long>(name, numBytes)).orElse(null);
+		} else if (PROPERTY_QUOTA_USED.equals(name)) {
+			return node.fileSystem().quotaUsedBytes().map(numBytes -> new DefaultDavProperty<Long>(name, numBytes)).orElse(null);
+		} else {
+			return super.getProperty(name);
+		}
+	}
+
 }

+ 3 - 2
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<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"};
-	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;