diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index 3a8216b4..4c0c3afd 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=0.761 \ No newline at end of file +kobalt.version=0.774 \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt index 855d4271..e55f1b2a 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BasePluginTask.kt @@ -4,8 +4,9 @@ import com.beust.kobalt.api.IPlugin import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.Project -public abstract class BasePluginTask(override val plugin: IPlugin, +abstract class BasePluginTask(override val plugin: IPlugin, override val name: String, override val doc: String, + override val group: String, override val project: Project) : PluginTask() diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Plugins.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Plugins.kt index 1c1d9dd1..c31837b0 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Plugins.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/Plugins.kt @@ -14,6 +14,7 @@ import com.beust.kobalt.misc.log import com.google.inject.Provider import java.lang.reflect.Method import java.lang.reflect.Modifier +import java.net.URLClassLoader import java.util.* import java.util.jar.JarFile import javax.inject.Inject @@ -148,7 +149,7 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider() - fun installPlugins(dependencies: List, classLoader: ClassLoader) { + fun installPlugins(dependencies: List, scriptClassLoader: ClassLoader) { val executor = executors.newExecutor("Plugins", 5) dependencies.forEach { // @@ -161,7 +162,8 @@ class Plugins @Inject constructor (val taskManagerProvider : Provider = listOf(), val reverseDependsOn: List = listOf(), diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt index 5a9cba74..292bb255 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt @@ -7,6 +7,7 @@ import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.misc.KobaltExecutors +import java.io.File class KobaltContext(val args: Args) { var variant: Variant = Variant() @@ -47,4 +48,9 @@ class InternalContext { * will be disabled. */ var buildFileOutOfDate: Boolean = false + + /** + * The absolute directory of the current project. + */ + var absoluteDir: File? = null } \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/PluginTask.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/PluginTask.kt index a2d2b7b7..b416f96b 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/PluginTask.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/PluginTask.kt @@ -8,11 +8,13 @@ interface ITask : Callable> { val project: Project val name: String val doc: String + val group: String } abstract class PluginTask : ITask { override val name: String = "" override open val doc: String = "" + override open val group: String = "other" override fun toString() = project.name + ":" + name } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/TaskContributor.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/TaskContributor.kt index 0d1c1333..2cae53fa 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/TaskContributor.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/TaskContributor.kt @@ -23,6 +23,7 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme * depends on variants of that task. */ fun addVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, + group: String, dependsOn: List = emptyList(), reverseDependsOn : List = emptyList(), runBefore : List = emptyList(), @@ -30,7 +31,7 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme runTask: (Project) -> TaskResult) { Variant.allVariants(project).forEach { variant -> val variantTaskName = variant.toTask(taskName) - dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, project, + dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, group, project, dependsOn = dependsOn.map { variant.toTask(it) }, reverseDependsOn = reverseDependsOn.map { variant.toTask(it) }, runBefore = runBefore.map { variant.toTask(it) }, @@ -43,6 +44,7 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme } fun addIncrementalVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, + group: String, dependsOn: List = emptyList(), reverseDependsOn : List = emptyList(), runBefore : List = emptyList(), @@ -50,7 +52,7 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme runTask: (Project) -> IncrementalTaskInfo) { Variant.allVariants(project).forEach { variant -> val variantTaskName = variant.toTask(taskName) - dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, project, + dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, group, project, dependsOn = dependsOn.map { variant.toTask(it) }, reverseDependsOn = reverseDependsOn.map { variant.toTask(it) }, runBefore = runBefore.map { variant.toTask(it) }, diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/annotation/Annotations.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/annotation/Annotations.kt index ff93b05d..baa87322 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/annotation/Annotations.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/annotation/Annotations.kt @@ -8,9 +8,15 @@ annotation class Directive @Retention(AnnotationRetention.RUNTIME) annotation class Task( + /* This task's name */ val name: String, + + /* The documentation for this task */ val description: String = "", + /** Used to show the task in the correct group in the IDE */ + val group: String = "other", + /** Dependency: tasks this task depends on */ val dependsOn: Array = arrayOf(), @@ -29,9 +35,15 @@ annotation class Task( @Retention(AnnotationRetention.RUNTIME) annotation class IncrementalTask( + /* This task's name */ val name: String, + + /* The documentation for this task */ val description: String = "", + /** Used to show the task in the correct group in the IDE */ + val group: String = "other", + /** Dependency: tasks this task depends on */ val dependsOn: Array = arrayOf(), diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt index 0fad304c..90266dab 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt @@ -4,6 +4,7 @@ import com.beust.kobalt.* import com.beust.kobalt.api.* import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.log +import com.google.common.annotations.VisibleForTesting import java.io.File import java.util.* @@ -48,8 +49,6 @@ abstract class GenericTestRunner: ITestRunnerContributor { */ fun runTests(project: Project, context: KobaltContext, classpath: List, configName: String) : Boolean { - val jvm = JavaInfo.create(File(SystemProperties.javaBase)) - val java = jvm.javaExecutable var result = false val testConfig = project.testConfigs.firstOrNull { it.name == configName } @@ -58,36 +57,13 @@ abstract class GenericTestRunner: ITestRunnerContributor { val args = args(project, classpath, testConfig) if (args.size > 0) { - // Default JVM args - val jvmFlags = arrayListOf().apply { - addAll(testConfig.jvmArgs) - add("-classpath") - add(classpath.map { it.jarFile.get().absolutePath }.joinToString(File.pathSeparator)) - add(mainClass) - } - - val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java) - - // JVM flags from the contributors - val flagsFromContributors = pluginInfo.testJvmFlagContributors.flatMap { - it.testJvmFlagsFor(project, context, jvmFlags) - } - - // JVM flags from the interceptors (these overwrite flags instead of just adding to the list) - var interceptedArgs = ArrayList(flagsFromContributors) - pluginInfo.testJvmFlagInterceptors.forEach { - val newFlags = it.testJvmFlagsFor(project, context, interceptedArgs) - interceptedArgs.clear() - interceptedArgs.addAll(newFlags) - } - - if (interceptedArgs.any()) { - log(2, "Final JVM test flags after running the contributors and interceptors: $interceptedArgs") - } - + val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable + val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath, + Kobalt.INJECTOR.getInstance (PluginInfo::class.java)) val allArgs = arrayListOf().apply { add(java!!.absolutePath) - addAll(interceptedArgs) + addAll(jvmArgs) + add(mainClass) addAll(args) } @@ -113,5 +89,39 @@ abstract class GenericTestRunner: ITestRunnerContributor { } return result } + + /* + ** @return all the JVM flags from contributors and interceptors. + */ + @VisibleForTesting + fun calculateAllJvmArgs(project: Project, context: KobaltContext, + testConfig: TestConfig, classpath: List, pluginInfo: IPluginInfo) : List { + // Default JVM args + val jvmFlags = arrayListOf().apply { + addAll(testConfig.jvmArgs) + add("-classpath") + add(classpath.map { it.jarFile.get().absolutePath }.joinToString(File.pathSeparator)) + } + + // JVM flags from the contributors + val jvmFlagsFromContributors = pluginInfo.testJvmFlagContributors.flatMap { + it.testJvmFlagsFor(project, context, jvmFlags) + } + + // JVM flags from the interceptors (these overwrite flags instead of just adding to the list) + var result = ArrayList(jvmFlags + jvmFlagsFromContributors) + pluginInfo.testJvmFlagInterceptors.forEach { + val newFlags = it.testJvmFlagsFor(project, context, result) + result.clear() + result.addAll(newFlags) + } + + if (result.any()) { + log(2, "Final JVM test flags after running the contributors and interceptors: $result") + } + + return result + } + } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 4f418343..db4519c0 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -48,6 +48,10 @@ open class JvmCompilerPlugin @Inject constructor( const val TASK_TEST = "test" const val DOCS_DIRECTORY = "docs/javadoc" + + const val GROUP_TEST = "test" + const val GROUP_BUILD = "build" + const val GROUP_DOCUMENTATION = "documentation" } override val name: String = PLUGIN_NAME @@ -64,7 +68,7 @@ open class JvmCompilerPlugin @Inject constructor( override fun apply(project: Project, context: KobaltContext) { super.apply(project, context) // cleanUpActors() - taskContributor.addIncrementalVariantTasks(this, project, context, "compile", + taskContributor.addIncrementalVariantTasks(this, project, context, "compile", GROUP_BUILD, runTask = { taskCompile(project) }) // @@ -77,7 +81,7 @@ open class JvmCompilerPlugin @Inject constructor( project.testConfigs.forEach { config -> val taskName = if (config.name.isEmpty()) TASK_TEST else TASK_TEST + config.name - taskManager.addTask(this, project, taskName, + taskManager.addTask(this, project, taskName, group = GROUP_TEST, dependsOn = listOf(JvmCompilerPlugin.TASK_COMPILE, JvmCompilerPlugin.TASK_COMPILE_TEST), task = { taskTest(project, config.name)} ) } @@ -98,7 +102,7 @@ open class JvmCompilerPlugin @Inject constructor( } } - @Task(name = TASK_CLEAN, description = "Clean the project") + @Task(name = TASK_CLEAN, description = "Clean the project", group = GROUP_BUILD) fun taskClean(project: Project): TaskResult { java.io.File(project.directory, project.buildDirectory).let { dir -> if (!dir.deleteRecursively()) { @@ -139,7 +143,7 @@ open class JvmCompilerPlugin @Inject constructor( } } - @IncrementalTask(name = TASK_COMPILE_TEST, description = "Compile the tests", + @IncrementalTask(name = TASK_COMPILE_TEST, description = "Compile the tests", group = GROUP_BUILD, dependsOn = arrayOf(TASK_COMPILE)) fun taskCompileTest(project: Project): IncrementalTaskInfo { sourceTestDirectories.addAll(context.variant.sourceDirectories(project, context, SourceSet.of(isTest = true))) @@ -155,7 +159,7 @@ open class JvmCompilerPlugin @Inject constructor( ) } - @IncrementalTask(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project", + @IncrementalTask(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project", group = GROUP_BUILD, runAfter = arrayOf(TASK_CLEAN)) fun taskCompile(project: Project): IncrementalTaskInfo { // Generate the BuildConfig before invoking sourceDirectories() since that call @@ -243,7 +247,7 @@ open class JvmCompilerPlugin @Inject constructor( project.projectProperties.put(DEPENDENT_PROJECTS, allProjects) } - @Task(name = "doc", description = "Generate the documentation for the project") + @Task(name = "doc", description = "Generate the documentation for the project", group = GROUP_DOCUMENTATION) fun taskJavadoc(project: Project): TaskResult { val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors) if (docGenerator != null) { diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt index f3138a75..b062dc62 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt @@ -1,5 +1,6 @@ package com.beust.kobalt.internal +import com.beust.kobalt.KobaltException import com.beust.kobalt.api.* import com.beust.kobalt.misc.log import java.io.ByteArrayInputStream @@ -49,12 +50,22 @@ class ClassNameXml { var className: List = arrayListOf() } +interface IPluginInfo { + val testJvmFlagContributors : List + val testJvmFlagInterceptors : List +} + +open class BasePluginInfo : IPluginInfo { + override val testJvmFlagContributors = arrayListOf() + override val testJvmFlagInterceptors = 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?) { +class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?, val classLoader: ClassLoader?) + : BasePluginInfo() { val plugins = arrayListOf() val projectContributors = arrayListOf() val classpathContributors = arrayListOf() @@ -79,8 +90,11 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { // Not documented yet val buildConfigContributors = arrayListOf() val mavenIdInterceptors = arrayListOf() - val testJvmFlagContributors = arrayListOf() - val testJvmFlagInterceptors = arrayListOf() + + // Note: intentionally repeating them here even though they are defined by our base class so + // that this class always contains the full list of contributors and interceptors + override val testJvmFlagContributors = arrayListOf() + override val testJvmFlagInterceptors = arrayListOf() companion object { /** @@ -112,16 +126,24 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { /** * Read a general kobalt-plugin.xml. */ - fun readPluginXml(ins: InputStream, classLoader: ClassLoader? = null): PluginInfo { + fun readPluginXml(ins: InputStream, pluginClassLoader: ClassLoader? = null, + classLoader: ClassLoader? = null): PluginInfo { val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java) - val kotlinPlugin: KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(ins) + val kobaltPlugin: KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(ins) as KobaltPluginXml - log(2, "Parsed plugin XML file, found: " + kotlinPlugin.name) - return PluginInfo(kotlinPlugin, classLoader) + log(2, "Parsed plugin XML file, found: " + kobaltPlugin.name) + val result = + try { + PluginInfo(kobaltPlugin, pluginClassLoader, classLoader) + } catch(ex: Exception) { + throw KobaltException("Couldn't create PluginInfo: " + ex.message, ex) + } + return result } - fun readPluginXml(s: String, classLoader: ClassLoader? = null) - = readPluginXml(ByteArrayInputStream(s.toByteArray(Charsets.UTF_8)), classLoader) + fun readPluginXml(s: String, pluginClassLoader: ClassLoader?, scriptClassLoader: ClassLoader? = null) + = readPluginXml(ByteArrayInputStream(s.toByteArray(Charsets.UTF_8)), pluginClassLoader, + scriptClassLoader) } init { @@ -132,7 +154,8 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { } fun forName(className: String) = - if (classLoader != null) classLoader.loadClass(className) + if (pluginClassLoader != null) pluginClassLoader.loadClass(className) + else if (classLoader != null) classLoader.loadClass(className) else Class.forName(className) // @@ -189,7 +212,7 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { } /** - * Populate pluginInfo with what was found in the plug-in's kobalt-plugin.xml + * Add the content of @param[pluginInfo] to this pluginInfo. */ fun addPluginInfo(pluginInfo: PluginInfo) { log(2, "Found new plug-in, adding it to pluginInfo: $pluginInfo") @@ -216,6 +239,7 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { buildConfigContributors.addAll(pluginInfo.buildConfigContributors) assemblyContributors.addAll(pluginInfo.assemblyContributors) incrementalAssemblyContributors.addAll(pluginInfo.incrementalAssemblyContributors) + testJvmFlagContributors.addAll(pluginInfo.testJvmFlagContributors) testJvmFlagInterceptors.addAll(pluginInfo.testJvmFlagInterceptors) } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt index 8f902b7c..bd117f8b 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt @@ -430,6 +430,7 @@ class TaskManager @Inject constructor(val args: Args, private val taskAnnotations = arrayListOf() class TaskAnnotation(val method: Method, val plugin: IPlugin, val name: String, val description: String, + val group: String, val dependsOn: Array, val reverseDependsOn: Array, val runBefore: Array, val runAfter: Array, val alwaysRunAfter: Array, @@ -441,7 +442,7 @@ class TaskManager @Inject constructor(val args: Args, * Invoking a @Task means simply calling the method and returning its returned TaskResult. */ fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: Task) - = TaskAnnotation(method, plugin, ta.name, ta.description, ta.dependsOn, ta.reverseDependsOn, + = TaskAnnotation(method, plugin, ta.name, ta.description, ta.group, ta.dependsOn, ta.reverseDependsOn, ta.runBefore, ta.runAfter, ta.alwaysRunAfter, { project -> method.invoke(plugin, project) as TaskResult @@ -452,7 +453,7 @@ class TaskManager @Inject constructor(val args: Args, * of the returned IncrementalTaskInfo. */ fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: IncrementalTask) - = TaskAnnotation(method, plugin, ta.name, ta.description, ta.dependsOn, ta.reverseDependsOn, + = TaskAnnotation(method, plugin, ta.name, ta.description, ta.group, ta.dependsOn, ta.reverseDependsOn, ta.runBefore, ta.runAfter, ta.alwaysRunAfter, incrementalManagerFactory.create().toIncrementalTaskClosure(ta.name, { project -> method.invoke(plugin, project) as IncrementalTaskInfo @@ -481,7 +482,7 @@ class TaskManager @Inject constructor(val args: Args, private fun installDynamicTasks(projects: List) { dynamicTasks.forEach { task -> projects.filter { task.plugin.accept(it) }.forEach { project -> - addTask(task.plugin, project, task.name, task.doc, + addTask(task.plugin, project, task.name, task.doc, task.group, task.dependsOn, task.reverseDependsOn, task.runBefore, task.runAfter, task.alwaysRunAfter, task.closure) } @@ -504,13 +505,13 @@ class TaskManager @Inject constructor(val args: Args, private fun addAnnotationTask(plugin: IPlugin, project: Project, annotation: TaskAnnotation, task: (Project) -> TaskResult) { - addTask(plugin, project, annotation.name, annotation.description, + addTask(plugin, project, annotation.name, annotation.description, annotation.group, annotation.dependsOn.toList(), annotation.reverseDependsOn.toList(), annotation.runBefore.toList(), annotation.runAfter.toList(), annotation.alwaysRunAfter.toList(), task) } - fun addTask(plugin: IPlugin, project: Project, name: String, description: String = "", + fun addTask(plugin: IPlugin, project: Project, name: String, description: String = "", group: String, dependsOn: List = listOf(), reverseDependsOn: List = listOf(), runBefore: List = listOf(), @@ -518,7 +519,7 @@ class TaskManager @Inject constructor(val args: Args, alwaysRunAfter: List = listOf(), task: (Project) -> TaskResult) { annotationTasks.add( - object : BasePluginTask(plugin, name, description, project) { + object : BasePluginTask(plugin, name, description, group, project) { override fun call(): TaskResult2 { val taskResult = task(project) return TaskResult2(taskResult.success, taskResult.errorMessage, this) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt index e4efb9e9..f23b1716 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt @@ -1,6 +1,7 @@ package com.beust.kobalt.internal.build import com.beust.kobalt.misc.KFiles +import com.beust.kobalt.misc.log import java.io.File import java.nio.file.Files import java.nio.file.Path @@ -23,4 +24,13 @@ class BuildFile(val path: Path, val name: String, val realPath: Path = path) { val dotKobaltDir: File get() = File(directory.parentFile.parentFile, KFiles.KOBALT_DOT_DIR).apply { mkdirs() } + + /** + * @return the absolute directory of this project's location, assuming the build file is in + * $project/kobalt/src/Build.kt. + */ + val absoluteDir : File? get() { + log(1, "Current path: $path") + return path.parent?.parent?.parent?.toFile() + } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt index 968056b6..6085ad61 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt @@ -7,6 +7,7 @@ import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.log +import com.beust.kobalt.misc.warn import com.google.common.collect.ArrayListMultimap import java.io.File import java.util.* @@ -30,7 +31,15 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors, val val path = if (project?.directory != null) { val idPath = id.substring(FileDependency.PREFIX_FILE.length) if (! File(idPath).isAbsolute) { - File(project!!.directory, idPath) + // If the project directory is relative, we might not be in the correct directory to locate + // that file, so we'll use the absolute directory deduced from the build file path. Pick + // the first one that produces an actual file + val result = listOf(File(project!!.directory), Kobalt.context?.internalContext?.absoluteDir).map { + File(it, idPath) + }.first { + it.exists() + } + result } else { File(idPath) } @@ -119,7 +128,14 @@ class DependencyManager @Inject constructor(val executors: KobaltExecutors, val } } - val result2 = reorderDependencies(result).filter { + val reordered = reorderDependencies(result) + + val nonexistent = reordered.filter{ ! it.jarFile.get().exists() } + if (nonexistent.any()) { + warn("Nonexistent dependencies: $nonexistent") + } + + val result2 = reordered.filter { // Only keep existent files (nonexistent files are probably optional dependencies or parent poms // that point to other poms but don't have a jar file themselves) it.jarFile.get().exists() diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/LocalRepo.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/LocalRepo.kt index e42cc75d..5077d5b9 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/LocalRepo.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/LocalRepo.kt @@ -39,7 +39,7 @@ open class LocalRepo @Inject constructor(val kobaltSettings: KobaltSettings) { v2.compareTo(v1) // we want the most recent at position 0 }) val result = directories[0].name - val newDep = LocalDep(MavenId.create(groupId, artifactId, packaging, result), this) + val newDep = LocalDep(MavenId.create(groupId, artifactId, packaging, null, result), this) if (existsPom(newDep, result) && existsJar(newDep, result)) { return result } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/MavenId.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/MavenId.kt index e80d5925..1ab12db7 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/MavenId.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/MavenId.kt @@ -14,11 +14,11 @@ import org.eclipse.aether.artifact.DefaultArtifact * usually means "latest version") but it doesn't handle version ranges yet. */ class MavenId private constructor(val groupId: String, val artifactId: String, val packaging: String?, - val version: String?) { + val classifier: String?, val version: String?) { companion object { fun isMavenId(id: String) = with(id.split(":")) { - size == 3 || size == 4 + size >= 3 && size <= 5 } fun isRangedVersion(s: String): Boolean { @@ -29,7 +29,7 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v * Similar to create(MavenId) but don't run IMavenIdInterceptors. */ fun createNoInterceptors(id: String) : MavenId = DefaultArtifact(id).run { - MavenId(groupId, artifactId, extension, version) + MavenId(groupId, artifactId, extension, classifier, version) } fun toKobaltId(id: String) = if (id.endsWith(":")) id + "(0,]" else id @@ -51,18 +51,19 @@ class MavenId private constructor(val groupId: String, val artifactId: String, v return interceptedMavenId } - fun create(groupId: String, artifactId: String, packaging: String?, version: String?) = - create(toId(groupId, artifactId, packaging, version)) + fun create(groupId: String, artifactId: String, packaging: String?, classifier: String?, version: String?) = + create(toId(groupId, artifactId, packaging, classifier, version)) - fun toId(groupId: String, artifactId: String, packaging: String? = null, version: String?) = + fun toId(groupId: String, artifactId: String, packaging: String? = null, classifier: String? = null, version: String?) = "$groupId:$artifactId" + (if (packaging != null && packaging != "") ":$packaging" else "") + + (if (classifier != null && classifier != "") ":$classifier" else "") + ":$version" } val hasVersion = version != null - val toId = MavenId.toId(groupId, artifactId, packaging, version) + val toId = MavenId.toId(groupId, artifactId, packaging, classifier, version) } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/PomGenerator.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/PomGenerator.kt index 460ccc4e..2ccc9250 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/PomGenerator.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/PomGenerator.kt @@ -56,10 +56,11 @@ public class PomGenerator @Inject constructor(@Assisted val project: Project) { val buildDir = KFiles.makeDir(project.directory, project.buildDirectory) val outputDir = KFiles.makeDir(buildDir.path, "libs") - val mavenId = MavenId.create(project.group!!, project.artifactId!!, project.packaging, project.version!!) + val NO_CLASSIFIER = null + val mavenId = MavenId.create(project.group!!, project.artifactId!!, project.packaging, NO_CLASSIFIER, project.version!!) val pomFile = SimpleDep(mavenId).toPomFileName() val outputFile = File(outputDir, pomFile) outputFile.writeText(s.toString(), Charset.defaultCharset()) log(1, " Created $outputFile") } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/beust/kobalt/app/BuildFileCompiler.kt b/src/main/kotlin/com/beust/kobalt/app/BuildFileCompiler.kt index 47918c44..58ee7438 100644 --- a/src/main/kotlin/com/beust/kobalt/app/BuildFileCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/app/BuildFileCompiler.kt @@ -73,6 +73,11 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b val pluginUrls = parsedBuildFile.pluginUrls val buildScriptJarFile = File(KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR)) + // + // Save the current build script absolute directory + // + context.internalContext.absoluteDir = buildFile.absoluteDir + // If the script jar files were generated by a different version, wipe them in case the API // changed in-between buildScriptJarFile.parentFile.let { dir -> @@ -96,6 +101,10 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b errorTaskResult = taskResult } } + + // Clear the absolute dir + context.internalContext.absoluteDir = null + } val pluginUrls = parsedBuildFiles.flatMap { it.pluginUrls } return FindProjectResult(projects, pluginUrls, if (errorTaskResult != null) errorTaskResult!! else TaskResult()) diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt b/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt index a7ff91fa..7a4f4eec 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt @@ -56,7 +56,7 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep val sources = project.sourceDirectories.partition { KFiles.isResource(it) } val tests = project.sourceDirectoriesTest.partition { KFiles.isResource(it) } val allTasks = taskManager.tasksByNames(project).values().map { - TaskData(it.name, it.doc) + TaskData(it.name, it.doc, it.group) } projectDatas.add(ProjectData(project.name, project.directory, dependentProjects, compileDependencies, testDependencies, @@ -72,7 +72,7 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep // class DependencyData(val id: String, val scope: String, val path: String) - class TaskData(val name: String, val description: String) + class TaskData(val name: String, val description: String, val group: String) class ProjectData(val name: String, val directory: String, val dependentProjects: List, diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt b/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt index 4e871cfc..996d4296 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt @@ -7,6 +7,7 @@ import com.google.gson.Gson import spark.ResponseTransformer import spark.Route import spark.Spark +import java.util.concurrent.Executors class SparkServer(val initCallback: (String) -> List, val cleanUpCallback: () -> Unit) : KobaltServer .IServer { @@ -28,7 +29,17 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba override fun run(port: Int) { Spark.port(port) - Spark.get("/hello", { req, res -> "Hello world" }) + Spark.get("/ping", { req, res -> "The Kobalt server is up and running" }) + Spark.get("/quit", { req, res -> + Executors.newFixedThreadPool(1).let { executor -> + executor.submit { + Thread.sleep(1000) + Spark.stop() + executor.shutdown() + } + "ok" + } + }) Spark.get("/v0/getDependencies", "application/json", Route { request, response -> val buildFile = request.queryParams("buildFile") initCallback(buildFile) @@ -40,12 +51,13 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba dependencyData.dependenciesDataFor(buildFile, args) } catch(ex: Exception) { - "Error: " + ex.message + DependencyData.GetDependenciesData(emptyList(), ex.message) } finally { cleanUpCallback() } } else { - "error" + DependencyData.GetDependenciesData(emptyList(), + "buildFile wasn't passed in the query parameter") } cleanUpCallback() result diff --git a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt index a4855109..38aa114e 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt @@ -48,7 +48,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor): List { + return listOf("-agent", "foo") + } + } + + private val interceptor = object : ITestJvmFlagInterceptor { + override fun testJvmFlagsFor(project: Project, context: KobaltContext, + currentFlags: List): List { + return currentFlags.map { if (it == A_JAR) B_JAR else it } + } + } + + @BeforeClass + fun beforeClass() { + Kobalt.init(TestModule()) + } + + private fun runTest(pluginInfo: IPluginInfo, expected: List) { + val result = TestNgRunner().calculateAllJvmArgs(project, context, TestConfig(project), + classpath, pluginInfo) + assertThat(result).isEqualTo(expected) + } + + @Test + fun noContributorsNoInterceptors() { + runTest(BasePluginInfo(), listOf("-classpath", A_JAR)) + } + + @Test + fun contributorOnly() { + runTest(BasePluginInfo().apply { testJvmFlagContributors.add(contributor) }, + listOf("-classpath", A_JAR, "-agent", "foo")) + } + + @Test + fun interceptorOnly() { + runTest(BasePluginInfo().apply { testJvmFlagInterceptors.add(interceptor) }, + listOf("-classpath", B_JAR)) + } + + @Test + fun contributorAndInterceptor() { + runTest(BasePluginInfo().apply { + testJvmFlagContributors.add(contributor) + testJvmFlagInterceptors.add(interceptor) + }, + listOf("-classpath", B_JAR, "-agent", "foo")) + } +} + diff --git a/src/test/kotlin/com/beust/kobalt/maven/DependencyTest.kt b/src/test/kotlin/com/beust/kobalt/maven/DependencyTest.kt index cb6a0bec..adc7096f 100644 --- a/src/test/kotlin/com/beust/kobalt/maven/DependencyTest.kt +++ b/src/test/kotlin/com/beust/kobalt/maven/DependencyTest.kt @@ -10,7 +10,7 @@ import javax.inject.Inject import kotlin.properties.Delegates @Guice(modules = arrayOf(TestModule::class)) -public class DependencyTest @Inject constructor(val executors: KobaltExecutors) { +class DependencyTest @Inject constructor(val executors: KobaltExecutors) { @DataProvider fun dpVersions(): Array> {