Merge remote-tracking branch 'origin/master'

This commit is contained in:
jiahua.liu 2020-01-18 21:31:23 +08:00
commit 3a2f0f3267

View File

@ -1,16 +1,16 @@
package net.mamoe.mirai.plugin package net.mamoe.mirai.plugin
import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLogger
import java.io.BufferedReader import net.mamoe.mirai.utils.io.encodeToString
import java.io.File import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import java.net.JarURLConnection
import java.net.URL import java.net.URL
import java.util.jar.JarFile import java.util.jar.JarFile
abstract class PluginBase constructor() { abstract class PluginBase constructor() {
val dataFolder by lazy {
File(PluginManager.pluginsPath + pluginDescription.name).also { it.mkdir() }
}
open fun onLoad() { open fun onLoad() {
@ -24,38 +24,27 @@ abstract class PluginBase constructor() {
} }
fun getPluginManager(): PluginManager {
return PluginManager
}
private lateinit var pluginDescription: PluginDescription private lateinit var pluginDescription: PluginDescription
internal fun init(pluginDescription: PluginDescription) { internal fun init(pluginDescription: PluginDescription) {
this.pluginDescription = pluginDescription this.pluginDescription = pluginDescription
this.onLoad() this.onLoad()
} }
fun getDataFolder(): File {
return File(PluginManager.pluginsPath + pluginDescription.pluginName).also {
it.mkdirs()
}
}
} }
class PluginDescription( class PluginDescription(
val pluginName: String, val name: String,
val pluginAuthor: String, val author: String,
val pluginBasePath: String, val basePath: String,
val pluginVersion: String, val version: String,
val pluginInfo: String, val info: String,
val depends: List<String>,//插件的依赖 val depends: List<String>,//插件的依赖
internal var loaded: Boolean = false, internal var loaded: Boolean = false,
internal var noCircularDepend: Boolean = true internal var noCircularDepend: Boolean = true
) { ) {
override fun toString(): String { override fun toString(): String {
return "name: $pluginName\nauthor: $pluginAuthor\npath: $pluginBasePath\nver: $pluginVersion\ninfo: $pluginInfo\ndepends: $depends" return "name: $name\nauthor: $author\npath: $basePath\nver: $version\ninfo: $info\ndepends: $depends"
} }
companion object { companion object {
@ -83,9 +72,9 @@ class PluginDescription(
lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> { lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> {
info = line.substringAfter(":").trim() info = line.substringAfter(":").trim()
} }
lowercaseLine.startsWith("main") || lowercaseLine.startsWith("path") || lowercaseLine.startsWith( lowercaseLine.startsWith("main") ||
"basepath" lowercaseLine.startsWith("path") ||
) -> { lowercaseLine.startsWith("basepath") -> {
basePath = line.substringAfter(":").trim() basePath = line.substringAfter(":").trim()
} }
lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> { lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> {
@ -113,7 +102,6 @@ object PluginManager {
private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf() private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
/** /**
* 尝试加载全部插件 * 尝试加载全部插件
*/ */
@ -122,29 +110,18 @@ object PluginManager {
val pluginsLocation: MutableMap<String, JarFile> = mutableMapOf() val pluginsLocation: MutableMap<String, JarFile> = mutableMapOf()
File(pluginsPath).listFiles()?.forEach { file -> File(pluginsPath).listFiles()?.forEach { file ->
if (file != null) { if (file != null && file.extension == "jar") {
if (file.extension == "jar") {
val jar = JarFile(file) val jar = JarFile(file)
val pluginYml = val pluginYml =
jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull() jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
if (pluginYml == null) { if (pluginYml == null) {
logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin") logger.info("plugin.yml not found in jar " + jar.name + ", it will not be considered as a Plugin")
} else { } else {
val url = URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name) val description =
val jarConnection: JarURLConnection = url PluginDescription.readFromContent(URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.readAllBytes().encodeToString())
.openConnection() as JarURLConnection
val inputStream: InputStream = jarConnection.getInputStream()
val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
var con: String?
val sb = StringBuffer()
while (br.readLine().also { con = it } != null) {
sb.append(con).append("\n")
}
val description = PluginDescription.readFromContent(sb.toString())
println(description) println(description)
pluginsFound[description.pluginName] = description pluginsFound[description.name] = description
pluginsLocation[description.pluginName] = jar pluginsLocation[description.name] = jar
}
} }
} }
} }
@ -155,7 +132,7 @@ object PluginManager {
return return
} }
existDepends.add(target.pluginName) existDepends.add(target.name)
if (needDepends.any { existDepends.contains(it) }) { if (needDepends.any { existDepends.contains(it) }) {
target.noCircularDepend = false target.noCircularDepend = false
@ -180,57 +157,50 @@ object PluginManager {
fun loadPlugin(description: PluginDescription): Boolean { fun loadPlugin(description: PluginDescription): Boolean {
if (!description.noCircularDepend) { if (!description.noCircularDepend) {
return false.also { logger.error("Failed to load plugin " + description.name + " because it has circular dependency")
logger.error("Failed to load plugin " + description.pluginName + " because it has circular dependency") return false
}
} }
//load depends first //load depends first
description.depends.forEach{ description.depends.forEach { dependentName ->
if(!pluginsFound.containsKey(it)){ val dependent = pluginsFound[dependentName]
return false.also { _ -> if (dependent == null) {
logger.error("Failed to load plugin " + description.pluginName + " because it need " + it + " as dependency") logger.error("Failed to load plugin " + description.name + " because it need " + dependentName + " as dependency")
return false
} }
}
val depend = pluginsFound[it]!!
//还没有加载 //还没有加载
if(!depend.loaded) { if (!dependent.loaded && !loadPlugin(dependent)) {
if (!loadPlugin(pluginsFound[it]!!)) { logger.error("Failed to load plugin " + description.name + " because " + dependentName + " as dependency failed to load")
return false.also { _ -> return false
logger.error("Failed to load plugin " + description.pluginName + " because " + it + " as dependency failed to load")
}
}
} }
} }
//在这里所有的depends都已经加载了 //在这里所有的depends都已经加载了
//real load //real load
logger.info("loading plugin " + description.pluginName) logger.info("loading plugin " + description.name)
try { try {
this.javaClass.classLoader.loadClass(description.pluginBasePath) this.javaClass.classLoader.loadClass(description.basePath)
return try { return try {
val subClass = javaClass.asSubclass(PluginBase::class.java) val subClass = javaClass.asSubclass(PluginBase::class.java)
val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance() val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance()
description.loaded = true description.loaded = true
logger.info("successfully loaded plugin " + description.pluginName) logger.info("successfully loaded plugin " + description.name)
logger.info(description.pluginInfo) logger.info(description.info)
nameToPluginBaseMap[description.pluginName] = plugin nameToPluginBaseMap[description.name] = plugin
plugin.init(description) plugin.init(description)
true true
} catch (e: ClassCastException) { } catch (e: ClassCastException) {
false.also { logger.error("failed to load plugin " + description.name + " , Main class does not extends PluginBase ")
logger.error("failed to load plugin " + description.pluginName + " , Main class does not extends PluginBase ") false
}
} }
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
e.printStackTrace() e.printStackTrace()
return false.also { logger.error("failed to load plugin " + description.name + " , Main class not found under " + description.basePath)
logger.error("failed to load plugin " + description.pluginName + " , Main class not found under " + description.pluginBasePath) return false
}
} }
} }
@ -240,8 +210,6 @@ object PluginManager {
} }
} }