diff --git a/pom.xml b/pom.xml index 47dd52e5..9edc1126 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.cryptomator cryptofs - 2.6.1 + 2.6.2 Cryptomator Crypto Filesystem This library provides the Java filesystem provider used by Cryptomator. https://github.com/cryptomator/cryptofs @@ -18,8 +18,8 @@ 17 - 2.1.0 - 4.2.1 + 2.1.2 + 4.3.0 2.44.2 31.1-jre 2.0.3 @@ -30,7 +30,7 @@ 2.2 - 7.3.2 + 8.1.2 0.8.8 1.6.13 diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemComponent.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemComponent.java index d82b2675..85e0379f 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemComponent.java @@ -12,25 +12,13 @@ public interface CryptoFileSystemComponent { CryptoFileSystemImpl cryptoFileSystem(); - @Subcomponent.Builder - interface Builder { - - @BindsInstance - Builder cryptor(Cryptor cryptor); - - @BindsInstance - Builder vaultConfig(VaultConfig vaultConfig); - - @BindsInstance - Builder provider(CryptoFileSystemProvider provider); - - @BindsInstance - Builder pathToVault(@PathToVault Path pathToVault); - - @BindsInstance - Builder properties(CryptoFileSystemProperties cryptoFileSystemProperties); - - CryptoFileSystemComponent build(); + @Subcomponent.Factory + interface Factory { + CryptoFileSystemComponent create(@BindsInstance Cryptor cryptor, // + @BindsInstance VaultConfig vaultConfig, // + @BindsInstance CryptoFileSystemProvider provider, // + @BindsInstance @PathToVault Path pathToVault, // + @BindsInstance CryptoFileSystemProperties cryptoFileSystemProperties); } } diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystems.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystems.java index 646f8628..e64ab36a 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystems.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystems.java @@ -33,13 +33,13 @@ class CryptoFileSystems { private static final Logger LOG = LoggerFactory.getLogger(CryptoFileSystems.class); private final ConcurrentMap fileSystems = new ConcurrentHashMap<>(); - private final CryptoFileSystemComponent.Builder cryptoFileSystemComponentBuilder; // sharing reusable builder via synchronized + private final CryptoFileSystemComponent.Factory cryptoFileSystemComponentFactory; private final FileSystemCapabilityChecker capabilityChecker; private final SecureRandom csprng; @Inject - public CryptoFileSystems(CryptoFileSystemComponent.Builder cryptoFileSystemComponentBuilder, FileSystemCapabilityChecker capabilityChecker, SecureRandom csprng) { - this.cryptoFileSystemComponentBuilder = cryptoFileSystemComponentBuilder; + public CryptoFileSystems(CryptoFileSystemComponent.Factory cryptoFileSystemComponentFactory, FileSystemCapabilityChecker capabilityChecker, SecureRandom csprng) { + this.cryptoFileSystemComponentFactory = cryptoFileSystemComponentFactory; this.capabilityChecker = capabilityChecker; this.csprng = csprng; } @@ -59,7 +59,7 @@ public CryptoFileSystemImpl create(CryptoFileSystemProvider provider, Path pathT checkVaultRootExistence(pathToVault, cryptor); return fileSystems.compute(normalizedPathToVault, (path, fs) -> { if (fs == null) { - return create(provider, normalizedPathToVault, adjustedProperties, cryptor, config); + return cryptoFileSystemComponentFactory.create(cryptor, config, provider, normalizedPathToVault, adjustedProperties).cryptoFileSystem(); } else { throw new FileSystemAlreadyExistsException(); } @@ -86,18 +86,6 @@ private void checkVaultRootExistence(Path pathToVault, Cryptor cryptor) throws C } } - // synchronized access to non-threadsafe cryptoFileSystemComponentBuilder required - private synchronized CryptoFileSystemImpl create(CryptoFileSystemProvider provider, Path pathToVault, CryptoFileSystemProperties properties, Cryptor cryptor, VaultConfig config) { - return cryptoFileSystemComponentBuilder // - .cryptor(cryptor) // - .vaultConfig(config) // - .pathToVault(pathToVault) // - .properties(properties) // - .provider(provider) // - .build() // - .cryptoFileSystem(); - } - /** * Attempts to read a vault config file * diff --git a/src/main/java/org/cryptomator/cryptofs/attr/AttributeComponent.java b/src/main/java/org/cryptomator/cryptofs/attr/AttributeComponent.java index a3cea066..91f755ad 100644 --- a/src/main/java/org/cryptomator/cryptofs/attr/AttributeComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/attr/AttributeComponent.java @@ -24,18 +24,12 @@ default T attributes(Class type) { } } - @Subcomponent.Builder - interface Builder { + @Subcomponent.Factory + interface Factory { - @BindsInstance - Builder ciphertextPath(Path ciphertextPath); + AttributeComponent create(@BindsInstance Path ciphertextPath, // + @BindsInstance CiphertextFileType ciphertextFileType, // + @BindsInstance @Named("ciphertext") BasicFileAttributes ciphertextAttributes); - @BindsInstance - Builder ciphertextFileType(CiphertextFileType ciphertextFileType); - - @BindsInstance - Builder ciphertextAttributes(@Named("ciphertext") BasicFileAttributes ciphertextAttributes); - - AttributeComponent build(); } } diff --git a/src/main/java/org/cryptomator/cryptofs/attr/AttributeProvider.java b/src/main/java/org/cryptomator/cryptofs/attr/AttributeProvider.java index 02e15459..b2195161 100644 --- a/src/main/java/org/cryptomator/cryptofs/attr/AttributeProvider.java +++ b/src/main/java/org/cryptomator/cryptofs/attr/AttributeProvider.java @@ -16,7 +16,6 @@ import org.cryptomator.cryptofs.common.CiphertextFileType; import javax.inject.Inject; -import javax.inject.Provider; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; @@ -26,13 +25,13 @@ @CryptoFileSystemScoped public class AttributeProvider { - private final Provider attributeComponentBuilderProvider; + private final AttributeComponent.Factory attributeComponentFactory; private final CryptoPathMapper pathMapper; private final Symlinks symlinks; @Inject - AttributeProvider(Provider attributeComponentBuilderProvider, CryptoPathMapper pathMapper, Symlinks symlinks) { - this.attributeComponentBuilderProvider = attributeComponentBuilderProvider; + AttributeProvider(AttributeComponent.Factory attributeComponentFactory, CryptoPathMapper pathMapper, Symlinks symlinks) { + this.attributeComponentFactory = attributeComponentFactory; this.pathMapper = pathMapper; this.symlinks = symlinks; } @@ -45,13 +44,10 @@ public A readAttributes(CryptoPath cleartextPath } Path ciphertextPath = getCiphertextPath(cleartextPath, ciphertextFileType); A ciphertextAttrs = Files.readAttributes(ciphertextPath, type); - AttributeComponent.Builder builder = attributeComponentBuilderProvider.get(); - return builder // - .ciphertextFileType(ciphertextFileType) // - .ciphertextPath(ciphertextPath) // - .ciphertextAttributes(ciphertextAttrs) // - .build() // - .attributes(type); + return attributeComponentFactory.create(ciphertextPath, // + ciphertextFileType, // + ciphertextAttrs) // + .attributes(type); // } private Path getCiphertextPath(CryptoPath path, CiphertextFileType type) throws IOException { diff --git a/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewComponent.java b/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewComponent.java index 7374be6a..d009cb56 100644 --- a/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewComponent.java @@ -14,19 +14,11 @@ public interface AttributeViewComponent { Optional attributeView(); - @Subcomponent.Builder - interface Builder { + @Subcomponent.Factory + interface Factory { - @BindsInstance - Builder cleartextPath(CryptoPath cleartextPath); + AttributeViewComponent create(@BindsInstance CryptoPath cleartextPath, @BindsInstance Class type, @BindsInstance LinkOption[] linkOptions); - @BindsInstance - Builder viewType(Class type); - - @BindsInstance - Builder linkOptions(LinkOption[] linkOptions); - - AttributeViewComponent build(); } } diff --git a/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewProvider.java b/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewProvider.java index c3d753e2..470deae6 100644 --- a/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewProvider.java +++ b/src/main/java/org/cryptomator/cryptofs/attr/AttributeViewProvider.java @@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javax.inject.Provider; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.attribute.FileAttributeView; @@ -25,27 +24,21 @@ public class AttributeViewProvider { private static final Logger LOG = LoggerFactory.getLogger(AttributeViewProvider.class); - private final Provider attrViewComponentBuilderProvider; + private final AttributeViewComponent.Factory attrViewComponentFactory; @Inject - AttributeViewProvider(Provider attrViewComponentBuilderProvider) { - this.attrViewComponentBuilderProvider = attrViewComponentBuilderProvider; + AttributeViewProvider(AttributeViewComponent.Factory attrViewComponentFactory) { + this.attrViewComponentFactory = attrViewComponentFactory; } /** * @param cleartextPath the unencrypted path to the file - * @param type the Class object corresponding to the file attribute view + * @param type the Class object corresponding to the file attribute view * @return a file attribute view of the specified type, or null if the attribute view type is not available * @see Files#getFileAttributeView(java.nio.file.Path, Class, java.nio.file.LinkOption...) */ public A getAttributeView(CryptoPath cleartextPath, Class type, LinkOption... options) { - AttributeViewComponent.Builder builder = attrViewComponentBuilderProvider.get(); - Optional view = builder // - .cleartextPath(cleartextPath) // - .viewType(type) // - .linkOptions(options) // - .build() // - .attributeView(); + Optional view = attrViewComponentFactory.create(cleartextPath, type, options).attributeView(); if (view.isPresent() && type.isInstance(view.get())) { return type.cast(view.get()); } else { diff --git a/src/main/java/org/cryptomator/cryptofs/ch/ChannelComponent.java b/src/main/java/org/cryptomator/cryptofs/ch/ChannelComponent.java index a3f419da..706a9185 100644 --- a/src/main/java/org/cryptomator/cryptofs/ch/ChannelComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/ch/ChannelComponent.java @@ -13,25 +13,14 @@ public interface ChannelComponent { CleartextFileChannel channel(); - @Subcomponent.Builder - interface Builder { - - @BindsInstance - Builder openOptions(EffectiveOpenOptions options); - - @BindsInstance - Builder onClose(ChannelCloseListener listener); - - @BindsInstance - Builder ciphertextChannel(FileChannel ciphertextChannel); - - @BindsInstance - Builder mustWriteHeader(@MustWriteHeader boolean mustWriteHeader); - - @BindsInstance - Builder fileHeader(FileHeader fileHeader); - - ChannelComponent build(); + @Subcomponent.Factory + interface Factory { + + ChannelComponent create(@BindsInstance FileChannel ciphertextChannel, // + @BindsInstance FileHeader fileHeader, // + @BindsInstance @MustWriteHeader boolean mustWriteHeader, // + @BindsInstance EffectiveOpenOptions options, // + @BindsInstance ChannelCloseListener listener); // } } diff --git a/src/main/java/org/cryptomator/cryptofs/ch/CleartextFileChannel.java b/src/main/java/org/cryptomator/cryptofs/ch/CleartextFileChannel.java index b1c9039a..436dde78 100644 --- a/src/main/java/org/cryptomator/cryptofs/ch/CleartextFileChannel.java +++ b/src/main/java/org/cryptomator/cryptofs/ch/CleartextFileChannel.java @@ -93,7 +93,7 @@ protected boolean isReadable() { } @Override - protected int readLocked(ByteBuffer dst, long position) throws IOException { + protected synchronized int readLocked(ByteBuffer dst, long position) throws IOException { int origLimit = dst.limit(); long limitConsideringEof = fileSize.get() - position; if (limitConsideringEof < 1) { diff --git a/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamComponent.java b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamComponent.java index 4eac6698..a1b55695 100644 --- a/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamComponent.java @@ -14,25 +14,14 @@ public interface DirectoryStreamComponent { CryptoDirectoryStream directoryStream(); - @Subcomponent.Builder - interface Builder { - - @BindsInstance - Builder cleartextPath(@Named("cleartextPath") Path cleartextPath); - - @BindsInstance - Builder dirId(@Named("dirId") String dirId); - - @BindsInstance - Builder ciphertextDirectoryStream(DirectoryStream ciphertextDirectoryStream); - - @BindsInstance - Builder filter(DirectoryStream.Filter filter); - - @BindsInstance - Builder onClose(Consumer onClose); - - DirectoryStreamComponent build(); + @Subcomponent.Factory + interface Factory { + + DirectoryStreamComponent create(@BindsInstance @Named("cleartextPath") Path cleartextPath, // + @BindsInstance @Named("dirId") String dirId, // + @BindsInstance DirectoryStream ciphertextDirectoryStream, // + @BindsInstance DirectoryStream.Filter filter, // + @BindsInstance Consumer onClose); } } diff --git a/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactory.java b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactory.java index 9aae97fd..651d7dff 100644 --- a/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactory.java +++ b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactory.java @@ -20,31 +20,25 @@ public class DirectoryStreamFactory { private final CryptoPathMapper cryptoPathMapper; - private final DirectoryStreamComponent.Builder directoryStreamComponentBuilder; // sharing reusable builder via synchronized + private final DirectoryStreamComponent.Factory directoryStreamComponentFactory; private final Map> streams = new HashMap<>(); private volatile boolean closed = false; @Inject - public DirectoryStreamFactory(CryptoPathMapper cryptoPathMapper, DirectoryStreamComponent.Builder directoryStreamComponentBuilder) { + public DirectoryStreamFactory(CryptoPathMapper cryptoPathMapper, DirectoryStreamComponent.Factory directoryStreamComponentFactory) { this.cryptoPathMapper = cryptoPathMapper; - this.directoryStreamComponentBuilder = directoryStreamComponentBuilder; + this.directoryStreamComponentFactory = directoryStreamComponentFactory; } + //TODO: is synchronized still needed? One reason was, that a dagger builder was used (replaced by thread safe factory) public synchronized CryptoDirectoryStream newDirectoryStream(CryptoPath cleartextDir, Filter filter) throws IOException { if (closed) { throw new ClosedFileSystemException(); } CiphertextDirectory ciphertextDir = cryptoPathMapper.getCiphertextDir(cleartextDir); DirectoryStream ciphertextDirStream = Files.newDirectoryStream(ciphertextDir.path, this::matchesEncryptedContentPattern); - CryptoDirectoryStream cleartextDirStream = directoryStreamComponentBuilder // - .dirId(ciphertextDir.dirId) // - .ciphertextDirectoryStream(ciphertextDirStream) // - .cleartextPath(cleartextDir) // - .filter(filter) // - .onClose(streams::remove) // - .build() // - .directoryStream(); + var cleartextDirStream = directoryStreamComponentFactory.create(cleartextDir, ciphertextDir.dirId, ciphertextDirStream, filter, streams::remove).directoryStream(); streams.put(cleartextDirStream, ciphertextDirStream); return cleartextDirStream; } diff --git a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFile.java b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFile.java index b41e35fe..24d03020 100644 --- a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFile.java +++ b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFile.java @@ -9,7 +9,6 @@ package org.cryptomator.cryptofs.fh; import org.cryptomator.cryptofs.EffectiveOpenOptions; -import org.cryptomator.cryptofs.ch.ChannelComponent; import org.cryptomator.cryptofs.ch.CleartextFileChannel; import org.cryptomator.cryptolib.api.Cryptor; import org.cryptomator.cryptolib.api.FileHeader; @@ -87,14 +86,9 @@ public synchronized FileChannel newFileChannel(EffectiveOpenOptions options, Fil isNewHeader = false; } initFileSize(ciphertextFileChannel); - ChannelComponent channelComponent = component.newChannelComponent() // - .ciphertextChannel(ciphertextFileChannel) // - .openOptions(options) // - .onClose(this::channelClosed) // - .mustWriteHeader(isNewHeader) // - .fileHeader(header) // - .build(); - cleartextFileChannel = channelComponent.channel(); + cleartextFileChannel = component.newChannelComponent() // + .create(ciphertextFileChannel, header, isNewHeader, options, this::channelClosed) // + .channel(); } finally { if (cleartextFileChannel == null) { // i.e. something didn't work closeQuietly(ciphertextFileChannel); diff --git a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFileComponent.java b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFileComponent.java index dd3ee6a5..9db16024 100644 --- a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFileComponent.java +++ b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFileComponent.java @@ -12,18 +12,13 @@ public interface OpenCryptoFileComponent { OpenCryptoFile openCryptoFile(); - ChannelComponent.Builder newChannelComponent(); + ChannelComponent.Factory newChannelComponent(); - @Subcomponent.Builder - interface Builder { + @Subcomponent.Factory + interface Factory { - @BindsInstance - Builder path(@OriginalOpenFilePath Path path); - - @BindsInstance - Builder onClose(FileCloseListener listener); - - OpenCryptoFileComponent build(); + OpenCryptoFileComponent create(@BindsInstance @OriginalOpenFilePath Path path, // + @BindsInstance FileCloseListener onCloseListener); } } diff --git a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFiles.java b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFiles.java index 7dd4ecee..1fa916d7 100644 --- a/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFiles.java +++ b/src/main/java/org/cryptomator/cryptofs/fh/OpenCryptoFiles.java @@ -12,7 +12,6 @@ import org.cryptomator.cryptofs.EffectiveOpenOptions; import javax.inject.Inject; -import javax.inject.Provider; import java.io.Closeable; import java.io.IOException; import java.nio.BufferUnderflowException; @@ -30,12 +29,12 @@ @CryptoFileSystemScoped public class OpenCryptoFiles implements Closeable { - private final Provider openCryptoFileComponentBuilderProvider; + private final OpenCryptoFileComponent.Factory openCryptoFileComponentFactory; private final ConcurrentMap openCryptoFiles = new ConcurrentHashMap<>(); @Inject - OpenCryptoFiles(Provider openCryptoFileComponentBuilderProvider) { - this.openCryptoFileComponentBuilderProvider = openCryptoFileComponentBuilderProvider; + OpenCryptoFiles(OpenCryptoFileComponent.Factory openCryptoFileComponentFactory) { + this.openCryptoFileComponentFactory = openCryptoFileComponentFactory; } /** @@ -61,16 +60,7 @@ public Optional get(Path ciphertextPath) { */ public OpenCryptoFile getOrCreate(Path ciphertextPath) { Path normalizedPath = ciphertextPath.toAbsolutePath().normalize(); - return openCryptoFiles.computeIfAbsent(normalizedPath, this::create); // computeIfAbsent is atomic, "create" is called at most once - } - - private OpenCryptoFile create(Path normalizedPath) { - OpenCryptoFileComponent.Builder builder = openCryptoFileComponentBuilderProvider.get(); - OpenCryptoFileComponent openCryptoFileComponent = builder // - .path(normalizedPath) // - .onClose(openCryptoFiles::remove) // - .build(); - return openCryptoFileComponent.openCryptoFile(); + return openCryptoFiles.computeIfAbsent(normalizedPath, p -> openCryptoFileComponentFactory.create(p, openCryptoFiles::remove).openCryptoFile()); // computeIfAbsent is atomic, "create" is called at most once } public void writeCiphertextFile(Path ciphertextPath, EffectiveOpenOptions openOptions, ByteBuffer contents) throws IOException { diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java index fc2e80ac..26dcf5e6 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemsTest.java @@ -57,7 +57,7 @@ public class CryptoFileSystemsTest { private final CryptorProvider cryptorProvider = mock(CryptorProvider.class); private final Cryptor cryptor = mock(Cryptor.class); private final FileNameCryptor fileNameCryptor = mock(FileNameCryptor.class); - private final CryptoFileSystemComponent.Builder cryptoFileSystemComponentBuilder = mock(CryptoFileSystemComponent.Builder.class); + private final CryptoFileSystemComponent.Factory cryptoFileSystemComponentFactory = mock(CryptoFileSystemComponent.Factory.class); private MockedStatic vaultConficClass; @@ -65,7 +65,7 @@ public class CryptoFileSystemsTest { private MockedStatic cryptorProviderClass; private MockedStatic backupHelperClass; - private final CryptoFileSystems inTest = new CryptoFileSystems(cryptoFileSystemComponentBuilder, capabilityChecker, csprng); + private final CryptoFileSystems inTest = new CryptoFileSystems(cryptoFileSystemComponentFactory, capabilityChecker, csprng); @BeforeEach public void setup() throws IOException, MasterkeyLoadingFailedException { @@ -96,12 +96,7 @@ public void setup() throws IOException, MasterkeyLoadingFailedException { when(dataDirPath.resolve("AB")).thenReturn(preContenRootPath); when(preContenRootPath.resolve("CDEFGHIJKLMNOP")).thenReturn(contenRootPath); filesClass.when(() -> Files.exists(contenRootPath)).thenReturn(true); - when(cryptoFileSystemComponentBuilder.cryptor(any())).thenReturn(cryptoFileSystemComponentBuilder); - when(cryptoFileSystemComponentBuilder.vaultConfig(any())).thenReturn(cryptoFileSystemComponentBuilder); - when(cryptoFileSystemComponentBuilder.pathToVault(any())).thenReturn(cryptoFileSystemComponentBuilder); - when(cryptoFileSystemComponentBuilder.properties(any())).thenReturn(cryptoFileSystemComponentBuilder); - when(cryptoFileSystemComponentBuilder.provider(any())).thenReturn(cryptoFileSystemComponentBuilder); - when(cryptoFileSystemComponentBuilder.build()).thenReturn(cryptoFileSystemComponent); + when(cryptoFileSystemComponentFactory.create(any(),any(),any(),any(),any())).thenReturn(cryptoFileSystemComponent); when(cryptoFileSystemComponent.cryptoFileSystem()).thenReturn(cryptoFileSystem); } @@ -124,12 +119,7 @@ public void testContainsReturnsTrueForContainedFileSystem() throws IOException, Assertions.assertSame(cryptoFileSystem, impl); Assertions.assertTrue(inTest.contains(cryptoFileSystem)); - verify(cryptoFileSystemComponentBuilder).cryptor(cryptor); - verify(cryptoFileSystemComponentBuilder).vaultConfig(vaultConfig); - verify(cryptoFileSystemComponentBuilder).pathToVault(normalizedPathToVault); - verify(cryptoFileSystemComponentBuilder).properties(properties); - verify(cryptoFileSystemComponentBuilder).provider(provider); - verify(cryptoFileSystemComponentBuilder).build(); + verify(cryptoFileSystemComponentFactory,Mockito.times(1)).create(cryptor, vaultConfig, provider, normalizedPathToVault, properties); } @Test diff --git a/src/test/java/org/cryptomator/cryptofs/attr/AttributeProviderTest.java b/src/test/java/org/cryptomator/cryptofs/attr/AttributeProviderTest.java index 11616263..85dd5916 100644 --- a/src/test/java/org/cryptomator/cryptofs/attr/AttributeProviderTest.java +++ b/src/test/java/org/cryptomator/cryptofs/attr/AttributeProviderTest.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import javax.inject.Provider; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.LinkOption; @@ -29,12 +28,12 @@ import java.nio.file.attribute.DosFileAttributes; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.spi.FileSystemProvider; -import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; public class AttributeProviderTest { - private Provider attributeComponentBuilderProvider; - private AttributeComponent.Builder attributeComponentBuilder; + private AttributeComponent.Factory attributeComponentFactory; private AttributeComponent attributeComponent; private CryptoPathMapper pathMapper; private CryptoPath cleartextPath; @@ -47,14 +46,9 @@ public class AttributeProviderTest { @BeforeEach public void setup() throws IOException { - attributeComponentBuilderProvider = Mockito.mock(Provider.class); - attributeComponentBuilder = Mockito.mock(AttributeComponent.Builder.class); + attributeComponentFactory = Mockito.mock(AttributeComponent.Factory.class); attributeComponent = Mockito.mock(AttributeComponent.class); - Mockito.when(attributeComponentBuilderProvider.get()).thenReturn(attributeComponentBuilder); - Mockito.when(attributeComponentBuilder.ciphertextFileType(Mockito.any())).thenReturn(attributeComponentBuilder); - Mockito.when(attributeComponentBuilder.ciphertextPath(Mockito.any())).thenReturn(attributeComponentBuilder); - Mockito.when(attributeComponentBuilder.ciphertextAttributes(Mockito.any())).thenReturn(attributeComponentBuilder); - Mockito.when(attributeComponentBuilder.build()).thenReturn(attributeComponent); + Mockito.when(attributeComponentFactory.create(any(), any(), any())).thenReturn(attributeComponent); pathMapper = Mockito.mock(CryptoPathMapper.class); cleartextPath = Mockito.mock(CryptoPath.class, "cleartextPath"); @@ -68,9 +62,9 @@ public void setup() throws IOException { ciphertextBasicAttr = Mockito.mock(BasicFileAttributes.class); ciphertextPosixAttr = Mockito.mock(PosixFileAttributes.class); ciphertextDosAttr = Mockito.mock(DosFileAttributes.class); - Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(BasicFileAttributes.class), Mockito.any())).thenReturn(ciphertextBasicAttr); - Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(PosixFileAttributes.class), Mockito.any())).thenReturn(ciphertextPosixAttr); - Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(DosFileAttributes.class), Mockito.any())).thenReturn(ciphertextDosAttr); + Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(BasicFileAttributes.class), any())).thenReturn(ciphertextBasicAttr); + Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(PosixFileAttributes.class), any())).thenReturn(ciphertextPosixAttr); + Mockito.when(provider.readAttributes(Mockito.same(ciphertextRawPath), Mockito.same(DosFileAttributes.class), any())).thenReturn(ciphertextDosAttr); Mockito.when(pathMapper.getCiphertextFileType(cleartextPath)).thenReturn(CiphertextFileType.FILE); Mockito.when(pathMapper.getCiphertextFilePath(cleartextPath)).thenReturn(ciphertextPath); @@ -92,7 +86,7 @@ public void setup() throws IOException { Mockito.when(pathMapper.getCiphertextFileType(cleartextPath)).thenReturn(CiphertextFileType.FILE); Mockito.when(pathMapper.getCiphertextFilePath(cleartextPath)).thenReturn(ciphertextPath); - prov = new AttributeProvider(attributeComponentBuilderProvider, pathMapper, symlinks); + prov = new AttributeProvider(attributeComponentFactory, pathMapper, symlinks); } @Test @@ -101,9 +95,7 @@ public void testReadBasicAttributes() throws IOException { BasicFileAttributes attr = prov.readAttributes(cleartextPath, BasicFileAttributes.class); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.FILE); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextBasicAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.FILE, ciphertextBasicAttr); Assertions.assertEquals(ciphertextBasicAttr, attr); } @@ -113,9 +105,7 @@ public void testReadPosixAttributes() throws IOException { PosixFileAttributes attr = prov.readAttributes(cleartextPath, PosixFileAttributes.class); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.FILE); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextPosixAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.FILE, ciphertextPosixAttr); Assertions.assertEquals(ciphertextPosixAttr, attr); } @@ -125,9 +115,7 @@ public void testReadDosAttributes() throws IOException { DosFileAttributes attr = prov.readAttributes(cleartextPath, DosFileAttributes.class); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.FILE); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextDosAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.FILE, ciphertextDosAttr); Assertions.assertEquals(ciphertextDosAttr, attr); } @@ -138,8 +126,7 @@ public void testReadUnsupportedAttributes() { Assertions.assertThrows(UnsupportedOperationException.class, () -> { prov.readAttributes(cleartextPath, UnsupportedAttributes.class); }); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.FILE); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(Mockito.eq(ciphertextRawPath), Mockito.eq(CiphertextFileType.FILE), any()); } } @@ -155,7 +142,7 @@ public void setup() throws IOException { Mockito.when(pathMapper.getCiphertextFileType(cleartextPath)).thenReturn(CiphertextFileType.DIRECTORY); Mockito.when(pathMapper.getCiphertextDir(cleartextPath)).thenReturn(new CiphertextDirectory("foo", ciphertextRawPath)); - prov = new AttributeProvider(attributeComponentBuilderProvider, pathMapper, symlinks); + prov = new AttributeProvider(attributeComponentFactory, pathMapper, symlinks); } @Test @@ -164,9 +151,7 @@ public void testReadBasicAttributes() throws IOException { BasicFileAttributes attr = prov.readAttributes(cleartextPath, BasicFileAttributes.class); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.DIRECTORY); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextBasicAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.DIRECTORY, ciphertextBasicAttr); Assertions.assertEquals(ciphertextBasicAttr, attr); } @@ -181,7 +166,7 @@ public class SymbolicLinks { public void setup() throws IOException { Mockito.when(pathMapper.getCiphertextFileType(cleartextPath)).thenReturn(CiphertextFileType.SYMLINK); - prov = new AttributeProvider(attributeComponentBuilderProvider, pathMapper, symlinks); + prov = new AttributeProvider(attributeComponentFactory, pathMapper, symlinks); } @Test @@ -192,9 +177,7 @@ public void testReadBasicAttributesNoFollow() throws IOException { BasicFileAttributes attr = prov.readAttributes(cleartextPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.SYMLINK); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextBasicAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.SYMLINK, ciphertextBasicAttr); Assertions.assertEquals(ciphertextBasicAttr, attr); } @@ -208,9 +191,7 @@ public void testReadBasicAttributesOfTarget() throws IOException { BasicFileAttributes attr = prov.readAttributes(cleartextPath, BasicFileAttributes.class); - Mockito.verify(attributeComponentBuilder).ciphertextPath(ciphertextRawPath); - Mockito.verify(attributeComponentBuilder).ciphertextFileType(CiphertextFileType.FILE); - Mockito.verify(attributeComponentBuilder).ciphertextAttributes(ciphertextBasicAttr); + Mockito.verify(attributeComponentFactory, Mockito.times(1)).create(ciphertextRawPath, CiphertextFileType.FILE, ciphertextBasicAttr); Assertions.assertEquals(ciphertextBasicAttr, attr); } diff --git a/src/test/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactoryTest.java b/src/test/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactoryTest.java index 981a885d..c4361278 100644 --- a/src/test/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactoryTest.java +++ b/src/test/java/org/cryptomator/cryptofs/dir/DirectoryStreamFactoryTest.java @@ -34,20 +34,15 @@ public class DirectoryStreamFactoryTest { private final FileSystemProvider provider = mock(FileSystemProvider.class, "provider"); private final CryptoPathMapper cryptoPathMapper = mock(CryptoPathMapper.class); private final DirectoryStreamComponent directoryStreamComp = mock(DirectoryStreamComponent.class); - private final DirectoryStreamComponent.Builder directoryStreamBuilder = mock(DirectoryStreamComponent.Builder.class); + private final DirectoryStreamComponent.Factory directoryStreamFactory = mock(DirectoryStreamComponent.Factory.class); - private final DirectoryStreamFactory inTest = new DirectoryStreamFactory(cryptoPathMapper, directoryStreamBuilder); + private final DirectoryStreamFactory inTest = new DirectoryStreamFactory(cryptoPathMapper, directoryStreamFactory); @SuppressWarnings("unchecked") @BeforeEach public void setup() throws IOException { - when(directoryStreamBuilder.cleartextPath(Mockito.any())).thenReturn(directoryStreamBuilder); - when(directoryStreamBuilder.dirId(Mockito.any())).thenReturn(directoryStreamBuilder); - when(directoryStreamBuilder.ciphertextDirectoryStream(Mockito.any())).thenReturn(directoryStreamBuilder); - when(directoryStreamBuilder.filter(Mockito.any())).thenReturn(directoryStreamBuilder); - when(directoryStreamBuilder.onClose(Mockito.any())).thenReturn(directoryStreamBuilder); - when(directoryStreamBuilder.build()).thenReturn(directoryStreamComp); + when(directoryStreamFactory.create(any(),any(),any(),any(),any())).thenReturn(directoryStreamComp); when(directoryStreamComp.directoryStream()).then(invocation -> mock(CryptoDirectoryStream.class)); when(fileSystem.provider()).thenReturn(provider); } diff --git a/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFileTest.java b/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFileTest.java index 343aa2bd..afd5616d 100644 --- a/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFileTest.java +++ b/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFileTest.java @@ -1,7 +1,6 @@ package org.cryptomator.cryptofs.fh; import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Feature; import com.google.common.jimfs.Jimfs; import org.cryptomator.cryptofs.EffectiveOpenOptions; import org.cryptomator.cryptofs.ReadonlyFlag; @@ -53,7 +52,7 @@ public class OpenCryptoFileTest { private AtomicLong fileSize = new AtomicLong(-1l); private AtomicReference lastModified = new AtomicReference(Instant.ofEpochMilli(0)); private OpenCryptoFileComponent openCryptoFileComponent = mock(OpenCryptoFileComponent.class); - private ChannelComponent.Builder channelComponentBuilder = mock(ChannelComponent.Builder.class); + private ChannelComponent.Factory channelComponentFactory = mock(ChannelComponent.Factory.class); private ChannelComponent channelComponent = mock(ChannelComponent.class); @BeforeAll @@ -107,19 +106,12 @@ public void setup() throws IOException { listener = new AtomicReference<>(); ciphertextChannel = new AtomicReference<>(); - Mockito.when(openCryptoFileComponent.newChannelComponent()).thenReturn(channelComponentBuilder); - Mockito.when(channelComponentBuilder.ciphertextChannel(Mockito.any())).thenAnswer(invocation -> { + Mockito.when(openCryptoFileComponent.newChannelComponent()).thenReturn(channelComponentFactory); + Mockito.when(channelComponentFactory.create(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any())).thenAnswer(invocation -> { ciphertextChannel.set(invocation.getArgument(0)); - return channelComponentBuilder; + listener.set(invocation.getArgument(4)); + return channelComponent; }); - Mockito.when(channelComponentBuilder.openOptions(Mockito.any())).thenReturn(channelComponentBuilder); - Mockito.when(channelComponentBuilder.onClose(Mockito.any())).thenAnswer(invocation -> { - listener.set(invocation.getArgument(0)); - return channelComponentBuilder; - }); - Mockito.when(channelComponentBuilder.fileHeader(Mockito.any())).thenReturn(channelComponentBuilder); - Mockito.when(channelComponentBuilder.mustWriteHeader(Mockito.anyBoolean())).thenReturn(channelComponentBuilder); - Mockito.when(channelComponentBuilder.build()).thenReturn(channelComponent); Mockito.when(channelComponent.channel()).thenReturn(cleartextFileChannel); } diff --git a/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFilesTest.java b/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFilesTest.java index ea71bd91..fa01dbfb 100644 --- a/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFilesTest.java +++ b/src/test/java/org/cryptomator/cryptofs/fh/OpenCryptoFilesTest.java @@ -20,8 +20,7 @@ public class OpenCryptoFilesTest { - private final Provider openCryptoFileComponentBuilderProvider = mock(Provider.class); - private final OpenCryptoFileComponent.Builder openCryptoFileComponentBuilder = mock(OpenCryptoFileComponent.Builder.class); + private final OpenCryptoFileComponent.Factory openCryptoFileComponentFactory = mock(OpenCryptoFileComponent.Factory.class); private final OpenCryptoFile file = mock(OpenCryptoFile.class, "file"); private final FileChannel ciphertextFileChannel = Mockito.mock(FileChannel.class); @@ -32,14 +31,10 @@ public void setup() throws IOException, ReflectiveOperationException { OpenCryptoFileComponent subComponent = mock(OpenCryptoFileComponent.class); Mockito.when(subComponent.openCryptoFile()).thenReturn(file); - Mockito.when(openCryptoFileComponentBuilderProvider.get()).thenReturn(openCryptoFileComponentBuilder); - Mockito.when(openCryptoFileComponentBuilder.path(Mockito.any())).thenReturn(openCryptoFileComponentBuilder); - Mockito.when(openCryptoFileComponentBuilder.onClose(Mockito.any())).thenReturn(openCryptoFileComponentBuilder); - Mockito.when(openCryptoFileComponentBuilder.build()).thenReturn(subComponent); - + Mockito.when(openCryptoFileComponentFactory.create(Mockito.any(), Mockito.any())).thenReturn(subComponent); Mockito.when(file.newFileChannel(Mockito.any())).thenReturn(ciphertextFileChannel); - inTest = new OpenCryptoFiles(openCryptoFileComponentBuilderProvider); + inTest = new OpenCryptoFiles(openCryptoFileComponentFactory); } @Test @@ -52,7 +47,7 @@ public void testGetOrCreate() { OpenCryptoFile file2 = mock(OpenCryptoFile.class); Mockito.when(subComponent2.openCryptoFile()).thenReturn(file2); - Mockito.when(openCryptoFileComponentBuilder.build()).thenReturn(subComponent1, subComponent2); + Mockito.when(openCryptoFileComponentFactory.create(Mockito.any(), Mockito.any())).thenReturn(subComponent1, subComponent2); Path p1 = Paths.get("/foo"); Path p2 = Paths.get("/bar"); @@ -140,24 +135,18 @@ public void testCloseClosesRemainingOpenFiles() { Path path1 = Mockito.mock(Path.class, "/file1"); Mockito.when(path1.toAbsolutePath()).thenReturn(path1); Mockito.when(path1.normalize()).thenReturn(path1); - OpenCryptoFileComponent.Builder subComponentBuilder1 = mock(OpenCryptoFileComponent.Builder.class); OpenCryptoFileComponent subComponent1 = mock(OpenCryptoFileComponent.class); OpenCryptoFile file1 = mock(OpenCryptoFile.class, "file1"); - Mockito.when(openCryptoFileComponentBuilder.path(path1)).thenReturn(subComponentBuilder1); - Mockito.when(subComponentBuilder1.onClose(Mockito.any())).thenReturn(subComponentBuilder1); - Mockito.when(subComponentBuilder1.build()).thenReturn(subComponent1); + Mockito.when(openCryptoFileComponentFactory.create(Mockito.eq(path1), Mockito.any())).thenReturn(subComponent1); Mockito.when(subComponent1.openCryptoFile()).thenReturn(file1); Mockito.when(file1.getCurrentFilePath()).thenReturn(path1); Path path2 = Mockito.mock(Path.class, "/file2"); Mockito.when(path2.toAbsolutePath()).thenReturn(path2); Mockito.when(path2.normalize()).thenReturn(path2); - OpenCryptoFileComponent.Builder subComponentBuilder2 = mock(OpenCryptoFileComponent.Builder.class); OpenCryptoFileComponent subComponent2 = mock(OpenCryptoFileComponent.class); OpenCryptoFile file2 = mock(OpenCryptoFile.class, "file2"); - Mockito.when(openCryptoFileComponentBuilder.path(path2)).thenReturn(subComponentBuilder2); - Mockito.when(subComponentBuilder2.onClose(Mockito.any())).thenReturn(subComponentBuilder2); - Mockito.when(subComponentBuilder2.build()).thenReturn(subComponent2); + Mockito.when(openCryptoFileComponentFactory.create(Mockito.eq(path2), Mockito.any())).thenReturn(subComponent2); Mockito.when(subComponent2.openCryptoFile()).thenReturn(file2); Mockito.when(file2.getCurrentFilePath()).thenReturn(path2); diff --git a/suppression.xml b/suppression.xml index ebb877b8..a7fe7425 100644 --- a/suppression.xml +++ b/suppression.xml @@ -9,4 +9,12 @@ cpe:/a:cryptomator:cryptomator CVE-2022-25366 + + + ^pkg:maven/com\.google\.guava/guava@.*$ + CVE-2020-8908 + CVE-2020-8908 + \ No newline at end of file