fix plugin load issue regards to depends

This commit is contained in:
jiahua.liu 2020-03-30 22:30:13 +08:00
parent d92b43e91b
commit 31f75a1710
2 changed files with 18 additions and 29 deletions

View File

@ -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)

View File

@ -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)