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:
parent
f5601b1f5c
commit
91b9cc64f4
6 changed files with 148 additions and 123 deletions
|
@ -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"))
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.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))
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue