From 35c08e8b16abcb513aed6fcd8e0c62cbaaee3213 Mon Sep 17 00:00:00 2001
From: Karlatemp <karlatemp@vip.qq.com>
Date: Sat, 23 Apr 2022 17:13:58 +0800
Subject: [PATCH] Link mirai-core in console IT, fix non-hard-linked
 dependencies resolving

---
 .../backend/integration-test/build.gradle.kts |  1 +
 .../internal/plugin/JvmPluginClassLoader.kt   | 38 ++++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/mirai-console/backend/integration-test/build.gradle.kts b/mirai-console/backend/integration-test/build.gradle.kts
index a0577f49f..76f09da0d 100644
--- a/mirai-console/backend/integration-test/build.gradle.kts
+++ b/mirai-console/backend/integration-test/build.gradle.kts
@@ -27,6 +27,7 @@ kotlin {
 dependencies {
     api(project(":mirai-core-api"))
     api(project(":mirai-core-utils"))
+    testRuntimeOnly(project(":mirai-core"))
     api(project(":mirai-console-compiler-annotations"))
     api(project(":mirai-console"))
     api(project(":mirai-console-terminal"))
diff --git a/mirai-console/backend/mirai-console/src/internal/plugin/JvmPluginClassLoader.kt b/mirai-console/backend/mirai-console/src/internal/plugin/JvmPluginClassLoader.kt
index 7d0fbe70e..f37e1e2a7 100644
--- a/mirai-console/backend/mirai-console/src/internal/plugin/JvmPluginClassLoader.kt
+++ b/mirai-console/backend/mirai-console/src/internal/plugin/JvmPluginClassLoader.kt
@@ -104,6 +104,40 @@ internal class DynLibClassLoader(
         }
     }
 
+    internal fun findButNoSystem(name: String): Class<*>? {
+        val pt = this.parent
+        if (pt is DynLibClassLoader) {
+            pt.findButNoSystem(name)?.let { return it }
+        }
+        synchronized(getClassLoadingLock(name)) {
+            findLoadedClass(name)?.let { return it }
+            try {
+                findClass(name)?.let { return it }
+            } catch (ignored: ClassNotFoundException) {
+            }
+        }
+        return null
+    }
+
+    override fun loadClass(name: String, resolve: Boolean): Class<*> {
+        if (name.startsWith("java.")) return Class.forName(name, false, null)
+        val pt = this.parent
+        val topPt: ClassLoader? = if (pt is DynLibClassLoader) {
+            pt.findButNoSystem(name)?.let { return it }
+
+            generateSequence<ClassLoader>(pt) { it.parent }.firstOrNull { it !is DynLibClassLoader }
+        } else pt
+
+
+        synchronized(getClassLoadingLock(name)) {
+            findLoadedClass(name)?.let { return it }
+            try {
+                return findClass(name)
+            } catch (ignored: ClassNotFoundException) {
+            }
+            return Class.forName(name, false, topPt)
+        }
+    }
 }
 
 @Suppress("JoinDeclarationAndAssignment")
@@ -134,6 +168,7 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
         init0()
     }
 
+    @Suppress("Since15")
     private constructor(file: File, ctx: JvmPluginsLoadingCtx) : super(
         file.name,
         arrayOf(), ctx.sharedLibrariesLoader
@@ -223,7 +258,7 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
             } else {
                 pluginIndependentCL.addLib(lib)
             }
-            logger.debug { "Linked $artifact $linkType" }
+            logger.debug { "Linked $artifact $linkType <${if (shared) pluginSharedCL else pluginIndependentCL}>" }
         }
     }
 
@@ -268,6 +303,7 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
     override fun loadClass(name: String, resolve: Boolean): Class<*> = loadClass(name)
 
     override fun loadClass(name: String): Class<*> {
+        if (name.startsWith("java.")) return Class.forName(name, false, null)
         if (name.startsWith("io.netty") || name in AllDependenciesClassesHolder.allclasses) {
             return AllDependenciesClassesHolder.appClassLoader.loadClass(name)
         }