1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 08:27:12 -07:00

Switch to the new plug-in architecture.

This commit is contained in:
Cedric Beust 2015-11-05 02:52:08 -08:00
parent f5601b1f5c
commit 91b9cc64f4
6 changed files with 148 additions and 123 deletions

View file

@ -1,7 +1,9 @@
package com.beust.kobalt
import com.beust.jcommander.JCommander
import com.beust.kobalt.api.*
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginInfo
import com.beust.kobalt.api.Project
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.remote.KobaltClient
import com.beust.kobalt.internal.remote.KobaltServer
@ -17,7 +19,6 @@ import java.io.File
import java.nio.file.Paths
import java.util.*
import javax.inject.Inject
import javax.xml.bind.JAXBContext
public fun main(argv: Array<String>) {
val result = mainNoExit(argv)
@ -34,6 +35,7 @@ private fun parseArgs(argv: Array<String>): Main.RunInfo {
return Main.RunInfo(result, args)
}
public fun mainNoExit(argv: Array<String>) : Int {
val (jc, args) = parseArgs(argv)
Kobalt.INJECTOR = Guice.createInjector(MainModule(args))
@ -54,7 +56,7 @@ private class Main @Inject constructor(
val updateKobalt: UpdateKobalt,
val client: KobaltClient,
val server: KobaltServer,
val pluginInfoDescription: PluginInfoDescription) {
val pluginInfo: PluginInfo) {
data class RunInfo(val jc: JCommander, val args: Args)
@ -93,11 +95,11 @@ private class Main @Inject constructor(
public fun runTest() {
val file = File("src\\main\\resources\\META-INF\\plugin.xml")
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
val pluginInfo = PluginInfo.create(kotlinPlugin)
System.out.println(kotlinPlugin.name)
// val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
//
// val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
// val pluginInfo = PluginInfo.create(kotlinPlugin)
// System.out.println(kotlinPlugin.name)
}
private fun runWithArgs(jc: JCommander, args: Args) : Int {
@ -124,10 +126,10 @@ private class Main @Inject constructor(
if (! buildFile.exists()) {
error(buildFile.path.toFile().path + " does not exist")
} else {
var allProjects = listOf<Project>()
val pluginInfo = PluginInfo(pluginInfoDescription)
var allProjects = arrayListOf<Project>()
try {
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo).compileBuildFiles(args)
allProjects.addAll(buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
.compileBuildFiles(args))
} catch(ex: Throwable) {
// This can happen if the ABI for the build script file changed. Try to wipe .kobalt.
log(2, "Couldn't parse preBuildScript.jar: ${ex.message}")
@ -136,8 +138,8 @@ private class Main @Inject constructor(
return 1
} else {
log(1, "Deleted .kobalt")
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
.compileBuildFiles(args)
allProjects.addAll(buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
.compileBuildFiles(args))
}
}
@ -172,7 +174,6 @@ private class Main @Inject constructor(
}
return result
}
private fun findBuildFile(): File {
val files = arrayListOf("Build.kt", "build.kobalt", KFiles.src("build.kobalt"),
KFiles.src("Build.kt"))

View file

@ -37,6 +37,9 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
companion object {
public val MANIFEST_PLUGIN_CLASS : String = "Kobalt-Plugin-Class"
/** The name of the XML file describing a plug-in */
val PLUGIN_XML = "plugin.xml"
private var pluginMap = hashMapOf<String, Plugin>()
// private var storageMap = HashMap<String, HashMap<String, Any>>()
// fun storeValue(pluginName: String, key: String, value: Any) {

View file

@ -1,104 +0,0 @@
package com.beust.kobalt.api
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.plugin.java.JavaPlugin
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
import java.util.*
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
class ProjectDescription(val project: Project, val dependsOn: List<Project>)
interface IProjectContributor {
fun projects() : List<ProjectDescription>
}
/**
* Implement this interface in order to add your own entries to the classpath. A list of contributors
* can be found on the `KobaltContext`.
*/
interface IClasspathContributor {
fun entriesFor(project: Project) : Collection<IClasspathDependency>
}
interface IFactory {
fun <T> instanceOf(c: Class<T>) : T
}
class ContributorFactory : IFactory {
override fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
}
/**
* All the information gathered from the various plugin.xml that were collected.
*/
class PluginInfoDescription {
fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
val projectContributors : ArrayList<Class<out IProjectContributor>> =
arrayListOf(JavaPlugin::class.java, KotlinPlugin::class.java)
val classpathContributors: ArrayList<Class<out IClasspathContributor>> =
arrayListOf(KotlinPlugin::class.java)
// Future contributors:
// compilerArgs
// source files
// compilers
// --init
}
/**
* Turn the classes found in PluginInfoDescription into concrete objects that plugins can then use.
*/
class PluginInfo(val description: PluginInfoDescription?) {
val projectContributors = arrayListOf<IProjectContributor>()
val classpathContributors = arrayListOf<IClasspathContributor>()
companion object {
fun create(xml: KobaltPluginXml) : PluginInfo {
val factory = Class.forName(xml.factoryClassName).newInstance() as IFactory
val result = PluginInfo(null)
xml.classpathContributors?.className?.forEach {
result.classpathContributors.add(factory.instanceOf(Class.forName(it)) as IClasspathContributor)
}
xml.projectContributors?.className?.forEach {
result.projectContributors.add(factory.instanceOf(Class.forName(it)) as IProjectContributor)
}
return result
}
}
init {
if (description != null) {
classpathContributors.addAll(description.classpathContributors.map { description.instanceOf(it) })
projectContributors.addAll(description.projectContributors.map { description.instanceOf(it) })
}
}
}
class ContributorXml {
@XmlElement @JvmField
val name: String? = null
}
class ContributorsXml {
@XmlElement(name = "class-name") @JvmField
var className: List<String> = arrayListOf<String>()
}
@XmlRootElement(name = "kobalt-plugin")
class KobaltPluginXml {
@XmlElement @JvmField
var name: String? = null
@XmlElement(name = "factory-class-name") @JvmField
var factoryClassName: String? = null
@XmlElement(name = "classpath-contributors") @JvmField
var classpathContributors : ContributorsXml? = null
@XmlElement(name = "project-contributors") @JvmField
var projectContributors : ContributorsXml? = null
}

View file

@ -0,0 +1,123 @@
package com.beust.kobalt.api
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KFiles
import java.io.InputStream
import javax.xml.bind.JAXBContext
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
/////
// Contributors
//
class ProjectDescription(val project: Project, val dependsOn: List<Project>)
/**
* Implement this interface in order to add your own projects.
*/
interface IProjectContributor {
fun projects() : List<ProjectDescription>
}
/**
* Implement this interface to add your own entries to the classpath.
*/
interface IClasspathContributor {
fun entriesFor(project: Project) : Collection<IClasspathDependency>
}
/**
* The factory function to use to instantiate all the contributors and other entities
* found in plugin.xml.
*/
interface IFactory {
fun <T> instanceOf(c: Class<T>) : T
}
class ContributorFactory : 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 plugin.xml file.
/**
* The root element of plugin.xml
*/
@XmlRootElement(name = "kobalt-plugin")
class KobaltPluginXml {
@XmlElement @JvmField
var name: String? = null
@XmlElement(name = "factory-class-name") @JvmField
var factoryClassName: String? = null
@XmlElement(name = "classpath-contributors") @JvmField
var classpathContributors : ContributorsXml? = null
@XmlElement(name = "project-contributors") @JvmField
var projectContributors : ContributorsXml? = null
}
class ContributorXml {
@XmlElement @JvmField
val name: String? = null
}
class ContributorsXml {
@XmlElement(name = "class-name") @JvmField
var className: List<String> = arrayListOf<String>()
}
/**
* Turn a KobaltPluginXml (the raw content of plugin.xml) into a PluginInfo object, which contains
* all the contributors instantiated and other information that Kobalt can actually use.
*/
class PluginInfo(val xml: KobaltPluginXml) {
val projectContributors = arrayListOf<IProjectContributor>()
val classpathContributors = arrayListOf<IClasspathContributor>()
// Future contributors:
// compilerArgs
// source files
// compilers
// --init
companion object {
/**
* Read Kobalt's own plugin.xml.
*/
fun readKobaltPluginXml() : PluginInfo {
val pluginXml = KFiles.joinDir("META-INF", "plugin.xml") // Plugins.PLUGIN_XML)
val url = Kobalt::class.java.classLoader.getResource(pluginXml)
if (url != null) {
return readPluginXml(url.openConnection().inputStream)
} else {
throw AssertionError("Couldn't find $pluginXml")
}
}
/**
* Read a general plugin.xml.
*/
private fun readPluginXml(ins: InputStream): PluginInfo {
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
val kotlinPlugin: KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(ins)
as KobaltPluginXml
return PluginInfo(kotlinPlugin)
}
}
init {
val factory = Class.forName(xml.factoryClassName).newInstance() as IFactory
xml.classpathContributors?.className?.forEach {
classpathContributors.add(factory.instanceOf(Class.forName(it)) as IClasspathContributor)
}
xml.projectContributors?.className?.forEach {
projectContributors.add(factory.instanceOf(Class.forName(it)) as IProjectContributor)
}
}
}

View file

@ -2,7 +2,6 @@ package com.beust.kobalt.internal.remote
import com.beust.kobalt.Args
import com.beust.kobalt.api.PluginInfo
import com.beust.kobalt.api.PluginInfoDescription
import com.beust.kobalt.kotlin.BuildFile
import com.beust.kobalt.kotlin.BuildFileCompiler
import com.beust.kobalt.maven.DependencyManager
@ -26,11 +25,11 @@ import javax.inject.Inject
*/
class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
val buildFileCompilerFactory: BuildFileCompiler.IFactory, val args: Args,
val dependencyManager: DependencyManager, val pluginInfoDescription: PluginInfoDescription) : ICommand {
val dependencyManager: DependencyManager, val pluginInfo: PluginInfo) : ICommand {
override val name = "getDependencies"
override fun run(sender: ICommandSender, received: JsonObject) {
val buildFile = BuildFile(Paths.get(received.get("buildFile").asString), "GetDependenciesCommand")
val scriptCompiler = buildFileCompilerFactory.create(listOf(buildFile), PluginInfo(pluginInfoDescription))
val scriptCompiler = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
scriptCompiler.observable.subscribe {
buildScriptInfo -> if (buildScriptInfo.projects.size > 0) {
sender.sendData(toData(buildScriptInfo))

View file

@ -1,6 +1,7 @@
package com.beust.kobalt.misc
import com.beust.kobalt.Args
import com.beust.kobalt.api.PluginInfo
import com.beust.kobalt.kotlin.BuildFileCompiler
import com.beust.kobalt.maven.*
import com.beust.kobalt.plugin.publish.JCenterApi
@ -9,7 +10,6 @@ import com.google.inject.BindingAnnotation
import com.google.inject.Provider
import com.google.inject.TypeLiteral
import com.google.inject.assistedinject.FactoryModuleBuilder
import java.lang.annotation.RetentionPolicy
import java.util.concurrent.ExecutorService
//@Singleton
@ -49,9 +49,12 @@ public open class MainModule(val args: Args) : AbstractModule() {
bind(object: TypeLiteral<KobaltExecutors>() {}).toInstance(executors)
bind(object: TypeLiteral<ExecutorService>() {}).annotatedWith(DependencyExecutor::class.java)
.toInstance(executors.dependencyExecutor)
bind(Args::class.java).toProvider(object : Provider<Args> {
bind(Args::class.java).toProvider(object: Provider<Args> {
override fun get(): Args? = args
})
bind(PluginInfo::class.java).toProvider(object: Provider<PluginInfo> {
override fun get(): PluginInfo? = PluginInfo.readKobaltPluginXml()
})
// bindListener(Matchers.any(), object: TypeListener {