mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-13 19:30:10 +08:00
faster proxy
This commit is contained in:
parent
d170678182
commit
3ae1044999
@ -1,7 +1,7 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.6.20"
|
||||
kotlin("jvm") version "1.8.0"
|
||||
`maven-publish`
|
||||
id("ts-gradle")
|
||||
}
|
||||
@ -10,12 +10,7 @@ allprojects {
|
||||
group = "cn.tursom"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
//mavenCentral()
|
||||
maven {
|
||||
url = uri("https://nvm.tursom.cn/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
useTursomRepositories()
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
@ -23,9 +18,7 @@ allprojects {
|
||||
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
|
||||
if (project.gradle.startParameter.taskNames.firstOrNull { taskName ->
|
||||
taskName.endsWith(":test")
|
||||
} == null) {
|
||||
if (!isTestRunning) {
|
||||
tasks.withType<Test> {
|
||||
enabled = false
|
||||
}
|
||||
@ -37,6 +30,8 @@ allprojects {
|
||||
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
//kotlinOptions.useIR = true
|
||||
}
|
||||
|
||||
autoConfigPublish()
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +45,3 @@ dependencies {
|
||||
artifacts {
|
||||
archives(tasks["kotlinSourcesJar"])
|
||||
}
|
||||
|
||||
publishing {
|
||||
publish(this)
|
||||
}
|
||||
|
@ -19,3 +19,6 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
|
||||
project.groupId=cn.tursom
|
||||
project.version=1.0-SNAPSHOT
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -15,6 +15,4 @@ dependencies {
|
||||
testApi(group = "junit", name = "junit", version = "4.13.2")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
autoConfigPublish()
|
||||
|
@ -4,7 +4,7 @@ import cn.tursom.core.uncheckedCast
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class ArrayContextEnv : ContextEnv {
|
||||
val envId = ContextEnv.newEnvId()
|
||||
override val envId = ContextEnv.newEnvId()
|
||||
private val idGenerator = AtomicInteger()
|
||||
private val emptyContext = EmptyArrayContext(envId, idGenerator)
|
||||
|
||||
|
@ -8,6 +8,8 @@ interface ContextEnv {
|
||||
fun newEnvId() = contextEnvIdGenerator.incrementAndGet()
|
||||
}
|
||||
|
||||
val envId: Int
|
||||
|
||||
fun emptyContext(): Context = newContext()
|
||||
fun newContext(): Context
|
||||
fun <T> newKey(): ContextKey<T>
|
||||
|
@ -4,7 +4,7 @@ import cn.tursom.core.uncheckedCast
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class HashMapContextEnv : ContextEnv {
|
||||
val envId = ContextEnv.newEnvId()
|
||||
override val envId = ContextEnv.newEnvId()
|
||||
private val idGenerator = AtomicInteger()
|
||||
|
||||
override fun newContext(): Context = HashMapContext(envId)
|
||||
|
@ -1,12 +1,33 @@
|
||||
import java.math.BigInteger
|
||||
|
||||
enum class Status(val id: Int) : (Int) -> Int {
|
||||
S1(1), S2(2), S3(3);
|
||||
|
||||
override fun invoke(i: Int): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
infix fun or(status: Status) = status.id or id
|
||||
infix fun or(status: Int) = id or status
|
||||
}
|
||||
|
||||
infix fun Int.or(status: Status) = this or status.id
|
||||
|
||||
inline fun <reified T> Any.instanceOf() = this is T
|
||||
|
||||
fun main() {
|
||||
val two = BigInteger.valueOf(2)
|
||||
val three = BigInteger.valueOf(3)
|
||||
val ten = BigInteger.TEN
|
||||
var i = BigInteger.ONE
|
||||
repeat(1000) {
|
||||
i *= two
|
||||
print("${i / ten / ten / ten % ten}")
|
||||
}
|
||||
println(1.instanceOf<Int>())
|
||||
println(1L.instanceOf<Int>())
|
||||
println(1f.instanceOf<Int>())
|
||||
|
||||
//var i1 = 1 or Status.S1
|
||||
//
|
||||
//val two = BigInteger.valueOf(2)
|
||||
//val three = BigInteger.valueOf(3)
|
||||
//val ten = BigInteger.TEN
|
||||
//var i = BigInteger.ONE
|
||||
//repeat(1000) {
|
||||
// i *= two
|
||||
// print("${i / ten / ten / ten % ten}")
|
||||
//}
|
||||
}
|
8
ts-core/ts-coroutine/src/test/kotlin/main.kt
Normal file
8
ts-core/ts-coroutine/src/test/kotlin/main.kt
Normal file
@ -0,0 +1,8 @@
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
tailrec fun pow(i: Int, n: Int = 1): Int = if (i <= 0) n else pow(i - 1, i * n)
|
||||
|
||||
suspend fun main() {
|
||||
delay(pow(10).toLong())
|
||||
println("finished")
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cn.tursom.core.curry
|
||||
|
||||
import cn.tursom.core.allMemberPropertiesSequence
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
fun example(f: (Int) -> (Int) -> (Int) -> Int) {
|
||||
f(1)(2)(3)
|
||||
|
||||
f(1, 2, 3)
|
||||
}
|
||||
|
||||
fun example2(f: (Int, Int, Int) -> Int) {
|
||||
f(1, 2, 3)
|
||||
|
||||
f(1, 2)(3)
|
||||
}
|
@ -8,10 +8,12 @@ import kotlin.reflect.KProperty
|
||||
* 如果你还需要对这个属性进行加锁,你就可以在后方加一个 .locked 即可
|
||||
* 如果还需要用指定的锁,在后面再加一个 (lock) 就玩成了
|
||||
* 使用例:
|
||||
* ```
|
||||
* class XXXImpl: XXX, FieldChangeListener by FieldChangeListenerImpl() {
|
||||
* val lock = ReentrantLock()
|
||||
* val field by listened(0).locker(lock)
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
interface DelegatedField<in T, out V> {
|
||||
/**
|
||||
|
@ -0,0 +1,49 @@
|
||||
package cn.tursom.core.delegation.observer
|
||||
|
||||
import cn.tursom.core.delegation.expirable
|
||||
import cn.tursom.core.delegation.filter
|
||||
import cn.tursom.core.delegation.notNull
|
||||
import java.lang.Thread.sleep
|
||||
|
||||
class A {
|
||||
@OptIn(Listenable::class)
|
||||
var field by listenable(0)
|
||||
.filter { _, new ->
|
||||
new >= 0
|
||||
}
|
||||
.expirable(100)
|
||||
.notNull {
|
||||
throw IllegalAccessError()
|
||||
}
|
||||
|
||||
@OptIn(Listenable::class)
|
||||
var canServer by listenable(true)
|
||||
|
||||
@OptIn(Listenable::class)
|
||||
var count: Int by listenable(0)
|
||||
}
|
||||
|
||||
fun f(obj: A) {
|
||||
obj::field.listen { old: Int?, new: Int? ->
|
||||
println("old: $old, new: $new")
|
||||
}
|
||||
|
||||
obj::canServer.listen { old, new ->
|
||||
println(new)
|
||||
}
|
||||
|
||||
obj::count.listen { old, new ->
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val a = A()
|
||||
f(a)
|
||||
|
||||
a.field = 1
|
||||
println(a.field)
|
||||
|
||||
sleep(1000)
|
||||
println(a.field)
|
||||
}
|
@ -11,7 +11,7 @@ dependencies {
|
||||
api(project(":ts-core"))
|
||||
api(project(":ts-core:ts-reflectasm"))
|
||||
api(group = "cglib", name = "cglib", version = "3.3.0")
|
||||
implementation(group = "net.bytebuddy", name = "byte-buddy", version = "1.12.22")
|
||||
//implementation(group = "net.bytebuddy", name = "byte-buddy", version = "1.12.22")
|
||||
implementation(group = "org.apache.commons", name = "commons-lang3", version = "3.8.1")
|
||||
testApi(group = "junit", name = "junit", version = "4.13.2")
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package cn.tursom.proxy.function;
|
||||
|
||||
import cn.tursom.proxy.container.ProxyContainer;
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction;
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class JavaReflectASMProxyMethodInvoker implements ProxyMethodCacheFunction {
|
||||
private final Object self;
|
||||
private final MethodAccess methodAccess;
|
||||
private final int index;
|
||||
|
||||
public JavaReflectASMProxyMethodInvoker(Object self, MethodAccess methodAccess, int index) {
|
||||
this.self = self;
|
||||
this.methodAccess = methodAccess;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(
|
||||
@Nullable Object obj,
|
||||
@NotNull ProxyContainer c,
|
||||
@Nullable Method method,
|
||||
@Nullable Object[] args,
|
||||
@Nullable MethodProxy proxy
|
||||
) {
|
||||
return methodAccess.invoke(self, index, args);
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import cn.tursom.proxy.container.ListProxyContainer
|
||||
import cn.tursom.proxy.container.MutableProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.function.ProxyMethod
|
||||
import cn.tursom.proxy.interceptor.CachedMethodInterceptor
|
||||
import cn.tursom.proxy.interceptor.LocalCachedProxyInterceptor
|
||||
import cn.tursom.proxy.interceptor.ProxyInterceptor
|
||||
import cn.tursom.reflect.final
|
||||
@ -23,14 +24,18 @@ object Proxy {
|
||||
it.final = false
|
||||
}
|
||||
|
||||
fun getContainer(obj: Any): ProxyContainer? {
|
||||
if (obj !is Factory) return null
|
||||
fun getContainer(obj: Factory): ProxyContainer? {
|
||||
val interceptor = obj.getCallback(0) as? ProxyInterceptor ?: return null
|
||||
return interceptor.container
|
||||
}
|
||||
|
||||
fun getMutableContainer(obj: Factory): MutableProxyContainer? {
|
||||
val interceptor = obj.getCallback(0) as? ProxyInterceptor ?: return null
|
||||
return interceptor.container as? MutableProxyContainer
|
||||
}
|
||||
|
||||
fun addProxy(obj: Any, proxy: ProxyMethod): Boolean {
|
||||
val container = getContainer(obj) as? MutableProxyContainer ?: return false
|
||||
val container = getContainer(obj as Factory) as? MutableProxyContainer ?: return false
|
||||
container.addProxy(proxy)
|
||||
return true
|
||||
}
|
||||
@ -48,7 +53,7 @@ object Proxy {
|
||||
container.target = obj
|
||||
container.ctx[directAccessorKey] = directAccessor
|
||||
|
||||
injectCallback(obj as Factory, container, directAccessor)
|
||||
injectCallback(obj as Factory, container, directAccessor as Factory)
|
||||
|
||||
return obj to container
|
||||
}
|
||||
@ -137,6 +142,7 @@ object Proxy {
|
||||
|
||||
fun <T : Any> newEnhancer(clazz: Class<T>, vararg interfaces: Class<*>): Enhancer {
|
||||
val enhancer = Enhancer()
|
||||
|
||||
enhancer.setSuperclass(clazz)
|
||||
if (interfaces.isNotEmpty()) {
|
||||
enhancer.setInterfaces(interfaces)
|
||||
@ -151,15 +157,17 @@ object Proxy {
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun injectCallback(obj: Any, container: ProxyContainer = defaultContainer(), target: Any = obj): ProxyContainer {
|
||||
obj as Factory
|
||||
fun injectCallback(
|
||||
obj: Factory,
|
||||
container: ProxyContainer = defaultContainer(),
|
||||
target: Factory = obj,
|
||||
): ProxyContainer {
|
||||
if (obj.getCallback(0) != null && obj.getCallback(0) is ProxyInterceptor) {
|
||||
return (obj.getCallback(0) as ProxyInterceptor).container
|
||||
}
|
||||
|
||||
val nonProxyClasses: MutableSet<Class<*>> = HashSet(listOf(Any::class.java))
|
||||
repeat(obj.callbacks.size) {
|
||||
obj.setCallback(it, LocalCachedProxyInterceptor(container, nonProxyClasses, target))
|
||||
obj.setCallback(it, LocalCachedProxyInterceptor(container, target))
|
||||
}
|
||||
return container
|
||||
}
|
||||
@ -170,27 +178,30 @@ object Proxy {
|
||||
|
||||
fun <T : Any> getSuperCaller(
|
||||
obj: T,
|
||||
): T = getContainer(obj)?.ctx?.get(directAccessorKey).uncheckedCast()
|
||||
): T = getContainer(obj as Factory)?.ctx?.get(directAccessorKey).uncheckedCast()
|
||||
|
||||
fun addNonProxyClass(target: Any, nonProxyClass: Class<*>): Boolean {
|
||||
if (target !is Factory ||
|
||||
target.getCallback(0) == null ||
|
||||
target.getCallback(0) !is ProxyInterceptor
|
||||
) {
|
||||
throw IllegalArgumentException()
|
||||
fun addNonProxyClass(target: Factory, nonProxyClass: Class<*>): Boolean {
|
||||
val container = getMutableContainer(target) ?: throw IllegalArgumentException()
|
||||
return container.nonProxyClasses.add(nonProxyClass)
|
||||
}
|
||||
|
||||
return (target.getCallback(0) as ProxyInterceptor).nonProxyClasses.add(nonProxyClass)
|
||||
fun removeNonProxyClass(target: Factory, nonProxyClass: Class<*>): Boolean {
|
||||
val container = getMutableContainer(target) ?: throw IllegalArgumentException()
|
||||
return container.nonProxyClasses.remove(nonProxyClass)
|
||||
}
|
||||
|
||||
fun removeNonProxyClass(target: Any, nonProxyClass: Class<*>): Boolean {
|
||||
if (target !is Factory ||
|
||||
target.getCallback(0) == null ||
|
||||
target.getCallback(0) !is ProxyInterceptor
|
||||
) {
|
||||
throw IllegalArgumentException()
|
||||
fun clearCallbackCache(target: Factory, container: ProxyContainer) {
|
||||
target.callbacks.forEachIndexed { index, callback ->
|
||||
if (callback == null) {
|
||||
target.setCallback(index, LocalCachedProxyInterceptor(container, target))
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
return (target.getCallback(0) as ProxyInterceptor).nonProxyClasses.remove(nonProxyClass)
|
||||
if (callback !is CachedMethodInterceptor) {
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
callback.clearCache()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,22 @@
|
||||
package cn.tursom.proxy.container
|
||||
|
||||
import cn.tursom.core.context.Context
|
||||
import cn.tursom.proxy.Proxy
|
||||
import cn.tursom.proxy.function.ProxyMethod
|
||||
import cn.tursom.proxy.util.CglibUtil
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import net.sf.cglib.proxy.Factory
|
||||
|
||||
|
||||
class ListProxyContainer(
|
||||
private val proxyList: MutableCollection<Any> = ArrayList(),
|
||||
override val nonProxyClasses: MutableSet<Class<*>> = HashSet(listOf(Any::class.java)),
|
||||
) : MutableProxyContainer {
|
||||
override lateinit var target: Any
|
||||
override val ctx: Context = ProxyContainer.ctxEnv.newContext()
|
||||
|
||||
private fun clearCache() {
|
||||
ctx[ProxyMethodCache.ctxKey].clear()
|
||||
|
||||
Proxy.clearCallbackCache(target as Factory, this)
|
||||
}
|
||||
|
||||
override fun addProxy(proxy: Any) {
|
||||
|
@ -2,6 +2,7 @@ package cn.tursom.proxy.container
|
||||
|
||||
interface MutableProxyContainer : ProxyContainer {
|
||||
override var target: Any
|
||||
override val nonProxyClasses: MutableSet<Class<*>>
|
||||
|
||||
fun addProxy(proxy: Any)
|
||||
fun addAllProxy(proxy: Collection<Any>?)
|
||||
|
@ -11,4 +11,5 @@ interface ProxyContainer : Iterable<Any> {
|
||||
// to impl, use override val context: Context = ProxyContainer.contextEnv.newContext()
|
||||
val ctx: Context
|
||||
val target: Any
|
||||
val nonProxyClasses: Set<Class<*>>
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package cn.tursom.proxy.container
|
||||
|
||||
import cn.tursom.proxy.function.ProxyMethod
|
||||
import cn.tursom.proxy.util.IntMap
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class ProxyMethodCache {
|
||||
companion object {
|
||||
@ -18,9 +20,22 @@ class ProxyMethodCache {
|
||||
}
|
||||
}
|
||||
|
||||
fun update(proxy: MethodProxy, function: ProxyMethodCacheFunction) {
|
||||
fun update(
|
||||
obj: Any,
|
||||
container: ProxyContainer,
|
||||
method: Method,
|
||||
proxy: MethodProxy,
|
||||
function: ProxyMethodCacheFunction,
|
||||
) {
|
||||
var handler = function
|
||||
container.forEach {
|
||||
if (it !is ProxyMethod) return@forEach
|
||||
|
||||
handler = it.onProxyHandlerCacheUpdate(handler, obj, container, method, proxy)
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
functionMap[proxy.superIndex] = function
|
||||
functionMap[proxy.superIndex] = handler
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
package cn.tursom.proxy.container
|
||||
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
fun interface ProxyMethodCacheFunction : (
|
||||
Any?,
|
||||
ProxyContainer,
|
||||
Method?,
|
||||
Array<out Any?>?,
|
||||
MethodProxy?,
|
||||
) -> Any?
|
||||
fun interface ProxyMethodCacheFunction {
|
||||
operator fun invoke(
|
||||
obj: Any?,
|
||||
c: ProxyContainer,
|
||||
method: Method?,
|
||||
args: Array<out Any?>?,
|
||||
proxy: MethodProxy?,
|
||||
): Any?
|
||||
}
|
||||
|
@ -15,11 +15,10 @@ class CachedOnForEachProxyImpl(
|
||||
a: Array<out Any?>?,
|
||||
proxy: MethodProxy?,
|
||||
): Any? {
|
||||
proxy!!
|
||||
|
||||
proxyList.forEach { p ->
|
||||
p(o, c, m, a, proxy)
|
||||
}
|
||||
return proxy.invokeSuper(o, a)
|
||||
|
||||
return proxy!!.invokeSuper(o, a)
|
||||
}
|
||||
}
|
@ -2,10 +2,22 @@ package cn.tursom.proxy.function
|
||||
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction
|
||||
import cn.tursom.reflect.asm.ReflectAsmUtils
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
object CallSuperProxyMethodCacheFunction : ProxyMethodCacheFunction {
|
||||
operator fun get(obj: Any, method: Method): ProxyMethodCacheFunction {
|
||||
val (methodAccess, index) = ReflectAsmUtils.getMethodByRegex(
|
||||
obj.javaClass,
|
||||
"CGLIB\\\$${method.name}\\\$.*".toRegex(),
|
||||
*method.parameterTypes,
|
||||
method.returnType,
|
||||
) ?: return CallSuperProxyMethodCacheFunction
|
||||
|
||||
return ReflectASMProxyMethodInvoker(obj, methodAccess, index).toJava()
|
||||
}
|
||||
|
||||
override fun invoke(
|
||||
obj: Any?,
|
||||
c: ProxyContainer,
|
||||
|
@ -4,21 +4,20 @@ import cn.tursom.proxy.annotation.ForEachProxy
|
||||
import cn.tursom.proxy.annotation.ForFirstProxy
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction
|
||||
import cn.tursom.reflect.asm.ReflectAsmInvoker
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
internal class JavaReflectProxyMethodInvoker(
|
||||
internal class JvmReflectProxyMethodInvoker(
|
||||
private val self: Any,
|
||||
private val method: Method,
|
||||
) : ProxyMethodCacheFunction {
|
||||
companion object {
|
||||
private val fastInvoker: Method.(Any?, Array<out Any?>?) -> Any? = Method::invoke
|
||||
|
||||
operator fun get(
|
||||
proxy: Any,
|
||||
method: Method,
|
||||
): JavaReflectProxyMethodInvoker? {
|
||||
var invoker: JavaReflectProxyMethodInvoker? = null
|
||||
): JvmReflectProxyMethodInvoker? {
|
||||
var invoker: JvmReflectProxyMethodInvoker? = null
|
||||
|
||||
val selfMethod: Method
|
||||
try {
|
||||
@ -39,9 +38,7 @@ internal class JavaReflectProxyMethodInvoker(
|
||||
selfMethod = proxy.javaClass.getMethod(methodName, *method.parameterTypes)
|
||||
selfMethod.isAccessible = true
|
||||
|
||||
invoker = JavaReflectProxyMethodInvoker(proxy, method)
|
||||
|
||||
//handlerCacheMap[method] = ProxyResult(invoker, true)
|
||||
invoker = JvmReflectProxyMethodInvoker(proxy, method)
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
|
||||
@ -56,6 +53,6 @@ internal class JavaReflectProxyMethodInvoker(
|
||||
args: Array<out Any?>?,
|
||||
proxy: MethodProxy?,
|
||||
): Any? {
|
||||
return fastInvoker(this.method, self, args)
|
||||
return ReflectAsmInvoker.invoke(this.method, self, args)
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ class OnForEachProxyImpl(
|
||||
proxy: MethodProxy?,
|
||||
): Any? {
|
||||
m!!
|
||||
proxy!!
|
||||
|
||||
val proxyList = if (cache) ArrayList() else emptyProxyList
|
||||
c.forEach { p ->
|
||||
@ -42,9 +41,13 @@ class OnForEachProxyImpl(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proxy!!
|
||||
|
||||
if (cache) {
|
||||
c.ctx[ProxyMethodCache.ctxKey].update(
|
||||
proxy, CachedOnForEachProxyImpl(proxyList)
|
||||
o!!, c, m, proxy,
|
||||
CachedOnForEachProxyImpl(proxyList),
|
||||
)
|
||||
}
|
||||
return proxy.invokeSuper(o, a)
|
||||
|
@ -32,6 +32,7 @@ class OnForFirstProxyImpl(
|
||||
): Any? {
|
||||
method!!
|
||||
proxy!!
|
||||
obj!!
|
||||
|
||||
container.forEach { p ->
|
||||
if (classes.isNotEmpty() && classes.none { c: Class<*> -> c.isInstance(p) }) {
|
||||
@ -40,7 +41,7 @@ class OnForFirstProxyImpl(
|
||||
|
||||
val handler = ProxyMethod.getHandler(p, method) ?: return@forEach
|
||||
if (ffpAnnotation.cache) {
|
||||
container.ctx[ProxyMethodCache.ctxKey].update(proxy, handler)
|
||||
container.ctx[ProxyMethodCache.ctxKey].update(obj, container, method, proxy, handler)
|
||||
}
|
||||
return handler(obj, container, method, args, proxy)
|
||||
}
|
||||
@ -68,15 +69,15 @@ class OnForFirstProxyImpl(
|
||||
val exceptionConstructor = ffpAnnotation.errClass.java.getConstructor(String::class.java)
|
||||
if (ffpAnnotation.cache) {
|
||||
container.ctx[ProxyMethodCache.ctxKey].update(
|
||||
proxy, ExceptionProxyMethodCacheFunctionImpl(exceptionConstructor, errMsg)
|
||||
obj, container, method, proxy, ExceptionProxyMethodCacheFunctionImpl(exceptionConstructor, errMsg)
|
||||
)
|
||||
}
|
||||
throw exceptionConstructor.newInstance(errMsg)
|
||||
}
|
||||
if (ffpAnnotation.cache) {
|
||||
container.ctx[ProxyMethodCache.ctxKey].update(
|
||||
proxy,
|
||||
CallSuperProxyMethodCacheFunction,
|
||||
obj, container, method, proxy,
|
||||
CallSuperProxyMethodCacheFunction[obj, method]
|
||||
)
|
||||
}
|
||||
return proxy.invokeSuper(obj, args)
|
||||
|
@ -14,6 +14,13 @@ interface ProxyMethod {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
fun onGet(f: ProxyMethodCacheFunction, method: Method): ProxyMethodCacheFunction = f
|
||||
|
||||
/**
|
||||
* disabled on default.
|
||||
*
|
||||
* override onCached to enable it
|
||||
*/
|
||||
fun onProxyInvoke(
|
||||
o: Any?,
|
||||
c: ProxyContainer,
|
||||
@ -25,12 +32,25 @@ interface ProxyMethod {
|
||||
return next(o, c, m, a, proxy)
|
||||
}
|
||||
|
||||
/**
|
||||
* 当有缓存更新时被调用
|
||||
*
|
||||
* 你可以以此替换缓存方法
|
||||
*/
|
||||
fun onProxyHandlerCacheUpdate(
|
||||
f: ProxyMethodCacheFunction,
|
||||
obj: Any,
|
||||
container: ProxyContainer,
|
||||
method: Method,
|
||||
proxy: MethodProxy,
|
||||
) = f
|
||||
|
||||
companion object {
|
||||
fun getHandler(proxy: Any, method: Method): ProxyMethodCacheFunction? {
|
||||
var handler = getReflectHandler(proxy, method) ?: return null
|
||||
|
||||
if (proxy is ProxyMethod) {
|
||||
handler = ProxyMethodInvoker(proxy, handler)
|
||||
handler = proxy.onGet(handler, method)
|
||||
}
|
||||
|
||||
return handler
|
||||
@ -39,10 +59,10 @@ interface ProxyMethod {
|
||||
private fun getReflectHandler(proxy: Any, method: Method): ProxyMethodCacheFunction? {
|
||||
val reflectAsmHandler = ReflectASMProxyMethodInvoker[proxy, method]
|
||||
if (reflectAsmHandler != null) {
|
||||
return reflectAsmHandler
|
||||
return reflectAsmHandler.toJava()
|
||||
}
|
||||
|
||||
val javaReflectHandler = JavaReflectProxyMethodInvoker[proxy, method]
|
||||
val javaReflectHandler = JvmReflectProxyMethodInvoker[proxy, method]
|
||||
if (javaReflectHandler != null) {
|
||||
return javaReflectHandler
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package cn.tursom.proxy.function
|
||||
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction
|
||||
import cn.tursom.reflect.asm.ReflectAsmInvoker
|
||||
import cn.tursom.reflect.asm.ReflectAsmUtils
|
||||
import com.esotericsoftware.reflectasm.MethodAccess
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
@ -13,19 +14,35 @@ internal class ReflectASMProxyMethodInvoker(
|
||||
private val index: Int,
|
||||
) : ProxyMethodCacheFunction {
|
||||
companion object {
|
||||
private val fastInvoker: MethodAccess.(Any, Int, Array<out Any?>?) -> Any? = MethodAccess::invoke
|
||||
|
||||
operator fun get(
|
||||
proxy: Any,
|
||||
method: Method,
|
||||
): ReflectASMProxyMethodInvoker? {
|
||||
val reflectAsmMethod = try {
|
||||
ReflectAsmUtils.getMethod(
|
||||
val methodParamTypes = method.parameterTypes
|
||||
val matchedMethods = ReflectAsmUtils.getMethodSequence(
|
||||
proxy.javaClass,
|
||||
method.name,
|
||||
paramTypes = method.parameterTypes,
|
||||
paramTypes = methodParamTypes,
|
||||
returnType = method.returnType,
|
||||
)
|
||||
).toList()
|
||||
when {
|
||||
matchedMethods.isEmpty() -> null
|
||||
|
||||
matchedMethods.size == 1 -> matchedMethods.first()
|
||||
|
||||
else -> matchedMethods.minBy { (methodAccess, methodIndex) ->
|
||||
var parameterIndex = 0
|
||||
methodAccess.parameterTypes[methodIndex].sumOf { parameterType ->
|
||||
if (methodParamTypes[parameterIndex++] != parameterType) {
|
||||
0L
|
||||
} else {
|
||||
1L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
@ -36,6 +53,8 @@ internal class ReflectASMProxyMethodInvoker(
|
||||
}
|
||||
}
|
||||
|
||||
fun toJava() = JavaReflectASMProxyMethodInvoker(self, methodAccess, index)
|
||||
|
||||
override fun invoke(
|
||||
obj: Any?,
|
||||
c: ProxyContainer,
|
||||
@ -43,6 +62,6 @@ internal class ReflectASMProxyMethodInvoker(
|
||||
args: Array<out Any?>?,
|
||||
proxy: MethodProxy?,
|
||||
): Any? {
|
||||
return fastInvoker(methodAccess, self, index, args)
|
||||
return ReflectAsmInvoker.invoke(methodAccess, self, index, args)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package cn.tursom.proxy.interceptor
|
||||
|
||||
import net.sf.cglib.proxy.MethodInterceptor
|
||||
|
||||
interface CachedMethodInterceptor : MethodInterceptor {
|
||||
fun clearCache()
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.tursom.proxy.interceptor
|
||||
|
||||
import cn.tursom.reflect.asm.ReflectAsmInvoker
|
||||
import cn.tursom.reflect.asm.ReflectAsmUtils
|
||||
import com.esotericsoftware.reflectasm.MethodAccess
|
||||
import net.sf.cglib.proxy.InvocationHandler
|
||||
@ -8,10 +9,6 @@ import java.lang.reflect.Method
|
||||
class LocalCachedNoProxyInvocationHandler(
|
||||
val proxy: Any,
|
||||
) : InvocationHandler {
|
||||
companion object {
|
||||
private val fastInvoker: MethodAccess.(Any, Int, Array<out Any?>?) -> Any? = MethodAccess::invoke
|
||||
}
|
||||
|
||||
private var handler: (method: Method?, args: Array<out Any>?) -> Any? = DefaultHandler()
|
||||
|
||||
override fun invoke(ignore: Any, method: Method?, args: Array<out Any>?): Any? {
|
||||
@ -29,7 +26,7 @@ class LocalCachedNoProxyInvocationHandler(
|
||||
method.returnType,
|
||||
)!!
|
||||
handler = MethodAccessHandler(methodAccess, index)
|
||||
return fastInvoker(methodAccess, proxy, index, args)
|
||||
return ReflectAsmInvoker.invoke(methodAccess, proxy, index, args)
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +34,7 @@ class LocalCachedNoProxyInvocationHandler(
|
||||
private val methodAccess: MethodAccess,
|
||||
private val index: Int,
|
||||
) : (Method?, Array<out Any>?) -> Any? {
|
||||
override fun invoke(method: Method?, args: Array<out Any>?) = fastInvoker(methodAccess, proxy, index, args)
|
||||
override fun invoke(method: Method?, args: Array<out Any>?) =
|
||||
ReflectAsmInvoker.invoke(methodAccess, proxy, index, args)
|
||||
}
|
||||
}
|
@ -3,29 +3,36 @@ package cn.tursom.proxy.interceptor
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyMethodCache
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction
|
||||
import net.sf.cglib.proxy.Factory
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class LocalCachedProxyInterceptor(
|
||||
container: ProxyContainer,
|
||||
nonProxyClasses: MutableSet<Class<*>>,
|
||||
val target: Any,
|
||||
) : ProxyInterceptor(container, nonProxyClasses) {
|
||||
val target: Factory,
|
||||
) : ProxyInterceptor(container), CachedMethodInterceptor {
|
||||
private var cache: ProxyMethodCacheFunction? = null
|
||||
private val c: ProxyContainer = container
|
||||
|
||||
override fun intercept(obj: Any?, method: Method?, args: Array<out Any?>?, proxy: MethodProxy): Any? {
|
||||
override fun clearCache() {
|
||||
cache = null
|
||||
}
|
||||
|
||||
override fun intercept(obj: Any?, method: Method?, args: Array<out Any?>?, proxy: MethodProxy?): Any? {
|
||||
var cache = this.cache
|
||||
|
||||
if (cache != null) {
|
||||
return cache(target, container, method, args, proxy)
|
||||
return cache(target, c, method, args, proxy)
|
||||
}
|
||||
|
||||
val methodCache = container.ctx[ProxyMethodCache.ctxKey]
|
||||
proxy!!
|
||||
|
||||
val methodCache = c.ctx[ProxyMethodCache.ctxKey]
|
||||
this.cache = methodCache[proxy]
|
||||
cache = this.cache
|
||||
|
||||
if (cache != null) {
|
||||
return cache(target, container, method, args, proxy)
|
||||
return cache(target, c, method, args, proxy)
|
||||
}
|
||||
|
||||
return super.intercept(target, method, args, proxy)
|
||||
|
@ -13,25 +13,25 @@ import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
|
||||
open class ProxyInterceptor(
|
||||
val container: ProxyContainer = ListProxyContainer(),
|
||||
val nonProxyClasses: MutableSet<Class<*>> = HashSet(listOf(Any::class.java)),
|
||||
val container: ProxyContainer = ListProxyContainer(nonProxyClasses = HashSet(listOf(Any::class.java))),
|
||||
) : MethodInterceptor {
|
||||
override fun intercept(obj: Any?, method: Method?, args: Array<out Any?>?, proxy: MethodProxy): Any? {
|
||||
override fun intercept(obj: Any?, method: Method?, args: Array<out Any?>?, proxy: MethodProxy?): Any? {
|
||||
val cache = container.ctx[ProxyMethodCache.ctxKey]
|
||||
var handler = cache[proxy]
|
||||
var handler = cache[proxy!!]
|
||||
if (handler != null) {
|
||||
return handler(obj, container, method, args, proxy)
|
||||
}
|
||||
|
||||
obj!!
|
||||
method!!
|
||||
|
||||
nonProxyClasses.forEach { nonProxyClass ->
|
||||
container.nonProxyClasses.forEach { nonProxyClass ->
|
||||
nonProxyClass.declaredMethods.forEach {
|
||||
if (it.name == method.name &&
|
||||
it.returnType.isAssignableFrom(method.returnType) &&
|
||||
it.parameterTypes.contentEquals(method.parameterTypes)
|
||||
) {
|
||||
cache.update(proxy, CallSuperProxyMethodCacheFunction)
|
||||
cache.update(obj, container, method, proxy, CallSuperProxyMethodCacheFunction[obj, method])
|
||||
return proxy.invokeSuper(obj, args)
|
||||
}
|
||||
}
|
||||
|
@ -2,37 +2,32 @@ package cn.tursom.proxy
|
||||
|
||||
import cn.tursom.core.allFieldsSequence
|
||||
import cn.tursom.core.static
|
||||
import cn.tursom.proxy.container.ProxyContainer
|
||||
import cn.tursom.proxy.container.ProxyMethodCacheFunction
|
||||
import cn.tursom.proxy.function.ProxyMethod
|
||||
import com.esotericsoftware.reflectasm.MethodAccess
|
||||
import net.sf.cglib.proxy.InvocationHandler
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import org.junit.Test
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class Example {
|
||||
companion object {
|
||||
var bytes: ByteArray? = null
|
||||
|
||||
fun saveBytes(b: ByteArray) {
|
||||
bytes = b
|
||||
}
|
||||
}
|
||||
|
||||
open class TestClass protected constructor() {
|
||||
open var a: Int = 0
|
||||
open var a: Int? = 0
|
||||
}
|
||||
|
||||
class GetA(
|
||||
t: TestClass,
|
||||
) {
|
||||
) : ProxyMethod {
|
||||
val t: TestClass = Proxy.getSuperCaller(t)
|
||||
|
||||
val a: Int
|
||||
get() = t.a + 1
|
||||
|
||||
//fun getA(): Int {
|
||||
// return t.a + 1
|
||||
//}
|
||||
val a get() = (t.a ?: 0) + 1
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -95,9 +90,35 @@ class Example {
|
||||
container.addProxy(GetA(t))
|
||||
|
||||
println(t.javaClass)
|
||||
repeat(1000000000) {
|
||||
for (l in 0..10_000_000_000L) {
|
||||
t.a = t.a
|
||||
//println(t.a)
|
||||
}
|
||||
}
|
||||
|
||||
interface IntContainer {
|
||||
var i: Int?
|
||||
}
|
||||
|
||||
class IntContainerImpl(override var i: Int?) : IntContainer
|
||||
|
||||
class IntProxy(
|
||||
private val c: IntContainer,
|
||||
) : IntContainer {
|
||||
override var i: Int?
|
||||
get() = (c.i ?: 0) + 1
|
||||
set(value) {
|
||||
c.i = value
|
||||
}
|
||||
}
|
||||
|
||||
private val a: IntContainerImpl = IntContainerImpl(0)
|
||||
|
||||
@Test
|
||||
fun benchmarkOrigin() {
|
||||
val p: IntContainer = IntProxy(a)
|
||||
|
||||
for (l in 0..10000000000L) {
|
||||
p.i = p.i
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cn.tursom.reflect.asm;
|
||||
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectAsmInvoker {
|
||||
@Nullable
|
||||
public static Object invoke(MethodAccess methodAccess, Object obj, int index, Object[] args) {
|
||||
return methodAccess.invoke(obj, index, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Object invoke(Method method, Object obj, Object[] args) throws InvocationTargetException, IllegalAccessException {
|
||||
return method.invoke(obj, args);
|
||||
}
|
||||
}
|
@ -62,6 +62,7 @@ object ReflectAsmUtils {
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
fieldAccessList.add(MethodAccess.get(analyzeFieldAccessClass)!!)
|
||||
methodAccessMap[this] = fieldAccessList
|
||||
fieldAccessList
|
||||
}
|
||||
@ -84,6 +85,41 @@ object ReflectAsmUtils {
|
||||
return null
|
||||
}
|
||||
|
||||
fun getMethodSequence(
|
||||
clazz: Class<*>,
|
||||
methodName: String,
|
||||
vararg paramTypes: Class<*>,
|
||||
returnType: Class<*> = Any::class.java,
|
||||
) = sequence {
|
||||
clazz.methodAccessList.forEach { methodAccess ->
|
||||
repeat(methodAccess.methodNames.size) { i ->
|
||||
if (methodAccess.methodNames[i] == methodName && methodAccess.parameterTypes[i] match paramTypes &&
|
||||
methodAccess.returnTypes[i] canCast returnType
|
||||
) {
|
||||
yield(methodAccess to i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMethodByRegex(
|
||||
clazz: Class<*>,
|
||||
methodName: Regex,
|
||||
vararg paramTypes: Class<*>,
|
||||
returnType: Class<*> = Any::class.java,
|
||||
): Pair<MethodAccess, Int>? {
|
||||
clazz.methodAccessList.forEach { methodAccess ->
|
||||
repeat(methodAccess.methodNames.size) { i ->
|
||||
if (methodName.matches(methodAccess.methodNames[i]) && methodAccess.parameterTypes[i] match paramTypes &&
|
||||
methodAccess.returnTypes[i] canCast returnType
|
||||
) {
|
||||
return methodAccess to i
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getMethod(method: Method): Pair<MethodAccess, Int>? = getMethod(
|
||||
method.declaringClass,
|
||||
method.name,
|
||||
|
@ -1,6 +1,6 @@
|
||||
package cn.tursom.database.ktorm.ext
|
||||
|
||||
import cn.tursom.proxy.ProxyMethod
|
||||
import cn.tursom.proxy.function.ProxyMethod
|
||||
import cn.tursom.reflect.asm.ReflectAsmKtField
|
||||
import org.ktorm.expression.SqlExpression
|
||||
import org.ktorm.expression.SqlFormatter
|
||||
|
@ -2,7 +2,7 @@
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.3.72"
|
||||
kotlin("jvm") version "1.7.10"
|
||||
`java-gradle-plugin`
|
||||
`maven-publish`
|
||||
}
|
||||
@ -14,10 +14,10 @@ try {
|
||||
ext.set(k.toString(), v)
|
||||
try {
|
||||
setProperty(k.toString(), v)
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
|
||||
group = "cn.tursom"
|
||||
@ -25,11 +25,13 @@ group = "cn.tursom"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = uri("https://nvm.tursom.cn/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(group = "org.yaml", name = "snakeyaml", version = "1.29")
|
||||
implementation(group = "org.yaml", name = "snakeyaml", version = "1.33")
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to arrayOf("*.jar"))))
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ publishing {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("cannot push to repository tursom")
|
||||
println("cannot push to repository tursom: ${e.javaClass}: ${e.message}")
|
||||
}
|
||||
try {
|
||||
maven {
|
||||
|
@ -1,12 +1,15 @@
|
||||
import org.gradle.api.DomainObjectCollection
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.PasswordCredentials
|
||||
import org.gradle.api.publish.PublicationContainer
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.internal.authentication.DefaultBasicAuthentication
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
var nettyVersion = "4.1.68.Final"
|
||||
|
||||
fun Project.excludeTest() {
|
||||
if (gradle.startParameter.taskNames.firstOrNull { taskName ->
|
||||
taskName.contains("test", true)
|
||||
@ -17,92 +20,13 @@ fun Project.excludeTest() {
|
||||
named("compileTestJava") { it.enabled = false }
|
||||
try {
|
||||
named("compileTestKotlin") { it.enabled = false }
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
named("processTestResources") { it.enabled = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.publish(publish: PublishingExtension) {
|
||||
val properties = rootProject.properties
|
||||
publish.repositories { repositoryHandler ->
|
||||
try {
|
||||
repositoryHandler.maven { repository ->
|
||||
repository.name = "tursom"
|
||||
repository.url = if (version.toString().endsWith("SNAPSHOT")) {
|
||||
uri("https://nvm.tursom.cn/repository/maven-snapshots/")
|
||||
} else {
|
||||
uri("https://nvm.tursom.cn/repository/maven-releases/")
|
||||
}
|
||||
repository.credentials { credentials ->
|
||||
val artifactoryUser: String = rootProject.ext["tursom.artifactoryUser"]!!.toString()
|
||||
val artifactoryPassword: String = rootProject.ext["tursom.artifactoryPassword"]!!.toString()
|
||||
credentials.username = artifactoryUser
|
||||
credentials.password = artifactoryPassword
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("cannot publish to repository tursom:\n${e.javaClass}: ${e.message}")
|
||||
}
|
||||
|
||||
val repositoriesRegex = "publishRepositories\\.[a-zA-z][a-zA-z0-9]*".toRegex()
|
||||
properties.keys.asSequence().filter {
|
||||
it matches repositoriesRegex
|
||||
}.forEach { repositoryName ->
|
||||
try {
|
||||
val artifactoryUser = rootProject.ext["$repositoryName.artifactoryUser"]?.toString()
|
||||
?: throw Exception("no artifactory user found")
|
||||
val artifactoryPassword = rootProject.ext["$repositoryName.artifactoryPassword"]?.toString()
|
||||
?: throw Exception("no artifactory password found")
|
||||
repositoryHandler.maven { repository ->
|
||||
repository.name = properties["$repository.name"]?.toString()
|
||||
?: repositoryName.substringAfterLast('.')
|
||||
val releasesRepoUrl = properties["$repositoryName.release"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
val snapshotRepoUrl = properties["$repositoryName.snapshot"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
val repoUrl = properties["$repositoryName.url"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
repository.url = if (version.toString().endsWith("SNAPSHOT") && snapshotRepoUrl != null) {
|
||||
snapshotRepoUrl
|
||||
} else {
|
||||
releasesRepoUrl
|
||||
} ?: repoUrl ?: throw Exception("no repo found")
|
||||
repository.credentials {
|
||||
it.username = artifactoryUser
|
||||
it.password = artifactoryPassword
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(
|
||||
"cannot publish to repository ${repositoryName.substringAfterLast('.')}:\n" +
|
||||
"${e.javaClass}: ${e.message}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
publish.publications {
|
||||
it.create("maven", MavenPublication::class.java) { mavenPublication ->
|
||||
mavenPublication.groupId = project.group.toString()
|
||||
mavenPublication.artifactId = project.name
|
||||
mavenPublication.version = project.version.toString()
|
||||
|
||||
try {
|
||||
mavenPublication.from(components.getByName("java"))
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
try {
|
||||
mavenPublication.artifact(tasks.getByName("kotlinSourcesJar"))
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DomainObjectCollection<Configuration>.noExpire() {
|
||||
all {
|
||||
it.resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
|
||||
@ -110,7 +34,7 @@ fun DomainObjectCollection<Configuration>.noExpire() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.userTursomRepositories(
|
||||
fun Project.useTursomRepositories(
|
||||
useAliyunMirror: Boolean = false,
|
||||
mavenCentral: Boolean = false,
|
||||
tursom: Boolean = true
|
||||
@ -132,6 +56,19 @@ fun Project.userTursomRepositories(
|
||||
}
|
||||
try {
|
||||
configurations.noExpire()
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> NamedDomainObjectCollection<T>.contains(name: String) = try {
|
||||
findByName(name)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
null
|
||||
} != null
|
||||
|
||||
operator fun Project.get(key: String) = ext[key]?.toString()
|
||||
|
||||
val Project.isTestRunning
|
||||
get() = gradle.startParameter.taskNames.firstOrNull { taskName ->
|
||||
taskName.endsWith(":test")
|
||||
} != null
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.tursom.gradle
|
||||
|
||||
import contains
|
||||
import excludeTest
|
||||
import ext
|
||||
import org.gradle.api.DefaultTask
|
||||
@ -37,19 +38,7 @@ class TursomGradlePlugin : Plugin<Project> {
|
||||
|
||||
target.excludeTest()
|
||||
|
||||
try {
|
||||
target.extensions.configure<PublishingExtension>("publishing") {
|
||||
target.publish(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
|
||||
if (try {
|
||||
target.tasks.findByName("install")
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
} == null
|
||||
) run install@{
|
||||
if (!target.tasks.contains("install")) run install@{
|
||||
val publishToMavenLocal = target.tasks.findByName("publishToMavenLocal") ?: return@install
|
||||
target.tasks.register("install", DefaultTask::class.java) {
|
||||
it.finalizedBy(publishToMavenLocal)
|
||||
@ -85,6 +74,7 @@ fun put(target: Project, key: String, value: Any?) {
|
||||
null -> return
|
||||
is String, is Byte, is Short, is Int, is Long, is Float, is Double, is Char ->
|
||||
setProperty(target, key, value)
|
||||
|
||||
else -> {
|
||||
setProperty(target, key, value)
|
||||
if (value is Map<*, *>) {
|
||||
|
1
ts-gradle/src/main/kotlin/consts.kt
Normal file
1
ts-gradle/src/main/kotlin/consts.kt
Normal file
@ -0,0 +1 @@
|
||||
var nettyVersion = "4.1.68.Final"
|
176
ts-gradle/src/main/kotlin/publish.kt
Normal file
176
ts-gradle/src/main/kotlin/publish.kt
Normal file
@ -0,0 +1,176 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.PasswordCredentials
|
||||
import org.gradle.api.publish.PublicationContainer
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.authentication.http.BasicAuthentication
|
||||
|
||||
fun Project.autoConfigPublish() {
|
||||
try {
|
||||
extensions.configure("publishing", ::publish)
|
||||
} catch (e: Exception) {
|
||||
println("auto config publish failed: ${e.javaClass} ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.publish(publish: PublishingExtension) {
|
||||
publish.repositories { repositoryHandler ->
|
||||
createTursomPublishRepository(repositoryHandler)
|
||||
scanAndCreatePublishRepository(repositoryHandler)
|
||||
}
|
||||
|
||||
publish.publications(::createMavenPublications)
|
||||
}
|
||||
|
||||
/**
|
||||
* create publish repository for tursom's server
|
||||
*/
|
||||
private fun Project.createTursomPublishRepository(repositoryHandler: RepositoryHandler) {
|
||||
try {
|
||||
repositoryHandler.maven { repository ->
|
||||
repository.name = "tursom"
|
||||
val version = getVersionWithProperties()
|
||||
if (warnVersionNotSet(version)) {
|
||||
return@maven
|
||||
}
|
||||
|
||||
repository.url = if (version.endsWith("SNAPSHOT")) {
|
||||
uri("https://nvm.tursom.cn/repository/maven-snapshots/")
|
||||
} else {
|
||||
uri("https://nvm.tursom.cn/repository/maven-releases/")
|
||||
}
|
||||
|
||||
repository.authentication{ ac ->
|
||||
ac.forEach {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
repository.credentials(PasswordCredentials::class.java) { credentials ->
|
||||
val artifactoryUser: String = rootProject.ext["tursom.artifactoryUser"]!!.toString()
|
||||
val artifactoryPassword: String = rootProject.ext["tursom.artifactoryPassword"]!!.toString()
|
||||
credentials.username = artifactoryUser
|
||||
credentials.password = artifactoryPassword
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("cannot publish to repository tursom:\n${e.javaClass}: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* scan properties begin with "publishRepositories" to create user defined publish repository
|
||||
*/
|
||||
private fun Project.scanAndCreatePublishRepository(repositoryHandler: RepositoryHandler) {
|
||||
val properties = rootProject.properties
|
||||
val repositoriesRegex = "^publishRepositories\\.[a-zA-z][a-zA-z0-9]*$".toRegex()
|
||||
|
||||
properties.keys.asSequence().filter {
|
||||
it matches repositoriesRegex
|
||||
}.forEach { repositoryName ->
|
||||
try {
|
||||
val artifactoryUser = rootProject.ext["$repositoryName.artifactoryUser"]?.toString()
|
||||
?: throw Exception("no artifactory user found")
|
||||
val artifactoryPassword = rootProject.ext["$repositoryName.artifactoryPassword"]?.toString()
|
||||
?: throw Exception("no artifactory password found")
|
||||
repositoryHandler.maven { repository ->
|
||||
repository.name = properties["$repository.name"]?.toString()
|
||||
?: repositoryName.substringAfterLast('.')
|
||||
val releasesRepoUrl = properties["$repositoryName.release"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
val snapshotRepoUrl = properties["$repositoryName.snapshot"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
val repoUrl = properties["$repositoryName.url"]?.let {
|
||||
uri(it.toString())
|
||||
}
|
||||
repository.url = if (version.toString().endsWith("SNAPSHOT") && snapshotRepoUrl != null) {
|
||||
snapshotRepoUrl
|
||||
} else {
|
||||
releasesRepoUrl
|
||||
} ?: repoUrl ?: throw Exception("no repo found")
|
||||
repository.credentials {
|
||||
it.username = artifactoryUser
|
||||
it.password = artifactoryPassword
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(
|
||||
"cannot publish to repository ${repositoryName.substringAfterLast('.')}:\n" +
|
||||
"${e.javaClass}: ${e.message}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createMavenPublications(pc: PublicationContainer) {
|
||||
pc.maybeCreate("maven", MavenPublication::class.java).let { mavenPublication ->
|
||||
|
||||
val groupId = project.group.toString()
|
||||
.ifBlank { ext.properties["project.groupId"]?.toString() }
|
||||
if (warnGroupIdNotSet(groupId)) {
|
||||
return
|
||||
}
|
||||
|
||||
val version = getVersionWithProperties()
|
||||
if (warnVersionNotSet(version)) {
|
||||
return
|
||||
}
|
||||
|
||||
mavenPublication.groupId = groupId
|
||||
mavenPublication.artifactId = project.name
|
||||
mavenPublication.version = version
|
||||
|
||||
try {
|
||||
mavenPublication.from(components.getByName("java"))
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
try {
|
||||
mavenPublication.artifact(tasks.getByName("kotlinSourcesJar"))
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* warn user that group id is not set.
|
||||
* @return true if group id is not set
|
||||
* false if group id is set.
|
||||
*/
|
||||
private fun Project.warnGroupIdNotSet(groupId: String?) = if (groupId.isNullOrEmpty()) {
|
||||
println(
|
||||
"cannot publish to maven of project $this cause group id is not set. " +
|
||||
"you can specific property \"project.groupId\" to solve it."
|
||||
)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* warn user that group id is not set.
|
||||
* @return true if group id is not set
|
||||
* false if group id is set.
|
||||
*/
|
||||
private fun Project.warnVersionNotSet(version: String?) = if (isEmptyVersion(version)) {
|
||||
println(
|
||||
"cannot publish to maven of project $this cause version is not set. " +
|
||||
"you can specific property \"project.version\" to solve it."
|
||||
)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
private fun isEmptyVersion(version: String?) = version.isNullOrEmpty() || version == Project.DEFAULT_VERSION
|
||||
|
||||
private fun Project.getVersionWithProperties(): String {
|
||||
var version = this.version.toString()
|
||||
if (isEmptyVersion(version)) {
|
||||
version = ext["project.version"]?.toString() ?: Project.DEFAULT_VERSION
|
||||
}
|
||||
|
||||
return version
|
||||
}
|
@ -313,7 +313,6 @@ open class RoutedHttpHandler(
|
||||
fun autoReturn(result: Any?, content: HttpContent, doLog: Boolean = true) {
|
||||
if (content.finished || result is Unit) return
|
||||
if (doLog) log?.debug("{}: autoReturn: {}", content.remoteAddress, result)
|
||||
result ?: return
|
||||
when (result) {
|
||||
null -> content.finish(404)
|
||||
is ByteBuffer -> content.finishText(result)
|
||||
@ -336,7 +335,6 @@ open class RoutedHttpHandler(
|
||||
fun finishHtml(result: Any?, content: HttpContent, doLog: Boolean = true) {
|
||||
if (content.finished || result is Unit) return
|
||||
if (doLog) log?.debug("{} finishHtml {}", content.remoteAddress, result)
|
||||
result ?: return
|
||||
when (result) {
|
||||
null -> content.finish(404)
|
||||
is ByteBuffer -> content.finishHtml(result)
|
||||
@ -355,7 +353,6 @@ open class RoutedHttpHandler(
|
||||
fun finishText(result: Any?, content: HttpContent, doLog: Boolean = true) {
|
||||
if (content.finished || result is Unit) return
|
||||
if (doLog) log?.debug("{} finishText {}", content.remoteAddress, result)
|
||||
result ?: return
|
||||
when (result) {
|
||||
null -> content.finish(404)
|
||||
is ByteBuffer -> content.finishText(result)
|
||||
@ -374,7 +371,6 @@ open class RoutedHttpHandler(
|
||||
fun finishJson(result: Any?, content: HttpContent, doLog: Boolean = true) {
|
||||
if (content.finished || result is Unit) return
|
||||
if (doLog) log?.debug("{} finishJson {}", content.remoteAddress, result)
|
||||
result ?: return
|
||||
when (result) {
|
||||
null -> content.finish(404)
|
||||
is ByteBuffer -> content.finishJson(result)
|
||||
|
@ -15,6 +15,7 @@ class NettyChunkedInput(private val chunked: Chunked) : ChunkedInput<ByteBuf> {
|
||||
override fun length() = chunked.length
|
||||
override fun isEndOfInput(): Boolean = chunked.endOfInput
|
||||
|
||||
@Deprecated("Deprecated in Java", ReplaceWith("readChunk(allocator)"))
|
||||
override fun readChunk(ctx: ChannelHandlerContext?): ByteBuf = readChunk()
|
||||
override fun readChunk(allocator: ByteBufAllocator?): ByteBuf = readChunk()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user