refactor: more secure DataCopy.kt

This commit is contained in:
SOR
2026-07-25 14:35:25 +08:00
parent 999ce5a68a
commit 994b2ff5b3
2 changed files with 25 additions and 41 deletions
@@ -1,56 +1,39 @@
package club.itstudio.itmanager.entity package club.itstudio.itmanager.entity
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
import kotlin.reflect.full.createInstance import kotlin.reflect.full.createInstance
import kotlin.reflect.full.declaredMemberProperties import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.javaField import kotlin.reflect.jvm.isAccessible
interface DataCopy { interface DataCopy {
fun <T : Any> toAnotherObject( fun <T : Any> toAnotherObject(
toClass: KClass<T>, toClass: KClass<T>,
otherProperties: Map<String, Any?> otherProperties: Map<String, Any?> = emptyMap()
): T { ): T {
try { @Suppress("UNCHECKED_CAST")
val voProperties = toClass.declaredMemberProperties val sourceProps = this::class.memberProperties
.associate { it.name to (it as KProperty1<Any, *>).get(this) }
return try {
val vo = toClass.createInstance() val vo = toClass.createInstance()
for (voProperty in voProperties) for (prop in toClass.declaredMemberProperties) {
copyFieldData(voProperty, otherProperties, vo) @Suppress("UNCHECKED_CAST")
return vo val mutableProp = prop as? KMutableProperty1<Any, Any?> ?: continue
val value = when {
sourceProps.containsKey(prop.name) -> sourceProps[prop.name]
otherProperties.containsKey(prop.name) -> otherProperties[prop.name]
else -> continue
}
mutableProp.isAccessible = true
mutableProp.set(vo, value)
}
vo
} catch (e: ReflectiveOperationException) { } catch (e: ReflectiveOperationException) {
throw RuntimeException( throw RuntimeException(
"${toClass.simpleName} has no fields.", "Failed to instantiate ${toClass.simpleName}. Does it have a no-arg constructor?", e
e
) )
} }
} }
private fun copyFieldData(
toProperty: KProperty<*>,
otherProperties: Map<String, Any?>,
another: Any
) {
try {
val thisProperty = this::class.memberProperties
.firstOrNull { it.name == toProperty.name }
val value =
if (thisProperty != null) {
thisProperty.getter.call(this)
} else if (otherProperties.containsKey(toProperty.name))
otherProperties[toProperty.name]
else
throw RuntimeException(
"Property ${toProperty.name} not found."
)
val field = toProperty.javaField!!
field.isAccessible = true
field.set(another, value)
} catch (e: Exception) {
e.printStackTrace()
}
}
} }
@@ -12,5 +12,6 @@ object Const {
const val FLOW_LIMIT_COUNTER = "flow:counter:" const val FLOW_LIMIT_COUNTER = "flow:counter:"
const val FLOW_LIMIT_BLOCK = "flow:block:" const val FLOW_LIMIT_BLOCK = "flow:block:"
val INTERNAL_ERROR_MONO = Mono.just("something went wrong. Please contact the administrator.") const val INTERNAL_ERROR_STR = "something went wrong. Please contact the administrator."
val INTERNAL_ERROR_MONO = Mono.just(INTERNAL_ERROR_STR)
} }