mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Switch to the new plug-in architecture.
This commit is contained in:
parent
f5601b1f5c
commit
91b9cc64f4
6 changed files with 148 additions and 123 deletions
|
@ -1,7 +1,9 @@
|
||||||
package com.beust.kobalt
|
package com.beust.kobalt
|
||||||
|
|
||||||
import com.beust.jcommander.JCommander
|
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.TaskManager
|
||||||
import com.beust.kobalt.internal.remote.KobaltClient
|
import com.beust.kobalt.internal.remote.KobaltClient
|
||||||
import com.beust.kobalt.internal.remote.KobaltServer
|
import com.beust.kobalt.internal.remote.KobaltServer
|
||||||
|
@ -17,7 +19,6 @@ import java.io.File
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.xml.bind.JAXBContext
|
|
||||||
|
|
||||||
public fun main(argv: Array<String>) {
|
public fun main(argv: Array<String>) {
|
||||||
val result = mainNoExit(argv)
|
val result = mainNoExit(argv)
|
||||||
|
@ -34,6 +35,7 @@ private fun parseArgs(argv: Array<String>): Main.RunInfo {
|
||||||
return Main.RunInfo(result, args)
|
return Main.RunInfo(result, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun mainNoExit(argv: Array<String>) : Int {
|
public fun mainNoExit(argv: Array<String>) : Int {
|
||||||
val (jc, args) = parseArgs(argv)
|
val (jc, args) = parseArgs(argv)
|
||||||
Kobalt.INJECTOR = Guice.createInjector(MainModule(args))
|
Kobalt.INJECTOR = Guice.createInjector(MainModule(args))
|
||||||
|
@ -54,7 +56,7 @@ private class Main @Inject constructor(
|
||||||
val updateKobalt: UpdateKobalt,
|
val updateKobalt: UpdateKobalt,
|
||||||
val client: KobaltClient,
|
val client: KobaltClient,
|
||||||
val server: KobaltServer,
|
val server: KobaltServer,
|
||||||
val pluginInfoDescription: PluginInfoDescription) {
|
val pluginInfo: PluginInfo) {
|
||||||
|
|
||||||
data class RunInfo(val jc: JCommander, val args: Args)
|
data class RunInfo(val jc: JCommander, val args: Args)
|
||||||
|
|
||||||
|
@ -93,11 +95,11 @@ private class Main @Inject constructor(
|
||||||
|
|
||||||
public fun runTest() {
|
public fun runTest() {
|
||||||
val file = File("src\\main\\resources\\META-INF\\plugin.xml")
|
val file = File("src\\main\\resources\\META-INF\\plugin.xml")
|
||||||
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
|
// val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
|
||||||
|
//
|
||||||
val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
|
// val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
|
||||||
val pluginInfo = PluginInfo.create(kotlinPlugin)
|
// val pluginInfo = PluginInfo.create(kotlinPlugin)
|
||||||
System.out.println(kotlinPlugin.name)
|
// System.out.println(kotlinPlugin.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runWithArgs(jc: JCommander, args: Args) : Int {
|
private fun runWithArgs(jc: JCommander, args: Args) : Int {
|
||||||
|
@ -124,10 +126,10 @@ private class Main @Inject constructor(
|
||||||
if (! buildFile.exists()) {
|
if (! buildFile.exists()) {
|
||||||
error(buildFile.path.toFile().path + " does not exist")
|
error(buildFile.path.toFile().path + " does not exist")
|
||||||
} else {
|
} else {
|
||||||
var allProjects = listOf<Project>()
|
var allProjects = arrayListOf<Project>()
|
||||||
val pluginInfo = PluginInfo(pluginInfoDescription)
|
|
||||||
try {
|
try {
|
||||||
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo).compileBuildFiles(args)
|
allProjects.addAll(buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||||
|
.compileBuildFiles(args))
|
||||||
} catch(ex: Throwable) {
|
} catch(ex: Throwable) {
|
||||||
// This can happen if the ABI for the build script file changed. Try to wipe .kobalt.
|
// 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}")
|
log(2, "Couldn't parse preBuildScript.jar: ${ex.message}")
|
||||||
|
@ -136,8 +138,8 @@ private class Main @Inject constructor(
|
||||||
return 1
|
return 1
|
||||||
} else {
|
} else {
|
||||||
log(1, "Deleted .kobalt")
|
log(1, "Deleted .kobalt")
|
||||||
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
allProjects.addAll(buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||||
.compileBuildFiles(args)
|
.compileBuildFiles(args))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +174,6 @@ private class Main @Inject constructor(
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findBuildFile(): File {
|
private fun findBuildFile(): File {
|
||||||
val files = arrayListOf("Build.kt", "build.kobalt", KFiles.src("build.kobalt"),
|
val files = arrayListOf("Build.kt", "build.kobalt", KFiles.src("build.kobalt"),
|
||||||
KFiles.src("Build.kt"))
|
KFiles.src("Build.kt"))
|
||||||
|
|
|
@ -37,6 +37,9 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
||||||
companion object {
|
companion object {
|
||||||
public val MANIFEST_PLUGIN_CLASS : String = "Kobalt-Plugin-Class"
|
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 pluginMap = hashMapOf<String, Plugin>()
|
||||||
// private var storageMap = HashMap<String, HashMap<String, Any>>()
|
// private var storageMap = HashMap<String, HashMap<String, Any>>()
|
||||||
// fun storeValue(pluginName: String, key: String, value: Any) {
|
// fun storeValue(pluginName: String, key: String, value: Any) {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
123
src/main/kotlin/com/beust/kobalt/api/KobaltPluginXml.kt
Normal file
123
src/main/kotlin/com/beust/kobalt/api/KobaltPluginXml.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.beust.kobalt.internal.remote
|
||||||
|
|
||||||
import com.beust.kobalt.Args
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.api.PluginInfo
|
import com.beust.kobalt.api.PluginInfo
|
||||||
import com.beust.kobalt.api.PluginInfoDescription
|
|
||||||
import com.beust.kobalt.kotlin.BuildFile
|
import com.beust.kobalt.kotlin.BuildFile
|
||||||
import com.beust.kobalt.kotlin.BuildFileCompiler
|
import com.beust.kobalt.kotlin.BuildFileCompiler
|
||||||
import com.beust.kobalt.maven.DependencyManager
|
import com.beust.kobalt.maven.DependencyManager
|
||||||
|
@ -26,11 +25,11 @@ import javax.inject.Inject
|
||||||
*/
|
*/
|
||||||
class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
||||||
val buildFileCompilerFactory: BuildFileCompiler.IFactory, val args: Args,
|
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 val name = "getDependencies"
|
||||||
override fun run(sender: ICommandSender, received: JsonObject) {
|
override fun run(sender: ICommandSender, received: JsonObject) {
|
||||||
val buildFile = BuildFile(Paths.get(received.get("buildFile").asString), "GetDependenciesCommand")
|
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 {
|
scriptCompiler.observable.subscribe {
|
||||||
buildScriptInfo -> if (buildScriptInfo.projects.size > 0) {
|
buildScriptInfo -> if (buildScriptInfo.projects.size > 0) {
|
||||||
sender.sendData(toData(buildScriptInfo))
|
sender.sendData(toData(buildScriptInfo))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.beust.kobalt.misc
|
package com.beust.kobalt.misc
|
||||||
|
|
||||||
import com.beust.kobalt.Args
|
import com.beust.kobalt.Args
|
||||||
|
import com.beust.kobalt.api.PluginInfo
|
||||||
import com.beust.kobalt.kotlin.BuildFileCompiler
|
import com.beust.kobalt.kotlin.BuildFileCompiler
|
||||||
import com.beust.kobalt.maven.*
|
import com.beust.kobalt.maven.*
|
||||||
import com.beust.kobalt.plugin.publish.JCenterApi
|
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.Provider
|
||||||
import com.google.inject.TypeLiteral
|
import com.google.inject.TypeLiteral
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder
|
import com.google.inject.assistedinject.FactoryModuleBuilder
|
||||||
import java.lang.annotation.RetentionPolicy
|
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
|
|
||||||
//@Singleton
|
//@Singleton
|
||||||
|
@ -49,9 +49,12 @@ public open class MainModule(val args: Args) : AbstractModule() {
|
||||||
bind(object: TypeLiteral<KobaltExecutors>() {}).toInstance(executors)
|
bind(object: TypeLiteral<KobaltExecutors>() {}).toInstance(executors)
|
||||||
bind(object: TypeLiteral<ExecutorService>() {}).annotatedWith(DependencyExecutor::class.java)
|
bind(object: TypeLiteral<ExecutorService>() {}).annotatedWith(DependencyExecutor::class.java)
|
||||||
.toInstance(executors.dependencyExecutor)
|
.toInstance(executors.dependencyExecutor)
|
||||||
bind(Args::class.java).toProvider(object : Provider<Args> {
|
bind(Args::class.java).toProvider(object: Provider<Args> {
|
||||||
override fun get(): Args? = 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 {
|
// bindListener(Matchers.any(), object: TypeListener {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue