diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index e389e979..576ec211 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -67,6 +67,7 @@ private class Main @Inject constructor( val pluginInfo: PluginInfo, val dependencyData: DependencyData, val projectGenerator: ProjectGenerator, + val serverFactory: KobaltServer.IFactory, val resolveDependency: ResolveDependency) { data class RunInfo(val jc: JCommander, val args: Args) @@ -99,7 +100,7 @@ private class Main @Inject constructor( // --listTemplates if (args.listTemplates) { - Templates().list(pluginInfo) + Templates().displayTemplates(pluginInfo) return 0 } @@ -158,7 +159,7 @@ private class Main @Inject constructor( jc.usage() } else if (args.serverMode) { // --server - val port = KobaltServer(args.force, args.port, + val port = serverFactory.create(args.force, args.port, { buildFile -> initForBuildFile(BuildFile(Paths.get(buildFile), buildFile), args)}, { cleanUp() }) .call() diff --git a/src/main/kotlin/com/beust/kobalt/app/MainModule.kt b/src/main/kotlin/com/beust/kobalt/app/MainModule.kt index 5731d69a..6453c331 100644 --- a/src/main/kotlin/com/beust/kobalt/app/MainModule.kt +++ b/src/main/kotlin/com/beust/kobalt/app/MainModule.kt @@ -1,6 +1,7 @@ package com.beust.kobalt.app import com.beust.kobalt.Args +import com.beust.kobalt.app.remote.KobaltServer import com.beust.kobalt.internal.IncrementalManager import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.PluginInfo @@ -29,12 +30,13 @@ public open class MainModule(val args: Args, val settings: KobaltSettings) : Abs configureTest() val builder = FactoryModuleBuilder() - arrayListOf( + listOf( PomGenerator.IFactory::class.java, BintrayApi.IFactory::class.java, Pom.IFactory::class.java, BuildFileCompiler.IFactory::class.java, - IncrementalManager.IFactory::class.java) + IncrementalManager.IFactory::class.java, + KobaltServer.IFactory::class.java) .forEach { install(builder.build(it)) } diff --git a/src/main/kotlin/com/beust/kobalt/app/Templates.kt b/src/main/kotlin/com/beust/kobalt/app/Templates.kt index 83c91c63..20a1da1e 100644 --- a/src/main/kotlin/com/beust/kobalt/app/Templates.kt +++ b/src/main/kotlin/com/beust/kobalt/app/Templates.kt @@ -7,23 +7,26 @@ import com.beust.kobalt.app.kotlin.KotlinTemplateGenerator import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.misc.log import com.google.common.collect.ArrayListMultimap -import com.google.inject.Inject +import com.google.common.collect.ListMultimap -class Templates @Inject constructor() : ITemplateContributor { +class Templates : ITemplateContributor { override val templates = listOf(JavaTemplateGenerator(), KotlinTemplateGenerator(), IdeaFilesTemplate()) - fun list(pluginInfo: PluginInfo) { + fun getTemplates(pluginInfo: PluginInfo): ListMultimap { val map = ArrayListMultimap.create() pluginInfo.initContributors.forEach { it.templates.forEach { map.put(it.pluginName, it) } } + return map + } - log(1, "Available templates") - map.keySet().forEach { + fun displayTemplates(pluginInfo : PluginInfo) { + val templates = getTemplates(pluginInfo) + templates.keySet().forEach { log(1, " Plug-in: $it") - map[it].forEach { + templates[it].forEach { log(1, " \"" + it.templateName + "\"\t\t" + it.templateDescription) } } diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt index 2b011334..2b0cb10b 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt @@ -12,6 +12,7 @@ import com.beust.kobalt.misc.warn import com.google.gson.JsonObject import com.google.gson.JsonParser import com.google.inject.Guice +import com.google.inject.Inject import okhttp3.OkHttpClient import retrofit2.Call import retrofit2.Retrofit @@ -49,44 +50,10 @@ class KobaltClient : Runnable { val dependencies = service.getDependencies(buildFile) val results = dependencies.execute() println("Dependencies: $results") -// .toString()) -// var done = false -// var attempts = 1 -// while (attempts < 10 && ! done) { -// try { -// val socket = Socket("localhost", portNumber) -// outgoing = PrintWriter(socket.outputStream, true) -// val testBuildfile = Paths.get(SystemProperties.homeDir, "kotlin/klaxon/kobalt/src/Build.kt") -// .toFile().absolutePath -// val c : String = """{ "name": "getDependencies", "buildFile": "$testBuildfile"}""" -// outgoing!!.println(c) -// val ins = BufferedReader(InputStreamReader(socket.inputStream)) -// var line = ins.readLine() -// while (! done && line != null) { -// log(1, "Received from server:\n" + line) -// val jo = JsonParser().parse(line) as JsonObject -// if (jo.has("name") && "quit" == jo.get("name").asString.toLowerCase()) { -// log(1, "Quitting") -//// outgoing!!.println("{ \"name\": \"Quit\" }") -// done = true -// } else { -// val data = jo.get("data").asString -// val dd = Gson().fromJson(data, DependencyData.GetDependenciesData::class.java) -// println("Read GetDependencyData, project count: ${dd.projects.size}") -// line = ins.readLine() -// } -// } -// } catch(ex: ConnectException) { -// log(1, "Server not up, sleeping a bit") -// Thread.sleep(2000) -// attempts++ -// } -// } } } - -class ServerProcess { +class ServerProcess @Inject constructor(val serverFactory: KobaltServer.IFactory) { val SERVER_FILE = KFiles.joinDir(homeDir(KFiles.KOBALT_DOT_DIR, "kobaltServer.properties")) val KEY_PORT = "port" val executor = Executors.newFixedThreadPool(5) @@ -95,7 +62,10 @@ class ServerProcess { var port = launchPrivate() while (port == 0) { executor.submit { - KobaltServer(force = true, initCallback = { buildFile -> emptyList()}, cleanUpCallback = {}).call() + serverFactory.create(force = true, + initCallback = { buildFile -> emptyList()}, + cleanUpCallback = {}) + .call() } // launchServer(ProcessUtil.findAvailablePort()) port = launchPrivate() diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltServer.kt b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltServer.kt index c0bcc22d..872ef509 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltServer.kt @@ -2,13 +2,17 @@ package com.beust.kobalt.app.remote import com.beust.kobalt.api.Project import com.beust.kobalt.homeDir +import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.log +import com.google.inject.Inject +import com.google.inject.assistedinject.Assisted import java.io.File import java.io.FileWriter import java.lang.management.ManagementFactory import java.util.* import java.util.concurrent.Callable +import javax.annotation.Nullable /** * Launch a Kobalt server. If @param{force} is specified, a new server will be launched even if one was detected @@ -17,9 +21,16 @@ import java.util.concurrent.Callable * The callbacks are used to initialize and clean up the state before and after each command, so that Kobalt's state * can be properly reset, making the server reentrant. */ -class KobaltServer(val force: Boolean, val givenPort: Int? = null, - val initCallback: (String) -> List, - val cleanUpCallback: () -> Unit) : Callable { +class KobaltServer @Inject constructor(@Assisted val force: Boolean, @Assisted @Nullable val givenPort: Int?, + @Assisted val initCallback: (String) -> List, + @Assisted val cleanUpCallback: () -> Unit, + val pluginInfo : PluginInfo) : Callable { + + interface IFactory { + fun create(force: Boolean, givenPort: Int? = null, + initCallback: (String) -> List, + cleanUpCallback: () -> Unit) : KobaltServer + } companion object { /** @@ -41,7 +52,7 @@ class KobaltServer(val force: Boolean, val givenPort: Int? = null, log(1, "KobaltServer listening on port $port") // OldServer(initCallback, cleanUpCallback).run(port) // JerseyServer(initCallback, cleanUpCallback).run(port) - SparkServer(initCallback, cleanUpCallback).run(port) + SparkServer(initCallback, cleanUpCallback, pluginInfo).run(port) // WasabiServer(initCallback, cleanUpCallback).run(port) } } catch(ex: Exception) { 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 57176d82..23132924 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt @@ -1,16 +1,20 @@ package com.beust.kobalt.app.remote import com.beust.kobalt.Args +import com.beust.kobalt.api.ITemplate import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Project +import com.beust.kobalt.app.Templates +import com.beust.kobalt.internal.PluginInfo +import com.google.common.collect.ListMultimap 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 { +class SparkServer(val initCallback: (String) -> List, val cleanUpCallback: () -> Unit, + val pluginInfo : PluginInfo) : KobaltServer.IServer { companion object { lateinit var initCallback: (String) -> List @@ -27,6 +31,9 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba override fun render(model: Any) = gson.toJson(model) } + private fun jsonRoute(path: String, route: Route) + = Spark.get(path, "application/json", route, JsonTransformer()) + override fun run(port: Int) { Spark.port(port) Spark.get("/ping", { req, res -> KobaltServer.OK }) @@ -40,7 +47,7 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba KobaltServer.OK } }) - Spark.get("/v0/getDependencies", "application/json", Route { request, response -> + jsonRoute("/v0/getDependencies", Route { request, response -> val buildFile = request.queryParams("buildFile") initCallback(buildFile) val result = @@ -61,7 +68,25 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba } cleanUpCallback() result - }, JsonTransformer()) + }) + jsonRoute("/v0/getTemplates", Route { request, response -> + TemplatesInfo.create(Templates().getTemplates(pluginInfo)) + }) + } +} + +class TemplateInfo(val pluginName: String, val templates: List) + +class TemplatesInfo(val templates: List) { + companion object { + fun create(map: ListMultimap) : TemplatesInfo { + val templateList = arrayListOf() + map.keySet().forEach { pluginName -> + val list = map[pluginName].map { it.templateName } + templateList.add(TemplateInfo(pluginName, list)) + } + return TemplatesInfo(templateList) + } } }