diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/Database.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/Database.kt index d1c225ff6ad834c587d9c52958888cc0241b7085..b8bbd6427bf2df9bddd4c7e88eb52311a116e3cd 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/Database.kt +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/Database.kt @@ -52,4 +52,17 @@ interface Database { @Throws(DbException::class) fun removeContact(txn: Connection, id: Int) + /** + * Runs the given task within a transaction. + */ + @Throws(DbException::class) + fun transaction(readOnly: Boolean, task: (Connection) -> Unit) + + /** + * Runs the given task within a transaction and returns the result of the + * task. + */ + @Throws(DbException::class) + fun <R> transactionWithResult(readOnly: Boolean, task: (Connection) -> R): R + } diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/JdbcDatabase.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/JdbcDatabase.kt index befc146cbb0cd6f33ef29926c9cb652444e08c1b..249058cb1c8023eada8839776e049283edc67b0d 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/JdbcDatabase.kt +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/db/JdbcDatabase.kt @@ -461,4 +461,35 @@ abstract class JdbcDatabase(private val dbTypes: DatabaseTypes, private val cloc } } + override fun transaction(readOnly: Boolean, task: (Connection) -> Unit) { + val txn = startTransaction() + var success = false + try { + task(txn) + success = true + } finally { + if (success) { + commitTransaction(txn) + } else { + abortTransaction(txn) + } + } + } + + override fun <R> transactionWithResult(readOnly: Boolean, task: (Connection) -> R): R { + val txn = startTransaction() + var success = false + try { + val result = task(txn) + success = true + return result + } finally { + if (success) { + commitTransaction(txn) + } else { + abortTransaction(txn) + } + } + } + } diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManager.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..2ec721b8eebabc6658256f8366e2f9d08aa3efb5 --- /dev/null +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManager.kt @@ -0,0 +1,25 @@ +package org.briarproject.mailbox.core.settings + +import org.briarproject.mailbox.core.db.DbException +import java.sql.Connection + +interface SettingsManager { + /** + * Returns all settings in the given namespace. + */ + @Throws(DbException::class) + fun getSettings(namespace: String): Settings + + /** + * Returns all settings in the given namespace. + */ + @Throws(DbException::class) + fun getSettings(txn: Connection, namespace: String): Settings + + /** + * Merges the given settings with any existing settings in the given + * namespace. + */ + @Throws(DbException::class) + fun mergeSettings(s: Settings, namespace: String) +} diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManagerImpl.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManagerImpl.kt new file mode 100644 index 0000000000000000000000000000000000000000..2c9801d0049e564bc297f3269c2a1dec608ffc0e --- /dev/null +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsManagerImpl.kt @@ -0,0 +1,28 @@ +package org.briarproject.mailbox.core.settings + +import org.briarproject.mailbox.core.db.Database +import org.briarproject.mailbox.core.db.DbException +import java.sql.Connection +import javax.annotation.concurrent.Immutable +import javax.inject.Inject + +@Immutable +internal class SettingsManagerImpl @Inject constructor(private val db: Database) : SettingsManager { + + @Throws(DbException::class) + override fun getSettings(namespace: String): Settings { + return db.transactionWithResult(true) { txn: Connection -> + db.getSettings(txn, namespace) + } + } + + @Throws(DbException::class) + override fun getSettings(txn: Connection, namespace: String): Settings { + return db.getSettings(txn, namespace) + } + + @Throws(DbException::class) + override fun mergeSettings(s: Settings, namespace: String) { + db.transaction(false) { txn: Connection -> db.mergeSettings(txn, s, namespace) } + } +} diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsModule.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..75490e09ff388f8b27c6bd5873d244c7cdbea4fd --- /dev/null +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/settings/SettingsModule.kt @@ -0,0 +1,13 @@ +package org.briarproject.mailbox.core.settings + +import dagger.Module +import dagger.Provides +import org.briarproject.mailbox.core.db.Database + +@Module +class SettingsModule { + @Provides + fun provideSettingsManager(db: Database): SettingsManager { + return SettingsManagerImpl(db) + } +} diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt index b41ac5c317e00b69e523b35112fb64ca5ee01b89..2a9abd05bca1b569c945e5ae0cc888f6bef197ec 100644 --- a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestComponent.kt @@ -1,7 +1,9 @@ package org.briarproject.mailbox.core import dagger.Component +import org.briarproject.mailbox.core.db.Database import org.briarproject.mailbox.core.lifecycle.LifecycleManager +import org.briarproject.mailbox.core.settings.SettingsManager import javax.inject.Singleton @Singleton @@ -13,4 +15,6 @@ import javax.inject.Singleton interface TestComponent { fun injectCoreEagerSingletons(): CoreEagerSingletons fun getLifecycleManager(): LifecycleManager + fun getSettingsManager(): SettingsManager + fun getDatabase(): Database } diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt index 38d46db1e289328a5f3f4fe3b4394327f2d043e0..20b9590c42713f4fc9ec144fbc436cdd995ec4db 100644 --- a/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/TestModule.kt @@ -8,6 +8,7 @@ import org.briarproject.mailbox.core.db.DatabaseConfig import org.briarproject.mailbox.core.db.DatabaseModule import org.briarproject.mailbox.core.lifecycle.LifecycleModule import org.briarproject.mailbox.core.server.WebServerModule +import org.briarproject.mailbox.core.settings.SettingsModule import org.briarproject.mailbox.core.system.Clock import java.io.File import javax.inject.Singleton @@ -17,6 +18,7 @@ import javax.inject.Singleton LifecycleModule::class, DatabaseModule::class, WebServerModule::class, + SettingsModule::class, // no Tor module ] ) diff --git a/mailbox-core/src/test/java/org/briarproject/mailbox/core/settings/SettingsManagerTest.kt b/mailbox-core/src/test/java/org/briarproject/mailbox/core/settings/SettingsManagerTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..3b2bfb542ec32e88eb02307334032e797eb4358c --- /dev/null +++ b/mailbox-core/src/test/java/org/briarproject/mailbox/core/settings/SettingsManagerTest.kt @@ -0,0 +1,49 @@ +package org.briarproject.mailbox.core.settings + +import org.briarproject.mailbox.core.DaggerTestComponent +import org.briarproject.mailbox.core.TestComponent +import org.briarproject.mailbox.core.TestModule +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle +import org.junit.jupiter.api.io.TempDir +import java.io.File +import kotlin.test.assertEquals + +@TestInstance(Lifecycle.PER_CLASS) +class SettingsManagerTest { + + private lateinit var testComponent: TestComponent + + @BeforeAll + fun setUp(@TempDir tempDir: File) { + testComponent = DaggerTestComponent.builder().testModule(TestModule(tempDir)).build() + testComponent.injectCoreEagerSingletons() + testComponent.getDatabase().open(null) + } + + @Test + @Throws(java.lang.Exception::class) + open fun testMergeSettings() { + val before = Settings() + before["foo"] = "bar" + before["baz"] = "bam" + val update = Settings() + update["baz"] = "qux" + val merged = Settings() + merged["foo"] = "bar" + merged["baz"] = "qux" + + val sm: SettingsManager = testComponent.getSettingsManager() + + // store 'before' + sm.mergeSettings(before, "namespace") + assertEquals(before, sm.getSettings("namespace")) + + // merge 'update' + sm.mergeSettings(update, "namespace") + assertEquals(merged, sm.getSettings("namespace")) + } + +}