diff --git a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt index 4839e699..827c1fee 100644 --- a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt +++ b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt @@ -11,6 +11,9 @@ import ch.qos.logback.classic.Level import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigRenderOptions +import com.typesafe.config.ConfigValue +import com.typesafe.config.ConfigValueFactory +import com.typesafe.config.parser.ConfigDocumentFactory import mu.KotlinLogging import java.io.File @@ -18,15 +21,17 @@ import java.io.File * Manages app config. */ open class ConfigManager { + val logger = KotlinLogging.logger {} private val generatedModules = mutableMapOf, ConfigModule>() - val config by lazy { loadConfigs() } + private val userConfigFile = File(ApplicationRootDir, "server.conf") + private var internalConfig = loadConfigs() + val config: Config + get() = internalConfig // Public read-only view of modules val loadedModules: Map, ConfigModule> get() = generatedModules - val logger = KotlinLogging.logger {} - /** * Get a config module */ @@ -54,7 +59,7 @@ open class ConfigManager { // Load user config val userConfig = - File(ApplicationRootDir, "server.conf").let { + userConfigFile.let { ConfigFactory.parseFile(it) } @@ -86,6 +91,20 @@ open class ConfigManager { registerModule(it) } } + + private fun updateUserConfigFile(path: String, value: ConfigValue) { + val userConfigDoc = ConfigDocumentFactory.parseFile(userConfigFile) + val updatedConfigDoc = userConfigDoc.withValue(path, value) + val newFileContent = updatedConfigDoc.render() + userConfigFile.writeText(newFileContent) + } + + fun updateValue(path: String, value: Any) { + val configValue = ConfigValueFactory.fromAnyRef(value) + + updateUserConfigFile(path, configValue) + internalConfig = internalConfig.withValue(path, configValue) + } } object GlobalConfigManager : ConfigManager() diff --git a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt index 145e7e9a..35940593 100644 --- a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt +++ b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt @@ -15,19 +15,23 @@ import kotlin.reflect.KProperty * Abstract config module. */ @Suppress("UNUSED_PARAMETER") -abstract class ConfigModule(config: Config) +abstract class ConfigModule(getConfig: () -> Config) /** * Abstract jvm-commandline-argument-overridable config module. */ -abstract class SystemPropertyOverridableConfigModule(config: Config, moduleName: String) : ConfigModule(config) { - val overridableConfig = SystemPropertyOverrideDelegate(config, moduleName) +abstract class SystemPropertyOverridableConfigModule(getConfig: () -> Config, moduleName: String) : ConfigModule(getConfig) { + val overridableConfig = SystemPropertyOverrideDelegate(getConfig, moduleName) } /** Defines a config property that is overridable with jvm `-D` commandline arguments prefixed with [CONFIG_PREFIX] */ -class SystemPropertyOverrideDelegate(val config: Config, val moduleName: String) { +class SystemPropertyOverrideDelegate(val getConfig: () -> Config, val moduleName: String) { + operator fun setValue(thisRef: R, property: KProperty<*>, value: Any) { + GlobalConfigManager.updateValue("$moduleName.${property.name}", value) + } + inline operator fun getValue(thisRef: R, property: KProperty<*>): T { - val configValue: T = config.getValue(thisRef, property) + val configValue: T = getConfig().getValue(thisRef, property) val combined = System.getProperty( "$CONFIG_PREFIX.$moduleName.${property.name}", diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt index 145d3650..1c3a2eb0 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt @@ -8,12 +8,12 @@ import xyz.nulldev.ts.config.ConfigModule * Application info config. */ -class ApplicationInfoConfigModule(config: Config) : ConfigModule(config) { - val packageName: String by config - val debug: Boolean by config +class ApplicationInfoConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) { + val packageName: String by getConfig() + val debug: Boolean by getConfig() companion object { fun register(config: Config) = - ApplicationInfoConfigModule(config.getConfig("android.app")) + ApplicationInfoConfigModule { config.getConfig("android.app") } } } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt index ff8bc9c0..8bb717db 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt @@ -8,27 +8,27 @@ import xyz.nulldev.ts.config.ConfigModule * Files configuration modules. Specifies where to store the Android files. */ -class FilesConfigModule(config: Config) : ConfigModule(config) { - val dataDir: String by config - val filesDir: String by config - val noBackupFilesDir: String by config - val externalFilesDirs: MutableList by config - val obbDirs: MutableList by config - val cacheDir: String by config - val codeCacheDir: String by config - val externalCacheDirs: MutableList by config - val externalMediaDirs: MutableList by config - val rootDir: String by config - val externalStorageDir: String by config - val downloadCacheDir: String by config - val databasesDir: String by config +class FilesConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) { + val dataDir: String by getConfig() + val filesDir: String by getConfig() + val noBackupFilesDir: String by getConfig() + val externalFilesDirs: MutableList by getConfig() + val obbDirs: MutableList by getConfig() + val cacheDir: String by getConfig() + val codeCacheDir: String by getConfig() + val externalCacheDirs: MutableList by getConfig() + val externalMediaDirs: MutableList by getConfig() + val rootDir: String by getConfig() + val externalStorageDir: String by getConfig() + val downloadCacheDir: String by getConfig() + val databasesDir: String by getConfig() - val prefsDir: String by config + val prefsDir: String by getConfig() - val packageDir: String by config + val packageDir: String by getConfig() companion object { fun register(config: Config) = - FilesConfigModule(config.getConfig("android.files")) + FilesConfigModule { config.getConfig("android.files") } } } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt index 182ffb6c..5447ba6e 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt @@ -4,19 +4,19 @@ import com.typesafe.config.Config import io.github.config4k.getValue import xyz.nulldev.ts.config.ConfigModule -class SystemConfigModule(val config: Config) : ConfigModule(config) { - val isDebuggable: Boolean by config +class SystemConfigModule(val getConfig: () -> Config) : ConfigModule(getConfig) { + val isDebuggable: Boolean by getConfig() val propertyPrefix = "properties." - fun getStringProperty(property: String) = config.getString("$propertyPrefix$property")!! - fun getIntProperty(property: String) = config.getInt("$propertyPrefix$property") - fun getLongProperty(property: String) = config.getLong("$propertyPrefix$property") - fun getBooleanProperty(property: String) = config.getBoolean("$propertyPrefix$property") - fun hasProperty(property: String) = config.hasPath("$propertyPrefix$property") + fun getStringProperty(property: String) = getConfig().getString("$propertyPrefix$property")!! + fun getIntProperty(property: String) = getConfig().getInt("$propertyPrefix$property") + fun getLongProperty(property: String) = getConfig().getLong("$propertyPrefix$property") + fun getBooleanProperty(property: String) = getConfig().getBoolean("$propertyPrefix$property") + fun hasProperty(property: String) = getConfig().hasPath("$propertyPrefix$property") companion object { fun register(config: Config) = - SystemConfigModule(config.getConfig("android.system")) + SystemConfigModule { config.getConfig("android.system") } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt index 1fac844d..0008d2c5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt @@ -13,39 +13,39 @@ import xyz.nulldev.ts.config.SystemPropertyOverridableConfigModule import xyz.nulldev.ts.config.debugLogsEnabled private const val MODULE_NAME = "server" -class ServerConfig(config: Config, moduleName: String = MODULE_NAME) : SystemPropertyOverridableConfigModule(config, moduleName) { - val ip: String by overridableConfig - val port: Int by overridableConfig +class ServerConfig(getConfig: () -> Config, moduleName: String = MODULE_NAME) : SystemPropertyOverridableConfigModule(getConfig, moduleName) { + var ip: String by overridableConfig + var port: Int by overridableConfig // proxy - val socksProxyEnabled: Boolean by overridableConfig - val socksProxyHost: String by overridableConfig - val socksProxyPort: String by overridableConfig + var socksProxyEnabled: Boolean by overridableConfig + var socksProxyHost: String by overridableConfig + var socksProxyPort: String by overridableConfig // webUI - val webUIEnabled: Boolean by overridableConfig - val webUIFlavor: String by overridableConfig - val initialOpenInBrowserEnabled: Boolean by overridableConfig - val webUIInterface: String by overridableConfig - val electronPath: String by overridableConfig + var webUIEnabled: Boolean by overridableConfig + var webUIFlavor: String by overridableConfig + var initialOpenInBrowserEnabled: Boolean by overridableConfig + var webUIInterface: String by overridableConfig + var electronPath: String by overridableConfig // downloader - val downloadAsCbz: Boolean by overridableConfig - val downloadsPath: String by overridableConfig + var downloadAsCbz: Boolean by overridableConfig + var downloadsPath: String by overridableConfig // updater - val maxParallelUpdateRequests: Int by overridableConfig + var maxParallelUpdateRequests: Int by overridableConfig // Authentication - val basicAuthEnabled: Boolean by overridableConfig - val basicAuthUsername: String by overridableConfig - val basicAuthPassword: String by overridableConfig + var basicAuthEnabled: Boolean by overridableConfig + var basicAuthUsername: String by overridableConfig + var basicAuthPassword: String by overridableConfig // misc - val debugLogsEnabled: Boolean = debugLogsEnabled(GlobalConfigManager.config) - val systemTrayEnabled: Boolean by overridableConfig + var debugLogsEnabled: Boolean = debugLogsEnabled(GlobalConfigManager.config) + var systemTrayEnabled: Boolean by overridableConfig companion object { - fun register(config: Config) = ServerConfig(config.getConfig(MODULE_NAME)) + fun register(getConfig: () -> Config) = ServerConfig({ getConfig().getConfig(MODULE_NAME) }) } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt index 66108831..4312438b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt @@ -60,7 +60,7 @@ fun applicationSetup() { // register Tachidesk's config which is dubbed "ServerConfig" GlobalConfigManager.registerModule( - ServerConfig.register(GlobalConfigManager.config) + ServerConfig.register { GlobalConfigManager.config } ) // Application dirs