1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 16:28:12 -07:00
kobalt/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt
Cedric Beust baf06a9fb7 Refactor.
2015-12-05 15:15:07 -08:00

174 lines
7.3 KiB
Kotlin

package com.beust.kobalt.internal
import com.beust.kobalt.api.*
import com.beust.kobalt.misc.log
import java.io.ByteArrayInputStream
import java.io.File
import java.io.InputStream
import javax.xml.bind.JAXBContext
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
//
// Operations related to the parsing of kobalt-plugin.xml: XML parsing, PluginInfo, etc...
//
/**
* If a plug-in didn't specify a factory, we use our own injector to instantiate all its components.
*/
class GuiceFactory : IFactory {
override fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
}
/////
// XML parsing
//
// The following classes are used by JAXB to parse the kobalt-plugin.xml file.
/**
* The root element of kobalt-plugin.xml
*/
@XmlRootElement(name = "kobalt-plugin")
class KobaltPluginXml {
@XmlElement @JvmField
var name: String? = null
@XmlElement(name = "plugin-actors") @JvmField
var pluginActors : ClassNameXml? = null
@XmlElement(name = "factory-class-name") @JvmField
var factoryClassName: String? = null
}
class ContributorXml {
@XmlElement @JvmField
val name: String? = null
}
class ClassNameXml {
@XmlElement(name = "class-name") @JvmField
var className: List<String> = arrayListOf()
}
/**
* Turn a KobaltPluginXml (the raw content of kobalt-plugin.xml mapped to POJO's) into a PluginInfo object, which
* contains all the contributors instantiated and other information that Kobalt can actually use. Kobalt code that
* needs to access plug-in info can then just inject a PluginInfo object.
*/
class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
val plugins = arrayListOf<IPlugin>()
val projectContributors = arrayListOf<IProjectContributor>()
val classpathContributors = arrayListOf<IClasspathContributor>()
val initContributors = arrayListOf<IInitContributor<File>>()
val repoContributors = arrayListOf<IRepoContributor>()
val compilerFlagContributors = arrayListOf<ICompilerFlagContributor>()
val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoryIncerceptor>()
val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryIncerceptor>()
val runnerContributors = arrayListOf<IRunnerContributor>()
val testRunnerContributors = arrayListOf<ITestRunnerContributor>()
val classpathInterceptors = arrayListOf<IClasspathInterceptor>()
val compilerContributors = arrayListOf<ICompilerContributor>()
val docContributors = arrayListOf<IDocContributor>()
val sourceDirContributors = arrayListOf<ISourceDirectoryContributor>()
val buildConfigFieldContributors = arrayListOf<IBuildConfigFieldContributor>()
// Future contributors:
// source files
// compilers
companion object {
val PLUGIN_XML = "META-INF/kobalt-plugin.xml" // Plugins.PLUGIN_XML)
/**
* Read Kobalt's own kobalt-plugin.xml.
*/
fun readKobaltPluginXml(): PluginInfo {
// Note: use forward slash here since we're looking up this file in a .jar file
val url = Kobalt::class.java.classLoader.getResource(PLUGIN_XML)
if (url != null) {
return readPluginXml(url.openConnection().inputStream)
} else {
throw AssertionError("Couldn't find $PLUGIN_XML")
}
}
/**
* Read a general kobalt-plugin.xml.
*/
fun readPluginXml(ins: InputStream, classLoader: ClassLoader? = null): PluginInfo {
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
val kotlinPlugin: KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(ins)
as KobaltPluginXml
return PluginInfo(kotlinPlugin, classLoader)
}
fun readPluginXml(s: String, classLoader: ClassLoader? = null)
= readPluginXml(ByteArrayInputStream(s.toByteArray(Charsets.UTF_8)), classLoader)
}
init {
val factory = if (xml.factoryClassName != null) {
Class.forName(xml.factoryClassName).newInstance() as IFactory
} else {
GuiceFactory()
}
fun forName(className: String) =
if (classLoader != null) classLoader.loadClass(className)
else Class.forName(className)
//
// Populate pluginInfo with what was found in Kobalt's own kobalt-plugin.xml
//
xml.pluginActors?.className?.forEach {
with(factory.instanceOf(forName(it))) {
when(this) {
is IBuildConfigFieldContributor -> buildConfigFieldContributors.add(this)
is IBuildConfigFieldContributor -> buildConfigFieldContributors.add(this)
is IBuildDirectoryIncerceptor -> buildDirectoryInterceptors.add(this)
is IClasspathContributor -> classpathContributors.add(this)
is IClasspathInterceptor->classpathInterceptors.add(this)
is ICompilerContributor->compilerContributors.add(this)
is ICompilerFlagContributor->compilerFlagContributors.add(this)
is ICompilerInterceptor->compilerInterceptors.add(this)
is IDocContributor->docContributors.add(this)
is IInitContributor<*>->initContributors.add(this as IInitContributor<File>)
is IPlugin->plugins.add(this)
is IProjectContributor->projectContributors.add(this)
is IRepoContributor->repoContributors.add(this)
is IRunnerContributor->runnerContributors.add(this)
is ISourceDirectoryContributor->sourceDirContributors.add(this)
is ISourceDirectoryIncerceptor->sourceDirectoriesInterceptors.add(this)
is ITestRunnerContributor->testRunnerContributors.add(this)
else -> {}
}
}
}
}
/**
* Populate pluginInfo with what was found in the plug-in's kobalt-plugin.xml
*/
fun addPluginInfo(pluginInfo: PluginInfo) {
log(2, "Found new plug-in, adding it to pluginInfo: $pluginInfo")
plugins.addAll(pluginInfo.plugins)
classpathContributors.addAll(pluginInfo.classpathContributors)
projectContributors.addAll(pluginInfo.projectContributors)
initContributors.addAll(pluginInfo.initContributors)
repoContributors.addAll(pluginInfo.repoContributors)
compilerFlagContributors.addAll(pluginInfo.compilerFlagContributors)
compilerInterceptors.addAll(pluginInfo.compilerInterceptors)
sourceDirectoriesInterceptors.addAll(pluginInfo.sourceDirectoriesInterceptors)
buildDirectoryInterceptors.addAll(pluginInfo.buildDirectoryInterceptors)
runnerContributors.addAll(pluginInfo.runnerContributors)
testRunnerContributors.addAll(pluginInfo.testRunnerContributors)
classpathInterceptors.addAll(pluginInfo.classpathInterceptors)
compilerContributors.addAll(pluginInfo.compilerContributors)
docContributors.addAll(pluginInfo.docContributors)
sourceDirContributors.addAll(pluginInfo.sourceDirContributors)
buildConfigFieldContributors.addAll(pluginInfo.buildConfigFieldContributors)
}
}