mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 00:17:11 -07:00
Revamping the plug-in class loading.
This commit is contained in:
parent
bb8878ef63
commit
903f63b268
8 changed files with 260 additions and 155 deletions
|
@ -9,6 +9,7 @@ import com.beust.kobalt.kotlin.ScriptCompiler
|
|||
import com.beust.kobalt.maven.*
|
||||
import com.beust.kobalt.misc.*
|
||||
import com.beust.kobalt.SystemProperties
|
||||
import com.beust.kobalt.kotlin.ScriptCompiler2
|
||||
import com.beust.kobalt.plugin.publish.JCenterApi
|
||||
import com.beust.kobalt.plugin.publish.UnauthenticatedJCenterApi
|
||||
import com.beust.kobalt.wrapper.Wrapper
|
||||
|
@ -35,6 +36,7 @@ public fun main(argv: Array<String>) {
|
|||
|
||||
private class Main @Inject constructor(
|
||||
val scriptCompilerFactory: ScriptCompiler.IFactory,
|
||||
val script2: ScriptCompiler2.IFactory,
|
||||
val plugins: Plugins,
|
||||
val taskManager: TaskManager,
|
||||
val http: Http,
|
||||
|
@ -115,20 +117,21 @@ private class Main @Inject constructor(
|
|||
if (! buildFile.exists()) {
|
||||
jc.usage()
|
||||
} else {
|
||||
// Install all the plugins found
|
||||
plugins.installDynamicPlugins(arrayListOf(buildFile))
|
||||
|
||||
// Compile the build script
|
||||
val output = scriptCompilerFactory.create(plugins.pluginJarFiles,
|
||||
{ n: String, j: File? ->
|
||||
plugins.instantiateClassName(n, j)
|
||||
})
|
||||
.compile(buildFile, buildFile.lastModified(), KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR))
|
||||
val allProjects = script2.create(arrayListOf(buildFile)).findProjects()
|
||||
// // Install all the plugins found
|
||||
// val classLoaders = plugins.installDynamicPlugins(arrayListOf(buildFile))
|
||||
//
|
||||
// // Compile the build script
|
||||
// val output = scriptCompilerFactory.create(plugins.pluginJarFiles,
|
||||
// // @@
|
||||
// { cl: ClassLoader, n: String -> plugins.instantiateClassName(classLoaders.get(0), n) }
|
||||
// ).compile(buildFile, buildFile.lastModified(),
|
||||
// KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR))
|
||||
|
||||
//
|
||||
// Force each project.directory to be an absolute path, if it's not already
|
||||
//
|
||||
output.projects.forEach {
|
||||
allProjects.forEach {
|
||||
val fd = File(it.directory)
|
||||
if (! fd.isAbsolute) {
|
||||
it.directory =
|
||||
|
@ -140,7 +143,7 @@ private class Main @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
plugins.applyPlugins(KobaltContext(args), output.projects)
|
||||
plugins.applyPlugins(KobaltContext(args), allProjects)
|
||||
|
||||
if (args.tasks) {
|
||||
//
|
||||
|
@ -157,14 +160,14 @@ private class Main @Inject constructor(
|
|||
}
|
||||
println(sb.toString())
|
||||
} else if (args.checkVersions) {
|
||||
checkVersions.run(output.projects)
|
||||
checkVersions.run(allProjects)
|
||||
} else if (args.update) {
|
||||
updateKobalt.updateKobalt()
|
||||
} else {
|
||||
//
|
||||
// Launch the build
|
||||
//
|
||||
taskManager.runTargets(args.targets, output.projects)
|
||||
taskManager.runTargets(args.targets, allProjects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import com.beust.kobalt.api.*
|
|||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.internal.TaskManager
|
||||
import com.beust.kobalt.internal.TaskResult
|
||||
import com.beust.kobalt.kotlin.BuildFile
|
||||
import com.beust.kobalt.kotlin.ScriptCompiler
|
||||
import com.beust.kobalt.maven.DepFactory
|
||||
import com.beust.kobalt.maven.IClasspathDependency
|
||||
import com.beust.kobalt.maven.KobaltException
|
||||
|
@ -13,23 +11,17 @@ import com.beust.kobalt.maven.LocalRepo
|
|||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltExecutors
|
||||
import com.beust.kobalt.misc.KobaltLogger
|
||||
import com.beust.kobalt.misc.countChar
|
||||
import com.beust.kobalt.plugin.DefaultPlugin
|
||||
import com.beust.kobalt.plugin.java.JavaPlugin
|
||||
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
|
||||
import com.beust.kobalt.plugin.packaging.PackagingPlugin
|
||||
import com.beust.kobalt.plugin.publish.PublishPlugin
|
||||
import com.google.inject.Provider
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Paths
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -39,27 +31,25 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
val files: KFiles,
|
||||
val depFactory: DepFactory,
|
||||
val localRepo: LocalRepo,
|
||||
val executors: KobaltExecutors,
|
||||
val scriptCompilerFactory: ScriptCompiler.IFactory): KobaltLogger {
|
||||
val executors: KobaltExecutors): KobaltLogger {
|
||||
|
||||
companion object {
|
||||
public val MANIFEST_PLUGIN_CLASS : String = "Kobalt-Plugin-Class"
|
||||
|
||||
private var pluginMap = hashMapOf<String, Plugin>()
|
||||
private var storageMap = HashMap<String, HashMap<String, Any>>()
|
||||
|
||||
fun storeValue(pluginName: String, key: String, value: Any) {
|
||||
var values = storageMap.get(pluginName)
|
||||
if (values == null) {
|
||||
values = hashMapOf<String, Any>()
|
||||
storageMap.put(pluginName, values)
|
||||
}
|
||||
values.put(key, value)
|
||||
}
|
||||
|
||||
fun getValue(pluginName: String, key: String) : Any? {
|
||||
return storageMap.get(pluginName)?.get(key)
|
||||
}
|
||||
// private var storageMap = HashMap<String, HashMap<String, Any>>()
|
||||
// fun storeValue(pluginName: String, key: String, value: Any) {
|
||||
// var values = storageMap.get(pluginName)
|
||||
// if (values == null) {
|
||||
// values = hashMapOf<String, Any>()
|
||||
// storageMap.put(pluginName, values)
|
||||
// }
|
||||
// values.put(key, value)
|
||||
// }
|
||||
//
|
||||
// fun getValue(pluginName: String, key: String) : Any? {
|
||||
// return storageMap.get(pluginName)?.get(key)
|
||||
// }
|
||||
|
||||
val defaultPlugin : Plugin get() = getPlugin(DefaultPlugin.NAME)!!
|
||||
|
||||
|
@ -112,7 +102,6 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
plugin.apply(project, context)
|
||||
}
|
||||
|
||||
|
||||
var currentClass : Class<in Any> = plugin.javaClass
|
||||
|
||||
// Tasks can come from two different places: plugin classes and build files.
|
||||
|
@ -180,67 +169,30 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Jar files for all the plugins.
|
||||
*/
|
||||
public val pluginJarFiles : ArrayList<String> = arrayListOf()
|
||||
|
||||
val dependencies = arrayListOf<IClasspathDependency>()
|
||||
|
||||
/**
|
||||
* Parse the build files, locate all the plugins, download them and make them available to be
|
||||
* used on the classpath of the build file.
|
||||
*/
|
||||
fun installDynamicPlugins(files: List<BuildFile>) {
|
||||
//
|
||||
// Extract all the plugin() and repos() code into a separate script (pluginCode)
|
||||
//
|
||||
files.forEach {
|
||||
val pluginCode = arrayListOf<String>()
|
||||
var parenCount = 0
|
||||
it.path.toFile().forEachLine(Charset.defaultCharset()) { line ->
|
||||
if (line.startsWith("import")) {
|
||||
pluginCode.add(line)
|
||||
}
|
||||
var index = line.indexOf("plugins(")
|
||||
if (index == -1) index = line.indexOf("repos(")
|
||||
if (parenCount > 0 || index >= 0) {
|
||||
if (index == -1) index = 0
|
||||
with(line.substring(index)) {
|
||||
parenCount += line countChar '('
|
||||
if (parenCount > 0) {
|
||||
pluginCode.add(line)
|
||||
}
|
||||
parenCount -= line countChar ')'
|
||||
}
|
||||
public fun instantiateClassName(classLoader: ClassLoader, className : String) : Class<*> {
|
||||
try {
|
||||
log(2, "Instantiating ${className}")
|
||||
return classLoader.loadClass(className)
|
||||
} catch(ex: Exception) {
|
||||
val urls = Arrays.toString((classLoader as URLClassLoader).urLs)
|
||||
val message = "Couldn't instantiate ${className}\n with classLoader $urls: ${ex}"
|
||||
println(message)
|
||||
throw KobaltException(message)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Compile and run pluginCode, which contains all the plugins() calls extracted. This
|
||||
// will add all the dynamic plugins found in this code to Plugins.dynamicPlugins
|
||||
//
|
||||
val pluginSourceFile = KFiles.createTempFile(".kt")
|
||||
pluginSourceFile.writeText(pluginCode.join("\n"), Charset.defaultCharset())
|
||||
log(2, "Saved ${pluginSourceFile.absolutePath}")
|
||||
scriptCompilerFactory.create(pluginJarFiles,
|
||||
{ n: String, j: File? -> instantiateClassName(n, j)
|
||||
}).compile(BuildFile(Paths.get(pluginSourceFile.absolutePath), "Plugins"),
|
||||
it.lastModified(),
|
||||
KFiles.findBuildScriptLocation(it, "preBuildScript.jar"))
|
||||
val allTasks : List<PluginTask>
|
||||
get() {
|
||||
val result = arrayListOf<PluginTask>()
|
||||
Plugins.plugins.forEach { plugin ->
|
||||
result.addAll(plugin.tasks)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//
|
||||
// Locate all the jar files for the dynamic plugins we just discovered
|
||||
//
|
||||
dependencies.addAll(dynamicPlugins.map {
|
||||
pluginJarFiles.add(it.jarFile.get().absolutePath)
|
||||
it
|
||||
})
|
||||
|
||||
//
|
||||
// Materialize all the jar files, instantiate their plugin main class and add it to Plugins
|
||||
//
|
||||
fun installPlugins(dependencies: List<IClasspathDependency>, classLoader: ClassLoader) {
|
||||
val executor = executors.newExecutor("Plugins", 5)
|
||||
dependencies.forEach {
|
||||
//
|
||||
|
@ -256,13 +208,13 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
try {
|
||||
fis = FileInputStream(it.jarFile.get())
|
||||
jis = JarInputStream(fis)
|
||||
val manifest = jis.getManifest()
|
||||
val mainClass = manifest.getMainAttributes().getValue(Plugins.MANIFEST_PLUGIN_CLASS) ?:
|
||||
val manifest = jis.manifest
|
||||
val mainClass = manifest.mainAttributes.getValue(Plugins.MANIFEST_PLUGIN_CLASS) ?:
|
||||
throw KobaltException("Couldn't find \"${Plugins.MANIFEST_PLUGIN_CLASS}\" in the " +
|
||||
"manifest of ${it}")
|
||||
|
||||
val pluginClassName = mainClass.removeSuffix(" ")
|
||||
val c = instantiateClassName(pluginClassName)
|
||||
val c = instantiateClassName(classLoader, pluginClassName)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
Plugins.addPlugin(c as Class<BasePlugin>)
|
||||
log(1, "Added plugin ${c}")
|
||||
|
@ -274,48 +226,4 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
executor.shutdown()
|
||||
}
|
||||
|
||||
public fun instantiateClassName(className : String, buildScriptJarFile: File? = null) : Class<*> {
|
||||
// fun jarToUrl(jarAbsolutePath: String) = URL("file://" + jarAbsolutePath)
|
||||
|
||||
fun jarToUrl(path: String) = URL("jar", "", "file:${path}!/")
|
||||
|
||||
// We need the jar files to be first in the url list otherwise the Build.kt files resolved
|
||||
// might be Kobalt's own
|
||||
val urls = arrayListOf<URL>()
|
||||
buildScriptJarFile?.let {
|
||||
urls.add(jarToUrl(it.absolutePath))
|
||||
}
|
||||
urls.add(jarToUrl(files.kobaltJar))
|
||||
urls.addAll(pluginJarFiles.map { jarToUrl(it) })
|
||||
val classLoader = URLClassLoader(urls.toArray(arrayOfNulls<URL>(urls.size())))
|
||||
|
||||
try {
|
||||
log(2, "Instantiating ${className}")
|
||||
return classLoader.loadClass(className)
|
||||
} catch(ex: Exception) {
|
||||
throw KobaltException("Couldn't instantiate ${className}: ${ex}")
|
||||
}
|
||||
}
|
||||
|
||||
val allTasks : List<PluginTask>
|
||||
get() {
|
||||
val result = arrayListOf<PluginTask>()
|
||||
Plugins.plugins.forEach { plugin ->
|
||||
result.addAll(plugin.tasks)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tasks accepted by at least one project
|
||||
*/
|
||||
fun findTasks(task: String): List<PluginTask> {
|
||||
val tasks = allTasks.filter { task == it.name }
|
||||
if (tasks.isEmpty()) {
|
||||
throw KobaltException("Couldn't find task ${task}")
|
||||
} else {
|
||||
return tasks
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,13 +8,13 @@ import com.beust.kobalt.api.annotation.Task
|
|||
import com.beust.kobalt.maven.KobaltException
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltLogger
|
||||
import com.beust.kobalt.plugin.kotlin.kotlinCompiler
|
||||
import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate
|
||||
import com.google.inject.assistedinject.Assisted
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URLClassLoader
|
||||
import java.util.jar.JarInputStream
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
@ -24,17 +24,17 @@ import kotlin.properties.Delegates
|
|||
*/
|
||||
public class ScriptCompiler @Inject constructor(
|
||||
@Assisted("jarFiles") val jarFiles: List<String>,
|
||||
@Assisted("instantiate") val instantiate: (String, File?) -> Class<*>,
|
||||
@Assisted("instantiate") val instantiate: (ClassLoader, String) -> Class<*>,
|
||||
val files: KFiles) : KobaltLogger {
|
||||
|
||||
interface IFactory {
|
||||
fun create(@Assisted("jarFiles") jarFiles: List<String>,
|
||||
@Assisted("instantiate") instantiate: (String, File?) -> Class<*>) : ScriptCompiler
|
||||
@Assisted("instantiate") instantiate: (ClassLoader, String) -> Class<*>) : ScriptCompiler
|
||||
}
|
||||
|
||||
private var buildScriptJarFile by Delegates.notNull<File>()
|
||||
|
||||
public class CompileOutput(val projects: List<Project>, val plugins: List<String>)
|
||||
public class CompileOutput(val projects: List<Project>, val plugins: List<String>, val classLoader: ClassLoader)
|
||||
|
||||
public fun compile(buildFile: BuildFile, lastModified: Long, jarFileName: String) : CompileOutput {
|
||||
|
||||
|
@ -54,7 +54,8 @@ public class ScriptCompiler @Inject constructor(
|
|||
log(2, "Need to recompile ${buildFile.name}")
|
||||
generateJarFile(buildFile)
|
||||
}
|
||||
return CompileOutput(instantiateBuildFile(), arrayListOf<String>())
|
||||
val pi = instantiateBuildFile()
|
||||
return CompileOutput(pi.projects, arrayListOf<String>(), pi.classLoader)
|
||||
}
|
||||
|
||||
private fun generateJarFile(buildFile: BuildFile) {
|
||||
|
@ -66,10 +67,14 @@ public class ScriptCompiler @Inject constructor(
|
|||
}.compile()
|
||||
}
|
||||
|
||||
private fun instantiateBuildFile() : List<Project> {
|
||||
class ProjectInfo(val projects: List<Project>, val classLoader: ClassLoader)
|
||||
|
||||
private fun instantiateBuildFile() : ProjectInfo {
|
||||
val result = arrayListOf<Project>()
|
||||
var stream : InputStream? = null
|
||||
val classLoader = URLClassLoader(arrayOf(buildScriptJarFile.toURI().toURL()))
|
||||
try {
|
||||
log(1, "!!!!!!!!! CREATED CLASSLOADER FOR buildScriptJarFile: $classLoader")
|
||||
stream = JarInputStream(FileInputStream(buildScriptJarFile))
|
||||
var entry = stream.nextJarEntry
|
||||
|
||||
|
@ -78,7 +83,7 @@ public class ScriptCompiler @Inject constructor(
|
|||
val name = entry.name;
|
||||
if (name.endsWith(".class")) {
|
||||
val className = name.substring(0, name.length() - 6).replace("/", ".")
|
||||
var cl : Class<*>? = instantiate(className, buildScriptJarFile)
|
||||
var cl : Class<*>? = instantiate(classLoader, className)
|
||||
if (cl != null) {
|
||||
classes.add(cl)
|
||||
} else {
|
||||
|
@ -123,7 +128,7 @@ public class ScriptCompiler @Inject constructor(
|
|||
}
|
||||
|
||||
// Now that we all the projects, sort them topologically
|
||||
return Kobalt.sortProjects(result)
|
||||
return ProjectInfo(Kobalt.sortProjects(result), classLoader)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
178
src/main/kotlin/com/beust/kobalt/kotlin/ScriptCompiler2.kt
Normal file
178
src/main/kotlin/com/beust/kobalt/kotlin/ScriptCompiler2.kt
Normal file
|
@ -0,0 +1,178 @@
|
|||
package com.beust.kobalt.kotlin
|
||||
|
||||
import com.beust.kobalt.Plugins
|
||||
import com.beust.kobalt.api.Kobalt
|
||||
import com.beust.kobalt.api.Plugin
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.maven.KobaltException
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltLogger
|
||||
import com.beust.kobalt.misc.countChar
|
||||
import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate
|
||||
import com.google.inject.assistedinject.Assisted
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Paths
|
||||
import java.util.jar.JarInputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
public class ScriptCompiler2 @Inject constructor(@Assisted("buildFiles") val buildFiles: List<BuildFile>,
|
||||
val files: KFiles, val plugins: Plugins) : KobaltLogger {
|
||||
|
||||
interface IFactory {
|
||||
fun create(@Assisted("buildFiles") buildFiles: List<BuildFile>) : ScriptCompiler2
|
||||
}
|
||||
|
||||
private val SCRIPT_JAR = "buildScript.jar"
|
||||
|
||||
fun findProjects(): List<Project> {
|
||||
val result = arrayListOf<Project>()
|
||||
buildFiles.forEach { buildFile ->
|
||||
val pluginUrls = findPlugInUrls(buildFile)
|
||||
val script = File(KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR))
|
||||
|
||||
log(1, "Compiling main build file ${buildFile.path}")
|
||||
kotlinCompilePrivate {
|
||||
classpath(files.kobaltJar)
|
||||
classpath(pluginUrls.map { it.file })
|
||||
sourceFiles(listOf(buildFile.path.toFile().absolutePath))
|
||||
output = script.absolutePath
|
||||
}.compile()
|
||||
|
||||
val output = parseBuildScriptJarFile(script, pluginUrls)
|
||||
result.addAll(output.projects)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findPlugInUrls(buildFile: BuildFile): List<URL> {
|
||||
val result = arrayListOf<URL>()
|
||||
val pluginCode = arrayListOf(
|
||||
"import com.beust.kobalt.*",
|
||||
"import com.beust.kobalt.api.*"
|
||||
)
|
||||
var parenCount = 0
|
||||
buildFile.path.toFile().forEachLine(Charset.defaultCharset()) { line ->
|
||||
var index = line.indexOf("plugins(")
|
||||
if (index == -1) index = line.indexOf("repos(")
|
||||
if (parenCount > 0 || index >= 0) {
|
||||
if (index == -1) index = 0
|
||||
with(line.substring(index)) {
|
||||
parenCount += line countChar '('
|
||||
if (parenCount > 0) {
|
||||
pluginCode.add(line)
|
||||
}
|
||||
parenCount -= line countChar ')'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Compile and run pluginCode, which contains all the plugins() calls extracted. This
|
||||
// will add all the dynamic plugins found in this code to Plugins.dynamicPlugins
|
||||
//
|
||||
val pluginSourceFile = KFiles.createTempFile(".kt")
|
||||
pluginSourceFile.writeText(pluginCode.join("\n"), Charset.defaultCharset())
|
||||
log(2, "Saved ${pluginSourceFile.absolutePath}")
|
||||
|
||||
//
|
||||
// Compile to preBuildScript.jar
|
||||
//
|
||||
val buildScriptJar = KFiles.findBuildScriptLocation(buildFile, "preBuildScript.jar")
|
||||
val buildScriptJarFile = File(buildScriptJar)
|
||||
buildScriptJarFile.parentFile.mkdirs()
|
||||
generateJarFile(BuildFile(Paths.get(pluginSourceFile.path), "Plugins"), buildScriptJarFile)
|
||||
|
||||
//
|
||||
// Run preBuildScript.jar to initialize plugins and repos
|
||||
//
|
||||
val projectInfo = parseBuildScriptJarFile(buildScriptJarFile, arrayListOf<URL>())
|
||||
|
||||
//
|
||||
// All the plug-ins are now in Plugins.dynamicPlugins, download them if they're not already
|
||||
//
|
||||
Plugins.dynamicPlugins.forEach {
|
||||
result.add(it.jarFile.get().toURI().toURL())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun generateJarFile(buildFile: BuildFile, buildScriptJarFile: File) {
|
||||
kotlinCompilePrivate {
|
||||
classpath(files.kobaltJar)
|
||||
sourceFiles(buildFile.path.toFile().absolutePath)
|
||||
output = buildScriptJarFile.absolutePath
|
||||
}.compile()
|
||||
}
|
||||
|
||||
class BuildScriptInfo(val projects: List<Project>, val classLoader: ClassLoader)
|
||||
|
||||
private fun parseBuildScriptJarFile(buildScriptJarFile: File, urls: List<URL>) : BuildScriptInfo {
|
||||
val result = arrayListOf<Project>()
|
||||
var stream : InputStream? = null
|
||||
val allUrls = arrayListOf<URL>().plus(urls).plus(arrayOf(
|
||||
buildScriptJarFile.toURI().toURL(),
|
||||
File(files.kobaltJar).toURI().toURL()))
|
||||
.toTypedArray()
|
||||
val classLoader = URLClassLoader(allUrls)
|
||||
|
||||
//
|
||||
// Install all the plugins
|
||||
//
|
||||
plugins.installPlugins(Plugins.dynamicPlugins, classLoader)
|
||||
|
||||
try {
|
||||
stream = JarInputStream(FileInputStream(buildScriptJarFile))
|
||||
var entry = stream.nextJarEntry
|
||||
|
||||
val classes = hashSetOf<Class<*>>()
|
||||
while (entry != null) {
|
||||
val name = entry.name;
|
||||
if (name.endsWith(".class")) {
|
||||
val className = name.substring(0, name.length() - 6).replace("/", ".")
|
||||
var cl : Class<*>? = classLoader.loadClass(className)
|
||||
if (cl != null) {
|
||||
classes.add(cl)
|
||||
} else {
|
||||
throw KobaltException("Couldn't instantiate ${className}")
|
||||
}
|
||||
}
|
||||
entry = stream.nextJarEntry;
|
||||
}
|
||||
|
||||
// Invoke all the "val" found on the _DefaultPackage class (the Build.kt file)
|
||||
classes.filter { cls ->
|
||||
cls.name != "_DefaultPackage"
|
||||
}.forEach { cls ->
|
||||
cls.methods.forEach { method ->
|
||||
// Invoke vals and see if they return a Project
|
||||
if (method.name.startsWith("get") && Modifier.isStatic(method.modifiers)) {
|
||||
val r = method.invoke(null)
|
||||
if (r is Project) {
|
||||
log(2, "Found project ${r} in class ${cls}")
|
||||
result.add(r)
|
||||
}
|
||||
} else {
|
||||
val taskAnnotation = method.getAnnotation(Task::class.java)
|
||||
if (taskAnnotation != null) {
|
||||
// Plugins.defaultPlugin.addTask(taskAnnotation, )
|
||||
Plugins.defaultPlugin.methodTasks.add(Plugin.MethodTask(method, taskAnnotation))
|
||||
}
|
||||
|
||||
}}
|
||||
}
|
||||
} finally {
|
||||
stream?.close()
|
||||
}
|
||||
|
||||
// Now that we all the projects, sort them topologically
|
||||
return BuildScriptInfo(Kobalt.sortProjects(result), classLoader)
|
||||
}
|
||||
}
|
|
@ -18,6 +18,11 @@ public class KFiles {
|
|||
get() {
|
||||
val jar = joinDir(distributionsDir, Kobalt.version, "kobalt/wrapper/kobalt-" + Kobalt.version + ".jar")
|
||||
val jarFile = File(jar)
|
||||
val envJar = System.getenv("KOBALT_JAR")
|
||||
if (! jarFile.exists() && envJar != null) {
|
||||
KobaltLogger.debug("Using kobalt jar $envJar")
|
||||
return File(envJar).absolutePath
|
||||
}
|
||||
if (! jarFile.exists()) {
|
||||
// Will only happen when building kobalt itself: the jar file might not be in the dist/ directory
|
||||
// yet since we're currently building it. Instead, use the classes directly
|
||||
|
|
|
@ -20,6 +20,10 @@ public interface KobaltLogger {
|
|||
fun warn(s: String, e: Throwable? = null) {
|
||||
LoggerFactory.getLogger(KobaltLogger::class.java.simpleName).warn(s, e)
|
||||
}
|
||||
|
||||
fun debug(s: String) {
|
||||
LoggerFactory.getLogger(KobaltLogger::class.java.simpleName).debug(s)
|
||||
}
|
||||
}
|
||||
|
||||
final fun log(level: Int = 1, message: String) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.beust.kobalt.misc
|
|||
|
||||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.kotlin.ScriptCompiler
|
||||
import com.beust.kobalt.kotlin.ScriptCompiler2
|
||||
import com.beust.kobalt.maven.ArtifactFetcher
|
||||
import com.beust.kobalt.maven.LocalRepo
|
||||
import com.beust.kobalt.maven.Pom
|
||||
|
@ -41,6 +42,7 @@ public open class MainModule(val args: Args) : AbstractModule() {
|
|||
JCenterApi.IFactory::class.java,
|
||||
Pom.IFactory::class.java,
|
||||
ScriptCompiler.IFactory::class.java,
|
||||
ScriptCompiler2.IFactory::class.java,
|
||||
ArtifactFetcher.IFactory::class.java)
|
||||
.forEach {
|
||||
install(builder.build(it))
|
||||
|
|
|
@ -17,7 +17,7 @@ import kotlin.properties.Delegates
|
|||
* @since 08 03, 2015
|
||||
*/
|
||||
@Singleton
|
||||
private class KotlinCompiler @Inject constructor(override val localRepo : LocalRepo,
|
||||
class KotlinCompiler @Inject constructor(override val localRepo : LocalRepo,
|
||||
override val files: com.beust.kobalt.misc.KFiles,
|
||||
override val depFactory: DepFactory,
|
||||
override val dependencyManager: DependencyManager,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue