Преглед изворни кода

fix plugin load issue regards to depends

jiahua.liu пре 6 година
родитељ
комит
31f75a1710

+ 0 - 5
mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt

@@ -141,11 +141,9 @@ class PluginDescription(
     internal var loaded: Boolean = false,
     internal var noCircularDepend: Boolean = true
 ) {
-
     override fun toString(): String {
         return "name: $name\nauthor: $author\npath: $basePath\nver: $version\ninfo: $info\ndepends: $depends"
     }
-
     companion object {
         fun readFromContent(content_: String): PluginDescription {
             with(Config.load(content_, "yml")) {
@@ -185,6 +183,3 @@ class PluginDescription(
         }
     }
 }
-
-internal class PluginClassLoader(file: File, parent: ClassLoader) :
-    URLClassLoader(arrayOf(file.toURI().toURL()), parent)

+ 18 - 24
mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManager.kt

@@ -23,6 +23,7 @@ import java.io.InputStream
 import java.lang.reflect.Constructor
 import java.lang.reflect.Method
 import java.net.URL
+import java.net.URLClassLoader
 import java.util.jar.JarFile
 
 
@@ -100,6 +101,9 @@ object PluginManager {
             }
         }
 
+        val pluginsClassLoader = PluginsClassLoader(pluginsLocation.values,this.javaClass.classLoader)
+
+        //不仅要解决A->B->C->A, 还要解决A->B->C->A
         fun checkNoCircularDepends(
             target: PluginDescription,
             needDepends: List<String>,
@@ -125,51 +129,41 @@ object PluginManager {
             }
         }
 
-
         pluginsFound.values.forEach {
             checkNoCircularDepends(it, it.depends, mutableListOf())
         }
 
-        //load
-
-
+        //load plugin
         fun loadPlugin(description: PluginDescription): Boolean {
             if (!description.noCircularDepend) {
                 logger.error("Failed to load plugin " + description.name + " because it has circular dependency")
                 return false
             }
 
-            //load depends first
+            if(description.loaded || nameToPluginBaseMap.containsKey(description.name)){
+                return true
+            }
+
             description.depends.forEach { dependent ->
                 if (!pluginsFound.containsKey(dependent)) {
                     logger.error("Failed to load plugin " + description.name + " because it need " + dependent + " as dependency")
                     return false
                 }
                 val depend = pluginsFound[dependent]!!
-                //还没有加载
-                if (!depend.loaded && !loadPlugin(pluginsFound[dependent]!!)) {
+
+                if (loadPlugin(depend)) {
                     logger.error("Failed to load plugin " + description.name + " because " + dependent + " as dependency failed to load")
                     return false
                 }
             }
-            //在这里所有的depends都已经加载了
 
-
-            //real load
             logger.info("loading plugin " + description.name)
 
             try {
-                val pluginClass = try {
-                    PluginClassLoader(
-                        (pluginsLocation[description.name]!!),
-                        this.javaClass.classLoader
-                    ).loadClass(description.basePath)
+                val pluginClass = try{
+                    pluginsClassLoader.loadClass(description.basePath)
                 } catch (e: ClassNotFoundException) {
-                    logger.info("failed to find Main: " + description.basePath + " checking if it's kotlin's path")
-                    PluginClassLoader(
-                        (pluginsLocation[description.name]!!),
-                        this.javaClass.classLoader
-                    ).loadClass("${description.basePath}Kt")
+                    pluginsClassLoader.loadClass("${description.basePath}Kt")
                 }
 
                 return try {
@@ -285,7 +279,6 @@ object PluginManager {
         return null
     }
 
-
     /**
      * 根据插件名字找Jar中的文件
      * null => 没找到
@@ -297,8 +290,6 @@ object PluginManager {
             jar.entries().asSequence().filter { it.name == toFind }.firstOrNull() ?: return null
         return URL("jar:file:" + jarFile.absoluteFile + "!/" + toFindFile.name).openConnection().inputStream
     }
-
-
 }
 
 
@@ -306,6 +297,7 @@ private val trySetAccessibleMethod: Method? = runCatching {
     Class.forName("java.lang.reflect.AccessibleObject").getMethod("trySetAccessible")
 }.getOrNull()
 
+
 private fun Constructor<out PluginBase>.againstPermission() {
     kotlin.runCatching {
         trySetAccessibleMethod?.let { it.invoke(this) }
@@ -314,4 +306,6 @@ private fun Constructor<out PluginBase>.againstPermission() {
                 this.isAccessible = true
             }
     }
-}
+}
+
+internal class PluginsClassLoader(files: Collection<File>, parent: ClassLoader) : URLClassLoader(files.map{it.toURI().toURL()}.toTypedArray(), parent)