From 66d33c8584b9fe5e7035b5a7b983f7e011347465 Mon Sep 17 00:00:00 2001 From: julianseeger Date: Fri, 30 Sep 2016 15:12:56 +0200 Subject: [PATCH 1/6] public BoxNavigation::visit --- box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt | 2 +- box/src/main/java/de/qabel/box/storage/BoxNavigation.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index 79a6965a..fdec5dbf 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -187,7 +187,7 @@ abstract class AbstractNavigation( } } - fun visit(consumer: (AbstractNavigation, BoxObject) -> Unit): Unit { + override fun visit(consumer: (AbstractNavigation, BoxObject) -> Unit): Unit { listFolders().forEach { consumer(this, it) navigate(it).visit(consumer) diff --git a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt index 12127093..7642dbf0 100644 --- a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt @@ -278,4 +278,6 @@ interface BoxNavigation : ReadableBoxNavigation { @Throws(QblStorageException::class) fun hasVersionChanged(dm: DirectoryMetadata): Boolean + + fun visit(consumer: (AbstractNavigation, BoxObject) -> Unit): Unit } From 21e42397f1f7443b6b8aa7719500c141d64b2b91 Mon Sep 17 00:00:00 2001 From: julianseeger Date: Fri, 30 Sep 2016 15:55:11 +0200 Subject: [PATCH 2/6] moved read methods to ReadableBoxNavigation --- .../qabel/box/storage/AbstractNavigation.kt | 14 +-- .../de/qabel/box/storage/BoxNavigation.kt | 23 ----- .../box/storage/ReadableBoxNavigation.java | 57 ------------ .../box/storage/ReadableBoxNavigation.kt | 92 +++++++++++++++++++ .../box/storage/command/CreateFolderChange.kt | 2 +- ...DirectoryMetadataChange.kt => DMChange.kt} | 4 +- .../box/storage/command/DeleteFileChange.kt | 2 +- .../box/storage/command/DeleteFolderChange.kt | 2 +- .../box/storage/command/DeleteShareChange.kt | 2 +- .../box/storage/command/InsertShareChange.kt | 2 +- .../PostprocessDirectoryMetadataChange.kt | 2 +- .../box/storage/command/UpdateFileChange.kt | 2 +- .../box/storage/dto/DMChangeNotification.kt | 9 ++ .../DirectoryMetadataChangeNotification.kt | 9 -- .../box/storage/AbstractNavigationTest.kt | 6 +- .../de/qabel/box/storage/BoxVolumeTest.kt | 4 +- 16 files changed, 122 insertions(+), 110 deletions(-) delete mode 100644 box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.java create mode 100644 box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt rename box/src/main/java/de/qabel/box/storage/command/{DirectoryMetadataChange.kt => DMChange.kt} (76%) create mode 100644 box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt delete mode 100644 box/src/main/java/de/qabel/box/storage/dto/DirectoryMetadataChangeNotification.kt diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index fdec5dbf..80b5a897 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -4,7 +4,7 @@ import de.qabel.box.storage.cache.BoxNavigationCache import de.qabel.box.storage.cache.CachedFolderNavigationFactory import de.qabel.box.storage.command.* import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DirectoryMetadataChangeNotification +import de.qabel.box.storage.dto.DMChangeNotification import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.box.storage.exceptions.QblStorageInvalidKey import de.qabel.box.storage.exceptions.QblStorageNameConflict @@ -47,9 +47,9 @@ abstract class AbstractNavigation( } protected val cryptoUtils by lazy { CryptoUtils() } - private val pendingChanges = LinkedList>() - override val changes: Subject - = SerializedSubject(PublishSubject()) + private val pendingChanges = LinkedList>() + override val changes: Subject + = SerializedSubject(PublishSubject()) private var autocommit = true private var autocommitDelay = DEFAULT_AUTOCOMMIT_DELAY @@ -242,8 +242,8 @@ abstract class AbstractNavigation( private fun fileAdd(file: BoxFile) = UpdateFileChange(null, file) private fun localFileDelete(file: BoxFile) = DeleteFileChange(file, indexNavigation, writeBackend) - private fun push(change: DirectoryMetadataChange<*>) - = changes.onNext(DirectoryMetadataChangeNotification(change, this)) + private fun push(change: DMChange<*>) + = changes.onNext(DMChangeNotification(change, this)) private fun hashEquals(oneFile: BoxFile, otherFile: BoxFile): Boolean { if (!oneFile.isHashed() || !otherFile.isHashed()) { @@ -560,7 +560,7 @@ abstract class AbstractNavigation( execute(DeleteFolderChange(folder)) } - protected fun execute(command: DirectoryMetadataChange): T { + protected fun execute(command: DMChange): T { val result = command.execute(dm) pendingChanges.add(command) autocommit() diff --git a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt index 7642dbf0..7ea8de69 100644 --- a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt @@ -1,20 +1,14 @@ package de.qabel.box.storage import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DirectoryMetadataChangeNotification import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.core.crypto.QblECPublicKey -import rx.Observable import java.io.File import java.io.IOException import java.io.InputStream import java.security.InvalidKeyException interface BoxNavigation : ReadableBoxNavigation { - /** - * Absolute remote path to this navigation instance. - */ - val path: BoxPath.FolderLike /** * Fetches and returns the remote metadata file. @@ -33,23 +27,6 @@ interface BoxNavigation : ReadableBoxNavigation { @Throws(QblStorageException::class) fun commit() - /** - * Fetch the remote metadata, update the internal metadata with the newly fetched and apply pending changes to it. - * This is like a rebase to remote. - */ - @Throws(QblStorageException::class) - fun refresh() - - /** - * Fetch the remote metadata, update the internal metadata with the newly fetched and apply pending changes to it. - * This is like a rebase to remote. - * @param recursive Boolean if true, refresh subdirectories recursively. Depth- or breadth-first may vary. - */ - @Throws(QblStorageException::class) - fun refresh(recursive: Boolean = false) - - val changes: Observable - /** * commits the DM if it has been changed (uploads or deletes) */ diff --git a/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.java b/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.java deleted file mode 100644 index 659a7266..00000000 --- a/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.qabel.box.storage; - -import de.qabel.box.storage.exceptions.QblStorageException; - -import java.util.List; - -public interface ReadableBoxNavigation { - /** - * Create a new navigation object that starts at another {@link BoxFolder} - * - * @param target Target folder that is a direct subfolder - * @return {@link BoxNavigation} for the subfolder - */ - BoxNavigation navigate(BoxFolder target) throws QblStorageException; - - /** - * Create a new navigation object that starts at another {@link BoxExternal} - * - * @param target Target shared folder that is mounted in the current folder - * @return {@link BoxNavigation} for the external share - */ - BoxNavigation navigate(BoxExternal target); - - /** - * Create a list of all files in the current folder - * - * @return list of files - */ - List listFiles() throws QblStorageException; - - /** - * Create a list of all folders in the current folder - * - * @return list of folders - */ - List listFolders() throws QblStorageException; - - /** - * Create a list of external shares in the current folder - * - * @return list of external shares - */ - List listExternals() throws QblStorageException; - - /** - * Navigate to subfolder by name - */ - BoxNavigation navigate(String folderName) throws QblStorageException; - - BoxFolder getFolder(String name) throws QblStorageException; - - boolean hasFolder(String name) throws QblStorageException; - - BoxFile getFile(String name) throws QblStorageException; - - boolean hasFile(String name) throws QblStorageException; -} diff --git a/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt new file mode 100644 index 00000000..a41cb7e1 --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt @@ -0,0 +1,92 @@ +package de.qabel.box.storage + +import de.qabel.box.storage.dto.BoxPath +import de.qabel.box.storage.dto.DMChangeNotification +import de.qabel.box.storage.exceptions.QblStorageException +import rx.Observable + +interface ReadableBoxNavigation { + /** + * Absolute remote path to this navigation instance. + */ + val path: BoxPath.FolderLike + + val changes: Observable + + /** + * Create a new navigation object that starts at another [BoxFolder] + + * @param target Target folder that is a direct subfolder + * * + * @return [BoxNavigation] for the subfolder + */ + @Throws(QblStorageException::class) + fun navigate(target: BoxFolder): BoxNavigation + + /** + * Create a new navigation object that starts at another [BoxExternal] + + * @param target Target shared folder that is mounted in the current folder + * * + * @return [BoxNavigation] for the external share + */ + fun navigate(target: BoxExternal): BoxNavigation + + /** + * Create a list of all files in the current folder + + * @return list of files + */ + @Throws(QblStorageException::class) + fun listFiles(): List + + /** + * Create a list of all folders in the current folder + + * @return list of folders + */ + @Throws(QblStorageException::class) + fun listFolders(): List + + /** + * Create a list of external shares in the current folder + + * @return list of external shares + */ + @Throws(QblStorageException::class) + fun listExternals(): List + + /** + * Navigate to subfolder by name + */ + @Throws(QblStorageException::class) + fun navigate(folderName: String): BoxNavigation + + @Throws(QblStorageException::class) + fun getFolder(name: String): BoxFolder + + @Throws(QblStorageException::class) + fun hasFolder(name: String): Boolean + + @Throws(QblStorageException::class) + fun getFile(name: String): BoxFile + + @Throws(QblStorageException::class) + fun hasFile(name: String): Boolean + + /** + * Fetch the remote metadata, update the internal metadata with the newly fetched and apply pending changes to it. + * This is like a rebase to remote. + */ + @Throws(QblStorageException::class) + fun refresh() + + /** + * Fetch the remote metadata, update the internal metadata with the newly fetched and apply pending changes to it. + * This is like a rebase to remote. + * @param recursive Boolean if true, refresh subdirectories recursively. Depth- or breadth-first may vary. + */ + @Throws(QblStorageException::class) + fun refresh(recursive: Boolean = false) + +} diff --git a/box/src/main/java/de/qabel/box/storage/command/CreateFolderChange.kt b/box/src/main/java/de/qabel/box/storage/command/CreateFolderChange.kt index 601fc450..6ff7104a 100644 --- a/box/src/main/java/de/qabel/box/storage/command/CreateFolderChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/CreateFolderChange.kt @@ -9,7 +9,7 @@ class CreateFolderChange( val name: String, val navigationFactory: FolderNavigationFactory, val directoryFactory: DirectoryMetadataFactory -) : DirectoryMetadataChange> { +) : DMChange> { private val secretKey: KeyParameter by lazy { CryptoUtils().generateSymmetricKey() } private val result : ChangeResult by lazy { createAndUploadDM() } val folder: BoxFolder diff --git a/box/src/main/java/de/qabel/box/storage/command/DirectoryMetadataChange.kt b/box/src/main/java/de/qabel/box/storage/command/DMChange.kt similarity index 76% rename from box/src/main/java/de/qabel/box/storage/command/DirectoryMetadataChange.kt rename to box/src/main/java/de/qabel/box/storage/command/DMChange.kt index f5007bac..a59131d8 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DirectoryMetadataChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DMChange.kt @@ -7,10 +7,10 @@ import de.qabel.box.storage.exceptions.QblStorageException * If your change needs to be followed by a non-reversible action (like deleting a file on the block server), * let your change operation also implement Postprocessable */ -interface DirectoryMetadataChange { +interface DMChange { @Throws(QblStorageException::class) fun execute(dm: DirectoryMetadata): T } @Throws(QblStorageException::class) -fun List>.execute(dm: DirectoryMetadata) = forEach { it.execute(dm) } +fun List>.execute(dm: DirectoryMetadata) = forEach { it.execute(dm) } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt index 81939fa1..8f5f9a9f 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt @@ -8,7 +8,7 @@ class DeleteFileChange( val file: BoxFile, private val indexNavigation: IndexNavigation, private val writeBackend: StorageWriteBackend -): DirectoryMetadataChange, Postprocessable { +): DMChange, Postprocessable { private val logger by lazy { LoggerFactory.getLogger(DeleteFileChange::class.java) } override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt index 58625499..7de82048 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt @@ -4,7 +4,7 @@ import de.qabel.box.storage.BoxFolder import de.qabel.box.storage.DirectoryMetadata import de.qabel.box.storage.StorageWriteBackend -class DeleteFolderChange(val folder: BoxFolder) : DirectoryMetadataChange, Postprocessable { +class DeleteFolderChange(val folder: BoxFolder) : DMChange, Postprocessable { override fun execute(dm: DirectoryMetadata) = dm.deleteFolder(folder) override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) = writeBackend.delete(folder.ref) } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt index cef4eefc..cbcccba6 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt @@ -3,6 +3,6 @@ package de.qabel.box.storage.command import de.qabel.box.storage.BoxShare import de.qabel.box.storage.DirectoryMetadata -class DeleteShareChange(val share: BoxShare) : DirectoryMetadataChange { +class DeleteShareChange(val share: BoxShare) : DMChange { override fun execute(dm: DirectoryMetadata) = dm.deleteShare(share) } diff --git a/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt index ac8b91cb..f4768069 100644 --- a/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt @@ -3,6 +3,6 @@ package de.qabel.box.storage.command import de.qabel.box.storage.BoxShare import de.qabel.box.storage.DirectoryMetadata -class InsertShareChange(val share: BoxShare) : DirectoryMetadataChange { +class InsertShareChange(val share: BoxShare) : DMChange { override fun execute(dm: DirectoryMetadata) = dm.insertShare(share) } diff --git a/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt b/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt index 81002cdf..a3e32153 100644 --- a/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt @@ -3,7 +3,7 @@ package de.qabel.box.storage.command import de.qabel.box.storage.DirectoryMetadata import de.qabel.box.storage.StorageWriteBackend -fun List>.postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) +fun List>.postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) = filterIsInstance() .forEach { it.postprocess(dm, writeBackend) } diff --git a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt index a15f461d..74c0dca1 100644 --- a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt @@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory open class UpdateFileChange( val expectedFile: BoxFile?, val newFile: BoxFile - ) : DirectoryMetadataChange, Postprocessable { + ) : DMChange, Postprocessable { private val logger by lazy { LoggerFactory.getLogger(UpdateFileChange::class.java) } diff --git a/box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt b/box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt new file mode 100644 index 00000000..a872feb9 --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt @@ -0,0 +1,9 @@ +package de.qabel.box.storage.dto + +import de.qabel.box.storage.BoxNavigation +import de.qabel.box.storage.command.DMChange + +class DMChangeNotification( + val change: DMChange<*>, + val navigation: BoxNavigation +) diff --git a/box/src/main/java/de/qabel/box/storage/dto/DirectoryMetadataChangeNotification.kt b/box/src/main/java/de/qabel/box/storage/dto/DirectoryMetadataChangeNotification.kt deleted file mode 100644 index ce241880..00000000 --- a/box/src/main/java/de/qabel/box/storage/dto/DirectoryMetadataChangeNotification.kt +++ /dev/null @@ -1,9 +0,0 @@ -package de.qabel.box.storage.dto - -import de.qabel.box.storage.BoxNavigation -import de.qabel.box.storage.command.DirectoryMetadataChange - -class DirectoryMetadataChangeNotification( - val change: DirectoryMetadataChange<*>, - val navigation: BoxNavigation -) diff --git a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt index ba96420c..e788c6d3 100644 --- a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt +++ b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt @@ -5,7 +5,7 @@ import com.natpryce.hamkrest.equalTo import com.natpryce.hamkrest.hasSize import de.qabel.box.storage.command.DeleteFileChange import de.qabel.box.storage.command.UpdateFileChange -import de.qabel.box.storage.dto.DirectoryMetadataChangeNotification +import de.qabel.box.storage.dto.DMChangeNotification import de.qabel.box.storage.hash.QabelBoxDigestProvider import de.qabel.box.storage.jdbc.JdbcDirectoryMetadataFactory import de.qabel.core.crypto.CryptoUtils @@ -42,7 +42,7 @@ abstract class AbstractNavigationTest { tmpDir ) abstract val nav: AbstractNavigation - var subscriber = TestSubscriber() + var subscriber = TestSubscriber() @Before open fun setUp() { @@ -71,7 +71,7 @@ abstract class AbstractNavigationTest { @Test fun resubscribe() { - subscriber = TestSubscriber() + subscriber = TestSubscriber() nav.changes.subscribe(subscriber) } diff --git a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt index 36ffa02b..d2015ff1 100644 --- a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt @@ -6,7 +6,7 @@ import de.qabel.box.storage.command.DeleteFileChange import de.qabel.box.storage.command.DeleteFolderChange import de.qabel.box.storage.command.UpdateFileChange import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DirectoryMetadataChangeNotification +import de.qabel.box.storage.dto.DMChangeNotification import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.box.storage.exceptions.QblStorageNameConflict import de.qabel.box.storage.exceptions.QblStorageNotFound @@ -51,7 +51,7 @@ abstract class BoxVolumeTest { private var testFileName = "src/test/java/de/qabel/box/storage/testFile.txt" protected lateinit var contact: Contact protected lateinit var volumeTmpDir: File - val changes = mutableListOf() + val changes = mutableListOf() @Before open fun setUp() { From 1c8dc395dfd2fc9b930feb29399daa12f49a7b02 Mon Sep 17 00:00:00 2001 From: julianseeger Date: Mon, 3 Oct 2016 17:15:05 +0200 Subject: [PATCH 3/6] extracted sharing and unsharing to command --- .../qabel/box/storage/AbstractNavigation.kt | 67 +++++-------------- .../de/qabel/box/storage/BoxNavigation.kt | 25 +------ .../box/storage/DelayedIndexNavigation.kt | 23 +++++++ .../de/qabel/box/storage/DirectoryMetadata.kt | 15 +++-- .../de/qabel/box/storage/IndexNavigation.java | 12 +--- .../java/de/qabel/box/storage/ShareHolder.kt | 10 +++ .../box/storage/command/DeleteFileChange.kt | 38 +++-------- .../box/storage/command/DeleteFolderChange.kt | 4 +- .../box/storage/command/DeleteShareChange.kt | 3 + .../box/storage/command/InsertShareChange.kt | 3 + .../PostprocessDirectoryMetadataChange.kt | 9 ++- .../box/storage/command/Postprocessable.kt | 7 +- .../qabel/box/storage/command/ShareChange.kt | 19 ++++++ .../box/storage/command/UnshareChange.kt | 29 ++++++++ .../box/storage/command/UpdateFileChange.kt | 2 +- .../storage/command/DeleteFileChangeTest.kt | 6 +- .../storage/command/UpdateFileChangeTest.kt | 11 ++- .../qabel/chat/service/MainSharingService.kt | 4 +- 18 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt create mode 100644 box/src/main/java/de/qabel/box/storage/ShareHolder.kt create mode 100644 box/src/main/java/de/qabel/box/storage/command/ShareChange.kt create mode 100644 box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index 80b5a897..5dfefe7f 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -154,10 +154,12 @@ abstract class AbstractNavigation( info("DM conflicted while uploading, will retry merge and upload") } } - pendingChanges.postprocess(dm, writeBackend) + val delayedIndexNavigation = DelayedIndexNavigation(indexNavigation) + pendingChanges.postprocess(dm, writeBackend, delayedIndexNavigation) pendingChanges.clear() originalDm = clone(dm) + delayedIndexNavigation.execute() } @Synchronized @Throws(QblStorageException::class) @@ -240,7 +242,7 @@ abstract class AbstractNavigation( private fun remoteFolderAdd(it: BoxFolder) = CreateFolderChange(this, it.name, folderNavigationFactory, directoryFactory) private fun remoteFolderDelete(it: BoxFolder) = DeleteFolderChange(it) private fun fileAdd(file: BoxFile) = UpdateFileChange(null, file) - private fun localFileDelete(file: BoxFile) = DeleteFileChange(file, indexNavigation, writeBackend) + private fun localFileDelete(file: BoxFile) = DeleteFileChange(file) private fun push(change: DMChange<*>) = changes.onNext(DMChangeNotification(change, this)) @@ -431,7 +433,7 @@ abstract class AbstractNavigation( } @Throws(QblStorageException::class) - override fun createFileMetadata(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference { + fun createFileMetadata(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference { try { if (!boxFile.isShared()) { val block = UUID.randomUUID().toString() @@ -440,24 +442,19 @@ abstract class AbstractNavigation( val fileMetadata = fileFactory.create(owner, boxFile) uploadEncrypted(fileMetadata.path, key, block, null) - - // Overwrite = delete old file, upload new file - val oldFile = dm.getFile(boxFile.getName()) - if (oldFile != null) { - dm.deleteFile(oldFile) - } - dm.insertFile(boxFile) - autocommit() } - return BoxExternalReference(false, readBackend.getUrl(boxFile.meta), boxFile.getName(), owner, boxFile.metakey) + return getExternalReference(owner, boxFile) } catch (e: QblStorageException) { throw QblStorageException("Could not create or upload FileMetadata", e) } + } + override fun getExternalReference(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference { + return BoxExternalReference(false, readBackend.getUrl(boxFile.meta), boxFile.getName(), owner, boxFile.metakey) } @Throws(QblStorageException::class, IOException::class, InvalidKeyException::class) - override fun updateFileMetadata(boxFile: BoxFile) { + fun updateFileMetadata(boxFile: BoxFile) { val shared = boxFile.shared ?: throw QblStorageNotFound("FileMetadata is not set") try { @@ -515,7 +512,7 @@ abstract class AbstractNavigation( } @Synchronized @Throws(QblStorageException::class) - override fun delete(file: BoxFile) = execute(DeleteFileChange(file, indexNavigation, writeBackend)) + override fun delete(file: BoxFile) = execute(DeleteFileChange(file)) @Synchronized @Throws(QblStorageException::class) override fun unshare(boxObject: BoxObject) { @@ -529,21 +526,12 @@ abstract class AbstractNavigation( if (boxObject !is BoxFile) { throw NotImplementedException("unshare not implemented for " + boxObject.javaClass) } - removeFileMetadata(boxObject) - autocommit() + if (!boxObject.isShared()) { + return + } + execute(UnshareChange(boxObject)) } - /** - * Deletes FileMetadata and sets BoxFile.meta and BoxFile.metakey to null. Does not re-encrypt BoxFile thus - * receivers of the FileMetadata can still read the BoxFile. - - * @param boxFile BoxFile to remove FileMetadata from. - * * - * @return True if FileMetadata has been deleted. False if meta information is missing. - */ - @Throws(QblStorageException::class) - protected fun removeFileMetadata(boxFile: BoxFile) = removeFileMetadata(boxFile, writeBackend, dm) - @Synchronized @Throws(QblStorageException::class) override fun delete(folder: BoxFolder) { val folderNav = navigate(folder) @@ -624,15 +612,13 @@ abstract class AbstractNavigation( @Throws(QblStorageException::class) override fun share(owner: QblECPublicKey, file: BoxFile, recipient: String): BoxExternalReference { val ref = createFileMetadata(owner, file) - val share = BoxShare(file.meta, recipient) - indexNavigation.insertShare(share) + execute(ShareChange(file, recipient)) return ref } @Throws(QblStorageException::class) override fun getSharesOf(`object`: BoxObject): List { - return indexNavigation.listShares()?.filter({ share -> share.ref == `object`.ref })?.toList() - ?: throw QblStorageException("No index navigation") + return indexNavigation.listShares().filter({ share -> share.ref == `object`.ref }).toList() } @Throws(QblStorageException::class) @@ -646,24 +632,5 @@ abstract class AbstractNavigation( @JvmField @Deprecated("") var DEFAULT_AUTOCOMMIT_DELAY: Long = 0 - - @Throws(QblStorageException::class) - fun removeFileMetadata(boxFile: BoxFile, writeBackend: StorageWriteBackend, dm: DirectoryMetadata): Boolean { - if (!boxFile.isShared()) { - return false - } - - writeBackend.delete(boxFile.meta!!) - boxFile.shared = null - - // Overwrite = delete old file, upload new file - val oldFile = dm.getFile(boxFile.getName()) - if (oldFile != null) { - dm.deleteFile(oldFile) - } - dm.insertFile(boxFile) - - return true - } } } diff --git a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt index 7ea8de69..6f9b61ef 100644 --- a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt @@ -1,6 +1,5 @@ package de.qabel.box.storage -import de.qabel.box.storage.dto.BoxPath import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.core.crypto.QblECPublicKey import java.io.File @@ -212,28 +211,10 @@ interface BoxNavigation : ReadableBoxNavigation { var metadata: DirectoryMetadata /** - * Creates and uploads a FileMetadata object for a BoxFile. FileMetadata location is written to BoxFile.meta - * and encryption key to BoxFile.metakey. If BoxFile.meta or BoxFile.metakey is not null, BoxFile will not be - * modified and no FileMetadata will be created. - - * @param boxFile BoxFile to create FileMetadata from. - * * - * @return BoxExternalReference if FileMetadata has been successfully created and uploaded. - * * - */ - @Deprecated("should only be called internally (to ensure an index entry)") - @Throws(QblStorageException::class) - fun createFileMetadata(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference - - /** - * Updates and uploads a FileMetadata object for a BoxFile. - - * @param boxFile BoxFile to create FileMetadata from. - * * + * Generates a BoxExternalReference for an already shared boxFile. + * This interface only hides the absolute url generation from the caller. */ - @Deprecated("should only be called internally (on update)") - @Throws(QblStorageException::class, IOException::class, InvalidKeyException::class) - fun updateFileMetadata(boxFile: BoxFile) + fun getExternalReference(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference /** * Makes the BoxFile shareable. Creates FileMetadata for the file and a share entry in the IndexNavigation. diff --git a/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt b/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt new file mode 100644 index 00000000..5474d9a9 --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt @@ -0,0 +1,23 @@ +package de.qabel.box.storage + +class DelayedIndexNavigation(val indexNavigation: IndexNavigation): ShareHolder { + private val insertedShares = mutableListOf() + private val deletedShares = mutableListOf() + + override fun listShares() = indexNavigation.listShares() + + override fun getSharesOf(`object`: BoxObject) = indexNavigation.getSharesOf(`object`) + + override fun insertShare(share: BoxShare) { + insertedShares += share + } + + override fun deleteShare(share: BoxShare) { + deletedShares += share + } + + fun execute() { + insertedShares.forEach { indexNavigation.insertShare(it) } + deletedShares.forEach { indexNavigation.deleteShare(it) } + } +} diff --git a/box/src/main/java/de/qabel/box/storage/DirectoryMetadata.kt b/box/src/main/java/de/qabel/box/storage/DirectoryMetadata.kt index 34177140..b0bb7782 100644 --- a/box/src/main/java/de/qabel/box/storage/DirectoryMetadata.kt +++ b/box/src/main/java/de/qabel/box/storage/DirectoryMetadata.kt @@ -4,6 +4,10 @@ import de.qabel.box.storage.exceptions.QblStorageException import java.io.File interface DirectoryMetadata { + val path: File + val fileName: String + val version: ByteArray + @Throws(QblStorageException::class) fun insertFile(file: BoxFile) @@ -13,6 +17,12 @@ interface DirectoryMetadata { @Throws(QblStorageException::class) fun deleteFile(file: BoxFile) + @Throws(QblStorageException::class) + fun replaceFile(file: BoxFile) { + getFile(file.getName())?.let { deleteFile(it) } + insertFile(file) + } + @Throws(QblStorageException::class) fun deleteFolder(folder: BoxFolder) @@ -40,13 +50,8 @@ interface DirectoryMetadata { @Throws(QblStorageException::class) fun insertShare(share: BoxShare) - val version: ByteArray - @Throws(QblStorageException::class) fun commit() fun listShares(): List - - val path: File - val fileName: String } diff --git a/box/src/main/java/de/qabel/box/storage/IndexNavigation.java b/box/src/main/java/de/qabel/box/storage/IndexNavigation.java index f5e69287..380fa89a 100644 --- a/box/src/main/java/de/qabel/box/storage/IndexNavigation.java +++ b/box/src/main/java/de/qabel/box/storage/IndexNavigation.java @@ -1,13 +1,3 @@ package de.qabel.box.storage; -import de.qabel.box.storage.exceptions.QblStorageException; - -import java.util.List; - -public interface IndexNavigation extends BoxNavigation { - List listShares() throws QblStorageException; - - void insertShare(BoxShare share) throws QblStorageException; - - void deleteShare(BoxShare share) throws QblStorageException; -} +public interface IndexNavigation extends BoxNavigation, ShareHolder {} diff --git a/box/src/main/java/de/qabel/box/storage/ShareHolder.kt b/box/src/main/java/de/qabel/box/storage/ShareHolder.kt new file mode 100644 index 00000000..733bfba7 --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/ShareHolder.kt @@ -0,0 +1,10 @@ +package de.qabel.box.storage + +import de.qabel.box.storage.exceptions.QblStorageException + +interface ShareHolder { + @Throws(QblStorageException::class) fun listShares(): List + @Throws(QblStorageException::class) fun insertShare(share: BoxShare) + @Throws(QblStorageException::class) fun deleteShare(share: BoxShare) + @Throws(QblStorageException::class) fun getSharesOf(`object`: BoxObject): List +} diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt index 8f5f9a9f..a01237af 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt @@ -1,40 +1,22 @@ package de.qabel.box.storage.command -import de.qabel.box.storage.* -import de.qabel.box.storage.exceptions.QblStorageException -import org.slf4j.LoggerFactory - -class DeleteFileChange( - val file: BoxFile, - private val indexNavigation: IndexNavigation, - private val writeBackend: StorageWriteBackend -): DMChange, Postprocessable { - private val logger by lazy { LoggerFactory.getLogger(DeleteFileChange::class.java) } - - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) - = writeBackend.deleteBlock(file.block) +import de.qabel.box.storage.BoxFile +import de.qabel.box.storage.DirectoryMetadata +import de.qabel.box.storage.ShareHolder +import de.qabel.box.storage.StorageWriteBackend +class DeleteFileChange(val file: BoxFile): DMChange, Postprocessable { override fun execute(dm: DirectoryMetadata) { if (dm.hasFile(file.name)) { dm.deleteFile(file) } - - if (file.isShared()) { - removeSharesFromIndex() - removeFileMetadata(dm) - } } - private fun removeFileMetadata(dm: DirectoryMetadata) - = AbstractNavigation.removeFileMetadata(file, writeBackend, dm) - - private fun removeSharesFromIndex() { - indexNavigation.getSharesOf(file).forEach { share -> - try { - indexNavigation.deleteShare(share) - } catch (e: QblStorageException) { - logger.error("failed to delete share from indexNavigation: " + e.message, e) - } + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { + writeBackend.deleteBlock(file.block) + if (file.isShared()) { + UnshareChange(file).postprocess(dm, writeBackend, indexNavigation) + file.shared = null } } } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt index 7de82048..129fcb4b 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt @@ -2,9 +2,11 @@ package de.qabel.box.storage.command import de.qabel.box.storage.BoxFolder import de.qabel.box.storage.DirectoryMetadata +import de.qabel.box.storage.ShareHolder import de.qabel.box.storage.StorageWriteBackend class DeleteFolderChange(val folder: BoxFolder) : DMChange, Postprocessable { override fun execute(dm: DirectoryMetadata) = dm.deleteFolder(folder) - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) = writeBackend.delete(folder.ref) + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) + = writeBackend.delete(folder.ref) } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt index cbcccba6..46eb18e3 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteShareChange.kt @@ -3,6 +3,9 @@ package de.qabel.box.storage.command import de.qabel.box.storage.BoxShare import de.qabel.box.storage.DirectoryMetadata +/** + * Deletes the share from the IndexNavigations dm + */ class DeleteShareChange(val share: BoxShare) : DMChange { override fun execute(dm: DirectoryMetadata) = dm.deleteShare(share) } diff --git a/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt index f4768069..969e3200 100644 --- a/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/InsertShareChange.kt @@ -3,6 +3,9 @@ package de.qabel.box.storage.command import de.qabel.box.storage.BoxShare import de.qabel.box.storage.DirectoryMetadata +/** + * Inserts the share into the IndexNavigations dm + */ class InsertShareChange(val share: BoxShare) : DMChange { override fun execute(dm: DirectoryMetadata) = dm.insertShare(share) } diff --git a/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt b/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt index a3e32153..f8aa489f 100644 --- a/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/PostprocessDirectoryMetadataChange.kt @@ -1,10 +1,13 @@ package de.qabel.box.storage.command import de.qabel.box.storage.DirectoryMetadata +import de.qabel.box.storage.ShareHolder import de.qabel.box.storage.StorageWriteBackend -fun List>.postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) - = filterIsInstance() - .forEach { it.postprocess(dm, writeBackend) } +fun List>.postprocess( + dm: DirectoryMetadata, + writeBackend: StorageWriteBackend, + indexNavigation: ShareHolder +) = filterIsInstance().forEach { it.postprocess(dm, writeBackend, indexNavigation) } fun StorageWriteBackend.deleteBlock(blockReference: String) = delete("blocks/" + blockReference) diff --git a/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt b/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt index 9a5e50d4..2c4002b9 100644 --- a/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt +++ b/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt @@ -1,10 +1,15 @@ package de.qabel.box.storage.command import de.qabel.box.storage.DirectoryMetadata +import de.qabel.box.storage.ShareHolder import de.qabel.box.storage.StorageWriteBackend import de.qabel.box.storage.exceptions.QblStorageException interface Postprocessable { @Throws(QblStorageException::class) - fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) + fun postprocess( + dm: DirectoryMetadata, + writeBackend: StorageWriteBackend, + indexNavigation: ShareHolder + ) } diff --git a/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt new file mode 100644 index 00000000..d7b4c3c4 --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt @@ -0,0 +1,19 @@ +package de.qabel.box.storage.command + +import de.qabel.box.storage.* + +class ShareChange( + val file: BoxFile, + val recipient: String +): DMChange, Postprocessable { + val meta = file.shared?.meta ?: throw IllegalArgumentException("cannot share file without file metadata") + val share: BoxShare by lazy { BoxShare(meta, recipient) } + + override fun execute(dm: DirectoryMetadata) { + dm.replaceFile(file) // replace file entry to update file metadata reference + } + + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { + indexNavigation.insertShare(BoxShare(file.ref, recipient)) + } +} diff --git a/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt new file mode 100644 index 00000000..5c3c935e --- /dev/null +++ b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt @@ -0,0 +1,29 @@ +package de.qabel.box.storage.command + +import de.qabel.box.storage.BoxFile +import de.qabel.box.storage.DirectoryMetadata +import de.qabel.box.storage.ShareHolder +import de.qabel.box.storage.StorageWriteBackend +import de.qabel.box.storage.exceptions.QblStorageException +import de.qabel.core.logging.QabelLog + +class UnshareChange(val file: BoxFile) : DMChange, Postprocessable, QabelLog { + val oldMeta = file.shared?.meta ?: throw IllegalArgumentException("cannot unshare file without share") + + override fun execute(dm: DirectoryMetadata) { + file.shared = null + dm.replaceFile(file) // replace file entry to update file metadata reference + } + + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { + indexNavigation.getSharesOf(file).forEach { share -> + try { + indexNavigation.deleteShare(share) + } catch (e: QblStorageException) { + error(e.message, e) + } + } + + writeBackend.delete(oldMeta) + } +} diff --git a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt index 74c0dca1..82ec1b5a 100644 --- a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt @@ -15,7 +15,7 @@ open class UpdateFileChange( private fun hasSameHash(obj: BoxObject) = obj is BoxFile && obj.isHashed() && obj.hashed == newFile.hashed - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend) { + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { if (sameFileByHash) { writeBackend.deleteBlock(newFile.block) } diff --git a/box/src/test/java/de/qabel/box/storage/command/DeleteFileChangeTest.kt b/box/src/test/java/de/qabel/box/storage/command/DeleteFileChangeTest.kt index 45505ddb..493a4939 100644 --- a/box/src/test/java/de/qabel/box/storage/command/DeleteFileChangeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/command/DeleteFileChangeTest.kt @@ -18,18 +18,18 @@ class DeleteFileChangeTest { val indexNavigation: IndexNavigation = mock() @Test - fun ignoresAlreadyDeletedFiles() = DeleteFileChange(file, indexNavigation, writeBackend).execute(dm) + fun ignoresAlreadyDeletedFiles() = DeleteFileChange(file).execute(dm) @Test fun deletesExistingFile() { dm.insertFile(file) writeBackend.upload("blocks/${file.block}", ByteArrayInputStream("content".toByteArray())) - val change = DeleteFileChange(file, indexNavigation, writeBackend) + val change = DeleteFileChange(file) change.execute(dm) assertThat(dm.hasFile(file.name), equalTo(false)) - change.postprocess(dm, writeBackend) + change.postprocess(dm, writeBackend, indexNavigation) assertThrows(QblStorageNotFound::class) { readBackend.download("blocks/${file.block}") } diff --git a/box/src/test/java/de/qabel/box/storage/command/UpdateFileChangeTest.kt b/box/src/test/java/de/qabel/box/storage/command/UpdateFileChangeTest.kt index a6db5f42..bb5fbd81 100644 --- a/box/src/test/java/de/qabel/box/storage/command/UpdateFileChangeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/command/UpdateFileChangeTest.kt @@ -1,9 +1,7 @@ package de.qabel.box.storage.command -import de.qabel.box.storage.BoxFile -import de.qabel.box.storage.InMemoryDirectoryMetadata -import de.qabel.box.storage.LocalWriteBackend -import de.qabel.box.storage.StorageWriteBackend +import com.nhaarman.mockito_kotlin.mock +import de.qabel.box.storage.* import org.hamcrest.Matchers.* import org.junit.Assert.* import org.junit.Before @@ -17,6 +15,7 @@ class UpdateFileChangeTest { val anotherFile = BoxFile("p", "block3", "filename", 999, 666, ByteArray(0)) val anotherConflictFile = BoxFile("p", "block4", "filename_conflict", 999, 666, ByteArray(0)) val writeBackend = LocalWriteBackend(createTempDir().toPath()) + val indexNavigation: IndexNavigation = mock() @Before fun setUp() { @@ -81,7 +80,7 @@ class UpdateFileChangeTest { } val change = UpdateFileChange(null, file) change.execute(dm) - change.postprocess(dm, backend) + change.postprocess(dm, backend, mock()) assertNotEquals("Block was deleted", "blocks/" + file.block, deleted) assertNotEquals("Block was deleted", "blocks/" + hashedFile.block, deleted) } @@ -102,7 +101,7 @@ class UpdateFileChangeTest { val change = UpdateFileChange(null, hashedFile) change.execute(dm) - change.postprocess(dm, backend) + change.postprocess(dm, backend, mock()) assertEquals("Block was not deleted", "blocks/" + hashedFile.block, deleted) assertThat(dm.listFiles(), allOf(containsInAnyOrder(hashedFile), hasSize(1))) diff --git a/chat/src/main/java/de/qabel/chat/service/MainSharingService.kt b/chat/src/main/java/de/qabel/chat/service/MainSharingService.kt index 61f716e3..e69b3032 100644 --- a/chat/src/main/java/de/qabel/chat/service/MainSharingService.kt +++ b/chat/src/main/java/de/qabel/chat/service/MainSharingService.kt @@ -3,7 +3,6 @@ package de.qabel.chat.service import de.qabel.box.storage.* import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.box.storage.exceptions.QblStorageNotFound -import de.qabel.box.storage.jdbc.JdbcFileMetadataFactory import de.qabel.chat.repository.ChatShareRepository import de.qabel.chat.repository.entities.BoxFileChatShare import de.qabel.chat.repository.entities.ChatDropMessage @@ -30,8 +29,7 @@ class MainSharingService(private val chatShareRepository: ChatShareRepository, override fun getOrCreateOutgoingShare(identity: Identity, contact: Contact, boxFile: BoxFile, boxNavigation: BoxNavigation): BoxFileChatShare = (boxNavigation.getSharesOf(boxFile).find { it.recipient == contact.keyIdentifier }?.let { - //TODO May find other way to create reference obj - boxNavigation.createFileMetadata(identity.ecPublicKey, boxFile) + boxNavigation.getExternalReference(identity.ecPublicKey, boxFile) } ?: boxNavigation.share(identity.ecPublicKey, boxFile, contact.keyIdentifier)).let { chatShareRepository.findByBoxReference(identity, it.url, it.key) ?: createNewBoxFileShare(it, boxFile, identity, ShareStatus.CREATED).apply { From 9196e790825bd185349661af522c0b6fb5958aae Mon Sep 17 00:00:00 2001 From: julianseeger Date: Mon, 3 Oct 2016 18:16:02 +0200 Subject: [PATCH 4/6] AbstractNavigation pushes share events --- .../qabel/box/storage/AbstractNavigation.kt | 18 +++++++-- .../qabel/box/storage/command/ShareChange.kt | 2 +- .../box/storage/command/UnshareChange.kt | 6 ++- .../box/storage/AbstractNavigationTest.kt | 38 +++++++++++++++++-- .../de/qabel/box/storage/BoxVolumeTest.kt | 1 + .../de/qabel/box/storage/StubReadBackend.kt | 2 +- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index 5dfefe7f..fdcefd1e 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -233,6 +233,18 @@ abstract class AbstractNavigation( .filter { originalDm.hasFile(it.name) && !hashEquals(originalDm.getFile(it.name)!!, it) } .map { fileChange(it) } .forEach { push(it) } + + // detect new shared files + newDm.listFiles() + .filter { it.isShared() && !(originalDm.getFile(it.name)?.isShared() ?: true) } + .map { shareChange(it) } + .forEach { push(it) } + + // detect unshared files + newDm.listFiles() + .filter { !it.isShared() && originalDm.getFile(it.name)?.isShared() ?: false } + .map { unshareChange(it) } + .forEach { push(it) } } private fun fileChange(file: BoxFile) = UpdateFileChange( @@ -243,9 +255,10 @@ abstract class AbstractNavigation( private fun remoteFolderDelete(it: BoxFolder) = DeleteFolderChange(it) private fun fileAdd(file: BoxFile) = UpdateFileChange(null, file) private fun localFileDelete(file: BoxFile) = DeleteFileChange(file) + private fun shareChange(file: BoxFile) = ShareChange(file, "") + private fun unshareChange(file: BoxFile) = UnshareChange(file) - private fun push(change: DMChange<*>) - = changes.onNext(DMChangeNotification(change, this)) + private fun push(change: DMChange<*>) = changes.onNext(DMChangeNotification(change, this)) private fun hashEquals(oneFile: BoxFile, otherFile: BoxFile): Boolean { if (!oneFile.isHashed() || !otherFile.isHashed()) { @@ -429,7 +442,6 @@ abstract class AbstractNavigation( } catch (e: InvalidKeyException) { throw QblStorageException(e) } - } @Throws(QblStorageException::class) diff --git a/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt index d7b4c3c4..d9e8db35 100644 --- a/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt @@ -14,6 +14,6 @@ class ShareChange( } override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { - indexNavigation.insertShare(BoxShare(file.ref, recipient)) + indexNavigation.insertShare(share) } } diff --git a/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt index 5c3c935e..d502a562 100644 --- a/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt @@ -8,9 +8,11 @@ import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.core.logging.QabelLog class UnshareChange(val file: BoxFile) : DMChange, Postprocessable, QabelLog { - val oldMeta = file.shared?.meta ?: throw IllegalArgumentException("cannot unshare file without share") - + val oldMeta by lazy { + file.shared?.meta ?: throw IllegalArgumentException("cannot unshare file without share") + } override fun execute(dm: DirectoryMetadata) { + oldMeta file.shared = null dm.replaceFile(file) // replace file entry to update file metadata reference } diff --git a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt index e788c6d3..f34616b4 100644 --- a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt +++ b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt @@ -4,12 +4,15 @@ import com.natpryce.hamkrest.assertion.assertThat import com.natpryce.hamkrest.equalTo import com.natpryce.hamkrest.hasSize import de.qabel.box.storage.command.DeleteFileChange +import de.qabel.box.storage.command.ShareChange +import de.qabel.box.storage.command.UnshareChange import de.qabel.box.storage.command.UpdateFileChange import de.qabel.box.storage.dto.DMChangeNotification import de.qabel.box.storage.hash.QabelBoxDigestProvider import de.qabel.box.storage.jdbc.JdbcDirectoryMetadataFactory import de.qabel.core.crypto.CryptoUtils import de.qabel.core.crypto.QblECKeyPair +import de.qabel.core.extensions.letApply import org.junit.Assert.* import org.junit.Before import org.junit.Test @@ -51,7 +54,7 @@ abstract class AbstractNavigationTest { @Test fun notifiesAboutFileCreates() { - nav.upload("test", ByteArrayInputStream("content".toByteArray()), 7) + upload("test") assertChange(UpdateFileChange::class.java) { assertEquals("test", newFile.name) assertNull(expectedFile) @@ -60,7 +63,7 @@ abstract class AbstractNavigationTest { @Test fun notifiesAboutFileDeletes() { - val file = nav.upload("test", ByteArrayInputStream("content".toByteArray()), 7) + val file = upload("test") resubscribe() nav.delete(file) @@ -69,6 +72,35 @@ abstract class AbstractNavigationTest { } } + private fun upload(filename: String) = nav.upload(filename, ByteArrayInputStream("content".toByteArray()), 7) + + @Test + fun notifiesAboutShares() { + upload("test").letApply { + resubscribe() + nav.share(keyPair.pub, it, "recipient") + } + + assertChange(ShareChange::class.java) { + assertEquals("test", file.name) + assertTrue(file.isShared()) + } + } + + @Test + fun notifiesAboutUnshares() { + upload("test").letApply { + nav.share(keyPair.pub, it, "recipient") + resubscribe() + nav.unshare(it) + } + + assertChange(UnshareChange::class.java) { + assertEquals("test", file.name) + assertFalse(file.isShared()) + } + } + @Test fun resubscribe() { subscriber = TestSubscriber() @@ -77,7 +109,7 @@ abstract class AbstractNavigationTest { fun assertChange(clazz: Class, block: T.() -> Unit) : T { val changes = subscriber.onNextEvents - assertThat(changes, hasSize(equalTo(1))) + assertThat("no event happend, but expecting one", changes, hasSize(equalTo(1))) val change = changes.first().change if (!clazz.isInstance(change)) { diff --git a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt index d2015ff1..49eed035 100644 --- a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt @@ -517,6 +517,7 @@ abstract class BoxVolumeTest { val file = File(testFileName) val boxFile = nav.upload("file1", file) nav.share(keyPair.pub, boxFile, contact.keyIdentifier) + assertTrue(boxFile.isShared()) val nav2 = volume2.navigate() val boxFile2 = nav2.getFile("file1") diff --git a/box/src/test/java/de/qabel/box/storage/StubReadBackend.kt b/box/src/test/java/de/qabel/box/storage/StubReadBackend.kt index b4e209dc..cfae893b 100644 --- a/box/src/test/java/de/qabel/box/storage/StubReadBackend.kt +++ b/box/src/test/java/de/qabel/box/storage/StubReadBackend.kt @@ -16,7 +16,7 @@ class StubReadBackend : StorageReadBackend, QabelLog { override fun download(name: String?, ifModifiedVersion: String?) = download(name) - override fun getUrl(meta: String?): String = throw UnsupportedOperationException("not implemented") + override fun getUrl(meta: String?): String = "http://some.url/" + meta override fun download(name: String?): StorageDownload { debug("downloading $name") From 6af5fcb7bbcc19deacb8caee38f0df34f1aeaf8f Mon Sep 17 00:00:00 2001 From: julianseeger Date: Tue, 4 Oct 2016 18:04:58 +0200 Subject: [PATCH 5/6] merge indexNavigation to current changes on commit --- .../qabel/box/storage/AbstractNavigation.kt | 28 ++++++++++++++----- .../de/qabel/box/storage/BoxVolumeTest.kt | 26 +++++++++++++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index fdcefd1e..1234c7ce 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -25,6 +25,7 @@ import java.security.MessageDigest import java.util.* import java.util.concurrent.Executors import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean abstract class AbstractNavigation( override val path: BoxPath.FolderLike, @@ -47,7 +48,8 @@ abstract class AbstractNavigation( } protected val cryptoUtils by lazy { CryptoUtils() } - private val pendingChanges = LinkedList>() + private var pendingChanges: List> = emptyList() + private val committing = AtomicBoolean(false) override val changes: Subject = SerializedSubject(PublishSubject()) @@ -124,6 +126,19 @@ abstract class AbstractNavigation( @Synchronized @Throws(QblStorageException::class) override fun commit() { + if (!committing.compareAndSet(false, true)) { + return + } + do { + val commitChanges = pendingChanges + pendingChanges = emptyList() + + commit(commitChanges) + } while (!pendingChanges.isEmpty()) + committing.set(false) + } + + private fun commit(changes: List>) { val version = dm.version dm.commit() info("Committing version " + String(Hex.encodeHex(dm.version)) @@ -144,7 +159,7 @@ abstract class AbstractNavigation( // ignore our local directory metadata // all changes that are not inserted in the new dm are _lost_! dm = updatedDM - pendingChanges.execute(dm) + changes.execute(dm) dm.commit() } try { @@ -154,12 +169,9 @@ abstract class AbstractNavigation( info("DM conflicted while uploading, will retry merge and upload") } } - val delayedIndexNavigation = DelayedIndexNavigation(indexNavigation) - pendingChanges.postprocess(dm, writeBackend, delayedIndexNavigation) + changes.postprocess(dm, writeBackend, indexNavigation) - pendingChanges.clear() originalDm = clone(dm) - delayedIndexNavigation.execute() } @Synchronized @Throws(QblStorageException::class) @@ -560,9 +572,11 @@ abstract class AbstractNavigation( execute(DeleteFolderChange(folder)) } + @Synchronized protected fun execute(command: DMChange): T { val result = command.execute(dm) - pendingChanges.add(command) + pendingChanges += command + autocommit() return result } diff --git a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt index 49eed035..424f63ce 100644 --- a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt @@ -385,7 +385,7 @@ abstract class BoxVolumeTest { assertThat(nav.listFolders().size, `is`(2)) } - private fun setupConflictNav1(): BoxNavigation { + private fun setupConflictNav1(): IndexNavigation { val nav = volume.navigate() nav.setAutocommit(false) return nav @@ -505,7 +505,29 @@ abstract class BoxVolumeTest { assertThat(nav.listFiles()[0].name, equalTo("foobar")) } - private fun setupConflictNav2(): BoxNavigation { + @Test + open fun testResolvesConflictsWhileCommittingShare() { + val (nav1, nav2) = setupConflictNavs() + val file = File(testFileName) + val boxFile = nav1.upload(DEFAULT_UPLOAD_FILENAME, file) + nav1.commit() + nav2.refresh() + + nav1.share(keyPair.pub, boxFile, "recipient") + nav2.apply { createFolder("just some conflict") }.commit() + nav1.commit() + + nav2.refresh() + assertThat(nav2.listShares(), hasSize(1)) + with (nav2.getFile(DEFAULT_UPLOAD_FILENAME)) { + assertThat(this.isShared(), equalTo(true)) + assertThat(nav2.getSharesOf(this), hasSize(1)) + } + } + + private fun setupConflictNavs() = Pair(setupConflictNav1(), setupConflictNav2()) + + private fun setupConflictNav2(): IndexNavigation { val nav2 = volume2.navigate() nav2.setAutocommit(false) return nav2 From f99709c012f5730f0f9f70f530c6f79dfba8190d Mon Sep 17 00:00:00 2001 From: julianseeger Date: Fri, 7 Oct 2016 12:58:32 +0200 Subject: [PATCH 6/6] #624 cleanup --- .../qabel/box/storage/AbstractNavigation.kt | 33 ++++++++----------- .../de/qabel/box/storage/BoxNavigation.kt | 28 ++++------------ .../box/storage/DelayedIndexNavigation.kt | 2 +- .../box/storage/ReadableBoxNavigation.kt | 12 +++---- .../java/de/qabel/box/storage/ShareHolder.kt | 2 +- .../box/storage/command/DeleteFileChange.kt | 4 +-- .../box/storage/command/DeleteFolderChange.kt | 2 +- .../box/storage/command/Postprocessable.kt | 2 +- .../qabel/box/storage/command/ShareChange.kt | 4 +-- .../box/storage/command/UnshareChange.kt | 6 ++-- .../box/storage/command/UpdateFileChange.kt | 2 +- ...ChangeNotification.kt => DMChangeEvent.kt} | 2 +- .../box/storage/AbstractNavigationTest.kt | 6 ++-- .../de/qabel/box/storage/BoxVolumeTest.kt | 4 +-- 14 files changed, 43 insertions(+), 66 deletions(-) rename box/src/main/java/de/qabel/box/storage/dto/{DMChangeNotification.kt => DMChangeEvent.kt} (86%) diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index 1234c7ce..ab540fd1 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -4,7 +4,7 @@ import de.qabel.box.storage.cache.BoxNavigationCache import de.qabel.box.storage.cache.CachedFolderNavigationFactory import de.qabel.box.storage.command.* import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DMChangeNotification +import de.qabel.box.storage.dto.DMChangeEvent import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.box.storage.exceptions.QblStorageInvalidKey import de.qabel.box.storage.exceptions.QblStorageNameConflict @@ -50,8 +50,8 @@ abstract class AbstractNavigation( private var pendingChanges: List> = emptyList() private val committing = AtomicBoolean(false) - override val changes: Subject - = SerializedSubject(PublishSubject()) + override val changes: Subject + = SerializedSubject(PublishSubject()) private var autocommit = true private var autocommitDelay = DEFAULT_AUTOCOMMIT_DELAY @@ -270,7 +270,7 @@ abstract class AbstractNavigation( private fun shareChange(file: BoxFile) = ShareChange(file, "") private fun unshareChange(file: BoxFile) = UnshareChange(file) - private fun push(change: DMChange<*>) = changes.onNext(DMChangeNotification(change, this)) + private fun push(change: DMChange<*>) = changes.onNext(DMChangeEvent(change, this)) private fun hashEquals(oneFile: BoxFile, otherFile: BoxFile): Boolean { if (!oneFile.isHashed() || !otherFile.isHashed()) { @@ -286,7 +286,7 @@ abstract class AbstractNavigation( @Throws(QblStorageException::class) protected abstract fun uploadDirectoryMetadata() - override fun navigate(target: BoxExternal): BoxNavigation = TODO() + override fun navigate(target: BoxExternalFolder): BoxNavigation = TODO() @Throws(QblStorageException::class) override fun listFiles(): List { @@ -473,9 +473,8 @@ abstract class AbstractNavigation( } } - override fun getExternalReference(owner: QblECPublicKey, boxFile: BoxFile): BoxExternalReference { - return BoxExternalReference(false, readBackend.getUrl(boxFile.meta), boxFile.getName(), owner, boxFile.metakey) - } + override fun getExternalReference(owner: QblECPublicKey, boxFile: BoxFile) + = BoxExternalReference(false, readBackend.getUrl(boxFile.meta), boxFile.getName(), owner, boxFile.metakey) @Throws(QblStorageException::class, IOException::class, InvalidKeyException::class) fun updateFileMetadata(boxFile: BoxFile) { @@ -540,20 +539,14 @@ abstract class AbstractNavigation( @Synchronized @Throws(QblStorageException::class) override fun unshare(boxObject: BoxObject) { - indexNavigation.getSharesOf(boxObject).forEach { share -> - try { - indexNavigation.deleteShare(share) - } catch (e: QblStorageException) { - error(e.message, e) - } - } if (boxObject !is BoxFile) { throw NotImplementedException("unshare not implemented for " + boxObject.javaClass) } - if (!boxObject.isShared()) { - return + if (boxObject.isShared()) { + execute(UnshareChange(boxObject)) + } else { + warn("unable to unshare ${boxObject.name} because it is not shared") } - execute(UnshareChange(boxObject)) } @Synchronized @Throws(QblStorageException::class) @@ -643,8 +636,8 @@ abstract class AbstractNavigation( } @Throws(QblStorageException::class) - override fun getSharesOf(`object`: BoxObject): List { - return indexNavigation.listShares().filter({ share -> share.ref == `object`.ref }).toList() + override fun getSharesOf(boxObject: BoxObject): List { + return indexNavigation.listShares().filter({ share -> share.ref == boxObject.ref }).toList() } @Throws(QblStorageException::class) diff --git a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt index 6f9b61ef..bf638c23 100644 --- a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt @@ -19,7 +19,6 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Bumps the version and uploads the metadata file * - * * All actions are not guaranteed to be finished before the commit * method returned. */ @@ -34,13 +33,10 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Upload a new file to the current folder - + * * @param name name of the file, must be unique - * * * @param file file object that must be readable - * * * @return the resulting BoxFile object - * * * @throws QblStorageException if the upload failed or the name is not unique */ @Throws(QblStorageException::class) @@ -48,13 +44,10 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Upload a new file to the current folder - + * * @param name name of the file, must be unique - * * * @param file file object that must be readable - * * * @return the resulting BoxFile object - * * * @throws QblStorageException if the upload failed or the name is not unique */ @Throws(QblStorageException::class) @@ -62,15 +55,11 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Upload a new file to the current folder - + * * @param name name of the file, must be unique - * * * @param file stream with contents of the file - * * * @param size size of the file (of the fully read stream) - * * * @return the resulting BoxFile object - * * * @throws QblStorageException if the upload failed or the name is not unique */ @Throws(QblStorageException::class) @@ -78,13 +67,10 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Upload a new file to the current folder - + * * @param name name of the file, must be unique - * * * @param file stream with contents of the file - * * * @param size size of the file (of the fully read stream) - * * * @return the resulting BoxFile object * * * @throws QblStorageException if the upload failed or the name is not unique @@ -203,7 +189,7 @@ interface BoxNavigation : ReadableBoxNavigation { /** * Sets the delay between actions and an automated commit. * Requires autocommit=true - + * * @param delay in milliseconds */ fun setAutocommitDelay(delay: Long) @@ -220,9 +206,7 @@ interface BoxNavigation : ReadableBoxNavigation { * Makes the BoxFile shareable. Creates FileMetadata for the file and a share entry in the IndexNavigation. * @param owner owner of the share - * * * @param file file to share - * * * @param recipient KeyId of the recipients (Contact) public key */ @Throws(QblStorageException::class) @@ -232,7 +216,7 @@ interface BoxNavigation : ReadableBoxNavigation { * List all created (and not yet deleted) shares for the given BoxObject */ @Throws(QblStorageException::class) - fun getSharesOf(`object`: BoxObject): List + fun getSharesOf(boxObject: BoxObject): List @Throws(QblStorageException::class) fun hasVersionChanged(dm: DirectoryMetadata): Boolean diff --git a/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt b/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt index 5474d9a9..f910147b 100644 --- a/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/DelayedIndexNavigation.kt @@ -6,7 +6,7 @@ class DelayedIndexNavigation(val indexNavigation: IndexNavigation): ShareHolder override fun listShares() = indexNavigation.listShares() - override fun getSharesOf(`object`: BoxObject) = indexNavigation.getSharesOf(`object`) + override fun getSharesOf(boxObject: BoxObject) = indexNavigation.getSharesOf(boxObject) override fun insertShare(share: BoxShare) { insertedShares += share diff --git a/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt index a41cb7e1..5a0f41c0 100644 --- a/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/ReadableBoxNavigation.kt @@ -1,7 +1,7 @@ package de.qabel.box.storage import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DMChangeNotification +import de.qabel.box.storage.dto.DMChangeEvent import de.qabel.box.storage.exceptions.QblStorageException import rx.Observable @@ -11,12 +11,12 @@ interface ReadableBoxNavigation { */ val path: BoxPath.FolderLike - val changes: Observable + val changes: Observable /** * Create a new navigation object that starts at another [BoxFolder] - * @param target Target folder that is a direct subfolder + * @param target folder that is a direct subfolder * * * @return [BoxNavigation] for the subfolder */ @@ -24,13 +24,13 @@ interface ReadableBoxNavigation { fun navigate(target: BoxFolder): BoxNavigation /** - * Create a new navigation object that starts at another [BoxExternal] + * Create a new navigation object that starts at another [BoxExternalFolder] - * @param target Target shared folder that is mounted in the current folder + * @param target shared folder that is mounted in the current folder * * * @return [BoxNavigation] for the external share */ - fun navigate(target: BoxExternal): BoxNavigation + fun navigate(target: BoxExternalFolder): BoxNavigation /** * Create a list of all files in the current folder diff --git a/box/src/main/java/de/qabel/box/storage/ShareHolder.kt b/box/src/main/java/de/qabel/box/storage/ShareHolder.kt index 733bfba7..d5380051 100644 --- a/box/src/main/java/de/qabel/box/storage/ShareHolder.kt +++ b/box/src/main/java/de/qabel/box/storage/ShareHolder.kt @@ -6,5 +6,5 @@ interface ShareHolder { @Throws(QblStorageException::class) fun listShares(): List @Throws(QblStorageException::class) fun insertShare(share: BoxShare) @Throws(QblStorageException::class) fun deleteShare(share: BoxShare) - @Throws(QblStorageException::class) fun getSharesOf(`object`: BoxObject): List + @Throws(QblStorageException::class) fun getSharesOf(boxObject: BoxObject): List } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt index a01237af..bc6f49ca 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFileChange.kt @@ -12,10 +12,10 @@ class DeleteFileChange(val file: BoxFile): DMChange, Postprocessable { } } - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, shares: ShareHolder) { writeBackend.deleteBlock(file.block) if (file.isShared()) { - UnshareChange(file).postprocess(dm, writeBackend, indexNavigation) + UnshareChange(file).postprocess(dm, writeBackend, shares) file.shared = null } } diff --git a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt index 129fcb4b..5881f8e5 100644 --- a/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/DeleteFolderChange.kt @@ -7,6 +7,6 @@ import de.qabel.box.storage.StorageWriteBackend class DeleteFolderChange(val folder: BoxFolder) : DMChange, Postprocessable { override fun execute(dm: DirectoryMetadata) = dm.deleteFolder(folder) - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, shares: ShareHolder) = writeBackend.delete(folder.ref) } diff --git a/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt b/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt index 2c4002b9..b8105629 100644 --- a/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt +++ b/box/src/main/java/de/qabel/box/storage/command/Postprocessable.kt @@ -10,6 +10,6 @@ interface Postprocessable { fun postprocess( dm: DirectoryMetadata, writeBackend: StorageWriteBackend, - indexNavigation: ShareHolder + shares: ShareHolder ) } diff --git a/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt index d9e8db35..a191a76e 100644 --- a/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/ShareChange.kt @@ -13,7 +13,7 @@ class ShareChange( dm.replaceFile(file) // replace file entry to update file metadata reference } - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { - indexNavigation.insertShare(share) + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, shares: ShareHolder) { + shares.insertShare(share) } } diff --git a/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt index d502a562..d1f74aed 100644 --- a/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/UnshareChange.kt @@ -17,10 +17,10 @@ class UnshareChange(val file: BoxFile) : DMChange, Postprocessable, QabelL dm.replaceFile(file) // replace file entry to update file metadata reference } - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { - indexNavigation.getSharesOf(file).forEach { share -> + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, shares: ShareHolder) { + shares.getSharesOf(file).forEach { share -> try { - indexNavigation.deleteShare(share) + shares.deleteShare(share) } catch (e: QblStorageException) { error(e.message, e) } diff --git a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt index 82ec1b5a..db06f37a 100644 --- a/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt +++ b/box/src/main/java/de/qabel/box/storage/command/UpdateFileChange.kt @@ -15,7 +15,7 @@ open class UpdateFileChange( private fun hasSameHash(obj: BoxObject) = obj is BoxFile && obj.isHashed() && obj.hashed == newFile.hashed - override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, indexNavigation: ShareHolder) { + override fun postprocess(dm: DirectoryMetadata, writeBackend: StorageWriteBackend, shares: ShareHolder) { if (sameFileByHash) { writeBackend.deleteBlock(newFile.block) } diff --git a/box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt b/box/src/main/java/de/qabel/box/storage/dto/DMChangeEvent.kt similarity index 86% rename from box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt rename to box/src/main/java/de/qabel/box/storage/dto/DMChangeEvent.kt index a872feb9..f7ada685 100644 --- a/box/src/main/java/de/qabel/box/storage/dto/DMChangeNotification.kt +++ b/box/src/main/java/de/qabel/box/storage/dto/DMChangeEvent.kt @@ -3,7 +3,7 @@ package de.qabel.box.storage.dto import de.qabel.box.storage.BoxNavigation import de.qabel.box.storage.command.DMChange -class DMChangeNotification( +class DMChangeEvent( val change: DMChange<*>, val navigation: BoxNavigation ) diff --git a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt index f34616b4..37cc4434 100644 --- a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt +++ b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt @@ -7,7 +7,7 @@ import de.qabel.box.storage.command.DeleteFileChange import de.qabel.box.storage.command.ShareChange import de.qabel.box.storage.command.UnshareChange import de.qabel.box.storage.command.UpdateFileChange -import de.qabel.box.storage.dto.DMChangeNotification +import de.qabel.box.storage.dto.DMChangeEvent import de.qabel.box.storage.hash.QabelBoxDigestProvider import de.qabel.box.storage.jdbc.JdbcDirectoryMetadataFactory import de.qabel.core.crypto.CryptoUtils @@ -45,7 +45,7 @@ abstract class AbstractNavigationTest { tmpDir ) abstract val nav: AbstractNavigation - var subscriber = TestSubscriber() + var subscriber = TestSubscriber() @Before open fun setUp() { @@ -103,7 +103,7 @@ abstract class AbstractNavigationTest { @Test fun resubscribe() { - subscriber = TestSubscriber() + subscriber = TestSubscriber() nav.changes.subscribe(subscriber) } diff --git a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt index 424f63ce..b21fdd4a 100644 --- a/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt +++ b/box/src/test/java/de/qabel/box/storage/BoxVolumeTest.kt @@ -6,7 +6,7 @@ import de.qabel.box.storage.command.DeleteFileChange import de.qabel.box.storage.command.DeleteFolderChange import de.qabel.box.storage.command.UpdateFileChange import de.qabel.box.storage.dto.BoxPath -import de.qabel.box.storage.dto.DMChangeNotification +import de.qabel.box.storage.dto.DMChangeEvent import de.qabel.box.storage.exceptions.QblStorageException import de.qabel.box.storage.exceptions.QblStorageNameConflict import de.qabel.box.storage.exceptions.QblStorageNotFound @@ -51,7 +51,7 @@ abstract class BoxVolumeTest { private var testFileName = "src/test/java/de/qabel/box/storage/testFile.txt" protected lateinit var contact: Contact protected lateinit var volumeTmpDir: File - val changes = mutableListOf() + val changes = mutableListOf() @Before open fun setUp() {