From 883610878ae4cd031a2c2b242e7dad0a8c67c0e3 Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Thu, 10 Sep 2020 18:48:47 +0200 Subject: [PATCH 1/3] Start zip output --- pom.xml | 10 +++++++ src/main/kotlin/starter/KotlinStarter.kt | 19 ++++++++++--- src/main/kotlin/starter/Models.kt | 4 ++- src/main/kotlin/starter/ProjectZip.kt | 18 +++++++++++++ src/main/kotlin/starter/Server.kt | 15 ++++++++--- src/main/kotlin/starter/Templates.kt | 21 +++++++++++++++ src/main/kotlin/starter/Views.kt | 23 +--------------- src/main/kotlin/starter/utils/PebbleUtils.kt | 11 ++++++++ .../starter/{Utils.kt => utils/XmlUtils.kt} | 2 +- src/main/kotlin/starter/utils/ZipOutput.kt | 27 +++++++++++++++++++ src/main/resources/starter/@dependencies.twig | 2 +- 11 files changed, 121 insertions(+), 31 deletions(-) create mode 100644 src/main/kotlin/starter/ProjectZip.kt create mode 100644 src/main/kotlin/starter/Templates.kt create mode 100644 src/main/kotlin/starter/utils/PebbleUtils.kt rename src/main/kotlin/starter/{Utils.kt => utils/XmlUtils.kt} (98%) create mode 100644 src/main/kotlin/starter/utils/ZipOutput.kt diff --git a/pom.xml b/pom.xml index 28be0da..9a813da 100644 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,16 @@ javalin 3.10.1 + + org.apache.commons + commons-compress + 1.20 + + + org.koin + koin-core + 2.1.6 + diff --git a/src/main/kotlin/starter/KotlinStarter.kt b/src/main/kotlin/starter/KotlinStarter.kt index 34f23fd..9b3c774 100644 --- a/src/main/kotlin/starter/KotlinStarter.kt +++ b/src/main/kotlin/starter/KotlinStarter.kt @@ -1,8 +1,21 @@ package starter +import org.koin.core.context.startKoin +import org.koin.dsl.module + +val module = module { + single { Config().load() } + single { PebbleModule().engine() } + single { Server(get(), get(), get()) } + single { Templates(get()) } + single { Views(get()) } + single { ProjectZip(get()) } +} + fun main() { - val config = Config() - val loaded = config.load() - val server = Server(Views(PebbleModule().engine()),loaded) + val koin = startKoin { + modules(module) + }.koin + val server = koin.get() server.run() } diff --git a/src/main/kotlin/starter/Models.kt b/src/main/kotlin/starter/Models.kt index 0cb1836..3ac1711 100644 --- a/src/main/kotlin/starter/Models.kt +++ b/src/main/kotlin/starter/Models.kt @@ -18,4 +18,6 @@ data class Dependency( val scope: Scope ) -data class Input(val name: String, val display: String, val value: String? = null) \ No newline at end of file +data class Input(val name: String, val display: String, val value: String? = null) + +data class Project(val name: String, val basePackage: String) \ No newline at end of file diff --git a/src/main/kotlin/starter/ProjectZip.kt b/src/main/kotlin/starter/ProjectZip.kt new file mode 100644 index 0000000..f892584 --- /dev/null +++ b/src/main/kotlin/starter/ProjectZip.kt @@ -0,0 +1,18 @@ +package starter + +import starter.utils.ZipOutput +import starter.utils.prettyPrintXml + +class ProjectZip(private val templates: Templates) { + + fun createZip(project: Project, inputs: List, dependencies: List) { + val pom = templates.pom(dependencies, inputs) + val prettyPom = prettyPrintXml(pom) + + ZipOutput(project.name).use { + it.write("pom.xml", prettyPom) + } + + } + +} \ No newline at end of file diff --git a/src/main/kotlin/starter/Server.kt b/src/main/kotlin/starter/Server.kt index ba11bee..b5832b5 100644 --- a/src/main/kotlin/starter/Server.kt +++ b/src/main/kotlin/starter/Server.kt @@ -2,7 +2,11 @@ package starter import io.javalin.Javalin -class Server(private val views: Views, private val conf: StarterConfig) { +class Server( + private val views: Views, + private val conf: StarterConfig, + private val projectZip: ProjectZip, +) { fun run() { val app = Javalin.create { it.addStaticFiles("/assets") @@ -25,8 +29,13 @@ class Server(private val views: Views, private val conf: StarterConfig) { conf.inputs.find { it.name == name }!!.copy(value = value.first()) } - val generatedPom = views.pom(deps, inputs) - ctx.result(prettyPrintXml(generatedPom)) + val projectName = inputs.find { it.name == "name" }!!.value!! + val basePackage = inputs.find { it.name == "basePackage" }!!.value!! + val project = Project(projectName, basePackage) + + projectZip.createZip(project, inputs, deps) + TODO() + ctx.result("prettyPrintXml(generatedPom)") ctx.contentType("text/xml") } } diff --git a/src/main/kotlin/starter/Templates.kt b/src/main/kotlin/starter/Templates.kt new file mode 100644 index 0000000..3e3f540 --- /dev/null +++ b/src/main/kotlin/starter/Templates.kt @@ -0,0 +1,21 @@ +package starter + +import com.mitchellbosecke.pebble.PebbleEngine +import starter.utils.render + +class Templates(private val engine: PebbleEngine) { + fun pom(dependencies: List, inputs: List): String { + + val args: MutableMap = mutableMapOf( + "dependencies" to dependencies.sortedBy { it.scope }, + ) + + inputs.forEach { + args[it.name] = it.value + } + + return engine.render("starter/pom", + args + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/starter/Views.kt b/src/main/kotlin/starter/Views.kt index e596a84..2999ad9 100644 --- a/src/main/kotlin/starter/Views.kt +++ b/src/main/kotlin/starter/Views.kt @@ -2,14 +2,7 @@ package starter import com.mitchellbosecke.pebble.PebbleEngine import org.slf4j.LoggerFactory -import java.io.StringWriter - -private fun PebbleEngine.render(name: String, args: Map = mapOf()): String { - val template = getTemplate(name) - val writer = StringWriter() - template.evaluate(writer, args) - return writer.toString() -} +import starter.utils.render class Views(private val engine: PebbleEngine) { private val logger = LoggerFactory.getLogger(javaClass) @@ -21,18 +14,4 @@ class Views(private val engine: PebbleEngine) { ) } - fun pom(dependencies: List, inputs: List): String { - - val args: MutableMap = mutableMapOf( - "dependencies" to dependencies.sortedBy { it.scope }, - ) - - inputs.forEach { - args[it.name] = it.value - } - - return engine.render("starter/pom", - args - ) - } } \ No newline at end of file diff --git a/src/main/kotlin/starter/utils/PebbleUtils.kt b/src/main/kotlin/starter/utils/PebbleUtils.kt new file mode 100644 index 0000000..6a52f56 --- /dev/null +++ b/src/main/kotlin/starter/utils/PebbleUtils.kt @@ -0,0 +1,11 @@ +package starter.utils + +import com.mitchellbosecke.pebble.PebbleEngine +import java.io.StringWriter + +fun PebbleEngine.render(name: String, args: Map = mapOf()): String { + val template = getTemplate(name) + val writer = StringWriter() + template.evaluate(writer, args) + return writer.toString() +} \ No newline at end of file diff --git a/src/main/kotlin/starter/Utils.kt b/src/main/kotlin/starter/utils/XmlUtils.kt similarity index 98% rename from src/main/kotlin/starter/Utils.kt rename to src/main/kotlin/starter/utils/XmlUtils.kt index 9048e2c..7e1a7de 100644 --- a/src/main/kotlin/starter/Utils.kt +++ b/src/main/kotlin/starter/utils/XmlUtils.kt @@ -1,4 +1,4 @@ -package starter +package starter.utils import org.w3c.dom.Document import org.w3c.dom.NodeList diff --git a/src/main/kotlin/starter/utils/ZipOutput.kt b/src/main/kotlin/starter/utils/ZipOutput.kt new file mode 100644 index 0000000..23b3646 --- /dev/null +++ b/src/main/kotlin/starter/utils/ZipOutput.kt @@ -0,0 +1,27 @@ +package starter.utils + +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream +import java.io.File +import java.nio.file.Paths + +class ZipOutput(name: String) : AutoCloseable { + private val baseDir = File(".").canonicalFile + private val zipPath = Paths.get(baseDir.path, "$name.zip") + private val zipFile = zipPath.toAbsolutePath().normalize().toFile().apply { + createNewFile() + } + private val outputStream = ZipArchiveOutputStream(zipFile.outputStream()) + + fun write(path: String, content: String) { + val entry = ZipArchiveEntry(path) + outputStream.putArchiveEntry(entry) + outputStream.write(content.toByteArray()) + outputStream.closeArchiveEntry() + } + + override fun close() { + outputStream.finish() + outputStream.close() + } +} \ No newline at end of file diff --git a/src/main/resources/starter/@dependencies.twig b/src/main/resources/starter/@dependencies.twig index d999ec8..e609248 100644 --- a/src/main/resources/starter/@dependencies.twig +++ b/src/main/resources/starter/@dependencies.twig @@ -4,7 +4,7 @@ {{ dep.groupId }} {{ dep.artifactId }} {{ dep.version }} - {% if dep.scope.toString == "Test" %} + {% if dep.scope == "Test" %} test {% endif %} From ddf85585782c1990c52a755663de96d45473ca8d Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Thu, 10 Sep 2020 19:03:24 +0200 Subject: [PATCH 2/3] Return zip --- src/main/kotlin/starter/ProjectZip.kt | 9 +++++++-- src/main/kotlin/starter/Server.kt | 10 +++++++--- src/main/kotlin/starter/utils/PathUtils.kt | 3 +++ src/main/kotlin/starter/utils/ZipOutput.kt | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 src/main/kotlin/starter/utils/PathUtils.kt diff --git a/src/main/kotlin/starter/ProjectZip.kt b/src/main/kotlin/starter/ProjectZip.kt index f892584..4e23396 100644 --- a/src/main/kotlin/starter/ProjectZip.kt +++ b/src/main/kotlin/starter/ProjectZip.kt @@ -2,17 +2,22 @@ package starter import starter.utils.ZipOutput import starter.utils.prettyPrintXml +import starter.utils.sanitizeFilename class ProjectZip(private val templates: Templates) { - fun createZip(project: Project, inputs: List, dependencies: List) { + fun createZip(project: Project, inputs: List, dependencies: List): String { val pom = templates.pom(dependencies, inputs) val prettyPom = prettyPrintXml(pom) - ZipOutput(project.name).use { + val name: String + + ZipOutput(sanitizeFilename(project.name)).use { + name = it.name it.write("pom.xml", prettyPom) } + return name } } \ No newline at end of file diff --git a/src/main/kotlin/starter/Server.kt b/src/main/kotlin/starter/Server.kt index b5832b5..6221fa1 100644 --- a/src/main/kotlin/starter/Server.kt +++ b/src/main/kotlin/starter/Server.kt @@ -1,6 +1,8 @@ package starter import io.javalin.Javalin +import starter.utils.sanitizeFilename +import java.io.File class Server( private val views: Views, @@ -33,10 +35,12 @@ class Server( val basePackage = inputs.find { it.name == "basePackage" }!!.value!! val project = Project(projectName, basePackage) - projectZip.createZip(project, inputs, deps) - TODO() - ctx.result("prettyPrintXml(generatedPom)") + ctx.contentType("text/xml") + ctx.header("Content-Disposition", "attachment; filename=\"${sanitizeFilename(projectName)}.zip\"") + val zipFile = projectZip.createZip(project, inputs, deps) + ctx.result(File(zipFile).readBytes()) } } + } \ No newline at end of file diff --git a/src/main/kotlin/starter/utils/PathUtils.kt b/src/main/kotlin/starter/utils/PathUtils.kt new file mode 100644 index 0000000..81eb342 --- /dev/null +++ b/src/main/kotlin/starter/utils/PathUtils.kt @@ -0,0 +1,3 @@ +package starter.utils + +fun sanitizeFilename(inputName: String): String = inputName.replace("[^a-zA-Z0-9-_.]".toRegex(), "_") diff --git a/src/main/kotlin/starter/utils/ZipOutput.kt b/src/main/kotlin/starter/utils/ZipOutput.kt index 23b3646..282bbd9 100644 --- a/src/main/kotlin/starter/utils/ZipOutput.kt +++ b/src/main/kotlin/starter/utils/ZipOutput.kt @@ -12,6 +12,8 @@ class ZipOutput(name: String) : AutoCloseable { createNewFile() } private val outputStream = ZipArchiveOutputStream(zipFile.outputStream()) + val name: String + get() = zipFile.name fun write(path: String, content: String) { val entry = ZipArchiveEntry(path) From 8ba3dac0b23f0611cd377a15ba4bd18eb77b8e03 Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Thu, 10 Sep 2020 19:08:31 +0200 Subject: [PATCH 3/3] Separate templates --- src/main/kotlin/starter/KotlinStarter.kt | 16 +++++++++---- src/main/kotlin/starter/Models.kt | 7 +++++- src/main/kotlin/starter/ProjectZip.kt | 16 ++++++------- src/main/kotlin/starter/Server.kt | 10 ++++---- src/main/kotlin/starter/Templates.kt | 21 ----------------- .../kotlin/starter/templates/MainTemplate.kt | 13 +++++++++++ .../kotlin/starter/templates/PomTemplate.kt | 23 +++++++++++++++++++ src/main/kotlin/starter/templates/Template.kt | 8 +++++++ src/main/resources/starter/main/main.twig | 6 +++++ .../starter/{ => pom}/@dependencies.twig | 0 .../resources/starter/{ => pom}/@plugins.twig | 6 ++--- .../starter/{ => pom}/@repositories.twig | 0 .../starter/{ => pom}/plugins/@default.twig | 0 .../starter/{ => pom}/plugins/@kotlin.twig | 0 .../starter/{ => pom}/plugins/@shade.twig | 0 src/main/resources/starter/{ => pom}/pom.twig | 6 ++--- 16 files changed, 86 insertions(+), 46 deletions(-) delete mode 100644 src/main/kotlin/starter/Templates.kt create mode 100644 src/main/kotlin/starter/templates/MainTemplate.kt create mode 100644 src/main/kotlin/starter/templates/PomTemplate.kt create mode 100644 src/main/kotlin/starter/templates/Template.kt create mode 100644 src/main/resources/starter/main/main.twig rename src/main/resources/starter/{ => pom}/@dependencies.twig (100%) rename src/main/resources/starter/{ => pom}/@plugins.twig (56%) rename src/main/resources/starter/{ => pom}/@repositories.twig (100%) rename src/main/resources/starter/{ => pom}/plugins/@default.twig (100%) rename src/main/resources/starter/{ => pom}/plugins/@kotlin.twig (100%) rename src/main/resources/starter/{ => pom}/plugins/@shade.twig (100%) rename src/main/resources/starter/{ => pom}/pom.twig (82%) diff --git a/src/main/kotlin/starter/KotlinStarter.kt b/src/main/kotlin/starter/KotlinStarter.kt index 9b3c774..44f9494 100644 --- a/src/main/kotlin/starter/KotlinStarter.kt +++ b/src/main/kotlin/starter/KotlinStarter.kt @@ -1,20 +1,28 @@ package starter import org.koin.core.context.startKoin +import org.koin.dsl.bind import org.koin.dsl.module +import starter.templates.MainTemplate +import starter.templates.PomTemplate +import starter.templates.Template -val module = module { +val mainModule = module { single { Config().load() } single { PebbleModule().engine() } single { Server(get(), get(), get()) } - single { Templates(get()) } single { Views(get()) } - single { ProjectZip(get()) } + single { ProjectZip(getAll()) } +} + +val templateModule = module { + single { PomTemplate(get()) } bind Template::class + single { MainTemplate(get()) } bind Template::class } fun main() { val koin = startKoin { - modules(module) + modules(mainModule, templateModule) }.koin val server = koin.get() server.run() diff --git a/src/main/kotlin/starter/Models.kt b/src/main/kotlin/starter/Models.kt index 3ac1711..672c6a7 100644 --- a/src/main/kotlin/starter/Models.kt +++ b/src/main/kotlin/starter/Models.kt @@ -20,4 +20,9 @@ data class Dependency( data class Input(val name: String, val display: String, val value: String? = null) -data class Project(val name: String, val basePackage: String) \ No newline at end of file +data class Project( + val name: String, + val basePackage: String, + val inputs: List, + val dependencies: List, +) diff --git a/src/main/kotlin/starter/ProjectZip.kt b/src/main/kotlin/starter/ProjectZip.kt index 4e23396..9a2db33 100644 --- a/src/main/kotlin/starter/ProjectZip.kt +++ b/src/main/kotlin/starter/ProjectZip.kt @@ -1,23 +1,23 @@ package starter +import starter.templates.Template import starter.utils.ZipOutput -import starter.utils.prettyPrintXml import starter.utils.sanitizeFilename -class ProjectZip(private val templates: Templates) { - - fun createZip(project: Project, inputs: List, dependencies: List): String { - val pom = templates.pom(dependencies, inputs) - val prettyPom = prettyPrintXml(pom) +class ProjectZip(private val templates: List