ScalaBot/scalabot-meta/src/main/kotlin/serializer/Serializer.kt
LamGC b8a99a4491
fix(config): 修正 BotConfigSerializer 中使用的错误默认值.
由于默认值未及时变更, 导致出现默认值与预期不符的情况;
目前已调整了新的默认值获取方式, 以便于后续调整默认值.
2022-06-24 19:51:27 +08:00

263 lines
9.8 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package net.lamgc.scalabot.config.serializer
import com.google.gson.*
import com.google.gson.reflect.TypeToken
import net.lamgc.scalabot.config.*
import org.eclipse.aether.artifact.AbstractArtifact
import org.eclipse.aether.artifact.Artifact
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.repository.Authentication
import org.eclipse.aether.repository.Proxy
import org.eclipse.aether.util.repository.AuthenticationBuilder
import java.lang.reflect.Type
import java.net.MalformedURLException
import java.net.URL
object ProxyTypeSerializer : JsonDeserializer<ProxyType>,
JsonSerializer<ProxyType> {
override fun deserialize(
json: JsonElement,
typeOfT: Type?,
context: JsonDeserializationContext?
): ProxyType {
if (json.isJsonNull) {
return ProxyType.NO_PROXY
}
if (!json.isJsonPrimitive) {
throw JsonParseException("Wrong configuration value type.")
}
val value = json.asString.trim()
try {
return ProxyType.valueOf(value.uppercase())
} catch (e: IllegalArgumentException) {
throw JsonParseException("Invalid value: $value")
}
}
override fun serialize(
src: ProxyType,
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
return JsonPrimitive(src.toString())
}
}
object ArtifactSerializer : JsonSerializer<Artifact>, JsonDeserializer<Artifact> {
override fun serialize(src: Artifact, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return if (src is AbstractArtifact) {
JsonPrimitive(src.toString())
} else {
JsonPrimitive(
DefaultArtifact(
src.groupId,
src.artifactId,
src.classifier,
src.extension,
src.version
).toString()
)
}
}
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Artifact {
if (!json.isJsonPrimitive) {
throw JsonParseException("Wrong configuration value type.")
}
val artifactStr = json.asString.trim()
try {
return DefaultArtifact(artifactStr)
} catch (e: IllegalArgumentException) {
throw JsonParseException("Invalid artifact format: `${artifactStr}`.")
}
}
}
object AuthenticationSerializer : JsonDeserializer<Authentication> {
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Authentication {
if (json !is JsonObject) {
throw JsonParseException("Unsupported JSON type.")
}
val username = SerializerUtils.checkJsonKey(json, "username")
val password = SerializerUtils.checkJsonKey(json, "password")
val builder = AuthenticationBuilder()
builder.addUsername(username)
builder.addPassword(password)
return builder.build()
}
}
private object SerializerUtils {
fun checkJsonKey(json: JsonObject, key: String): String {
if (!json.has(key)) {
throw JsonParseException("Required field does not exist: $key")
} else if (!json.get(key).isJsonPrimitive) {
throw JsonParseException("Wrong field `$key` type: ${json.get(key)::class.java}")
}
return json.get(key).asString
}
}
object MavenRepositoryConfigSerializer
: JsonDeserializer<MavenRepositoryConfig> {
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): MavenRepositoryConfig {
return when (json) {
is JsonObject -> {
MavenRepositoryConfig(
id = json.get("id")?.asString,
url = URL(SerializerUtils.checkJsonKey(json, "url")),
proxy = if (json.has("proxy") && json.get("proxy").isJsonObject)
context.deserialize<Proxy>(
json.getAsJsonObject("proxy"), Proxy::class.java
) else null,
layout = json.get("layout")?.asString ?: "default",
enableReleases = json.get("enableReleases")?.asBoolean ?: true,
enableSnapshots = json.get("enableSnapshots")?.asBoolean ?: true,
authentication = if (json.has("authentication") && json.get("authentication").isJsonObject)
context.deserialize<Authentication>(
json.getAsJsonObject("authentication"), Authentication::class.java
) else null
)
}
is JsonPrimitive -> {
try {
return MavenRepositoryConfig(url = URL(json.asString))
} catch (e: MalformedURLException) {
throw JsonParseException("Invalid URL: ${json.asString}", e)
}
}
else -> {
throw JsonParseException("Unsupported Maven repository configuration type. (Only support JSON object or url string)")
}
}
}
}
object UsernameAuthenticatorSerializer : JsonSerializer<UsernameAuthenticator>,
JsonDeserializer<UsernameAuthenticator> {
override fun serialize(
src: UsernameAuthenticator,
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
return src.toJsonObject()
}
override fun deserialize(
json: JsonElement,
typeOfT: Type?,
context: JsonDeserializationContext?
): UsernameAuthenticator? {
if (json.isJsonNull) {
return null
} else if (!json.isJsonObject) {
throw JsonParseException("Invalid attribute value type.")
}
val jsonObj = json.asJsonObject
if (jsonObj["username"]?.isJsonPrimitive != true) {
throw JsonParseException("Invalid attribute value: username")
} else if (jsonObj["password"]?.isJsonPrimitive != true) {
throw JsonParseException("Invalid attribute value: password")
}
if (jsonObj["username"].asString.isEmpty() || jsonObj["password"].asString.isEmpty()) {
throw JsonParseException("`username` or `password` is empty.")
}
return UsernameAuthenticator(jsonObj["username"].asString, jsonObj["password"].asString)
}
}
object ProxyConfigSerializer : JsonSerializer<ProxyConfig>, JsonDeserializer<ProxyConfig> {
override fun serialize(src: ProxyConfig?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
if (src == null) {
return JsonNull.INSTANCE
}
return JsonObject().apply {
addProperty("type", src.type.name)
addProperty("host", src.host)
addProperty("port", src.port)
}
}
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): ProxyConfig {
if (json == null || json.isJsonNull) {
return ProxyConfig()
} else if (json !is JsonObject) {
throw JsonParseException("Invalid json type.")
}
val typeStr = json["type"]?.asString ?: return ProxyConfig()
val type = try {
ProxyType.valueOf(typeStr)
} catch (e: IllegalArgumentException) {
throw JsonParseException("Invalid proxy type: `$typeStr`")
}
if (!json.has("host") || !json.has("port")) {
throw JsonParseException("Missing `host` field or `port` field.")
}
return ProxyConfig(
type = type,
host = json["host"].asString,
port = json["port"].asInt
)
}
}
object BotConfigSerializer : JsonSerializer<BotConfig>, JsonDeserializer<BotConfig> {
private val defaultConfig = BotConfig(account = BotAccount("__Default__", "__Default__", 0))
override fun serialize(src: BotConfig, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
return JsonObject().apply {
addProperty("enabled", src.enabled)
add("account", context.serialize(src.account))
addProperty("disableBuiltInAbility", src.disableBuiltInAbility)
addProperty("autoUpdateCommandList", src.autoUpdateCommandList)
add("extensions", context.serialize(src.extensions))
add("proxy", ProxyConfigSerializer.serialize(src.proxy, ProxyConfig::class.java, context))
addProperty("baseApiUrl", src.baseApiUrl)
}
}
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): BotConfig {
if (json !is JsonObject) {
throw JsonParseException("Unsupported JSON type.")
}
if (!json.has("account")) {
throw JsonParseException("Missing `account` field.")
} else if (!json.get("account").isJsonObject) {
throw JsonParseException("Invalid `account` field type.")
}
// 从 json 反序列化 BotConfig使用构造函数
return BotConfig(
enabled = json.get("enabled")?.asBoolean ?: defaultConfig.enabled,
account = context.deserialize(json.get("account"), BotAccount::class.java)!!,
disableBuiltInAbility = json.get("disableBuiltInAbility")?.asBoolean ?: defaultConfig.disableBuiltInAbility,
autoUpdateCommandList = json.get("autoUpdateCommandList")?.asBoolean ?: defaultConfig.autoUpdateCommandList,
extensions = context.deserialize(json.get("extensions"), object : TypeToken<Set<Artifact>>() {}.type)
?: defaultConfig.extensions,
proxy = context.deserialize(json.get("proxy"), ProxyConfig::class.java) ?: defaultConfig.proxy,
baseApiUrl = json.get("baseApiUrl")?.asString ?: defaultConfig.baseApiUrl
)
}
}