optimize plugin loading API
This commit is contained in:
parent
167dc752ea
commit
5b053d60a2
@ -71,7 +71,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load given plugin into this manager and return loaded instance.
|
* Load given plugin into this manager and return loaded instance.
|
||||||
* Throw error if plugin of the same class already exists in manager
|
* Throw error if plugin of the same type and tag already exists in manager.
|
||||||
*
|
*
|
||||||
* @param plugin
|
* @param plugin
|
||||||
* @return
|
* @return
|
||||||
@ -79,10 +79,12 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
|||||||
fun <T : Plugin> load(plugin: T): T {
|
fun <T : Plugin> load(plugin: T): T {
|
||||||
if (context.isActive) error("Can't load plugin into active context")
|
if (context.isActive) error("Can't load plugin into active context")
|
||||||
|
|
||||||
if (get(plugin::class, recursive = false) != null) {
|
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
||||||
throw RuntimeException("Plugin of type ${plugin::class} already exists in ${context.name}")
|
error("Plugin of type ${plugin::class} already exists in ${context.name}")
|
||||||
} else {
|
} else {
|
||||||
loadDependencies(plugin)
|
for (tag in plugin.dependsOn()) {
|
||||||
|
fetch(tag, true)
|
||||||
|
}
|
||||||
|
|
||||||
logger.info { "Loading plugin ${plugin.name} into ${context.name}" }
|
logger.info { "Loading plugin ${plugin.name} into ${context.name}" }
|
||||||
plugin.attach(context)
|
plugin.attach(context)
|
||||||
@ -91,11 +93,14 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDependencies(plugin: Plugin) {
|
/**
|
||||||
for (tag in plugin.dependsOn()) {
|
* Load a plugin using its factory
|
||||||
load(tag)
|
*/
|
||||||
}
|
fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = EmptyMeta): T =
|
||||||
}
|
load(factory(meta))
|
||||||
|
|
||||||
|
fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
|
||||||
|
load(factory, buildMeta(metaBuilder))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a plugin from [PluginManager]
|
* Remove a plugin from [PluginManager]
|
||||||
@ -111,22 +116,11 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get plugin instance via plugin resolver and load it.
|
* Get an existing plugin with given meta or load new one using provided factory
|
||||||
*
|
*
|
||||||
* @param tag
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
fun load(tag: PluginTag, meta: Meta = EmptyMeta): Plugin {
|
fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = EmptyMeta): T {
|
||||||
val loaded = get(tag, false)
|
val loaded = get(factory.type, factory.tag, recursive)
|
||||||
return when {
|
|
||||||
loaded == null -> load(PluginRepository.fetch(tag, meta))
|
|
||||||
loaded.meta == meta -> loaded // if meta is the same, return existing plugin
|
|
||||||
else -> throw RuntimeException("Can't load plugin with tag $tag. Plugin with this tag and different configuration already exists in context.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun load(factory: PluginFactory<*>, meta: Meta = EmptyMeta): Plugin {
|
|
||||||
val loaded = get(factory.tag, false)
|
|
||||||
return when {
|
return when {
|
||||||
loaded == null -> load(factory(meta))
|
loaded == null -> load(factory(meta))
|
||||||
loaded.meta == meta -> loaded // if meta is the same, return existing plugin
|
loaded.meta == meta -> loaded // if meta is the same, return existing plugin
|
||||||
@ -134,43 +128,12 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun <T : Plugin> fetch(
|
||||||
* Load plugin by its class and meta. Ignore if plugin with this meta is already loaded.
|
factory: PluginFactory<T>,
|
||||||
* Throw an exception if there exists plugin with the same type, but different meta
|
recursive: Boolean = true,
|
||||||
*/
|
metaBuilder: MetaBuilder.() -> Unit
|
||||||
fun <T : Plugin> load(type: KClass<T>, meta: Meta = EmptyMeta): T {
|
): T = fetch(factory, recursive, buildMeta(metaBuilder))
|
||||||
val loaded = get(type, recursive = false)
|
|
||||||
return when {
|
|
||||||
loaded == null -> {
|
|
||||||
val plugin = PluginRepository.list().find { it.type == type }?.invoke(meta)
|
|
||||||
?: error("Plugin factory for class $type not found")
|
|
||||||
if (type.isInstance(plugin)) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
load(plugin as T)
|
|
||||||
} else {
|
|
||||||
error("Corrupt type information in plugin repository")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loaded.meta == meta -> loaded // if meta is the same, return existing plugin
|
|
||||||
else -> throw RuntimeException("Can't load plugin with type $type. Plugin with this type and different configuration already exists in context.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T : Plugin> load(noinline metaBuilder: MetaBuilder.() -> Unit = {}): T {
|
|
||||||
return load(T::class, buildMeta(metaBuilder))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun load(name: String, meta: Meta = EmptyMeta): Plugin {
|
|
||||||
return load(PluginTag.fromString(name), meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<Plugin> = plugins.iterator()
|
override fun iterator(): Iterator<Plugin> = plugins.iterator()
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a plugin if it exists or load it with given meta if it is not.
|
|
||||||
*/
|
|
||||||
inline fun <reified T : Plugin> getOrLoad(noinline metaBuilder: MetaBuilder.() -> Unit = {}): T {
|
|
||||||
return get(recursive = true) ?: load(metaBuilder)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user