From 13b0d515c2d20e8cc36fa567c24a253cca57ef8a Mon Sep 17 00:00:00 2001 From: Cyenoch <1759761439@qq.com> Date: Fri, 14 Feb 2020 16:32:59 +0800 Subject: [PATCH 1/5] complete YamlConfig and IniConfig --- mirai-console/build.gradle.kts | 2 + .../net/mamoe/mirai/plugins/ConfigSection.kt | 46 +++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/mirai-console/build.gradle.kts b/mirai-console/build.gradle.kts index 1ce7990b8..fd393c5dc 100644 --- a/mirai-console/build.gradle.kts +++ b/mirai-console/build.gradle.kts @@ -40,5 +40,7 @@ dependencies { runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) api(kotlin("serialization")) api(group = "com.alibaba", name = "fastjson", version = "1.2.62") + api(group = "org.yaml", name = "snakeyaml", version = "1.25") + api(group = "org.ini4j", name = "ini4j", version = "0.5.4") // classpath is not set correctly by IDE } \ No newline at end of file diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt index 5c6b26c66..6d8a8c86f 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt @@ -14,7 +14,10 @@ import com.alibaba.fastjson.JSONObject import com.alibaba.fastjson.TypeReference import com.alibaba.fastjson.parser.Feature import kotlinx.serialization.* +import org.ini4j.Wini +import org.yaml.snakeyaml.Yaml import java.io.File +import java.util.LinkedHashMap import java.util.concurrent.ConcurrentHashMap import kotlin.properties.ReadWriteProperty import kotlin.reflect.KClass @@ -191,7 +194,6 @@ fun Config._smartCast(propertyName: String, _class: KClass): T { } - interface ConfigSection : Config { override fun getConfigSection(key: String): ConfigSection { return (get(key) ?: error("ConfigSection does not contain $key ")) as ConfigSection @@ -339,22 +341,48 @@ class JsonConfig internal constructor(file: File) : FileConfigImpl(file) { class YamlConfig internal constructor(file: File) : FileConfigImpl(file) { override fun deserialize(content: String): ConfigSection { - TODO("崔崔还没有写") //To change body of created functions use File | Settings | File Templates. + if (content.isEmpty() || content.isBlank()) { + return ConfigSectionImpl() + } + val yamlObj = Yaml().load>(content) + return JSON.parseObject( + JSONObject.toJSONString(yamlObj), + object : TypeReference() {}, + Feature.OrderedField + ) } override fun serialize(config: ConfigSection): String { - TODO("崔崔还没有写") //To change body of created functions use File | Settings | File Templates. + val jsonStr = (JSONObject.toJSONString(config)) + return Yaml().dump(JSON.parseObject(jsonStr)) } } -class IniConfig internal constructor(file: File) : FileConfigImpl(file) { - override fun deserialize(content: String): ConfigSection { - TODO("崔崔还没有写") //To change body of created functions use File | Settings | File Templates. +class IniConfig internal constructor(val file: File) : ConfigSection { + private val iniObj by lazy { + Wini(file) + } + private val rootSection + get() = iniObj["root"] + + override fun asMap(): Map { + return JSON.parseObject( + JSONObject.toJSONString(rootSection), + object : TypeReference() {}, + Feature.OrderedField + ).asMap() } - override fun serialize(config: ConfigSection): String { - TODO("崔崔还没有写") //To change body of created functions use File | Settings | File Templates. + override fun set(key: String, value: Any) { + iniObj.put("root", key, value) } -} + override fun get(key: String): Any? { + return iniObj.get("root", key) + } + + override fun save() { + iniObj.store() + } +} \ No newline at end of file From 1c6a3800d180a19be2e37071cc53e8924c3f5b5e Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Fri, 14 Feb 2020 17:07:55 +0800 Subject: [PATCH 2/5] Yaml config Supported --- .../kotlin/net/mamoe/mirai/MiraiConsole.kt | 2 +- .../net/mamoe/mirai/plugins/ConfigSection.kt | 67 ++++++++++++++++--- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt index f65894d66..0eedebfb7 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt @@ -267,7 +267,7 @@ object MiraiConsole { } object MiraiProperties { - var config = File("$path/mirai.json").loadAsConfig() + var config = File("$path/mirai.yml").loadAsConfig() var HTTP_API_ENABLE: Boolean by config.withDefaultWrite { true } var HTTP_API_PORT: Int by config.withDefaultWrite { 8080 } diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt index 6d8a8c86f..f866a0994 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt @@ -17,8 +17,9 @@ import kotlinx.serialization.* import org.ini4j.Wini import org.yaml.snakeyaml.Yaml import java.io.File -import java.util.LinkedHashMap +import java.util.* import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.HashMap import kotlin.properties.ReadWriteProperty import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -194,7 +195,7 @@ fun Config._smartCast(propertyName: String, _class: KClass): T { } -interface ConfigSection : Config { +interface ConfigSection : Config, MutableMap { override fun getConfigSection(key: String): ConfigSection { return (get(key) ?: error("ConfigSection does not contain $key ")) as ConfigSection } @@ -290,6 +291,21 @@ interface FileConfig : Config { fun serialize(config: ConfigSection): String } +open class ConfigSectionDelegation( + val delegation: MutableMap +) : ConfigSection, MutableMap by delegation { + override fun set(key: String, value: Any) { + delegation.put(key, value) + } + + override fun asMap(): Map { + return delegation + } + + override fun save() { + + } +} abstract class FileConfigImpl internal constructor( private val file: File @@ -299,6 +315,27 @@ abstract class FileConfigImpl internal constructor( deserialize(file.readText()) } + override val size: Int + get() = content.size + + override val entries: MutableSet> + get() = content.entries + + override val keys: MutableSet + get() = content.keys + + override val values: MutableCollection + get() = content.values + + override fun containsKey(key: String): Boolean = content.containsKey(key) + override fun containsValue(value: Any): Boolean = content.containsValue(value) + override fun put(key: String, value: Any): Any? = content.put(key, value) + override fun isEmpty(): Boolean = content.isEmpty() + override fun putAll(from: Map) = content.putAll(from) + override fun clear() = content.clear() + override fun remove(key: String): Any? = content.remove(key) + + override fun save() { if (!file.exists()) { file.createNewFile() @@ -320,7 +357,9 @@ abstract class FileConfigImpl internal constructor( } -class JsonConfig internal constructor(file: File) : FileConfigImpl(file) { +class JsonConfig internal constructor( + file: File +) : FileConfigImpl(file) { @UnstableDefault override fun deserialize(content: String): ConfigSection { if (content.isEmpty() || content.isBlank() || content == "{}") { @@ -344,22 +383,20 @@ class YamlConfig internal constructor(file: File) : FileConfigImpl(file) { if (content.isEmpty() || content.isBlank()) { return ConfigSectionImpl() } - val yamlObj = Yaml().load>(content) - return JSON.parseObject( - JSONObject.toJSONString(yamlObj), - object : TypeReference() {}, - Feature.OrderedField + return ConfigSectionDelegation( + Collections.synchronizedMap( + Yaml().load>(content) as LinkedHashMap + ) ) } override fun serialize(config: ConfigSection): String { - val jsonStr = (JSONObject.toJSONString(config)) - return Yaml().dump(JSON.parseObject(jsonStr)) + return Yaml().dumpAsMap(config) } } -class IniConfig internal constructor(val file: File) : ConfigSection { +class IniConfig internal constructor(val file: File) : FileConfigImpl(file) { private val iniObj by lazy { Wini(file) } @@ -385,4 +422,12 @@ class IniConfig internal constructor(val file: File) : ConfigSection { override fun save() { iniObj.store() } + + override fun deserialize(content: String): ConfigSection { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun serialize(config: ConfigSection): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } \ No newline at end of file From 15c84bd38e79e97371426b00b50698f461e96703 Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Fri, 14 Feb 2020 17:15:37 +0800 Subject: [PATCH 3/5] Ini config supported(TOML) --- mirai-console/build.gradle.kts | 2 +- .../kotlin/net/mamoe/mirai/MiraiConsole.kt | 2 +- .../net/mamoe/mirai/plugins/ConfigSection.kt | 37 ++++--------------- 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/mirai-console/build.gradle.kts b/mirai-console/build.gradle.kts index fd393c5dc..1a896636a 100644 --- a/mirai-console/build.gradle.kts +++ b/mirai-console/build.gradle.kts @@ -41,6 +41,6 @@ dependencies { api(kotlin("serialization")) api(group = "com.alibaba", name = "fastjson", version = "1.2.62") api(group = "org.yaml", name = "snakeyaml", version = "1.25") - api(group = "org.ini4j", name = "ini4j", version = "0.5.4") + api(group = "com.moandjiezana.toml", name = "toml4j", version = "0.7.2") // classpath is not set correctly by IDE } \ No newline at end of file diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt index 0eedebfb7..5a65dc299 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt @@ -267,7 +267,7 @@ object MiraiConsole { } object MiraiProperties { - var config = File("$path/mirai.yml").loadAsConfig() + var config = File("$path/mirai.properties").loadAsConfig() var HTTP_API_ENABLE: Boolean by config.withDefaultWrite { true } var HTTP_API_PORT: Int by config.withDefaultWrite { 8080 } diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt index f866a0994..2c6ab9523 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt @@ -13,6 +13,8 @@ import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONObject import com.alibaba.fastjson.TypeReference import com.alibaba.fastjson.parser.Feature +import com.moandjiezana.toml.Toml +import com.moandjiezana.toml.TomlWriter import kotlinx.serialization.* import org.ini4j.Wini import org.yaml.snakeyaml.Yaml @@ -396,38 +398,15 @@ class YamlConfig internal constructor(file: File) : FileConfigImpl(file) { } -class IniConfig internal constructor(val file: File) : FileConfigImpl(file) { - private val iniObj by lazy { - Wini(file) - } - private val rootSection - get() = iniObj["root"] - - override fun asMap(): Map { - return JSON.parseObject( - JSONObject.toJSONString(rootSection), - object : TypeReference() {}, - Feature.OrderedField - ).asMap() - } - - override fun set(key: String, value: Any) { - iniObj.put("root", key, value) - } - - override fun get(key: String): Any? { - return iniObj.get("root", key) - } - - override fun save() { - iniObj.store() - } - +class IniConfig internal constructor(file: File) : FileConfigImpl(file) { override fun deserialize(content: String): ConfigSection { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + if (content.isEmpty() || content.isBlank()) { + return ConfigSectionImpl() + } + return ConfigSectionDelegation(Toml().read(content).toMap()) } override fun serialize(config: ConfigSection): String { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + return TomlWriter().write(config) } } \ No newline at end of file From 425de4ae50b0cb32cff48b91ed3d7ce68e1efb5a Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Fri, 14 Feb 2020 17:17:34 +0800 Subject: [PATCH 4/5] rename INI to TOML --- .../net/mamoe/mirai/plugins/ConfigSection.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt index 2c6ab9523..6304da337 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt @@ -16,12 +16,10 @@ import com.alibaba.fastjson.parser.Feature import com.moandjiezana.toml.Toml import com.moandjiezana.toml.TomlWriter import kotlinx.serialization.* -import org.ini4j.Wini import org.yaml.snakeyaml.Yaml import java.io.File import java.util.* import java.util.concurrent.ConcurrentHashMap -import kotlin.collections.HashMap import kotlin.properties.ReadWriteProperty import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -69,11 +67,11 @@ interface Config { "yml" -> YamlConfig(file) "yaml" -> YamlConfig(file) "mirai" -> YamlConfig(file) - "ini" -> IniConfig(file) - "toml" -> IniConfig(file) - "properties" -> IniConfig(file) - "property" -> IniConfig(file) - "data" -> IniConfig(file) + "ini" -> TomlConfig(file) + "toml" -> TomlConfig(file) + "properties" -> TomlConfig(file) + "property" -> TomlConfig(file) + "data" -> TomlConfig(file) else -> error("Unsupported file config type ${file.extension.toLowerCase()}") } } @@ -398,7 +396,7 @@ class YamlConfig internal constructor(file: File) : FileConfigImpl(file) { } -class IniConfig internal constructor(file: File) : FileConfigImpl(file) { +class TomlConfig internal constructor(file: File) : FileConfigImpl(file) { override fun deserialize(content: String): ConfigSection { if (content.isEmpty() || content.isBlank()) { return ConfigSectionImpl() From d43211522e711b9ad8618ec2c130fec54072649d Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Fri, 14 Feb 2020 17:20:05 +0800 Subject: [PATCH 5/5] Thread safety --- .../net/mamoe/mirai/plugins/ConfigSection.kt | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt index 6304da337..41991dfb2 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugins/ConfigSection.kt @@ -284,15 +284,8 @@ open class ConfigSectionImpl() : ConcurrentHashMap(), ConfigSection } } - -interface FileConfig : Config { - fun deserialize(content: String): ConfigSection - - fun serialize(config: ConfigSection): String -} - open class ConfigSectionDelegation( - val delegation: MutableMap + private val delegation: MutableMap ) : ConfigSection, MutableMap by delegation { override fun set(key: String, value: Any) { delegation.put(key, value) @@ -307,6 +300,14 @@ open class ConfigSectionDelegation( } } + +interface FileConfig : Config { + fun deserialize(content: String): ConfigSection + + fun serialize(config: ConfigSection): String +} + + abstract class FileConfigImpl internal constructor( private val file: File ) : FileConfig, ConfigSection { @@ -315,18 +316,10 @@ abstract class FileConfigImpl internal constructor( deserialize(file.readText()) } - override val size: Int - get() = content.size - - override val entries: MutableSet> - get() = content.entries - - override val keys: MutableSet - get() = content.keys - - override val values: MutableCollection - get() = content.values - + override val size: Int get() = content.size + override val entries: MutableSet> get() = content.entries + override val keys: MutableSet get() = content.keys + override val values: MutableCollection get() = content.values override fun containsKey(key: String): Boolean = content.containsKey(key) override fun containsValue(value: Any): Boolean = content.containsValue(value) override fun put(key: String, value: Any): Any? = content.put(key, value) @@ -335,7 +328,6 @@ abstract class FileConfigImpl internal constructor( override fun clear() = content.clear() override fun remove(key: String): Any? = content.remove(key) - override fun save() { if (!file.exists()) { file.createNewFile() @@ -401,7 +393,11 @@ class TomlConfig internal constructor(file: File) : FileConfigImpl(file) { if (content.isEmpty() || content.isBlank()) { return ConfigSectionImpl() } - return ConfigSectionDelegation(Toml().read(content).toMap()) + return ConfigSectionDelegation( + Collections.synchronizedMap( + Toml().read(content).toMap() + ) + ) } override fun serialize(config: ConfigSection): String {