- read XOR write during BlockAlignedWritableFile (not r+w at the same time)

- simplified DelegatingFileSystem
This commit is contained in:
Sebastian Stenzel
2016-01-27 20:14:51 +01:00
parent a972480e72
commit b2a37c4b95
21 changed files with 156 additions and 439 deletions

View File

@@ -12,8 +12,10 @@ import java.io.UncheckedIOException;
import java.util.Optional;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
public abstract class DelegatingFile<R extends DelegatingReadableFile, W extends DelegatingWritableFile, D extends DelegatingFolder<R, W, D, ?>> extends DelegatingNode<File>implements File {
public abstract class DelegatingFile<D extends DelegatingFolder<D, ?>> extends DelegatingNode<File>implements File {
private final D parent;
@@ -28,15 +30,19 @@ public abstract class DelegatingFile<R extends DelegatingReadableFile, W extends
}
@Override
public abstract R openReadable() throws UncheckedIOException;
public ReadableFile openReadable() throws UncheckedIOException {
return delegate.openReadable();
}
@Override
public abstract W openWritable() throws UncheckedIOException;
public WritableFile openWritable() throws UncheckedIOException {
return delegate.openWritable();
}
@Override
public void copyTo(File destination) {
if (getClass().equals(destination.getClass())) {
final File delegateDest = ((DelegatingFile<?, ?, ?>) destination).delegate;
final File delegateDest = ((DelegatingFile<?>) destination).delegate;
delegate.copyTo(delegateDest);
} else {
delegate.copyTo(destination);
@@ -46,7 +52,7 @@ public abstract class DelegatingFile<R extends DelegatingReadableFile, W extends
@Override
public void moveTo(File destination) {
if (getClass().equals(destination.getClass())) {
final File delegateDest = ((DelegatingFile<?, ?, ?>) destination).delegate;
final File delegateDest = ((DelegatingFile<?>) destination).delegate;
delegate.moveTo(delegateDest);
} else {
throw new IllegalArgumentException("Can only move DelegatingFile to other DelegatingFile.");
@@ -56,7 +62,7 @@ public abstract class DelegatingFile<R extends DelegatingReadableFile, W extends
@Override
public int compareTo(File o) {
if (getClass().equals(o.getClass())) {
final File delegateOther = ((DelegatingFile<?, ?, ?>) o).delegate;
final File delegateOther = ((DelegatingFile<?>) o).delegate;
return delegate.compareTo(delegateOther);
} else {
return delegate.compareTo(o);

View File

@@ -18,8 +18,7 @@ import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
public abstract class DelegatingFolder<R extends DelegatingReadableFile, W extends DelegatingWritableFile, D extends DelegatingFolder<R, W, D, F>, F extends DelegatingFile<R, W, D>> extends DelegatingNode<Folder>
implements Folder {
public abstract class DelegatingFolder<D extends DelegatingFolder<D, F>, F extends DelegatingFile<D>> extends DelegatingNode<Folder>implements Folder {
private final D parent;
private final WeakValuedCache<Folder, D> folders = WeakValuedCache.usingLoader(this::newFolder);
@@ -81,7 +80,7 @@ public abstract class DelegatingFolder<R extends DelegatingReadableFile, W exten
@Override
public void copyTo(Folder destination) throws UncheckedIOException {
if (destination instanceof DelegatingFolder) {
final Folder delegateDest = ((DelegatingFolder<?, ?, ?, ?>) destination).delegate;
final Folder delegateDest = ((DelegatingFolder<?, ?>) destination).delegate;
delegate.copyTo(delegateDest);
} else {
delegate.copyTo(destination);
@@ -91,7 +90,7 @@ public abstract class DelegatingFolder<R extends DelegatingReadableFile, W exten
@Override
public void moveTo(Folder destination) {
if (getClass().equals(destination.getClass())) {
final Folder delegateDest = ((DelegatingFolder<?, ?, ?, ?>) destination).delegate;
final Folder delegateDest = ((DelegatingFolder<?, ?>) destination).delegate;
delegate.moveTo(delegateDest);
} else {
throw new IllegalArgumentException("Can only move DelegatingFolder to other DelegatingFolder.");

View File

@@ -1,49 +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.filesystem.delegating;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import org.cryptomator.filesystem.ReadableFile;
public class DelegatingReadableFile implements ReadableFile {
private final ReadableFile delegate;
public DelegatingReadableFile(ReadableFile delegate) {
this.delegate = delegate;
}
@Override
public boolean isOpen() {
return delegate.isOpen();
}
@Override
public int read(ByteBuffer target) throws UncheckedIOException {
return delegate.read(target);
}
@Override
public long size() throws UncheckedIOException {
return delegate.size();
}
@Override
public void position(long position) throws UncheckedIOException {
delegate.position(position);
}
@Override
public void close() throws UncheckedIOException {
delegate.close();
}
}

View File

@@ -1,75 +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.filesystem.delegating;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.time.Instant;
import org.cryptomator.filesystem.WritableFile;
public class DelegatingWritableFile implements WritableFile {
final WritableFile delegate;
public DelegatingWritableFile(WritableFile delegate) {
this.delegate = delegate;
}
@Override
public boolean isOpen() {
return delegate.isOpen();
}
@Override
public void moveTo(WritableFile destination) throws UncheckedIOException {
if (getClass().equals(destination.getClass())) {
final WritableFile delegateDest = ((DelegatingWritableFile) destination).delegate;
delegate.moveTo(delegateDest);
} else {
throw new IllegalArgumentException("Can only move DelegatingWritableFile to a DelegatingWritableFile.");
}
}
@Override
public void setLastModified(Instant instant) throws UncheckedIOException {
delegate.setLastModified(instant);
}
@Override
public void delete() throws UncheckedIOException {
delegate.delete();
}
@Override
public void truncate() throws UncheckedIOException {
delegate.truncate();
}
@Override
public int write(ByteBuffer source) throws UncheckedIOException {
return delegate.write(source);
}
@Override
public void position(long position) throws UncheckedIOException {
delegate.position(position);
}
@Override
public void close() throws UncheckedIOException {
delegate.close();
}
@Override
public void setCreationTime(Instant instant) throws UncheckedIOException {
delegate.setCreationTime(instant);
}
}

View File

@@ -23,7 +23,7 @@ public class DelegatingFileTest {
@Test
public void testName() {
File mockFile = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(null, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(null, mockFile);
Mockito.when(mockFile.name()).thenReturn("Test");
Assert.assertEquals(mockFile.name(), delegatingFile.name());
@@ -35,14 +35,14 @@ public class DelegatingFileTest {
File mockFile = Mockito.mock(File.class);
TestDelegatingFileSystem delegatingParent = TestDelegatingFileSystem.withRoot(mockFolder);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(delegatingParent, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(delegatingParent, mockFile);
Assert.assertEquals(delegatingParent, delegatingFile.parent().get());
}
@Test
public void testExists() {
File mockFile = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(null, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(null, mockFile);
Mockito.when(mockFile.exists()).thenReturn(true);
Assert.assertTrue(delegatingFile.exists());
@@ -57,7 +57,7 @@ public class DelegatingFileTest {
Instant now = Instant.now();
Mockito.when(mockFile.lastModified()).thenReturn(now);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(null, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(null, mockFile);
Assert.assertEquals(now, delegatingFile.lastModified());
}
@@ -67,7 +67,7 @@ public class DelegatingFileTest {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
Mockito.when(mockFile.openReadable()).thenReturn(mockReadableFile);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(null, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(null, mockFile);
Assert.assertNotNull(delegatingFile.openReadable());
}
@@ -77,7 +77,7 @@ public class DelegatingFileTest {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
Mockito.when(mockFile.openWritable()).thenReturn(mockWritableFile);
DelegatingFile<?, ?, ?> delegatingFile = new TestDelegatingFile(null, mockFile);
DelegatingFile<?> delegatingFile = new TestDelegatingFile(null, mockFile);
Assert.assertNotNull(delegatingFile.openWritable());
}
@@ -85,8 +85,8 @@ public class DelegatingFileTest {
public void testMoveTo() {
File mockFile1 = Mockito.mock(File.class);
File mockFile2 = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?, ?, ?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
DelegatingFile<?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
delegatingFile1.moveTo(delegatingFile2);
Mockito.verify(mockFile1).moveTo(mockFile2);
@@ -96,7 +96,7 @@ public class DelegatingFileTest {
public void testMoveToDestinationFromDifferentLayer() {
File mockFile1 = Mockito.mock(File.class);
File mockFile2 = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
delegatingFile1.moveTo(mockFile2);
}
@@ -105,8 +105,8 @@ public class DelegatingFileTest {
public void testCopyTo() {
File mockFile1 = Mockito.mock(File.class);
File mockFile2 = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?, ?, ?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
DelegatingFile<?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
delegatingFile1.copyTo(delegatingFile2);
Mockito.verify(mockFile1).copyTo(mockFile2);
@@ -116,7 +116,7 @@ public class DelegatingFileTest {
public void testCopyToDestinationFromDifferentLayer() {
File mockFile1 = Mockito.mock(File.class);
File mockFile2 = Mockito.mock(File.class);
DelegatingFile<?, ?, ?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
delegatingFile1.copyTo(mockFile2);
Mockito.verify(mockFile1).copyTo(mockFile2);
@@ -128,8 +128,8 @@ public class DelegatingFileTest {
File mockFile2 = Mockito.mock(File.class);
Mockito.when(mockFile1.compareTo(mockFile2)).thenReturn(-1);
DelegatingFile<?, ?, ?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?, ?, ?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
DelegatingFile<?> delegatingFile1 = new TestDelegatingFile(null, mockFile1);
DelegatingFile<?> delegatingFile2 = new TestDelegatingFile(null, mockFile2);
Assert.assertEquals(-1, delegatingFile1.compareTo(delegatingFile2));
}

View File

@@ -27,7 +27,7 @@ public class DelegatingFolderTest {
@Test
public void testName() {
Folder mockFolder = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
Mockito.when(mockFolder.name()).thenReturn("Test");
Assert.assertEquals(mockFolder.name(), delegatingFolder.name());
@@ -39,14 +39,14 @@ public class DelegatingFolderTest {
Folder mockFolder2 = Mockito.mock(Folder.class);
TestDelegatingFileSystem delegatingParent = TestDelegatingFileSystem.withRoot(mockFolder1);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(delegatingParent, mockFolder2);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(delegatingParent, mockFolder2);
Assert.assertEquals(delegatingParent, delegatingFolder.parent().get());
}
@Test
public void testExists() {
Folder mockFolder = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
Mockito.when(mockFolder.exists()).thenReturn(true);
Assert.assertTrue(delegatingFolder.exists());
@@ -61,7 +61,7 @@ public class DelegatingFolderTest {
Instant now = Instant.now();
Mockito.when(mockFolder.lastModified()).thenReturn(now);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
Assert.assertEquals(now, delegatingFolder.lastModified());
}
@@ -106,8 +106,8 @@ public class DelegatingFolderTest {
public void testMoveTo() {
Folder mockFolder1 = Mockito.mock(Folder.class);
Folder mockFolder2 = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?, ?, ?> delegatingFolder2 = new TestDelegatingFolder(null, mockFolder2);
DelegatingFolder<?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?> delegatingFolder2 = new TestDelegatingFolder(null, mockFolder2);
delegatingFolder1.moveTo(delegatingFolder2);
Mockito.verify(mockFolder1).moveTo(mockFolder2);
@@ -117,7 +117,7 @@ public class DelegatingFolderTest {
public void testMoveToDestinationFromDifferentLayer() {
Folder mockFolder1 = Mockito.mock(Folder.class);
Folder mockFolder2 = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
delegatingFolder1.moveTo(mockFolder2);
}
@@ -126,8 +126,8 @@ public class DelegatingFolderTest {
public void testCopyTo() {
Folder mockFolder1 = Mockito.mock(Folder.class);
Folder mockFolder2 = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?, ?, ?> delegatingFolder2 = new TestDelegatingFolder(null, mockFolder2);
DelegatingFolder<?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?> delegatingFolder2 = new TestDelegatingFolder(null, mockFolder2);
delegatingFolder1.copyTo(delegatingFolder2);
Mockito.verify(mockFolder1).copyTo(mockFolder2);
@@ -137,7 +137,7 @@ public class DelegatingFolderTest {
public void testCopyToDestinationFromDifferentLayer() {
Folder mockFolder1 = Mockito.mock(Folder.class);
Folder mockFolder2 = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
DelegatingFolder<?, ?> delegatingFolder1 = new TestDelegatingFolder(null, mockFolder1);
delegatingFolder1.copyTo(mockFolder2);
Mockito.verify(mockFolder1).copyTo(mockFolder2);
@@ -146,7 +146,7 @@ public class DelegatingFolderTest {
@Test
public void testCreate() {
Folder mockFolder = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
delegatingFolder.create();
Mockito.verify(mockFolder).create();
@@ -155,7 +155,7 @@ public class DelegatingFolderTest {
@Test
public void testDelete() {
Folder mockFolder = Mockito.mock(Folder.class);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
delegatingFolder.delete();
Mockito.verify(mockFolder).delete();
@@ -169,7 +169,7 @@ public class DelegatingFolderTest {
Mockito.when(mockFolder.folder("mockSubFolder")).thenReturn(mockSubFolder);
Mockito.when(mockFolder.file("mockSubFile")).thenReturn(mockSubFile);
DelegatingFolder<?, ?, ?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
DelegatingFolder<?, ?> delegatingFolder = new TestDelegatingFolder(null, mockFolder);
Assert.assertSame(delegatingFolder.folder("mockSubFolder"), delegatingFolder.folder("mockSubFolder"));
Assert.assertSame(delegatingFolder.file("mockSubFile"), delegatingFolder.file("mockSubFile"));
}

View File

@@ -1,64 +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.filesystem.delegating;
import java.nio.ByteBuffer;
import org.cryptomator.filesystem.ReadableFile;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class DelegatingReadableFileTest {
@Test
public void testIsOpen() {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
@SuppressWarnings("resource")
DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
Mockito.when(mockReadableFile.isOpen()).thenReturn(true);
Assert.assertTrue(delegatingReadableFile.isOpen());
Mockito.when(mockReadableFile.isOpen()).thenReturn(false);
Assert.assertFalse(delegatingReadableFile.isOpen());
}
@Test
public void testRead() {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
@SuppressWarnings("resource")
DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
ByteBuffer buf = ByteBuffer.allocate(4);
Mockito.when(mockReadableFile.read(buf)).thenReturn(4);
Assert.assertEquals(4, delegatingReadableFile.read(buf));
Mockito.verify(mockReadableFile).read(buf);
}
@Test
public void testPosition() {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
@SuppressWarnings("resource")
DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
delegatingReadableFile.position(42);
Mockito.verify(mockReadableFile).position(42);
}
@Test
public void testClose() {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
delegatingReadableFile.close();
Mockito.verify(mockReadableFile).close();
}
}

View File

@@ -1,119 +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.filesystem.delegating;
import java.nio.ByteBuffer;
import java.time.Instant;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class DelegatingWritableFileTest {
@Test
public void testIsOpen() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
Mockito.when(mockWritableFile.isOpen()).thenReturn(true);
Assert.assertTrue(delegatingWritableFile.isOpen());
Mockito.when(mockWritableFile.isOpen()).thenReturn(false);
Assert.assertFalse(delegatingWritableFile.isOpen());
}
@Test
public void testMoveTo() {
WritableFile mockWritableFile1 = Mockito.mock(WritableFile.class);
WritableFile mockWritableFile2 = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile1 = new DelegatingWritableFile(mockWritableFile1);
DelegatingWritableFile delegatingWritableFile2 = new DelegatingWritableFile(mockWritableFile2);
delegatingWritableFile1.moveTo(delegatingWritableFile2);
Mockito.verify(mockWritableFile1).moveTo(mockWritableFile2);
}
@Test(expected = IllegalArgumentException.class)
public void testMoveToDestinationFromDifferentLayer() {
WritableFile mockWritableFile1 = Mockito.mock(WritableFile.class);
WritableFile mockWritableFile2 = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile1 = new DelegatingWritableFile(mockWritableFile1);
delegatingWritableFile1.moveTo(mockWritableFile2);
}
@Test
public void testSetLastModified() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
Instant now = Instant.now();
delegatingWritableFile.setLastModified(now);
Mockito.verify(mockWritableFile).setLastModified(now);
}
@Test
public void testDelete() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
delegatingWritableFile.delete();
Mockito.verify(mockWritableFile).delete();
}
@Test
public void testTruncate() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
delegatingWritableFile.truncate();
Mockito.verify(mockWritableFile).truncate();
}
@Test
public void testWrite() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
ByteBuffer buf = ByteBuffer.allocate(4);
Mockito.when(mockWritableFile.write(buf)).thenReturn(4);
Assert.assertEquals(4, delegatingWritableFile.write(buf));
Mockito.verify(mockWritableFile).write(buf);
}
@Test
public void testPosition() {
WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
@SuppressWarnings("resource")
DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
delegatingWritableFile.position(42);
Mockito.verify(mockWritableFile).position(42);
}
@Test
public void testClose() {
ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
delegatingReadableFile.close();
Mockito.verify(mockReadableFile).close();
}
}

View File

@@ -1,23 +1,11 @@
package org.cryptomator.filesystem.delegating;
import java.io.UncheckedIOException;
import org.cryptomator.filesystem.File;
class TestDelegatingFile extends DelegatingFile<DelegatingReadableFile, DelegatingWritableFile, TestDelegatingFolder> {
class TestDelegatingFile extends DelegatingFile<TestDelegatingFolder> {
public TestDelegatingFile(TestDelegatingFolder parent, File delegate) {
super(parent, delegate);
}
@Override
public DelegatingReadableFile openReadable() throws UncheckedIOException {
return new DelegatingReadableFile(delegate.openReadable());
}
@Override
public DelegatingWritableFile openWritable() throws UncheckedIOException {
return new DelegatingWritableFile(delegate.openWritable());
}
}

View File

@@ -3,7 +3,7 @@ package org.cryptomator.filesystem.delegating;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
class TestDelegatingFolder extends DelegatingFolder<DelegatingReadableFile, DelegatingWritableFile, TestDelegatingFolder, TestDelegatingFile> {
class TestDelegatingFolder extends DelegatingFolder<TestDelegatingFolder, TestDelegatingFile> {
public TestDelegatingFolder(TestDelegatingFolder parent, Folder delegate) {
super(parent, delegate);

View File

@@ -13,7 +13,7 @@ import java.io.UncheckedIOException;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.delegating.DelegatingFile;
class BlockAlignedFile extends DelegatingFile<BlockAlignedReadableFile, BlockAlignedWritableFile, BlockAlignedFolder> {
class BlockAlignedFile extends DelegatingFile<BlockAlignedFolder> {
private final int blockSize;
@@ -29,7 +29,7 @@ class BlockAlignedFile extends DelegatingFile<BlockAlignedReadableFile, BlockAli
@Override
public BlockAlignedWritableFile openWritable() throws UncheckedIOException {
return new BlockAlignedWritableFile(delegate.openWritable(), delegate.openReadable(), blockSize);
return new BlockAlignedWritableFile(delegate::openWritable, delegate::openReadable, blockSize);
}
}

View File

@@ -12,7 +12,7 @@ import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.delegating.DelegatingFolder;
class BlockAlignedFolder extends DelegatingFolder<BlockAlignedReadableFile, BlockAlignedWritableFile, BlockAlignedFolder, BlockAlignedFile> {
class BlockAlignedFolder extends DelegatingFolder<BlockAlignedFolder, BlockAlignedFile> {
private final int blockSize;

View File

@@ -12,11 +12,11 @@ import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.delegating.DelegatingReadableFile;
import org.cryptomator.io.ByteBuffers;
class BlockAlignedReadableFile extends DelegatingReadableFile {
class BlockAlignedReadableFile implements ReadableFile {
private final ReadableFile delegate;
private final int blockSize;
private final ByteBuffer currentBlockBuffer;
private boolean eofReached = false;
@@ -27,10 +27,10 @@ class BlockAlignedReadableFile extends DelegatingReadableFile {
}
public BlockAlignedReadableFile(ReadableFile delegate, int blockSize) {
super(delegate);
if (blockSize < 1) {
throw new IllegalArgumentException("Invalid block size");
}
this.delegate = delegate;
this.blockSize = blockSize;
this.currentBlockBuffer = ByteBuffer.allocate(blockSize);
this.currentBlockBuffer.flip(); // so remaining() is 0 -> next read will read from physical source.
@@ -45,7 +45,7 @@ class BlockAlignedReadableFile extends DelegatingReadableFile {
int diff = (int) (logicalPosition - physicalPosition);
assert diff >= 0;
assert diff < blockSize;
super.position(physicalPosition);
delegate.position(physicalPosition);
eofReached = false;
readCurrentBlock();
currentBlockBuffer.position(diff);
@@ -60,7 +60,7 @@ class BlockAlignedReadableFile extends DelegatingReadableFile {
public int read(ByteBuffer target) throws UncheckedIOException {
switch (mode) {
case PASSTHROUGH:
return super.read(target);
return delegate.read(target);
case BLOCK_ALIGNED:
return readBlockAligned(target);
default:
@@ -85,10 +85,25 @@ class BlockAlignedReadableFile extends DelegatingReadableFile {
private void readCurrentBlock() {
currentBlockBuffer.clear();
if (super.read(currentBlockBuffer) == -1) {
if (delegate.read(currentBlockBuffer) == -1) {
eofReached = true;
}
currentBlockBuffer.flip();
}
@Override
public boolean isOpen() {
return delegate.isOpen();
}
@Override
public long size() throws UncheckedIOException {
return delegate.size();
}
@Override
public void close() throws UncheckedIOException {
delegate.close();
}
}

View File

@@ -10,44 +10,51 @@ package org.cryptomator.filesystem.blockaligned;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.Optional;
import java.util.function.Supplier;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
import org.cryptomator.filesystem.delegating.DelegatingWritableFile;
import org.cryptomator.io.ByteBuffers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class BlockAlignedWritableFile extends DelegatingWritableFile {
class BlockAlignedWritableFile implements WritableFile {
private static final Logger LOG = LoggerFactory.getLogger(BlockAlignedWritableFile.class);
private final Supplier<WritableFile> openWritable;
private final Supplier<ReadableFile> openReadable;
private final int blockSize;
private final ReadableFile readableFile;
private final ByteBuffer currentBlockBuffer;
private Mode mode = Mode.PASSTHROUGH;
private Optional<WritableFile> delegate;
private long logicalPosition;
private enum Mode {
BLOCK_ALIGNED, PASSTHROUGH;
}
public BlockAlignedWritableFile(WritableFile delegate, ReadableFile readableFile, int blockSize) {
super(delegate);
this.readableFile = readableFile;
public BlockAlignedWritableFile(Supplier<WritableFile> openWritable, Supplier<ReadableFile> openReadable, int blockSize) {
this.openWritable = openWritable;
this.openReadable = openReadable;
this.blockSize = blockSize;
this.currentBlockBuffer = ByteBuffer.allocate(blockSize);
currentBlockBuffer.flip(); // make sure the buffer has no remaining bytes by default
delegate = Optional.of(openWritable.get());
}
@Override
public void position(long logicalPosition) throws UncheckedIOException {
switchToBlockAlignedMode();
long blockNumber = logicalPosition / blockSize;
long physicalPosition = blockNumber * blockSize;
readableFile.position(physicalPosition);
readableFile.read(currentBlockBuffer);
int advance = (int) (logicalPosition - physicalPosition);
currentBlockBuffer.position(advance);
super.position(physicalPosition);
this.logicalPosition = logicalPosition;
readCurrentBlock();
}
// visible for testing
void switchToBlockAlignedMode() {
LOG.debug("switching to blockaligend write...");
mode = Mode.BLOCK_ALIGNED;
}
@@ -55,7 +62,7 @@ class BlockAlignedWritableFile extends DelegatingWritableFile {
public int write(ByteBuffer source) throws UncheckedIOException {
switch (mode) {
case PASSTHROUGH:
return super.write(source);
return delegate.get().write(source);
case BLOCK_ALIGNED:
return writeBlockAligned(source);
default:
@@ -64,20 +71,21 @@ class BlockAlignedWritableFile extends DelegatingWritableFile {
}
private int writeBlockAligned(ByteBuffer source) {
int written = 0;
int writtenTotal = 0;
while (source.hasRemaining()) {
written += ByteBuffers.copy(source, currentBlockBuffer);
int written = ByteBuffers.copy(source, currentBlockBuffer);
logicalPosition += written;
writeCurrentBlockIfNeeded();
writtenTotal += written;
}
return written;
return writtenTotal;
}
@Override
public void close() throws UncheckedIOException {
currentBlockBuffer.flip();
writeCurrentBlock();
readableFile.close();
super.close();
delegate.ifPresent(WritableFile::close);
}
private void writeCurrentBlockIfNeeded() {
@@ -89,13 +97,60 @@ class BlockAlignedWritableFile extends DelegatingWritableFile {
private void writeCurrentBlock() {
currentBlockBuffer.rewind();
super.write(currentBlockBuffer);
delegate.get().write(currentBlockBuffer);
}
private void readCurrentBlock() {
// TODO lock that shit
// determine right position:
long blockNumber = logicalPosition / blockSize;
long physicalPosition = blockNumber * blockSize;
// switch from write to read access:
delegate.get().close();
currentBlockBuffer.clear();
readableFile.read(currentBlockBuffer);
currentBlockBuffer.rewind();
try (ReadableFile r = openReadable.get()) {
r.position(physicalPosition);
r.read(currentBlockBuffer);
}
int advance = (int) (logicalPosition - physicalPosition);
currentBlockBuffer.position(advance);
// continue write access:
WritableFile w = openWritable.get();
w.position(physicalPosition);
delegate = Optional.of(w);
}
@Override
public boolean isOpen() {
return delegate.get().isOpen();
}
@Override
public void moveTo(WritableFile destination) throws UncheckedIOException {
if (destination instanceof BlockAlignedWritableFile) {
final WritableFile delegateDest = ((BlockAlignedWritableFile) destination).delegate.get();
delegate.get().moveTo(delegateDest);
} else {
throw new IllegalArgumentException("Can only move DelegatingWritableFile to a DelegatingWritableFile.");
}
}
@Override
public void setLastModified(Instant instant) throws UncheckedIOException {
delegate.get().setLastModified(instant);
}
@Override
public void delete() throws UncheckedIOException {
delegate.get().delete();
}
@Override
public void truncate() throws UncheckedIOException {
delegate.get().truncate();
}
}

View File

@@ -29,7 +29,7 @@ public class BlockAlignedWritableFileTest {
w.write(ByteBuffer.wrap(new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}));
}
BlockAlignedWritableFile writable = Mockito.spy(new BlockAlignedWritableFile(file.openWritable(), file.openReadable(), 2));
BlockAlignedWritableFile writable = Mockito.spy(new BlockAlignedWritableFile(file::openWritable, file::openReadable, 2));
writable.write(ByteBuffer.wrap(new byte[] {0x11, 0x12, 0x13}));
Mockito.verify(writable, Mockito.never()).switchToBlockAlignedMode();
writable.position(1);
@@ -59,7 +59,7 @@ public class BlockAlignedWritableFileTest {
}
private void testWrite(File file, int blockSize) {
try (WritableFile w = new BlockAlignedWritableFile(file.openWritable(), file.openReadable(), blockSize)) {
try (WritableFile w = new BlockAlignedWritableFile(file::openWritable, file::openReadable, blockSize)) {
w.position(4);
w.write(ByteBuffer.wrap(new byte[] {0x11, 0x22, 0x33}));
}

View File

@@ -1,26 +1,12 @@
package org.cryptomator.filesystem.blacklisting;
import java.io.UncheckedIOException;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.delegating.DelegatingFile;
import org.cryptomator.filesystem.delegating.DelegatingReadableFile;
import org.cryptomator.filesystem.delegating.DelegatingWritableFile;
class BlacklistingFile extends DelegatingFile<DelegatingReadableFile, DelegatingWritableFile, BlacklistingFolder> {
class BlacklistingFile extends DelegatingFile<BlacklistingFolder> {
public BlacklistingFile(BlacklistingFolder parent, File delegate) {
super(parent, delegate);
}
@Override
public DelegatingReadableFile openReadable() throws UncheckedIOException {
return new DelegatingReadableFile(delegate.openReadable());
}
@Override
public DelegatingWritableFile openWritable() throws UncheckedIOException {
return new DelegatingWritableFile(delegate.openWritable());
}
}

View File

@@ -9,10 +9,8 @@ import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
import org.cryptomator.filesystem.delegating.DelegatingFolder;
import org.cryptomator.filesystem.delegating.DelegatingReadableFile;
import org.cryptomator.filesystem.delegating.DelegatingWritableFile;
class BlacklistingFolder extends DelegatingFolder<DelegatingReadableFile, DelegatingWritableFile, BlacklistingFolder, BlacklistingFile> {
class BlacklistingFolder extends DelegatingFolder<BlacklistingFolder, BlacklistingFile> {
private final Predicate<Node> hiddenNodes;

View File

@@ -5,11 +5,10 @@ import java.util.concurrent.atomic.AtomicReference;
import org.cryptomator.common.LazyInitializer;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.WritableFile;
import org.cryptomator.filesystem.delegating.DelegatingFile;
import org.cryptomator.filesystem.delegating.DelegatingReadableFile;
import org.cryptomator.filesystem.delegating.DelegatingWritableFile;
class ShorteningFile extends DelegatingFile<DelegatingReadableFile, DelegatingWritableFile, ShorteningFolder> {
class ShorteningFile extends DelegatingFile<ShorteningFolder> {
private final AtomicReference<String> longName;
private final FilenameShortener shortener;
@@ -32,16 +31,11 @@ class ShorteningFile extends DelegatingFile<DelegatingReadableFile, DelegatingWr
}
@Override
public DelegatingReadableFile openReadable() throws UncheckedIOException {
return new DelegatingReadableFile(delegate.openReadable());
}
@Override
public DelegatingWritableFile openWritable() throws UncheckedIOException {
public WritableFile openWritable() throws UncheckedIOException {
if (shortener.isShortened(shortenedName())) {
shortener.saveMapping(name(), shortenedName());
}
return new DelegatingWritableFile(delegate.openWritable());
return super.openWritable();
}
}

View File

@@ -7,10 +7,8 @@ import org.cryptomator.common.LazyInitializer;
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;
class ShorteningFolder extends DelegatingFolder<DelegatingReadableFile, DelegatingWritableFile, ShorteningFolder, ShorteningFile> {
class ShorteningFolder extends DelegatingFolder<ShorteningFolder, ShorteningFile> {
private final AtomicReference<String> longName;
private final FilenameShortener shortener;

View File

@@ -8,16 +8,13 @@
*******************************************************************************/
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 {
public class FileLocator extends DelegatingFile<FolderLocator>implements FileSystemResourceLocator {
private final DavLocatorFactory factory;
private final String prefix;
@@ -29,16 +26,6 @@ public class FileLocator extends DelegatingFile<DelegatingReadableFile, Delegati
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;

View File

@@ -15,10 +15,8 @@ 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 {
public class FolderLocator extends DelegatingFolder<FolderLocator, FileLocator>implements FileSystemResourceLocator {
private final DavLocatorFactory factory;
private final String prefix;