mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-13 19:30:10 +08:00
update
This commit is contained in:
parent
3fb22b30bb
commit
b5150955a0
@ -20,6 +20,7 @@ include("ts-core:ts-json")
|
||||
include("ts-core:ts-xml")
|
||||
include("ts-core:ts-async-http")
|
||||
include("ts-core:ts-proxy")
|
||||
include("ts-core:ts-reflect")
|
||||
include("ts-socket")
|
||||
include("ts-web")
|
||||
include("ts-web:ts-web-netty")
|
||||
|
@ -30,12 +30,12 @@ import javax.mail.internet.MimeMultipart
|
||||
data class EmailData(
|
||||
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
||||
var to: String?, var subject: String?, var html: String? = null, var text: String? = null,
|
||||
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null
|
||||
) {
|
||||
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null,
|
||||
) : Mail {
|
||||
/**
|
||||
* 发送邮件
|
||||
*/
|
||||
fun send(transportListener: TransportListener? = null) {
|
||||
override fun send(transportListener: TransportListener?) {
|
||||
if (host == null || port == null || name == null || password == null || from == null || to == null || subject == null) return
|
||||
val props = Properties()
|
||||
// props["mail.debug"] = "true" // 开启debug调试
|
||||
@ -69,7 +69,7 @@ data class EmailData(
|
||||
html: String?,
|
||||
text: String?,
|
||||
image: Collection<Image>?,
|
||||
attachment: Collection<DataSource>?
|
||||
attachment: Collection<DataSource>?,
|
||||
): MimeMessage {
|
||||
//邮件内容部分
|
||||
val msg = MimeMessage(session)
|
||||
|
@ -15,9 +15,8 @@ data class GroupEmailData(
|
||||
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
||||
var to: Collection<String>?, var subject: String?, var html: String? = null, var text: String? = null,
|
||||
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null,
|
||||
) {
|
||||
fun send() = send(null)
|
||||
fun send(transportListener: TransportListener?) {
|
||||
) : Mail {
|
||||
override fun send(transportListener: TransportListener?) {
|
||||
if (host == null || port == null || name == null || password == null || from == null || to?.isEmpty() != false || subject == null) return
|
||||
val props = Properties()
|
||||
// props["mail.debug"] = "true" // 开启debug调试
|
||||
|
7
ts-core/ts-mail/src/main/kotlin/cn/tursom/mail/Mail.kt
Normal file
7
ts-core/ts-mail/src/main/kotlin/cn/tursom/mail/Mail.kt
Normal file
@ -0,0 +1,7 @@
|
||||
package cn.tursom.mail
|
||||
|
||||
import javax.mail.event.TransportListener
|
||||
|
||||
interface Mail {
|
||||
fun send(transportListener: TransportListener? = null)
|
||||
}
|
@ -4,6 +4,7 @@ import com.sun.mail.util.MailSSLSocketFactory
|
||||
import java.util.*
|
||||
import javax.mail.Address
|
||||
import javax.mail.Session
|
||||
import javax.mail.event.TransportListener
|
||||
import javax.mail.internet.InternetAddress
|
||||
|
||||
data class MultipleEmailData(
|
||||
@ -12,9 +13,9 @@ data class MultipleEmailData(
|
||||
var name: String?,
|
||||
var password: String?,
|
||||
var from: String?,
|
||||
var to: Collection<MailStructure>?
|
||||
) {
|
||||
fun send() {
|
||||
var to: Collection<MailStructure>?,
|
||||
) : Mail {
|
||||
override fun send(transportListener: TransportListener?) {
|
||||
val from = from ?: return
|
||||
val props = Properties()
|
||||
// props["mail.debug"] = "true" // 开启debug调试
|
||||
@ -32,6 +33,7 @@ data class MultipleEmailData(
|
||||
//发送邮件
|
||||
val transport = session.transport
|
||||
transport.connect(host, name, password)
|
||||
transportListener?.apply { transport.addTransportListener(this) }
|
||||
to?.forEach { (to, subject, html, text, image, attachment) ->
|
||||
//邮件内容部分
|
||||
val msg = EmailData.getMsg(session, from, subject, html, text, image, attachment)
|
||||
|
22
ts-core/ts-reflect/build.gradle.kts
Normal file
22
ts-core/ts-reflect/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
`maven-publish`
|
||||
id("ts-gradle")
|
||||
kotlin("plugin.allopen") version "1.5.21"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":ts-core"))
|
||||
api(project(":ts-core:ts-log"))
|
||||
testApi(group = "junit", name = "junit", version = "4.13.2")
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives(tasks["kotlinSourcesJar"])
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import java.lang.reflect.Method
|
||||
|
||||
inline fun <R> Class<*>.getDeclaredMethod(
|
||||
returnType: Class<*>,
|
||||
getMethod: Class<*>.() -> Method?,
|
||||
staticReturn: (method: Method) -> R,
|
||||
): R? {
|
||||
val method = this.getDeclaredMethod(returnType, false, getMethod)
|
||||
if (method != null) return staticReturn(method)
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <reified R : Any> Any.getMethod(
|
||||
name: String,
|
||||
clazz: Class<*> = javaClass,
|
||||
returnType: Class<R> = R::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name)
|
||||
},
|
||||
): (() -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ method(this).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod(name, returnType, getMethod)
|
||||
|
||||
inline fun <reified R : Any, reified T1> Any.getMethod1(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
clazz: Class<*> = javaClass,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type)
|
||||
},
|
||||
): ((T1) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ method(this, it).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod1(name, returnType, arg1Type, getMethod)
|
||||
|
||||
inline fun <reified R : Any, reified T1, reified T2> Any.getMethod2(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
clazz: Class<*> = javaClass,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type)
|
||||
},
|
||||
): ((T1, T2) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2 -> method(this, v1, v2).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod2(name, returnType, arg1Type, arg2Type, getMethod)
|
||||
|
||||
inline fun <reified R : Any, reified T1, reified T2, reified T3> Any.getMethod3(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
clazz: Class<*> = javaClass,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||
},
|
||||
): ((T1, T2, T3) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3 -> method(this, v1, v2, v3).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod3(name, returnType, arg1Type, arg2Type, arg3Type, getMethod)
|
||||
|
||||
inline fun <reified R : Any, reified T1, reified T2, reified T3, reified T4> Any.getMethod4(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
arg4Type: Class<T4> = T4::class.java,
|
||||
clazz: Class<*> = javaClass,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||
},
|
||||
): ((T1, T2, T3, T4) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3, v4 -> method(this, v1, v2, v3, v4).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod4(name, returnType, arg1Type, arg2Type, arg3Type, arg4Type, getMethod)
|
||||
|
||||
inline fun <reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Any.getMethod5(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
arg4Type: Class<T4> = T4::class.java,
|
||||
arg5Type: Class<T5> = T5::class.java,
|
||||
clazz: Class<*> = javaClass,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type)
|
||||
},
|
||||
): ((T1, T2, T3, T4, T5) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3, v4, v5 -> method(this, v1, v2, v3, v4, v5).uncheckedCast() }
|
||||
} ?: clazz.getStaticDeclaredMethod5(name, returnType, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type, getMethod)
|
||||
|
@ -0,0 +1,76 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import java.lang.reflect.Method
|
||||
|
||||
inline fun <This, reified R> Class<*>.getMethod(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
getMethod: Class<*>.() -> Method? = { getMethodFully(name) },
|
||||
): (This.() -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ method(this).uncheckedCast() }
|
||||
}
|
||||
|
||||
inline fun <This, reified R, reified T1> Class<*>.getMethod1(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
arg1Type: Class<in T1> = T1::class.java,
|
||||
getMethod: Class<*>.() -> Method? = { getMethodFully(name, arg1Type) },
|
||||
): (This.(T1) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ method(this, it).uncheckedCast() }
|
||||
}
|
||||
|
||||
inline fun <This, reified R, reified T1, reified T2> Class<*>.getMethod2(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
arg1Type: Class<in T1> = T1::class.java,
|
||||
arg2Type: Class<in T2> = T2::class.java,
|
||||
getMethod: Class<*>.() -> Method? = { getMethodFully(name, arg1Type, arg2Type) },
|
||||
): (This.(T1, T2) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2 -> method(this, v1, v2).uncheckedCast() }
|
||||
}
|
||||
|
||||
inline fun <This, reified R, reified T1, reified T2, reified T3> Class<*>.getMethod3(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
arg1Type: Class<in T1> = T1::class.java,
|
||||
arg2Type: Class<in T2> = T2::class.java,
|
||||
arg3Type: Class<in T3> = T3::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||
},
|
||||
): (This.(T1, T2, T3) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3 -> method(this, v1, v2, v3).uncheckedCast() }
|
||||
}
|
||||
|
||||
inline fun <This, reified R, reified T1, reified T2, reified T3, reified T4> Class<*>.getMethod4(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
arg1Type: Class<in T1> = T1::class.java,
|
||||
arg2Type: Class<in T2> = T2::class.java,
|
||||
arg3Type: Class<in T3> = T3::class.java,
|
||||
arg4Type: Class<in T4> = T4::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||
},
|
||||
): (This.(T1, T2, T3, T4) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3, v4 -> method(this, v1, v2, v3, v4).uncheckedCast() }
|
||||
}
|
||||
|
||||
inline fun <This, reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Class<*>.getMethod5(
|
||||
name: String,
|
||||
returnType: Class<out R> = R::class.java,
|
||||
arg1Type: Class<in T1> = T1::class.java,
|
||||
arg2Type: Class<in T2> = T2::class.java,
|
||||
arg3Type: Class<in T3> = T3::class.java,
|
||||
arg4Type: Class<in T4> = T4::class.java,
|
||||
arg5Type: Class<in T5> = T5::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||
},
|
||||
): (This.(T1, T2, T3, T4, T5) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||
{ v1, v2, v3, v4, v5 -> method(this, v1, v2, v3, v4, v5).uncheckedCast() }
|
||||
}
|
||||
|
@ -0,0 +1,198 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.allMethodsSequence
|
||||
import cn.tursom.core.companionObjectInstanceOrNull
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import java.lang.reflect.Method
|
||||
|
||||
inline fun <reified T> getType() = T::class.java
|
||||
|
||||
fun main() {
|
||||
println(Int::class.java canCast getType<Byte>())
|
||||
println(Int::class.java canCast getType<Int>())
|
||||
}
|
||||
|
||||
infix fun Class<*>.canCast(target: Class<*>): Boolean {
|
||||
return (target == Any::class.java || this == target) || (
|
||||
(this == Void.TYPE || this == Void::class.java) &&
|
||||
(target == Unit::class.java || target == Void.TYPE || target == Void::class.java)
|
||||
) || (
|
||||
(this == Byte::class.java || this == getType<Byte>()) &&
|
||||
(target == Byte::class.java || target == getType<Byte>())
|
||||
) || (
|
||||
(this == Short::class.java || this == getType<Short>()) &&
|
||||
(target == Short::class.java || target == getType<Short>())
|
||||
) || (
|
||||
(this == Int::class.java || this == getType<Int>()) &&
|
||||
(target == Int::class.java || target == getType<Int>())
|
||||
) || (
|
||||
(this == Long::class.java || this == getType<Long>()) &&
|
||||
(target == Long::class.java || target == getType<Long>())
|
||||
) || (
|
||||
(this == Float::class.java || this == getType<Float>()) &&
|
||||
(target == Float::class.java || target == getType<Float>())
|
||||
) || (
|
||||
(this == Double::class.java || this == getType<Double>()) &&
|
||||
(target == Double::class.java || target == getType<Double>())
|
||||
) || (
|
||||
(this == Boolean::class.java || this == getType<Boolean>()) &&
|
||||
(target == Boolean::class.java || target == getType<Boolean>())
|
||||
) || (
|
||||
(this == Char::class.java || this == getType<Char>()) &&
|
||||
(target == Char::class.java || target == getType<Char>())
|
||||
) || target.isAssignableFrom(this)
|
||||
}
|
||||
|
||||
private fun Method.match(name: String, vararg type: Class<*>): Boolean {
|
||||
if (this.name != name) return false
|
||||
if (this.parameterTypes.size != type.size) return false
|
||||
this.parameterTypes.forEachIndexed { index, clazz ->
|
||||
if (!(type[index] canCast clazz)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun Class<*>.getFirstMatchMethod(
|
||||
name: String,
|
||||
vararg type: Class<*>,
|
||||
): Method? {
|
||||
allMethodsSequence.forEach { method ->
|
||||
if (method.match(name, *type)) {
|
||||
return method
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun Class<*>.getMethodFully(
|
||||
name: String,
|
||||
vararg type: Class<*>,
|
||||
): Method? {
|
||||
val scanMethod = scanMethod(name, *type)
|
||||
return (scanMethod.firstOrNull { method ->
|
||||
method.parameterTypes.forEachIndexed { index, clazz ->
|
||||
if (type[index] != clazz) return@firstOrNull false
|
||||
}
|
||||
true
|
||||
} ?: scanMethod.firstOrNull())
|
||||
}
|
||||
|
||||
fun Class<*>.scanMethod(
|
||||
name: String,
|
||||
vararg type: Class<*>,
|
||||
): List<Method> {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
return buildList {
|
||||
allMethodsSequence.forEach { method ->
|
||||
if (method.match(name, *type)) add(method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun Class<*>.getDeclaredMethod(
|
||||
returnType: Class<*>,
|
||||
isStatic: Boolean = true,
|
||||
getMethod: Class<*>.() -> Method?,
|
||||
) = try {
|
||||
val method = getMethod()
|
||||
method?.isAccessible = true
|
||||
if (method != null && method.isStatic() == isStatic && method.returnType canCast returnType) method
|
||||
else null
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
inline fun <R> Class<*>.getStaticDeclaredMethod(
|
||||
returnType: Class<*>,
|
||||
getMethod: Class<*>.() -> Method?,
|
||||
staticReturn: (method: Method, companionObjectInstance: Any?) -> R,
|
||||
): R? {
|
||||
val method = getDeclaredMethod(returnType, true, getMethod)
|
||||
if (method != null) return staticReturn(method, null)
|
||||
|
||||
val companionObjectInstance = kotlin.companionObjectInstanceOrNull ?: return null
|
||||
val companionObjectClazz = companionObjectInstance.javaClass
|
||||
val companionMethod = companionObjectClazz.getDeclaredMethod(returnType, false, getMethod)
|
||||
if (companionMethod != null) return staticReturn(companionMethod, companionObjectInstance)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <reified R : Any> Class<*>.getStaticDeclaredMethod(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name)
|
||||
},
|
||||
): (() -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { method(companion).uncheckedCast() } }
|
||||
|
||||
inline fun <reified R, reified T1> Class<*>.getStaticDeclaredMethod1(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type)
|
||||
},
|
||||
): ((T1) -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { v1 -> method(companion, v1).uncheckedCast() } }
|
||||
|
||||
inline fun <reified R, reified T1, reified T2> Class<*>.getStaticDeclaredMethod2(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type)
|
||||
},
|
||||
): ((T1, T2) -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { v1, v2 -> method(companion, v1, v2).uncheckedCast() } }
|
||||
|
||||
inline fun <reified R, reified T1, reified T2, reified T3> Class<*>.getStaticDeclaredMethod3(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||
},
|
||||
): ((T1, T2, T3) -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { v1, v2, v3 -> method(companion, v1, v2, v3).uncheckedCast() } }
|
||||
|
||||
inline fun <reified R, reified T1, reified T2, reified T3, reified T4> Class<*>.getStaticDeclaredMethod4(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
arg4Type: Class<T4> = T4::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||
},
|
||||
): ((T1, T2, T3, T4) -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { v1, v2, v3, v4 -> method(companion, v1, v2, v3, v4).uncheckedCast() } }
|
||||
|
||||
inline fun <reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Class<*>.getStaticDeclaredMethod5(
|
||||
name: String,
|
||||
returnType: Class<R> = R::class.java,
|
||||
arg1Type: Class<T1> = T1::class.java,
|
||||
arg2Type: Class<T2> = T2::class.java,
|
||||
arg3Type: Class<T3> = T3::class.java,
|
||||
arg4Type: Class<T4> = T4::class.java,
|
||||
arg5Type: Class<T5> = T5::class.java,
|
||||
getMethod: Class<*>.() -> Method? = {
|
||||
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type)
|
||||
},
|
||||
): ((T1, T2, T3, T4, T5) -> R)? = getStaticDeclaredMethod(
|
||||
returnType, getMethod
|
||||
) { method, companion -> { v1, v2, v3, v4, v5 -> method(companion, v1, v2, v3, v4, v5).uncheckedCast() } }
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.UncheckedCast
|
||||
import cn.tursom.core.Unsafe
|
||||
import cn.tursom.core.cast
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
object InstantAllocator {
|
||||
enum class AllocateFunction { INSTANCE, UNSAFE, KOBJECT, NONE }
|
||||
|
||||
private val allocateFunctionMap = ConcurrentHashMap<Class<*>, AllocateFunction>()
|
||||
|
||||
@Throws(NoSuchMethodException::class)
|
||||
operator fun <T> invoke(clazz: Class<out T>, unsafe: Boolean = true): T = get(clazz, unsafe)
|
||||
|
||||
@Throws(NoSuchMethodException::class)
|
||||
inline operator fun <reified T : Any> invoke(unsafe: Boolean = true): T = get(T::class.java, unsafe)
|
||||
|
||||
@Throws(NoSuchMethodException::class)
|
||||
operator fun <T : Any> get(clazz: KClass<out T>, unsafe: Boolean = true): T = get(clazz.java, unsafe)
|
||||
|
||||
@Throws(NoSuchMethodException::class)
|
||||
operator fun <T> get(clazz: Class<out T>, unsafe: Boolean = true): T {
|
||||
return when (allocateFunctionMap[clazz]) {
|
||||
null -> try {
|
||||
val newInstance = clazz.newInstance()
|
||||
allocateFunctionMap[clazz] = AllocateFunction.INSTANCE
|
||||
newInstance
|
||||
} catch (e: Exception) {
|
||||
val kClass = clazz.kotlin
|
||||
val objectInstance = kClass.objectInstance
|
||||
if (objectInstance != null) {
|
||||
allocateFunctionMap[clazz] = AllocateFunction.KOBJECT
|
||||
objectInstance
|
||||
} else if (unsafe) try {
|
||||
allocateFunctionMap[clazz] = AllocateFunction.UNSAFE
|
||||
@OptIn(UncheckedCast::class)
|
||||
Unsafe.unsafe.allocateInstance(clazz).cast<T>()
|
||||
} catch (e: Exception) {
|
||||
allocateFunctionMap[clazz] = AllocateFunction.NONE
|
||||
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||
} else {
|
||||
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||
}
|
||||
}
|
||||
AllocateFunction.INSTANCE -> clazz.newInstance()
|
||||
AllocateFunction.UNSAFE -> if (unsafe) {
|
||||
Unsafe.unsafe.allocateInstance(clazz).uncheckedCast<T>()
|
||||
} else {
|
||||
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||
}
|
||||
AllocateFunction.KOBJECT -> clazz.kotlin.objectInstance!!
|
||||
AllocateFunction.NONE -> throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||
}
|
||||
}
|
||||
}
|
272
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Members.kt
Normal file
272
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Members.kt
Normal file
@ -0,0 +1,272 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.reflect
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
|
||||
private val fieldModifiersField: Field? = try {
|
||||
Field::class.java.getDeclaredField("modifiers").apply {
|
||||
isAccessible = true
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
var fieldModifiers: (Field, Int) -> Unit = { field, modifer ->
|
||||
fieldModifiersField!!.set(field, modifer)
|
||||
}
|
||||
|
||||
var Field.public: Boolean
|
||||
get() = Modifier.isPublic(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.PUBLIC
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.private: Boolean
|
||||
get() = Modifier.isPrivate(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.PRIVATE
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.protected: Boolean
|
||||
get() = Modifier.isProtected(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.PROTECTED
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.static: Boolean
|
||||
get() = Modifier.isStatic(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.STATIC
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.final: Boolean
|
||||
get() = Modifier.isFinal(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.FINAL
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.synchronized: Boolean
|
||||
get() = Modifier.isSynchronized(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.SYNCHRONIZED
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.volatile: Boolean
|
||||
get() = Modifier.isVolatile(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.VOLATILE
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.transient: Boolean
|
||||
get() = Modifier.isTransient(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.TRANSIENT
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.native: Boolean
|
||||
get() = Modifier.isNative(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.NATIVE
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.`interface`: Boolean
|
||||
get() = Modifier.isInterface(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.INTERFACE
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.abstract: Boolean
|
||||
get() = Modifier.isAbstract(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.ABSTRACT
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var Field.strict: Boolean
|
||||
get() = Modifier.isStrict(this.modifiers)
|
||||
set(value) {
|
||||
val modifier = Modifier.STRICT
|
||||
fieldModifiers(
|
||||
this,
|
||||
if (value) {
|
||||
modifiers or modifier
|
||||
} else {
|
||||
modifiers and modifier.inv()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun Member.isPublic(): Boolean {
|
||||
return Modifier.isPublic(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isPrivate(): Boolean {
|
||||
return Modifier.isPrivate(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isProtected(): Boolean {
|
||||
return Modifier.isProtected(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isStatic(): Boolean {
|
||||
return Modifier.isStatic(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isFinal(): Boolean {
|
||||
return Modifier.isFinal(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isSynchronized(): Boolean {
|
||||
return Modifier.isSynchronized(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isVolatile(): Boolean {
|
||||
return Modifier.isVolatile(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isTransient(): Boolean {
|
||||
return Modifier.isTransient(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isNative(): Boolean {
|
||||
return Modifier.isNative(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isInterface(): Boolean {
|
||||
return Modifier.isInterface(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isAbstract(): Boolean {
|
||||
return Modifier.isAbstract(this.modifiers)
|
||||
}
|
||||
|
||||
fun Member.isStrict(): Boolean {
|
||||
return Modifier.isStrict(this.modifiers)
|
||||
}
|
||||
|
||||
val Class<*>.isPublic: Boolean
|
||||
get() = Modifier.isPublic(this.modifiers)
|
||||
|
||||
val Class<*>.isPrivate: Boolean
|
||||
get() = Modifier.isPrivate(this.modifiers)
|
||||
|
||||
val Class<*>.isProtected: Boolean
|
||||
get() = Modifier.isProtected(this.modifiers)
|
||||
|
||||
val Class<*>.isStatic: Boolean
|
||||
get() = Modifier.isStatic(this.modifiers)
|
||||
|
||||
val Class<*>.isFinal: Boolean
|
||||
get() = Modifier.isFinal(this.modifiers)
|
||||
|
||||
val Class<*>.isSynchronized: Boolean
|
||||
get() = Modifier.isSynchronized(this.modifiers)
|
||||
|
||||
val Class<*>.isVolatile: Boolean
|
||||
get() = Modifier.isVolatile(this.modifiers)
|
||||
|
||||
val Class<*>.isTransient: Boolean
|
||||
get() = Modifier.isTransient(this.modifiers)
|
||||
|
||||
val Class<*>.isNative: Boolean
|
||||
get() = Modifier.isNative(this.modifiers)
|
||||
|
||||
//val Class<*>.isInterface: Boolean
|
||||
// get() = Modifier.isInterface(this.modifiers)
|
||||
|
||||
val Class<*>.isAbstract
|
||||
get() = Modifier.isAbstract(this.modifiers)
|
||||
|
||||
val Class<*>.isStrict
|
||||
get() = Modifier.isStrict(this.modifiers)
|
@ -0,0 +1,36 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
interface MethodFilter {
|
||||
fun filterMethod(clazz: Class<*>): Sequence<Method>
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
|
||||
class Arg1MethodFilter<R>(
|
||||
val prevFilter: ReturnTypeMethodFilter<R>,
|
||||
) : MethodFilter {
|
||||
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||
return prevFilter.filterMethod(clazz).filter { method ->
|
||||
method.parameterCount == 1
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> filter(clazz: Class<T>): Sequence<T.() -> R> {
|
||||
return filterMethod(clazz).map {
|
||||
{
|
||||
it.invoke(this) as R
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun filter(obj: Any): Sequence<() -> R> {
|
||||
return filterMethod(obj.javaClass).map {
|
||||
{
|
||||
it.invoke(obj) as R
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,456 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.UncheckedCast
|
||||
import cn.tursom.core.cast
|
||||
import cn.tursom.core.forAllMethods
|
||||
import cn.tursom.log.impl.Slf4jImpl
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.reflect.jvm.javaType
|
||||
import kotlin.reflect.jvm.kotlinFunction
|
||||
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
object MethodInspector : Slf4jImpl() {
|
||||
fun <R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Array<Class<*>>,
|
||||
self: Any? = null,
|
||||
handler: (Method, (Array<Any?>) -> R) -> Unit,
|
||||
) {
|
||||
clazz.forAllMethods { method ->
|
||||
val parameterTypes = method.parameterTypes
|
||||
val methodReturnType = if (
|
||||
method.returnType == Void.TYPE ||
|
||||
method.returnType == Void::class.java
|
||||
) Unit::class.java else method.returnType
|
||||
|
||||
val argumentTypeIterator = argumentType.iterator()
|
||||
if (parameterTypes.size == argumentType.size &&
|
||||
parameterTypes.all {
|
||||
argumentTypeIterator.next().isAssignableFrom(it)
|
||||
} &&
|
||||
returnType.isAssignableFrom(methodReturnType)
|
||||
) {
|
||||
method.isAccessible = true
|
||||
@OptIn(UncheckedCast::class)
|
||||
handler(method) { method.invoke(self, *it).cast() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Array<Class<*>>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend (Array<Any?>) -> R) -> Unit,
|
||||
) {
|
||||
clazz.forAllMethods { method ->
|
||||
val parameterTypes = method.parameterTypes
|
||||
val kotlinFunction = method.kotlinFunction ?: return@forAllMethods
|
||||
var methodReturnType = kotlinFunction.returnType.javaType
|
||||
while (methodReturnType is ParameterizedType) {
|
||||
methodReturnType = methodReturnType.rawType
|
||||
}
|
||||
|
||||
if (methodReturnType !is Class<*>) {
|
||||
warn("method return type {}({}) is not Class", methodReturnType, methodReturnType.javaClass)
|
||||
return@forAllMethods
|
||||
}
|
||||
|
||||
val argumentTypeIterator = argumentType.iterator()
|
||||
if (parameterTypes.size - 1 == argumentType.size &&
|
||||
parameterTypes.dropLast(1).all {
|
||||
argumentTypeIterator.next().isAssignableFrom(it)
|
||||
} &&
|
||||
Continuation::class.java.isAssignableFrom(parameterTypes.last()) &&
|
||||
returnType.isAssignableFrom(methodReturnType)
|
||||
) {
|
||||
method.isAccessible = true
|
||||
@OptIn(UncheckedCast::class)
|
||||
handler(method, { it: Array<Any?>, cont: Continuation<*> -> method.invoke(self, *it, cont) }.cast())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun forEachMethod(clazz: Class<*>, self: Any? = null, handler: (Method, () -> Unit) -> Unit) {
|
||||
forEachMethod(clazz, Unit::class.java, self, handler)
|
||||
}
|
||||
|
||||
fun <R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
self: Any? = null,
|
||||
handler: (Method, () -> R) -> Unit,
|
||||
) {
|
||||
clazz.javaClass.forAllMethods { method ->
|
||||
val parameterTypes = method.parameterTypes
|
||||
val methodReturnType = if (
|
||||
method.returnType == Void.TYPE ||
|
||||
method.returnType == Void::class.java
|
||||
) Unit::class.java else method.returnType
|
||||
if (parameterTypes.isEmpty() && returnType.isAssignableFrom(methodReturnType)) {
|
||||
method.isAccessible = true
|
||||
@OptIn(UncheckedCast::class)
|
||||
handler(method) { method.invoke(self).cast() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Class<T>,
|
||||
self: Any? = null,
|
||||
handler: (Method, (T) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(clazz, returnType, arrayOf(argumentType), self) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
self: Any? = null,
|
||||
handler: (Method, (T1, T2) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2),
|
||||
self
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2 ->
|
||||
m(arrayOf(t1, t2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
self: Any? = null,
|
||||
handler: (Method, (T1, T2, T3) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3),
|
||||
self
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3 ->
|
||||
m(arrayOf(t1, t2, t3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, T4, R> forEachMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
argumentType4: Class<T4>,
|
||||
self: Any? = null,
|
||||
handler: (Method, (T1, T2, T3, T4) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4),
|
||||
self
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3, t4 ->
|
||||
m(arrayOf(t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun forEachSuspendMethod(clazz: Class<*>, self: Any? = null, handler: (Method, suspend () -> Unit) -> Unit) {
|
||||
forEachSuspendMethod(clazz, Unit::class.java, self, handler)
|
||||
}
|
||||
|
||||
fun <R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend () -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(clazz, returnType, arrayOf(), self) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Class<T>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend (T) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType),
|
||||
self
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend (T1, T2) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2),
|
||||
self
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2 ->
|
||||
m(arrayOf(t1, t2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend (T1, T2, T3) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3),
|
||||
self
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3 ->
|
||||
m(arrayOf(t1, t2, t3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, T4, R> forEachSuspendMethod(
|
||||
clazz: Class<*>,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
argumentType4: Class<T4>,
|
||||
self: Any? = null,
|
||||
handler: (Method, suspend (T1, T2, T3, T4) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
clazz,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4),
|
||||
self
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3, t4 ->
|
||||
m(arrayOf(t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <R> forEachMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Array<Class<*>>,
|
||||
handler: (Method, (Array<Any?>) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(self.javaClass, returnType, argumentType, self, handler)
|
||||
}
|
||||
|
||||
fun <R> forEachSuspendMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Array<Class<*>>,
|
||||
handler: (Method, suspend (Array<Any?>) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(self.javaClass, returnType, argumentType, self, handler)
|
||||
}
|
||||
|
||||
fun forEachMethod(self: Any, handler: (Method, () -> Unit) -> Unit) {
|
||||
forEachMethod(self, Unit::class.java, handler)
|
||||
}
|
||||
|
||||
fun <R> forEachMethod(self: Any, returnType: Class<out R>, handler: (Method, () -> R) -> Unit) {
|
||||
forEachMethod(self.javaClass, returnType, self, handler)
|
||||
}
|
||||
|
||||
fun <T, R> forEachMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Class<T>,
|
||||
handler: (Method, (T) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(self, returnType, arrayOf(argumentType)) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, R> forEachMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
handler: (Method, (T1, T2) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2)
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2 ->
|
||||
m(arrayOf(t1, t2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, R> forEachMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
handler: (Method, (T1, T2, T3) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3)
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3 ->
|
||||
m(arrayOf(t1, t2, t3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, T4, R> forEachMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
argumentType4: Class<T4>,
|
||||
handler: (Method, (T1, T2, T3, T4) -> R) -> Unit,
|
||||
) {
|
||||
forEachMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4)
|
||||
) { method: Method, m: (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3, t4 ->
|
||||
m(arrayOf(t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun forEachSuspendMethod(self: Any, handler: (Method, suspend () -> Unit) -> Unit) {
|
||||
forEachSuspendMethod(self, Unit::class.java, handler)
|
||||
}
|
||||
|
||||
fun <R> forEachSuspendMethod(self: Any, returnType: Class<out R>, handler: (Method, suspend () -> R) -> Unit) {
|
||||
forEachSuspendMethod(self, returnType, arrayOf()) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> forEachSuspendMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType: Class<T>,
|
||||
handler: (Method, suspend (T) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(self, returnType, arrayOf(argumentType)) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) {
|
||||
m(arrayOf(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, R> forEachSuspendMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
handler: (Method, suspend (T1, T2) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2)
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2 ->
|
||||
m(arrayOf(t1, t2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, R> forEachSuspendMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
handler: (Method, suspend (T1, T2, T3) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3)
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3 ->
|
||||
m(arrayOf(t1, t2, t3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, T4, R> forEachSuspendMethod(
|
||||
self: Any,
|
||||
returnType: Class<out R>,
|
||||
argumentType1: Class<T1>,
|
||||
argumentType2: Class<T2>,
|
||||
argumentType3: Class<T3>,
|
||||
argumentType4: Class<T4>,
|
||||
handler: (Method, suspend (T1, T2, T3, T4) -> R) -> Unit,
|
||||
) {
|
||||
forEachSuspendMethod(
|
||||
self,
|
||||
returnType,
|
||||
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4)
|
||||
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||
handler(method) { t1, t2, t3, t4 ->
|
||||
m(arrayOf(t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class NoargMethodFilter<R>(
|
||||
val prevFilter: ReturnTypeMethodFilter<R>,
|
||||
) : MethodFilter {
|
||||
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||
return prevFilter.filterMethod(clazz).filter { method ->
|
||||
method.parameterCount == 0
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> filter(clazz: Class<T>): Sequence<T.() -> R> {
|
||||
return filterMethod(clazz).map {
|
||||
{
|
||||
it.invoke(this) as R
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun filter(obj: Any): Sequence<() -> R> {
|
||||
return filterMethod(obj.javaClass).map {
|
||||
{
|
||||
it.invoke(obj) as R
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <R> ReturnTypeMethodFilter<R>.noarg() = NoargMethodFilter(this)
|
210
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Parser.kt
Normal file
210
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Parser.kt
Normal file
@ -0,0 +1,210 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.*
|
||||
import java.lang.reflect.Array
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.util.*
|
||||
|
||||
object Parser {
|
||||
private val simpleDateFormat = ThreadLocalSimpleDateFormat()
|
||||
private val Field.actualTypeArguments get() = (genericType as ParameterizedType).actualTypeArguments[0] as Class<*>
|
||||
|
||||
fun <T> parse(yaml: Any, clazz: Class<T>): T? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@OptIn(UncheckedCast::class)
|
||||
return when {
|
||||
clazz.isInstance(yaml) -> yaml.cast()
|
||||
clazz.isInheritanceFrom(Enum::class.java) -> (clazz as Class<out Enum<*>>).valueOf(yaml.toString()) as? T?
|
||||
clazz.isInheritanceFrom(Map::class.java) -> {
|
||||
val map = try {
|
||||
clazz.newInstance()
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
Unsafe.unsafe.allocateInstance(clazz)
|
||||
} catch (e: Exception) {
|
||||
HashMap<Any?, Any?>()
|
||||
}
|
||||
}.cast<MutableMap<Any?, Any?>>()
|
||||
if (yaml !is Map<*, *>) return null
|
||||
yaml.forEach { (any, u) ->
|
||||
map[any] = u
|
||||
}
|
||||
map.cast<T>()
|
||||
}
|
||||
yaml is List<*> && clazz.isArray -> parseArray(yaml, clazz) as T
|
||||
else -> when (clazz) {
|
||||
Any::class.java -> yaml
|
||||
Int::class.java -> yaml.toInt()
|
||||
Long::class.java -> yaml.toLong()
|
||||
Float::class.java -> yaml.toFloat()
|
||||
Double::class.java -> yaml.toDouble()
|
||||
Boolean::class.java -> yaml.toBoolean()
|
||||
|
||||
getClazz<Int>() -> yaml.toInt()
|
||||
getClazz<Long>() -> yaml.toLong()
|
||||
getClazz<Float>() -> yaml.toFloat()
|
||||
getClazz<Double>() -> yaml.toDouble()
|
||||
getClazz<Boolean>() -> yaml.toBoolean()
|
||||
Date::class.java -> yaml.toDate()
|
||||
String::class.java -> yaml.toString()
|
||||
|
||||
else -> {
|
||||
if (yaml !is Map<*, *>) return null
|
||||
val instance = try {
|
||||
clazz.newInstance()
|
||||
} catch (e: Exception) {
|
||||
Unsafe.unsafe.allocateInstance(clazz)
|
||||
}
|
||||
val fields = clazz.declaredFields
|
||||
fields.forEach {
|
||||
if ((it.modifiers and (Modifier.STATIC or Modifier.TRANSIENT)) != 0) return@forEach
|
||||
try {
|
||||
val parse = parseField(yaml[it.name] ?: return@forEach, it) ?: return@forEach
|
||||
it.isAccessible = true
|
||||
it.set(instance, parse)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
instance
|
||||
}
|
||||
} as T
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseField(yaml: Any, field: Field): Any? {
|
||||
val clazz = field.type
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (yaml) {
|
||||
is List<*> -> {
|
||||
when {
|
||||
clazz.isAssignableFrom(List::class.java) -> {
|
||||
val type = field.actualTypeArguments
|
||||
if (type == Any::class.java) {
|
||||
yaml
|
||||
} else {
|
||||
val list = try {
|
||||
clazz.newInstance() as MutableList<Any>
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
Unsafe.unsafe.allocateInstance(clazz) as MutableList<Any>
|
||||
} catch (e: Exception) {
|
||||
ArrayList<Any>()
|
||||
}
|
||||
}
|
||||
yaml.forEach {
|
||||
list.add(parse(it ?: return@forEach, type) ?: return@forEach)
|
||||
}
|
||||
list
|
||||
}
|
||||
}
|
||||
clazz.isAssignableFrom(Set::class.java) -> {
|
||||
val type = field.actualTypeArguments
|
||||
if (type == Any::class.java) {
|
||||
yaml
|
||||
} else {
|
||||
val set: MutableSet<Any> = try {
|
||||
clazz.newInstance() as MutableSet<Any>
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
Unsafe.unsafe.allocateInstance(clazz) as MutableSet<Any>
|
||||
} catch (e: Exception) {
|
||||
HashSet()
|
||||
}
|
||||
}
|
||||
yaml.forEach {
|
||||
set.add(parse(it ?: return@forEach, type) ?: return@forEach)
|
||||
}
|
||||
set
|
||||
}
|
||||
}
|
||||
clazz.isArray -> parseArray(yaml, clazz)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else -> parse(yaml, clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> parseArray(yaml: List<Any?>, clazz: Class<T>): kotlin.Array<T>? {
|
||||
val componentType = clazz.componentType
|
||||
val list = ArrayList<Any>()
|
||||
yaml.forEach {
|
||||
list.add(parse(it ?: return@forEach, componentType) ?: return@forEach)
|
||||
}
|
||||
val instance = Array.newInstance(componentType, list.size)
|
||||
list.forEachIndexed { index, any -> Array.set(instance, index, any) }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return instance as kotlin.Array<T>?
|
||||
}
|
||||
|
||||
private fun Any.toInt() = when (this) {
|
||||
is Number -> toInt()
|
||||
is Boolean -> if (this) 1 else 0
|
||||
is String -> toIntOrNull()
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> toString().toIntOrNull()
|
||||
}
|
||||
|
||||
private fun Any.toLong() = when (this) {
|
||||
is Number -> toLong()
|
||||
is Boolean -> if (this) 1L else 0L
|
||||
is String -> toLongOrNull()
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> toString().toLongOrNull()
|
||||
}
|
||||
|
||||
private fun Any.toFloat() = when (this) {
|
||||
is Number -> toFloat()
|
||||
is Boolean -> if (this) 1.0f else 0.0f
|
||||
is String -> toFloatOrNull()
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> toString().toFloatOrNull()
|
||||
}
|
||||
|
||||
private fun Any.toDouble() = when (this) {
|
||||
is Number -> toDouble()
|
||||
is Boolean -> if (this) 1.0 else 0.0
|
||||
is String -> toDoubleOrNull()
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> toString().toDoubleOrNull()
|
||||
}
|
||||
|
||||
private fun Any.toBoolean(): Boolean? = when (this) {
|
||||
is Boolean -> this
|
||||
is Number -> 0 != toInt()
|
||||
is String -> equals("t", true) || equals("true", true)
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> toString().toBoolean()
|
||||
}
|
||||
|
||||
private fun Any.toDate(): Date? = when (this) {
|
||||
is Number -> Date(toLong())
|
||||
is Boolean -> null
|
||||
is String -> when (val time = toLongOrNull()) {
|
||||
null -> simpleDateFormat.get().parse(this)
|
||||
else -> Date(time)
|
||||
}
|
||||
is Iterable<*> -> null
|
||||
is Iterator<*> -> null
|
||||
is Map<*, *> -> null
|
||||
else -> {
|
||||
val str = toString()
|
||||
when (val time = str.toLongOrNull()) {
|
||||
null -> simpleDateFormat.get().parse(str)
|
||||
else -> Date(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.allMethodsSequence
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class ReturnTypeMethodFilter<R>(
|
||||
val returnType: Class<R>,
|
||||
) : MethodFilter {
|
||||
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||
return clazz.allMethodsSequence.filter { method ->
|
||||
val methodReturnType = if (
|
||||
method.returnType == Void.TYPE ||
|
||||
method.returnType == Void::class.java
|
||||
) Unit::class.java else method.returnType
|
||||
returnType.isAssignableFrom(methodReturnType)
|
||||
}
|
||||
}
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
inline fun <reified R> MethodFilter.Companion.returnType() = ReturnTypeMethodFilter(R::class.java)
|
@ -0,0 +1,47 @@
|
||||
package cn.tursom.reflect
|
||||
|
||||
import cn.tursom.core.Unsafe.get
|
||||
import cn.tursom.core.companionObjectInstanceOrNull
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
|
||||
inline fun <reified T : Annotation> Class<*>.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||
inline fun <reified T : Annotation> Field.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||
inline fun <reified T : Annotation> Method.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||
|
||||
operator fun Class<*>.contains(obj: Any): Boolean = isInstance(obj)
|
||||
|
||||
fun <T> Class<*>.getStaticField(name: String): T? {
|
||||
val staticField = getDeclaredField(name)
|
||||
if (staticField.isStatic()) {
|
||||
staticField.isAccessible = true
|
||||
return staticField.get(null).uncheckedCast()
|
||||
}
|
||||
|
||||
val companionObjectInstance = kotlin.companionObjectInstanceOrNull
|
||||
if (companionObjectInstance != null) {
|
||||
return companionObjectInstance[name]?.uncheckedCast()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <reified C : Any, T> getStaticField(name: String): T? {
|
||||
return C::class.java.getStaticField(name)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Enum<out T>> Class<out T>.valueOf(value: String): T? {
|
||||
var valueOf: Method? = null
|
||||
return try {
|
||||
valueOf = getDeclaredMethod("valueOf", String::class.java)
|
||||
valueOf.invoke(null, value) as T
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
valueOf?.invoke(null, value.toUpperCase()) as? T?
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cn.tursom.database.ktorm
|
||||
|
||||
import org.ktorm.dsl.AssignmentsBuilder
|
||||
import org.ktorm.schema.ColumnDeclaring
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
inline fun <reified T : Any, C : Any> AssignmentsBuilder.set(
|
||||
column: KProperty1<T, C?>,
|
||||
value: C?,
|
||||
) {
|
||||
set(AutoTable[T::class.java][column], value)
|
||||
}
|
||||
|
||||
inline fun <reified T : Any, C : Any> AssignmentsBuilder.set(
|
||||
column: KProperty1<T, C?>,
|
||||
expr: ColumnDeclaring<C>,
|
||||
) {
|
||||
set(AutoTable[T::class.java][column], expr)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package cn.tursom.database.ktorm
|
||||
|
||||
import org.ktorm.dsl.QueryRowSet
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
inline operator fun <reified T : Any, C : Any> QueryRowSet.get(column: KProperty1<in T, C?>) =
|
||||
get(AutoTable[T::class.java][column])
|
Loading…
Reference in New Issue
Block a user