mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-09 19:50:27 +08:00
JvmPluginClassLoaderAccess
This commit is contained in:
parent
b0711ed9ab
commit
237320317e
@ -11,7 +11,6 @@
|
||||
|
||||
package net.mamoe.console.itest.serviceloader
|
||||
|
||||
import net.mamoe.mirai.console.internal.plugin.JvmPluginClassLoaderN
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
|
||||
import net.mamoe.mirai.utils.info
|
||||
@ -21,9 +20,10 @@ import kotlin.test.assertEquals
|
||||
|
||||
internal object PMain : KotlinPlugin(JvmPluginDescription("net.mamoe.console.itest.serviceloader", "0.0.0")) {
|
||||
init {
|
||||
val cl = PMain.javaClass.classLoader as JvmPluginClassLoaderN
|
||||
cl.pluginSharedCL.addLib(File("modules/module-service-loader-typedef-0.0.0.jar"))
|
||||
cl.pluginSharedCL.addLib(File("modules/module-service-loader-impl-0.0.0.jar"))
|
||||
val access = jvmPluginClassLoaderAccess
|
||||
val sharedCL = access.pluginSharedLibrariesClassLoader
|
||||
access.addToPath(sharedCL, File("modules/module-service-loader-typedef-0.0.0.jar"))
|
||||
access.addToPath(sharedCL, File("modules/module-service-loader-impl-0.0.0.jar"))
|
||||
}
|
||||
|
||||
override fun onEnable() {
|
||||
|
@ -2157,6 +2157,7 @@ public abstract class net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin : net
|
||||
public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun getAutoSaveIntervalMillis ()Lkotlin/ranges/LongRange;
|
||||
public final fun getDataHolderName ()Ljava/lang/String;
|
||||
protected final fun getJvmPluginClassLoaderAccess ()Lnet/mamoe/mirai/console/plugin/jvm/JvmPluginClassLoaderAccess;
|
||||
public final fun getLoader ()Lnet/mamoe/mirai/console/plugin/jvm/JvmPluginLoader;
|
||||
public synthetic fun getLoader ()Lnet/mamoe/mirai/console/plugin/loader/PluginLoader;
|
||||
public final fun permissionId (Ljava/lang/String;)Lnet/mamoe/mirai/console/permission/PermissionId;
|
||||
@ -2213,6 +2214,15 @@ public final class net/mamoe/mirai/console/plugin/jvm/JvmPlugin$Companion {
|
||||
public final synthetic fun onLoad (Lnet/mamoe/mirai/console/plugin/jvm/JvmPlugin;Lnet/mamoe/mirai/console/extension/PluginComponentStorage;)V
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/console/plugin/jvm/JvmPluginClassLoaderAccess {
|
||||
public abstract fun addToPath (Ljava/lang/ClassLoader;Ljava/io/File;)V
|
||||
public abstract fun downloadAndAddToPath (Ljava/lang/ClassLoader;Ljava/util/Collection;)V
|
||||
public abstract fun getPluginClassLoader ()Ljava/lang/ClassLoader;
|
||||
public abstract fun getPluginFile ()Ljava/io/File;
|
||||
public abstract fun getPluginIndependentLibrariesClassLoader ()Ljava/lang/ClassLoader;
|
||||
public abstract fun getPluginSharedLibrariesClassLoader ()Ljava/lang/ClassLoader;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription : net/mamoe/mirai/console/plugin/description/PluginDescription {
|
||||
public static final field Companion Lnet/mamoe/mirai/console/plugin/jvm/JvmPluginDescription$Companion;
|
||||
public static fun loadFromResource ()Lnet/mamoe/mirai/console/plugin/jvm/JvmPluginDescription;
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.plugin.jvm.ExportManager
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginClassLoaderAccess
|
||||
import net.mamoe.mirai.utils.*
|
||||
import org.eclipse.aether.artifact.Artifact
|
||||
import org.eclipse.aether.graph.DependencyFilter
|
||||
@ -163,6 +164,7 @@ internal class DynLibClassLoader : URLClassLoader {
|
||||
|
||||
@Suppress("JoinDeclarationAndAssignment")
|
||||
internal class JvmPluginClassLoaderN : URLClassLoader {
|
||||
val openaccess: JvmPluginClassLoaderAccess = OpenAccess()
|
||||
val file: File
|
||||
val ctx: JvmPluginsLoadingCtx
|
||||
val sharedLibrariesLogger: DynLibClassLoader
|
||||
@ -224,10 +226,12 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
|
||||
internal var declaredFilter: ExportManager? = null
|
||||
|
||||
val sharedClLoadedDependencies = mutableSetOf<String>()
|
||||
val privateClLoadedDependencies = mutableSetOf<String>()
|
||||
internal fun containsSharedDependency(
|
||||
dependency: String
|
||||
): Boolean {
|
||||
if (dependency in sharedClLoadedDependencies) return true
|
||||
if (dependency in privateClLoadedDependencies) return true
|
||||
return dependencies.any { it.containsSharedDependency(dependency) }
|
||||
}
|
||||
|
||||
@ -282,6 +286,7 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
|
||||
sharedClLoadedDependencies.add(artifact.depId())
|
||||
} else {
|
||||
pluginIndependentCL.addLib(lib)
|
||||
privateClLoadedDependencies.add(artifact.depId())
|
||||
}
|
||||
logger.debug { "Linked $artifact $linkType <${if (shared) pluginSharedCL else pluginIndependentCL}>" }
|
||||
}
|
||||
@ -432,6 +437,50 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
|
||||
return "JvmPluginClassLoader{${file.name}}"
|
||||
}
|
||||
|
||||
inner class OpenAccess : JvmPluginClassLoaderAccess {
|
||||
override val pluginFile: File
|
||||
get() = this@JvmPluginClassLoaderN.file
|
||||
|
||||
override val pluginClassLoader: ClassLoader
|
||||
get() = this@JvmPluginClassLoaderN
|
||||
|
||||
override val pluginSharedLibrariesClassLoader: ClassLoader
|
||||
get() = pluginSharedCL
|
||||
override val pluginIndependentLibrariesClassLoader: ClassLoader
|
||||
get() = pluginIndependentCL
|
||||
|
||||
private val permitted by lazy {
|
||||
arrayOf(
|
||||
this@JvmPluginClassLoaderN,
|
||||
pluginSharedCL,
|
||||
pluginIndependentCL,
|
||||
)
|
||||
}
|
||||
|
||||
override fun addToPath(classLoader: ClassLoader, file: File) {
|
||||
if (classLoader !in permitted) {
|
||||
throw IllegalArgumentException("Unsupported classloader or cross plugin accessing: $classLoader")
|
||||
}
|
||||
if (classLoader == this@JvmPluginClassLoaderN) {
|
||||
this@JvmPluginClassLoaderN.addURL(file.toURI().toURL())
|
||||
return
|
||||
}
|
||||
classLoader as DynLibClassLoader
|
||||
classLoader.addLib(file)
|
||||
}
|
||||
|
||||
override fun downloadAndAddToPath(classLoader: ClassLoader, dependencies: Collection<String>) {
|
||||
if (classLoader !in permitted) {
|
||||
throw IllegalArgumentException("Unsupported classloader or cross plugin accessing: $classLoader")
|
||||
}
|
||||
if (classLoader === this@JvmPluginClassLoaderN) {
|
||||
throw IllegalArgumentException("Only support download dependencies to `plugin[Shared/Independent]LibrariesClassLoader`")
|
||||
}
|
||||
this@JvmPluginClassLoaderN.linkLibraries(
|
||||
linkedLogger, dependencies, classLoader === pluginSharedCL
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val JavaSystemPlatformClassLoader: ClassLoader by lazy {
|
||||
|
@ -14,6 +14,7 @@ package net.mamoe.mirai.console.plugin.jvm
|
||||
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
|
||||
import net.mamoe.mirai.console.data.PluginConfig
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.internal.plugin.JvmPluginClassLoaderN
|
||||
import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal
|
||||
import net.mamoe.mirai.console.permission.PermissionId
|
||||
import net.mamoe.mirai.console.permission.PermissionService
|
||||
@ -77,6 +78,21 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor(
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
public override val autoSaveIntervalMillis: LongRange = 30.secondsToMillis..10.minutesToMillis
|
||||
|
||||
/**
|
||||
* 获取 [JvmPluginClassLoaderAccess]
|
||||
*
|
||||
* 注: 仅插件通过 console 内置插件加载器加载时可用
|
||||
*
|
||||
* @since 2.12
|
||||
*/
|
||||
protected val jvmPluginClassLoaderAccess: JvmPluginClassLoaderAccess by lazy {
|
||||
val classLoader = this@AbstractJvmPlugin.javaClass.classLoader
|
||||
if (classLoader is JvmPluginClassLoaderN) {
|
||||
return@lazy classLoader.openaccess
|
||||
}
|
||||
error("jvmPluginClassLoaderAccess not available for $classLoader")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* 动态注册类搜索路径
|
||||
*
|
||||
* @since 2.12
|
||||
* @see AbstractJvmPlugin.jvmPluginClassLoaderAccess
|
||||
*/
|
||||
public interface JvmPluginClassLoaderAccess {
|
||||
public val pluginFile: File
|
||||
|
||||
/**
|
||||
* 插件本体的 [ClassLoader], 负责加载插件本身的类数据
|
||||
*
|
||||
* JVM NAME: `${pluginFile.name}`
|
||||
*/
|
||||
public val pluginClassLoader: ClassLoader
|
||||
|
||||
/**
|
||||
* 插件所使用的依赖, 可共享, 当其他插件依赖于当前插件时, 其他插件可以从此 [ClassLoader] 搜索类引用
|
||||
*
|
||||
* JVM NAME: ${pluginFile.name}[shared]
|
||||
*/
|
||||
public val pluginSharedLibrariesClassLoader: ClassLoader
|
||||
|
||||
/**
|
||||
* 插件内部使用的依赖, 不公开给其他插件, 其他插件搜索时不会搜索到此插件的依赖
|
||||
*
|
||||
* JVM NAME: ${pluginFile.name}[private]
|
||||
*/
|
||||
public val pluginIndependentLibrariesClassLoader: ClassLoader
|
||||
|
||||
/**
|
||||
* 将 [file] 加入 [classLoader] 的搜索路径内
|
||||
*
|
||||
* @throws IllegalArgumentException 当 [classLoader] 不是 [pluginClassLoader],
|
||||
* [pluginIndependentLibrariesClassLoader], [pluginSharedLibrariesClassLoader] 时抛出
|
||||
*/
|
||||
@kotlin.jvm.Throws(IllegalArgumentException::class)
|
||||
public fun addToPath(classLoader: ClassLoader, file: File)
|
||||
|
||||
/**
|
||||
* 下载依赖, 并注册进 [classLoader]
|
||||
*
|
||||
* 注: 如果需要同时修改 [pluginSharedLibrariesClassLoader] 和 [pluginIndependentLibrariesClassLoader],
|
||||
* 请先对 [pluginSharedLibrariesClassLoader] 以避免出现不和预期的问题
|
||||
*
|
||||
* @throws IllegalArgumentException 当 [classLoader] 不是
|
||||
* [pluginSharedLibrariesClassLoader], [pluginIndependentLibrariesClassLoader]
|
||||
* 时抛出
|
||||
* @throws Exception 网络错误 / 依赖未找到
|
||||
*/
|
||||
@kotlin.jvm.Throws(IllegalArgumentException::class, Exception::class)
|
||||
public fun downloadAndAddToPath(classLoader: ClassLoader, dependencies: Collection<String>)
|
||||
}
|
Loading…
Reference in New Issue
Block a user