jvmMain.ch.softappeal.yass2.remote.ServiceReflection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yass2-jvm Show documentation
Show all versions of yass2-jvm Show documentation
Yet Another Service Solution
package ch.softappeal.yass2.remote
import ch.softappeal.yass2.*
import java.lang.reflect.*
import java.util.concurrent.*
import kotlin.coroutines.*
import kotlin.reflect.*
import kotlin.reflect.full.*
internal class FunctionMapper(private val service: KClass<*>) {
private val functions = service.serviceFunctions().toTypedArray()
private val name2id = functions.withIndex().map { (index, function) -> function.name to index }.toMap()
fun toFunction(id: Int) = if (id >= 0 && id < functions.size) functions[id] else error("'$service' has no function $id")
fun toId(name: String) = name2id[name] ?: error("'$service' has no function '$name'")
}
private val FunctionMappers = ConcurrentHashMap, FunctionMapper>(16)
private fun functionMapper(service: KClass<*>) = FunctionMappers.computeIfAbsent(service) { FunctionMapper(service) }
fun reflectionRemoteProxyFactory(tunnel: Tunnel) = object : RemoteProxyFactory {
override fun create(serviceId: ServiceId): S {
serviceId.service.checkService()
val functionMapper = functionMapper(serviceId.service)
val javaClass = serviceId.service.java
@Suppress("UNCHECKED_CAST")
return Proxy.newProxyInstance(javaClass.classLoader, arrayOf(javaClass)) { _, method, args ->
invokeSuspendFunction(args.last() as Continuation<*>) {
tunnel(
Request(serviceId.id, functionMapper.toId(method.name), listOf(*args.copyOf(args.size - 1)))
).process()
}
} as S
}
}
suspend fun reflectionInvoker(request: Request, service: Service): Any? = try {
functionMapper(service.serviceId.service)
.toFunction(request.functionId)
.callSuspend(service.implementation, *request.parameters.toTypedArray())
} catch (e: InvocationTargetException) {
throw e.cause!!
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy