11package io.github.freya022.botcommands.internal.core.method.accessors
22
33import dev.freya02.botcommands.method.accessors.api.annotations.ExperimentalMethodAccessorsApi
4- import dev.freya02.botcommands.method.accessors.internal.ClassFileMethodAccessorFactory
54import dev.freya02.botcommands.method.accessors.internal.KotlinReflectMethodAccessorFactory
65import dev.freya02.botcommands.method.accessors.internal.MethodAccessor
76import dev.freya02.botcommands.method.accessors.internal.MethodAccessorFactory
@@ -11,37 +10,53 @@ import kotlin.reflect.KFunction
1110
1211internal object MethodAccessorFactoryProvider {
1312
14- private var logged = false
13+ private lateinit var accessorFactory: MethodAccessorFactory
14+ private val staticAccessors: MutableMap <KFunction <* >, MethodAccessor <* >> = hashMapOf()
15+
16+ internal fun getAccessorFactory (): MethodAccessorFactory {
17+ if (::accessorFactory.isInitialized) return accessorFactory
18+
19+ synchronized(this ) {
20+ if (::accessorFactory.isInitialized) return accessorFactory
1521
16- private val kotlinReflectAccessorFactory: MethodAccessorFactory = KotlinReflectMethodAccessorFactory ()
17- private val classFileAccessorFactory by lazy<MethodAccessorFactory ?> {
18- if (Runtime .version().feature() >= 24 ) {
19- ClassFileMethodAccessorFactory ()
20- } else {
21- null
22+ accessorFactory = loadAccessorFactory()
2223 }
23- }
2424
25- private val staticAccessors: MutableMap <KFunction <* >, MethodAccessor <* >> = hashMapOf()
25+ return accessorFactory
26+ }
2627
2728 @OptIn(ExperimentalMethodAccessorsApi ::class )
28- internal fun getAccessorFactory (): MethodAccessorFactory {
29- fun logUsage (msg : String ) {
30- if (logged) return
31- synchronized(this ) {
32- if (logged) return
33- logged = true
34- }
35- KotlinLogging .logger { }.info { msg }
29+ private fun loadAccessorFactory (): MethodAccessorFactory {
30+ if (BotCommands .preferClassFileAccessors) {
31+ val accessorFactory = tryLoadClassFileAccessor()
32+ if (accessorFactory != null ) return accessorFactory
3633 }
3734
38- return if (BotCommands .preferClassFileAccessors && classFileAccessorFactory != null ) {
39- logUsage(" Using ClassFile-based method accessor factory" )
40- classFileAccessorFactory!!
41- } else {
42- logUsage(" Using kotlin-reflect method accessor factory" )
43- kotlinReflectAccessorFactory
35+ val logger = KotlinLogging .logger { }
36+ logger.debug { " Using kotlin-reflect method accessors" }
37+ return KotlinReflectMethodAccessorFactory ()
38+ }
39+
40+ private fun tryLoadClassFileAccessor (): MethodAccessorFactory ? {
41+ val logger = KotlinLogging .logger { }
42+
43+ val runtimeFeature = Runtime .version().feature()
44+ if (runtimeFeature < 24 ) {
45+ logger.debug { " Cannot use ClassFile-based method accessors as this feature requires Java 24+, currently running on Java $runtimeFeature " }
46+ return null
4447 }
48+
49+ val accessorFactory = try {
50+ Class .forName(" dev.freya02.botcommands.method.accessors.internal.ClassFileMethodAccessorFactory" )
51+ .getDeclaredConstructor()
52+ .newInstance() as MethodAccessorFactory
53+ } catch (e: ClassNotFoundException ) {
54+ logger.debug(e) { " Cannot use ClassFile-based method accessors as the 'BotCommands-method-accessors-classfile' dependency is missing" }
55+ return null
56+ }
57+
58+ logger.debug { " Using ClassFile-based method accessors" }
59+ return accessorFactory
4560 }
4661
4762 internal fun <R > getStaticAccessor (function : KFunction <R >): MethodAccessor <R > = synchronized(this ) {
0 commit comments