mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 02:01:27 +00:00
support for RFC 4331: DAV:quota-available-bytes and DAV:quota-used-bytes
references #97; quota calculation in NIO filesystem still missing
This commit is contained in:
@@ -23,4 +23,8 @@ public interface FileSystem extends Folder {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<Long> quotaUsedBytes();
|
||||
|
||||
Optional<Long> quotaAvailableBytes();
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user