From 0dd36fa6b934ecf76ce28416f17029d073ce90ae Mon Sep 17 00:00:00 2001 From: Andy Damevin Date: Wed, 17 Jun 2020 15:12:39 +0200 Subject: [PATCH] Codestarts phase 1 draft This code gives same level of functionalitty (even a bit more) as the current codegen using Codestarts and Qute - Goal is to improve and validate the codestarts structure - There is no proper testing yet since I prefer to write them once we have discussed the structure - codestarts are located in devtools/platform-descriptor-json/src/main/resources/codestarts - It's possible to generate a set of Quarkus app (using the new codestarts) from `CodestartProjectTest` maven/gradle/kotlin/scala/java with or without example - It's also possible to try it with the mvn quarkus plugin: ``` mvn io.quarkus:quarkus-maven-plugin:999-SNAPSHOT:create \ -DprojectGroupId=org.acme \ -DprojectArtifactId=my-first-codestart \ -Dextensions="resteasy, resteasy-jsonb" \ -DplatformArtifactId="quarkus-bom" -DplatformVersion="999-SNAPSHOT" \ -DcodestartsEnabled -DwithExampleCode ``` - I will give a quick documentation to explain the codestart structure, but nothing to nice before we validate those concepts --- .../io/quarkus/maven/CreateProjectMojo.java | 10 +- .../impl/QuarkusJsonPlatformDescriptor.java | 10 ++ .../gradle/base/build-layout.include.qute | 37 +++++ .../gradle/base/gradle.qute.properties | 6 + .../gradle/base/settings.qute.gradle | 11 ++ .../base/buildtool/gradle/codestart.yml | 26 +++ .../buildtool/gradle/java/build.qute.gradle | 17 ++ .../buildtool/gradle/kotlin/build.qute.gradle | 32 ++++ .../buildtool/gradle/scala/build.qute.gradle | 15 ++ .../base/buildtool/maven/base/pom.qute.xml | 132 +++++++++++++++ .../base/buildtool/maven/codestart.yml | 27 +++ .../buildtool/maven/kotlin/pom.part.qute.xml | 67 ++++++++ .../buildtool/maven/scala/pom.part.qute.xml | 62 +++++++ .../base/README.part.qute.md | 3 + .../commandmode-example/codestart.yml | 9 + .../acme/commandmode/GreetingMain.qute.java | 27 +++ .../commandmode/GreetingService.qute.java | 12 ++ .../codestart/docker/base/.dockerignore.qute | 4 + .../src/main/docker/Dockerfile.qute.fast-jar | 56 +++++++ .../base/src/main/docker/Dockerfile.qute.jvm | 54 ++++++ .../src/main/docker/Dockerfile.qute.native | 24 +++ .../base/codestart/docker/codestart.yml | 3 + .../config/config-properties/codestart.yml | 4 + .../base/config/config-yaml/codestart.yml | 3 + .../base/language/java/codestart.yml | 4 + .../base/language/kotlin/codestart.yml | 3 + .../base/language/scala/codestart.yml | 3 + .../base/project/quarkus/base/.gitignore.qute | 31 ++++ .../base/project/quarkus/base/README.qute.md | 43 +++++ .../resources/application.qute.properties | 0 .../base/project/quarkus/codestart.yml | 9 + .../resteasy-example/base/README.part.qute.md | 5 + .../extensions/resteasy-example/codestart.yml | 11 ++ .../acme/resteasy/ExampleResource.qute.java | 16 ++ .../resources/META-INF/resources/index.html | 155 ++++++++++++++++++ .../resteasy/ExampleResourceTest.qute.java | 21 +++ .../resteasy/NativeExampleResourceIT.java | 9 + .../org/acme/resteasy/ExampleResource.qute.kt | 14 ++ .../resources/META-INF/resources/index.html | 155 ++++++++++++++++++ .../acme/resteasy/ExampleResourceTest.qute.kt | 20 +++ .../acme/resteasy/NativeExampleResourceIT.kt | 6 + .../resources/META-INF/resources/index.html | 155 ++++++++++++++++++ .../acme/resteasy/ExampleResource.qute.scala | 12 ++ .../resteasy/ExampleResourceTest.qute.scala | 20 +++ .../resteasy/NativeExampleResourceIT.scala | 6 + .../resources/META-INF/quarkus-extension.yaml | 1 + .../resources/META-INF/quarkus-extension.yaml | 1 + .../resources/META-INF/quarkus-extension.yaml | 1 + .../resources/META-INF/quarkus-extension.yaml | 1 + .../tools/devtools-common/pom.xml | 16 ++ .../devtools/commands/CreateProject.java | 10 ++ .../handlers/CreateProjectCommandHandler.java | 29 +++- .../buildfile/AbstractGradleBuildFile.java | 4 +- .../buildtool/GradleGenerator.java} | 8 +- .../project/codegen/codestarts/Codestart.java | 42 +++++ .../codegen/codestarts/CodestartData.java | 63 +++++++ .../codegen/codestarts/CodestartInput.java | 37 +++++ .../codegen/codestarts/CodestartLoader.java | 56 +++++++ .../codestarts/CodestartProcessor.java | 148 +++++++++++++++++ .../codegen/codestarts/CodestartProject.java | 94 +++++++++++ .../codegen/codestarts/CodestartQute.java | 125 ++++++++++++++ .../codegen/codestarts/CodestartSpec.java | 143 ++++++++++++++++ .../codegen/codestarts/Codestarts.java | 73 +++++++++ .../loader/json/ClassPathResourceLoader.java | 10 ++ .../loader/json/DirectoryResourceLoader.java | 21 ++- .../loader/json/ResourceLoader.java | 14 +- .../loader/json/ResourceLoaders.java | 37 +++++ .../loader/json/ZipResourceLoader.java | 14 +- .../io/quarkus/devtools/ProjectTestUtil.java | 29 ++++ ...CombinedQuarkusPlatformDescriptorTest.java | 7 +- .../descriptor}/PlatformAwareTestBase.java | 2 +- ...stDominatingQuarkusPlatformDescriptor.java | 14 +- .../QuarkusTestPlatformDescriptorLoader.java | 46 +++++- .../src/test/resources/dir/some-file.template | 3 + .../io/quarkus/dependencies/Extension.java | 11 ++ .../CombinedQuarkusPlatformDescriptor.java | 12 ++ .../descriptor/QuarkusPlatformDescriptor.java | 2 + .../descriptor/ResourcePathConsumer.java | 9 + ...QuarkusJsonPlatformDescriptorResolver.java | 7 +- .../TestJsonPlatformDescriptorLoader.java | 6 + independent-projects/tools/pom.xml | 22 +++ integration-tests/devtools/pom.xml | 65 ++++++++ .../devtools/PlatformAwareTestBase.java | 62 +++++++ .../io/quarkus/devtools/ProjectTestUtil.java | 30 ++++ .../commands/AbstractAddExtensionsTest.java | 23 ++- .../AbstractRemoveExtensionsTest.java | 17 +- .../commands/AddGradleExtensionsTest.java | 17 +- .../commands/AddMavenExtensionsTest.java | 15 +- .../devtools/commands/CreateProjectTest.java | 37 ++--- .../devtools/commands/ListExtensionsTest.java | 31 ++-- .../commands/RemoveGradleExtensionsTest.java | 15 +- .../commands/RemoveMavenExtensionsTest.java | 13 +- .../handlers/QuarkusCommandHandlersTest.java | 6 +- .../codestarts/CodestartProjectTest.java | 124 ++++++++++++++ .../codegen/codestarts/CodestartsTest.java | 101 ++++++++++++ .../rest/BasicRestProjectGeneratorTest.java | 16 +- .../compress/QuarkusProjectCompressTest.java | 16 +- integration-tests/pom.xml | 1 + 98 files changed, 2914 insertions(+), 142 deletions(-) create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/build-layout.include.qute create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/gradle.qute.properties create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/settings.qute.gradle create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/java/build.qute.gradle create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/kotlin/build.qute.gradle create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/scala/build.qute.gradle create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/base/pom.qute.xml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/kotlin/pom.part.qute.xml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/scala/pom.part.qute.xml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/base/README.part.qute.md create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingMain.qute.java create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingService.qute.java create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/.dockerignore.qute create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.fast-jar create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.jvm create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.native create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-properties/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-yaml/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/java/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/kotlin/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/scala/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/.gitignore.qute create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/README.qute.md create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/src/main/resources/application.qute.properties create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/base/README.part.qute.md create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/codestart.yml create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/java/org/acme/resteasy/ExampleResource.qute.java create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/resources/META-INF/resources/index.html create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/ExampleResourceTest.qute.java create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/NativeExampleResourceIT.java create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/kotlin/org/acme/resteasy/ExampleResource.qute.kt create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/resources/META-INF/resources/index.html create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/ExampleResourceTest.qute.kt create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/NativeExampleResourceIT.kt create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/resources/META-INF/resources/index.html create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/scala/org/acme/resteasy/ExampleResource.qute.scala create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/ExampleResourceTest.qute.scala create mode 100644 devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/NativeExampleResourceIT.scala rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/{buildfile/GradleBuildFilesCreator.java => codegen/buildtool/GradleGenerator.java} (97%) create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestart.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartData.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartInput.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartLoader.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProcessor.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProject.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartQute.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartSpec.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestarts.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java create mode 100644 independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/ProjectTestUtil.java rename independent-projects/tools/devtools-common/src/test/java/io/quarkus/{devtools/commands => test/platform/descriptor}/PlatformAwareTestBase.java (97%) create mode 100644 independent-projects/tools/devtools-common/src/test/resources/dir/some-file.template create mode 100644 independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/ResourcePathConsumer.java create mode 100644 integration-tests/devtools/pom.xml create mode 100644 integration-tests/devtools/src/test/java/io/quarkus/devtools/PlatformAwareTestBase.java create mode 100644 integration-tests/devtools/src/test/java/io/quarkus/devtools/ProjectTestUtil.java rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java (91%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java (92%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java (97%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java (95%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java (89%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java (95%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java (96%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java (95%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java (99%) create mode 100644 integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProjectTest.java create mode 100644 integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartsTest.java rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java (99%) rename {independent-projects/tools/devtools-common => integration-tests/devtools}/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java (95%) diff --git a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java index c8f45861476c03..39b40c78436bd0 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java @@ -74,6 +74,12 @@ public class CreateProjectMojo extends AbstractMojo { @Parameter(property = "projectVersion") private String projectVersion; + @Parameter(property = "codestartsEnabled") + private Boolean codestartsEnabled; + + @Parameter(property = "withExampleCode") + private Boolean withExampleCode; + /** * Group ID of the target platform BOM */ @@ -190,7 +196,9 @@ public void execute() throws MojoExecutionException { .version(projectVersion) .sourceType(sourceType) .className(className) - .extensions(extensions); + .extensions(extensions) + .codestartsEnabled(codestartsEnabled) + .withExampleCode(withExampleCode); if (path != null) { createProject.setValue("path", path); } diff --git a/devtools/platform-descriptor-json/src/main/java/io/quarkus/platform/descriptor/loader/json/impl/QuarkusJsonPlatformDescriptor.java b/devtools/platform-descriptor-json/src/main/java/io/quarkus/platform/descriptor/loader/json/impl/QuarkusJsonPlatformDescriptor.java index d346fd6fd07593..2fd03b68f11fcf 100644 --- a/devtools/platform-descriptor-json/src/main/java/io/quarkus/platform/descriptor/loader/json/impl/QuarkusJsonPlatformDescriptor.java +++ b/devtools/platform-descriptor-json/src/main/java/io/quarkus/platform/descriptor/loader/json/impl/QuarkusJsonPlatformDescriptor.java @@ -16,6 +16,7 @@ import io.quarkus.dependencies.Extension; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import io.quarkus.platform.descriptor.loader.json.ResourceLoader; import io.quarkus.platform.tools.DefaultMessageWriter; import io.quarkus.platform.tools.MessageWriter; @@ -126,6 +127,15 @@ public T loadResource(String name, ResourceInputStreamConsumer consumer) return resourceLoader.loadResource(name, consumer); } + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + getLog().debug("Loading Quarkus platform resource %s", name); + if (resourceLoader == null) { + throw new IllegalStateException("Resource loader has not been provided"); + } + return resourceLoader.loadResourcePath(name, consumer); + } + @Override public List getCategories() { return categories; diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/build-layout.include.qute b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/build-layout.include.qute new file mode 100644 index 00000000000000..dad4e95e49d598 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/build-layout.include.qute @@ -0,0 +1,37 @@ +{#insert plugins} +plugins { + id '{quarkus.plugin.id}' +} +{/} + +{#insert repositories} +repositories { + mavenLocal() + mavenCentral() +} +{/} + +{#insert dependencies} +dependencies { + implementation enforcedPlatform("$\{quarkusPlatformGroupId}:$\{quarkusPlatformArtifactId}:$\{quarkusPlatformVersion}") +{#for dep in dependencies} + implementation '{dep}' +{/for} + testImplementation 'io.quarkus:quarkus-junit5' +{#for dep in testDependencies} + testImplementation '{dep}' +{/for} +} +{/} + +{#insert project} +group '{project.group-id}' +version '{project.version}' +{/} + +{#insert java} +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} +{/} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/gradle.qute.properties b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/gradle.qute.properties new file mode 100644 index 00000000000000..72c7052dddd091 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/gradle.qute.properties @@ -0,0 +1,6 @@ +#Gradle properties +#Tue Jun 16 08:41:21 UTC 2020 +quarkusPluginVersion={quarkus.plugin.version} +quarkusPlatformGroupId={quarkus.platform.group-id} +quarkusPlatformArtifactId={quarkus.platform.artifact-id} +quarkusPlatformVersion={quarkus.platform.version} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/settings.qute.gradle b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/settings.qute.gradle new file mode 100644 index 00000000000000..adce2841385462 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/base/settings.qute.gradle @@ -0,0 +1,11 @@ +pluginManagement { + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + plugins { + id '{quarkus.plugin.id}' version "$\{quarkusPluginVersion}" + } +} +rootProject.name='{project.artifact-id}' diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/codestart.yml new file mode 100644 index 00000000000000..644f303fbf50e5 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/codestart.yml @@ -0,0 +1,26 @@ +name: gradle +type: buildtool +spec: + base: + local-data: + quarkus.plugin.id: io.quarkus + version.kotlin: 1.3.72 + version.scala: 2.12.8 + shared-data: + buildtool.build-dir: build + buildtool.cmd.dev: ./gradlew quarkusDev + buildtool.cmd.package: ./gradlew quarkusBuild + buildtool.cmd.package-uberjar: ./gradlew quarkusBuild --uber-jar + buildtool.cmd.package-native: ./gradlew build -Dquarkus.package.type=native + buildtool.cmd.package-native-container: ./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true + buildtool.guide: https://quarkus.io/guides/gradle-tooling#building-a-native-executable + gitignore: > + # Gradle + .gradle/ + build/ + kotlin: + dependencies: + - org.jetbrains.kotlin:kotlin-stdlib-jdk8 + scala: + dependencies: + - org.scala-lang:scala-library:${version.scala} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/java/build.qute.gradle b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/java/build.qute.gradle new file mode 100644 index 00000000000000..185ccdd49c664c --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/java/build.qute.gradle @@ -0,0 +1,17 @@ +{#include build-layout} +{#plugins} +plugins { + id 'java' + id '{quarkus.plugin.id}' +} +{/plugins} +{/include} + +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} + +compileTestJava { + options.encoding = 'UTF-8' +} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/kotlin/build.qute.gradle b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/kotlin/build.qute.gradle new file mode 100644 index 00000000000000..b38ff1c2ceabfd --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/kotlin/build.qute.gradle @@ -0,0 +1,32 @@ +{#include build-layout} +{#plugins} +plugins { + id 'org.jetbrains.kotlin.jvm' version "{version.kotlin}" + id "org.jetbrains.kotlin.plugin.allopen" version "{version.kotlin}" + id '{quarkus.plugin.id}' +} +{/plugins} +{/include} + +quarkus { + setOutputDirectory("$projectDir/build/classes/kotlin/main") +} + +quarkusDev { + setSourceDir("$projectDir/src/main/kotlin") +} + +allOpen { + annotation("javax.ws.rs.Path") + annotation("javax.enterprise.context.ApplicationScoped") + annotation("io.quarkus.test.junit.QuarkusTest") +} + +compileKotlin { + kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8 + kotlinOptions.javaParameters = true +} + +compileTestKotlin { + kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8 +} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/scala/build.qute.gradle b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/scala/build.qute.gradle new file mode 100644 index 00000000000000..5ad817212fd10f --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/gradle/scala/build.qute.gradle @@ -0,0 +1,15 @@ +{#include build-layout} +{#plugins} +plugins { + id 'scala' + id '{quarkus.plugin.id}' +} +{/plugins} +{/include} + +compileScala { + scalaCompileOptions.encoding = 'UTF-8' + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/base/pom.qute.xml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/base/pom.qute.xml new file mode 100644 index 00000000000000..e07313b82e9975 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/base/pom.qute.xml @@ -0,0 +1,132 @@ + + 4.0.0 + {project.group-id} + {project.artifact-id} + {project.version} + + + UTF-8 + UTF-8 + 1.8 + 1.8 + true + + {quarkus.platform.group-id} + {quarkus.platform.artifact-id} + {quarkus.platform.version} + {quarkus.plugin.version} + {version.maven-compiler-plugin} + {version.maven-surefire-plugin} + + + + + + $\{quarkus.platform.group-id} + $\{quarkus.platform.artifact-id} + $\{quarkus.platform.version} + pom + import + + + + + + {#each dependencies} + + {it.groupId} + {it.artifactId} + + {/each} + + + + io.quarkus + quarkus-junit5 + test + + {#each testDependencies} + + {it.groupId} + {it.artifactId} + test + + {/each} + + + + + + + {quarkus.plugin.group-id} + {quarkus.plugin.artifact-id} + $\{quarkus-plugin.version} + + + + build + + + + + + maven-compiler-plugin + $\{compiler-plugin.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + $\{surefire-plugin.version} + + + org.jboss.logmanager.LogManager + $\{maven.home} + + + + + + + + + + native + + + native + + + + native + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + $\{surefire-plugin.version} + + + + integration-test + verify + + + + $\{project.build.directory}/$\{project.build.finalName}-runner + org.jboss.logmanager.LogManager + $\{maven.home} + + + + + + + + + + + diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/codestart.yml new file mode 100644 index 00000000000000..dd5c58740a2318 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/codestart.yml @@ -0,0 +1,27 @@ +--- +name: maven +type: buildtool +default: true +spec: + base: + local-data: + version.kotlin: 1.3.72 + version.scala: 2.12.8 + version.scala-maven-plugin: 4.1.1 + version.maven-compiler-plugin: 3.8.1 + version.maven-surefire-plugin: 2.22.1 + shared-data: + buildtool.build-dir: target + buildtool.cmd.dev: ./mvnw compile quarkus:dev + buildtool.cmd.package: ./mvnw package + buildtool.cmd.package-uberjar: ./mvnw package -PuberJar + buildtool.cmd.package-native: ./mvnw package -Pnative + buildtool.cmd.package-native-container: ./mvnw package -Pnative -Dquarkus.native.container-build=true + buildtool.guide: https://quarkus.io/guides/building-native-image + gitignore: | + #Maven + target/ + pom.xml.tag + pom.xml.releaseBackup + pom.xml.versionsBackup + release.properties diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/kotlin/pom.part.qute.xml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/kotlin/pom.part.qute.xml new file mode 100644 index 00000000000000..20e194a7cce606 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/kotlin/pom.part.qute.xml @@ -0,0 +1,67 @@ + + + {version.kotlin} + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + + io.rest-assured + kotlin-extensions + test + + + + src/main/kotlin + src/test/kotlin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + $\{kotlin.version} + + + compile + + compile + + + + test-compile + + test-compile + + + + + true + 1.8 + + + all-open + + + + + + + + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + $\{kotlin.version} + + + + + + \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/scala/pom.part.qute.xml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/scala/pom.part.qute.xml new file mode 100644 index 00000000000000..93c4f605aa2dcf --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/buildtool/maven/scala/pom.part.qute.xml @@ -0,0 +1,62 @@ + + + {version.scala-maven-plugin} + {version.scala} + + + + io.quarkus + quarkus-scala + + + org.scala-lang + scala-library + $\{scala.version} + + + org.scala-lang + scala-reflect + $\{scala.version} + + + + src/main/scala + src/test/scala + + + net.alchim31.maven + scala-maven-plugin + $\{scala-maven-plugin.version} + + + scala-compile-first + process-resources + + add-source + compile + + + + scala-test-compile + process-test-resources + + add-source + testCompile + + + + + $\{scala.version} + + -deprecation + -feature + -explaintypes + -target:jvm-1.8 + -Ypartial-unification + + + + + + \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/base/README.part.qute.md b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/base/README.part.qute.md new file mode 100644 index 00000000000000..85b52a94b6f5b4 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/base/README.part.qute.md @@ -0,0 +1,3 @@ +# Command Mode + +Guide: https://quarkus.io/guides/command-mode-reference diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/codestart.yml new file mode 100644 index 00000000000000..738af0f1d3daa4 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/codestart.yml @@ -0,0 +1,9 @@ +--- +name: commandmode-example +ref: commandmode +example: true +spec: + base: + local-data: + greeting.message: "hello" + greeting.default-name: "commando" diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingMain.qute.java b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingMain.qute.java new file mode 100644 index 00000000000000..f1f4b7f4ce7d2c --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingMain.qute.java @@ -0,0 +1,27 @@ +package org.acme.commandmode; + +import javax.enterprise.context.control.ActivateRequestContext; +import javax.inject.Inject; + +import io.quarkus.runtime.Quarkus; +import io.quarkus.runtime.QuarkusApplication; +import io.quarkus.runtime.annotations.QuarkusMain; + +@QuarkusMain +public class GreetingMain implements QuarkusApplication { + + @Inject + GreetingService service; + + @Override + public int run(String... args) throws Exception { + + if(args.length>0) { + System.out.println(service.greeting(String.join(" ", args))); + } else { + System.out.println(service.greeting("{greeting.default-name}")); + } + + return 0; + } +} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingService.qute.java b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingService.qute.java new file mode 100644 index 00000000000000..08aee0c573065d --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/commandmode-example/java/src/main/java/org/acme/commandmode/GreetingService.qute.java @@ -0,0 +1,12 @@ +package org.acme.commandmode; + +import javax.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class GreetingService { + + public String greeting(String name) { + return "{greeting.message} " + name; + } + +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/.dockerignore.qute b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/.dockerignore.qute new file mode 100644 index 00000000000000..0060b04681bd04 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/.dockerignore.qute @@ -0,0 +1,4 @@ +* +!{buildtool.build-dir}/*-runner +!{buildtool.build-dir}/*-runner.jar +!{buildtool.build-dir}/lib/* \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.fast-jar b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.fast-jar new file mode 100644 index 00000000000000..fcfd215f023ccb --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.fast-jar @@ -0,0 +1,56 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the docker image run: +# +# mvn package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/{project.artifact-id}-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/{project.artifact-id}-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/{project.artifact-id}-jvm +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' + +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates $\{JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/$\{RUN_JAVA_VERSION}/run-java-sh-$\{RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" + +COPY {buildtool.build-dir}/quarkus-app/lib/* /deployments/lib/ +COPY {buildtool.build-dir}/quarkus-app/quarkus-run.jar /deployments/app.jar +COPY {buildtool.build-dir}/quarkus-app/app/* /deployments/app/ +COPY {buildtool.build-dir}/quarkus-app/quarkus/* /deployments/quarkus/ + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.jvm b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.jvm new file mode 100644 index 00000000000000..1ad005cd38df34 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.jvm @@ -0,0 +1,54 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the docker image run: +# +# mvn package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/{project.artifact-id}-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/{project.artifact-id}-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/{project.artifact-id}-jvm +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' + +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates $\{JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/$\{RUN_JAVA_VERSION}/run-java-sh-$\{RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" + +COPY {buildtool.build-dir}/lib/* /deployments/lib/ +COPY {buildtool.build-dir}/*-runner.jar /deployments/app.jar + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.native b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.native new file mode 100644 index 00000000000000..460d97b0ee86e6 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/base/src/main/docker/Dockerfile.qute.native @@ -0,0 +1,24 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +# +# Before building the docker image run: +# +# mvn package -Pnative -Dquarkus.native.container-build=true +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native -t quarkus/{project.artifact-id} . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/{project.artifact-id} +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 +WORKDIR /work/ +COPY --chown=1001:root {buildtool.build-dir}/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/codestart.yml new file mode 100644 index 00000000000000..ebd8ecd4cd4404 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/codestart/docker/codestart.yml @@ -0,0 +1,3 @@ +--- +name: docker +default: true diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-properties/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-properties/codestart.yml new file mode 100644 index 00000000000000..8efcec0ff2ffe9 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-properties/codestart.yml @@ -0,0 +1,4 @@ +--- +name: config-properties +type: config +default: true \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-yaml/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-yaml/codestart.yml new file mode 100644 index 00000000000000..5d1640f8defeb8 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/config/config-yaml/codestart.yml @@ -0,0 +1,3 @@ +--- +name: config-yaml +type: config diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/java/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/java/codestart.yml new file mode 100644 index 00000000000000..41cb8c8d818253 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/java/codestart.yml @@ -0,0 +1,4 @@ +--- +name: java +type: language +default: true \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/kotlin/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/kotlin/codestart.yml new file mode 100644 index 00000000000000..f0308134c2b872 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/kotlin/codestart.yml @@ -0,0 +1,3 @@ +--- +name: kotlin +type: language \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/scala/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/scala/codestart.yml new file mode 100644 index 00000000000000..80cbfab1babb20 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/language/scala/codestart.yml @@ -0,0 +1,3 @@ +--- +name: scala +type: language \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/.gitignore.qute b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/.gitignore.qute new file mode 100644 index 00000000000000..d4d7809fd7964f --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/.gitignore.qute @@ -0,0 +1,31 @@ +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode +.factorypath + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +{gitignore} diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/README.qute.md b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/README.qute.md new file mode 100644 index 00000000000000..30df131a7ba8aa --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/README.qute.md @@ -0,0 +1,43 @@ +# {project.artifact-id} project + +This project uses Quarkus, the Supersonic Subatomic Java Framework. + +If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . + +## Running the application in dev mode + +You can run your application in dev mode that enables live coding using: +```shell script +{buildtool.cmd.dev} +``` + +## Packaging and running the application + +The application can be packaged using: +```shell script +{buildtool.cmd.package} +``` +It produces the `{project.artifact-id}-{project.version}-runner.jar` file in the `/{buildtool.build-dir}` directory. +Be aware that it’s not an _über-jar_ as the dependencies are copied into the `{buildtool.build-dir}/lib` directory. +If you want to build an _über-jar_, just add the `--uber-jar` option to the command line: +```shell script +{buildtool.cmd.package-uberjar} +``` + +The application is now runnable using `java -jar {buildtool.build-dir}/{project.artifact-id}-{project.version}-runner.jar`. + +## Creating a native executable + +You can create a native executable using: +```shell script +{buildtool.cmd.package-native} +``` + +Or, if you don't have GraalVM installed, you can run the native executable build in a container using: +```shell script +{buildtool.cmd.package-native-container} +``` + +You can then execute your native executable with: `./{buildtool.build-dir}/{project.artifact-id}-{project.version}-runner` + +If you want to learn more about building native executables, please consult {buildtool.guide}. diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/src/main/resources/application.qute.properties b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/base/src/main/resources/application.qute.properties new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/codestart.yml new file mode 100644 index 00000000000000..4e0bf5f1e9e50c --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/base/project/quarkus/codestart.yml @@ -0,0 +1,9 @@ +--- +name: quarkus +type: project +default: true +spec: + base: + shared-data: + project.group-id: org.acme + project.artifact-id: quarkus-project diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/base/README.part.qute.md b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/base/README.part.qute.md new file mode 100644 index 00000000000000..ece65436dc3760 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/base/README.part.qute.md @@ -0,0 +1,5 @@ +# RESTEasy JAX-RS + +Guide: https://quarkus.io/guides/rest-json + + diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/codestart.yml new file mode 100644 index 00000000000000..fbdd91d5882d13 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/codestart.yml @@ -0,0 +1,11 @@ +--- +name: resteasy-example +ref: resteasy +example: true +spec: + base: + local-data: + rest.path: "/hello" + rest.response: "hello" + test-dependencies: + - io.rest-assured:rest-assured diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/java/org/acme/resteasy/ExampleResource.qute.java b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/java/org/acme/resteasy/ExampleResource.qute.java new file mode 100644 index 00000000000000..a605f5be229766 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/java/org/acme/resteasy/ExampleResource.qute.java @@ -0,0 +1,16 @@ +package org.acme.resteasy; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("{rest.path}") +public class ExampleResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "{rest.response}"; + } +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/resources/META-INF/resources/index.html b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/resources/META-INF/resources/index.html new file mode 100644 index 00000000000000..41964305c9c37b --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,155 @@ + + + + + code-with-quarkus - 1.0.0-SNAPSHOT + + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

Do you like Quarkus?

+

Go give it a star on GitHub.

+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: code-with-quarkus
  • +
  • Version: 1.0.0-SNAPSHOT
  • +
  • Quarkus Version: 1.5.1.Final
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/ExampleResourceTest.qute.java b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/ExampleResourceTest.qute.java new file mode 100644 index 00000000000000..2062b430ed275a --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/ExampleResourceTest.qute.java @@ -0,0 +1,21 @@ +package org.acme.resteasy; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +@QuarkusTest +public class ExampleResourceTest { + + @Test + public void testHelloEndpoint() { + given() + .when().get("{rest.path}") + .then() + .statusCode(200) + .body(is("{rest.response}")); + } + +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/NativeExampleResourceIT.java b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/NativeExampleResourceIT.java new file mode 100644 index 00000000000000..0a94d8d9ce4e66 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/java/src/test/java/org/acme/resteasy/NativeExampleResourceIT.java @@ -0,0 +1,9 @@ +package org.acme.resteasy; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class NativeExampleResourceIT extends ExampleResourceTest { + + // Execute the same tests but in native mode. +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/kotlin/org/acme/resteasy/ExampleResource.qute.kt b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/kotlin/org/acme/resteasy/ExampleResource.qute.kt new file mode 100644 index 00000000000000..8b60e4e0cf9cb4 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/kotlin/org/acme/resteasy/ExampleResource.qute.kt @@ -0,0 +1,14 @@ +package org.acme.resteasy + +import javax.ws.rs.GET +import javax.ws.rs.Path +import javax.ws.rs.Produces +import javax.ws.rs.core.MediaType + +@Path("{rest.path}") +class ExampleResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + fun hello() = "{rest.response}" +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/resources/META-INF/resources/index.html b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/resources/META-INF/resources/index.html new file mode 100644 index 00000000000000..18d3cd59faca97 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,155 @@ + + + + + kotlin - 1.0.0-SNAPSHOT + + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

Do you like Quarkus?

+

Go give it a star on GitHub.

+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: kotlin
  • +
  • Version: 1.0.0-SNAPSHOT
  • +
  • Quarkus Version: 1.5.1.Final
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/ExampleResourceTest.qute.kt b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/ExampleResourceTest.qute.kt new file mode 100644 index 00000000000000..c097be9645c3b2 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/ExampleResourceTest.qute.kt @@ -0,0 +1,20 @@ +package org.acme.resteasy + +import io.quarkus.test.junit.QuarkusTest +import io.restassured.RestAssured.given +import org.hamcrest.CoreMatchers.`is` +import org.junit.jupiter.api.Test + +@QuarkusTest +class ExampleResourceTest { + + @Test + fun testHelloEndpoint() { + given() + .`when`().get("{rest.path}") + .then() + .statusCode(200) + .body(`is`("{rest.response}")) + } + +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/NativeExampleResourceIT.kt b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/NativeExampleResourceIT.kt new file mode 100644 index 00000000000000..edf12f47ef27e9 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/kotlin/src/test/kotlin/org/acme/resteasy/NativeExampleResourceIT.kt @@ -0,0 +1,6 @@ +package org.acme.resteasy + +import io.quarkus.test.junit.NativeImageTest + +@NativeImageTest +class NativeExampleResourceIT : ExampleResourceTest() \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/resources/META-INF/resources/index.html b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/resources/META-INF/resources/index.html new file mode 100644 index 00000000000000..9e740c3acd1923 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,155 @@ + + + + + scala - 1.0.0-SNAPSHOT + + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

Do you like Quarkus?

+

Go give it a star on GitHub.

+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: scala
  • +
  • Version: 1.0.0-SNAPSHOT
  • +
  • Quarkus Version: 1.5.1.Final
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/scala/org/acme/resteasy/ExampleResource.qute.scala b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/scala/org/acme/resteasy/ExampleResource.qute.scala new file mode 100644 index 00000000000000..d1164266ad7d73 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/main/scala/org/acme/resteasy/ExampleResource.qute.scala @@ -0,0 +1,12 @@ +package org.acme.resteasy + +import javax.ws.rs.\{GET, Path, Produces} +import javax.ws.rs.core.MediaType + +@Path("{rest.path}") +class ExampleResource { + + @GET + @Produces(Array[String](MediaType.TEXT_PLAIN)) + def hello() = "{rest.response}" +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/ExampleResourceTest.qute.scala b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/ExampleResourceTest.qute.scala new file mode 100644 index 00000000000000..fb8524d9d849bb --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/ExampleResourceTest.qute.scala @@ -0,0 +1,20 @@ +package org.acme.resteasy + +import io.quarkus.test.junit.QuarkusTest +import io.restassured.RestAssured.given +import org.hamcrest.CoreMatchers.`is` +import org.junit.jupiter.api.Test + +@QuarkusTest +class ExampleResourceTest { + + @Test + def testHelloEndpoint() = { + given() + .`when`().get("{rest.path}") + .then() + .statusCode(200) + .body(`is`("{rest.response}")) + } + +} \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/NativeExampleResourceIT.scala b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/NativeExampleResourceIT.scala new file mode 100644 index 00000000000000..5227f9fe33c382 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/codestarts/extensions/resteasy-example/scala/src/test/scala/org/acme/resteasy/NativeExampleResourceIT.scala @@ -0,0 +1,6 @@ +package org.acme.resteasy + +import io.quarkus.test.junit.NativeImageTest + +@NativeImageTest +class NativeExampleResourceIT extends ExampleResourceTest \ No newline at end of file diff --git a/extensions/config-yaml/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/config-yaml/runtime/src/main/resources/META-INF/quarkus-extension.yaml index be50cd6e202844..d6fc7cb746bbb2 100644 --- a/extensions/config-yaml/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/config-yaml/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -9,3 +9,4 @@ metadata: - "core" status: "stable" guide: "https://quarkus.io/guides/config#yaml" + codestart: "config-yaml" diff --git a/extensions/kotlin/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/kotlin/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 0d3399729f86f0..12321b3a0d317c 100644 --- a/extensions/kotlin/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/kotlin/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -7,3 +7,4 @@ metadata: categories: - "alt-languages" status: "preview" + codestart: "kotlin" diff --git a/extensions/resteasy/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/resteasy/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 63e9dffb8c5a24..b2bd1ccb0bc06a 100644 --- a/extensions/resteasy/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/resteasy/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -11,3 +11,4 @@ metadata: categories: - "web" status: "stable" + codestart: "resteasy" diff --git a/extensions/scala/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/scala/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 24e2190eb812da..bf87dffc9b5752 100644 --- a/extensions/scala/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/scala/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -6,3 +6,4 @@ metadata: categories: - "alt-languages" status: "preview" + codestart: "scala" diff --git a/independent-projects/tools/devtools-common/pom.xml b/independent-projects/tools/devtools-common/pom.xml index 1c173d9c289198..bdee984ba3c8cd 100644 --- a/independent-projects/tools/devtools-common/pom.xml +++ b/independent-projects/tools/devtools-common/pom.xml @@ -34,6 +34,10 @@ io.quarkus quarkus-devtools-utilities + + io.quarkus.qute + qute-generator + io.quarkus quarkus-platform-descriptor-api @@ -42,6 +46,18 @@ org.apache.commons commons-compress + + io.fabric8 + maven-model-helper + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + org.apache.maven maven-plugin-api diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java index cd4e67689f1ede..a36a98c8d8a432 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java @@ -101,6 +101,16 @@ public CreateProject extensions(Set extensions) { return this; } + public CreateProject codestartsEnabled(boolean codestartsEnabled) { + setValue("codestarts.enabled", codestartsEnabled); + return this; + } + + public CreateProject withExampleCode(boolean withExampleCode) { + setValue("codestarts.with-example-code", withExampleCode); + return this; + } + public CreateProject setValue(String name, Object value) { values.put(name, value); return this; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/CreateProjectCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/CreateProjectCommandHandler.java index 1ac7a7376c7090..4db95f576f85a7 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/CreateProjectCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/CreateProjectCommandHandler.java @@ -4,14 +4,19 @@ import static io.quarkus.devtools.project.codegen.ProjectGenerator.*; import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.bootstrap.model.AppArtifactKey; import io.quarkus.devtools.commands.data.QuarkusCommandException; import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.buildfile.GradleBuildFilesCreator; import io.quarkus.devtools.project.codegen.ProjectGenerator; import io.quarkus.devtools.project.codegen.ProjectGeneratorRegistry; import io.quarkus.devtools.project.codegen.SourceType; +import io.quarkus.devtools.project.codegen.buildtool.GradleGenerator; +import io.quarkus.devtools.project.codegen.codestarts.CodestartData; +import io.quarkus.devtools.project.codegen.codestarts.CodestartInput; +import io.quarkus.devtools.project.codegen.codestarts.CodestartProject; +import io.quarkus.devtools.project.codegen.codestarts.Codestarts; import io.quarkus.devtools.project.codegen.rest.BasicRestProjectGenerator; import io.quarkus.devtools.project.extensions.ExtensionManager; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; @@ -22,6 +27,7 @@ import java.util.List; import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; /** * Instances of this class are thread-safe. They create a new project extracting all the necessary properties from an instance @@ -46,6 +52,23 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws } }); + if (invocation.getBooleanValue("codestarts.enabled")) { + final List extensionsToAdd = computeCoordsFromQuery(invocation, extensionsQuery).stream() + .map(AppArtifactCoords::getKey) + .collect(Collectors.toList()); + + try { + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(invocation.getPlatformDescriptor(), extensionsToAdd, + invocation.getBooleanValue("codestarts.with-example-code"), + CodestartData.DefaultKeys.convertFromLegacy(invocation.getValues()))); + Codestarts.generateProject(codestartProject, invocation.getQuarkusProject().getProjectDirPath()); + } catch (IOException e) { + throw new QuarkusCommandException("Failed to create project", e); + } + return QuarkusCommandOutcome.success(); + } + try { String className = invocation.getStringValue(CLASS_NAME); if (className != null) { @@ -69,8 +92,8 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws //TODO ia3andy extensions should be added directly during the project generation if (invocation.getQuarkusProject().getBuildTool().equals(BuildTool.GRADLE)) { - final GradleBuildFilesCreator creator = new GradleBuildFilesCreator(invocation.getQuarkusProject()); - creator.create( + final GradleGenerator generator = new GradleGenerator(invocation.getQuarkusProject()); + generator.generate( invocation.getStringValue(PROJECT_GROUP_ID), invocation.getStringValue(PROJECT_ARTIFACT_ID), invocation.getStringValue(PROJECT_VERSION), diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGradleBuildFile.java index bdd8b71b27daf6..dfcc029f7e5117 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGradleBuildFile.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGradleBuildFile.java @@ -63,7 +63,7 @@ protected void addDependencyInBuildFile(AppArtifactCoords coords) throws IOExcep addDependencyInModel(getModel(), coords); } - static void addDependencyInModel(Model model, AppArtifactCoords coords) throws IOException { + public static void addDependencyInModel(Model model, AppArtifactCoords coords) throws IOException { StringBuilder newBuildContent = new StringBuilder(); readLineByLine(model.getBuildContent(), currentLine -> { newBuildContent.append(currentLine).append(System.lineSeparator()); @@ -195,7 +195,7 @@ private static void readLineByLine(String content, Consumer lineConsumer } } - static class Model { + public static class Model { private String settingsContent; private String buildContent; private Properties propertiesContent; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GradleBuildFilesCreator.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/buildtool/GradleGenerator.java similarity index 97% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GradleBuildFilesCreator.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/buildtool/GradleGenerator.java index 22b4e2380282b4..167818321e6341 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GradleBuildFilesCreator.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/buildtool/GradleGenerator.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.buildfile; +package io.quarkus.devtools.project.codegen.buildtool; import static io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile.addDependencyInModel; @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -public final class GradleBuildFilesCreator { +public final class GradleGenerator { private static final String BUILD_GRADLE_PATH = "build.gradle"; private static final String SETTINGS_GRADLE_PATH = "settings.gradle"; @@ -29,11 +29,11 @@ public final class GradleBuildFilesCreator { private AtomicReference modelReference = new AtomicReference<>(); - public GradleBuildFilesCreator(QuarkusProject quarkusProject) { + public GradleGenerator(QuarkusProject quarkusProject) { this.quarkusProject = quarkusProject; } - public void create(String groupId, String artifactId, String version, + public void generate(String groupId, String artifactId, String version, Properties properties, List extensions) throws IOException { createSettingsContent(artifactId); createBuildContent(groupId, version); diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestart.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestart.java new file mode 100644 index 00000000000000..9271b2a5641b0b --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestart.java @@ -0,0 +1,42 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static io.quarkus.devtools.project.codegen.codestarts.CodestartData.mergeMaps; + +import java.util.Map; +import java.util.stream.Stream; + +final class Codestart { + public static final String BASE_LANGUAGE = "base"; + private final String resourceName; + private final CodestartSpec spec; + + public Codestart(final String resourceName, final CodestartSpec spec) { + this.resourceName = resourceName; + this.spec = spec; + } + + public String getResourceName() { + return resourceName; + } + + public CodestartSpec getSpec() { + return spec; + } + + public Map getLocalData(String languageName) { + return mergeMaps(Stream.of(getBaseLanguageSpec().getLocalData(), getLanguageSpec(languageName).getLocalData())); + } + + public Map getSharedData(String languageName) { + return mergeMaps(Stream.of(getBaseLanguageSpec().getSharedData(), getLanguageSpec(languageName).getSharedData())); + } + + public CodestartSpec.LanguageSpec getBaseLanguageSpec() { + return getSpec().getLanguagesSpec().getOrDefault(BASE_LANGUAGE, new CodestartSpec.LanguageSpec()); + } + + public CodestartSpec.LanguageSpec getLanguageSpec(String languageName) { + return getSpec().getLanguagesSpec().getOrDefault(languageName, new CodestartSpec.LanguageSpec()); + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartData.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartData.java new file mode 100644 index 00000000000000..b6092e00f8e615 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartData.java @@ -0,0 +1,63 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class CodestartData { + + private CodestartData() { + } + + public enum DefaultKeys { + BOM_GROUP_ID("quarkus.platform.group-id", "bom_groupId"), + BOM_ARTIFACT_ID("quarkus.platform.artifact-id", "bom_artifactId"), + BOM_VERSION("quarkus.platform.version", "bom_version"), + PROJECT_GROUP_ID("project.group-id", "project_groupId"), + PROJECT_ARTIFACT_ID("project.artifact-id", "project_artifactId"), + PROJECT_VERSION("project.version", "project_version"), + QUARKUS_PLUGIN_GROUP_ID("quarkus.plugin.group-id", "plugin_groupId"), + QUARKUS_PLUGIN_ARTIFACT_ID("quarkus.plugin.artifact-id", "plugin_artifactId"), + QUARKUS_PLUGIN_VERSION("quarkus.plugin.version", "plugin_version"), + QUARKUS_VERSION("quarkus.version", "quarkus_version"), + // MAVEN_REPOSITORIES("maven_repositories"), // TODO add compatibility with repo override + // MAVEN_PLUGIN_REPOSITORIES("maven_plugin_repositories"), // TODO add compatibility + ; + + private final String key; + private final String legacyKey; + + DefaultKeys(String key, String legacyKey) { + this.key = key; + this.legacyKey = legacyKey; + } + + public String getKey() { + return key; + } + + public String getLegacyKey() { + return legacyKey; + } + + public static Map convertFromLegacy(Map legacy) { + return Stream.of(values()) + .filter(v -> legacy.containsKey(v.getLegacyKey())) + .map(v -> new HashMap.SimpleImmutableEntry<>(v.getKey(), legacy.get(v.getLegacyKey()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + } + + static Map mergeData(final Codestart codestart, final String languageName, final Map data) { + return mergeMaps(Stream.of(codestart.getLocalData(languageName), data)); + } + + static Map mergeMaps(final Stream> stream) { + return stream + .map(Map::entrySet) + .flatMap(Set::stream) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2)); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartInput.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartInput.java new file mode 100644 index 00000000000000..44b7944d1c2c41 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartInput.java @@ -0,0 +1,37 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import java.util.Collection; +import java.util.Map; + +public class CodestartInput { + private final QuarkusPlatformDescriptor descriptor; + private final Collection extensions; + private final boolean includeExample; + private final Map data; + + public CodestartInput(QuarkusPlatformDescriptor descriptor, Collection extensions, boolean includeExample, + Map data) { + this.descriptor = descriptor; + this.extensions = extensions; + this.includeExample = includeExample; + this.data = data; + } + + public QuarkusPlatformDescriptor getDescriptor() { + return descriptor; + } + + public Collection getExtensions() { + return extensions; + } + + public boolean includeExample() { + return includeExample; + } + + public Map getData() { + return data; + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartLoader.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartLoader.java new file mode 100644 index 00000000000000..a5d1eda868d71b --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartLoader.java @@ -0,0 +1,56 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static io.quarkus.platform.descriptor.loader.json.ResourceLoaders.toResourceNameWalker; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +final class CodestartLoader { + private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()) + .enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING) + .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); + + private static final String CODESTARTS_DIR_BASE = "codestarts/base"; + private static final String CODESTARTS_DIR_EXTENSIONS = "codestarts/extensions"; + + private CodestartLoader() { + } + + public static List loadAddCodestarts(CodestartInput input) throws IOException { + return Stream.concat(CodestartLoader.loadBaseCodestarts(input.getDescriptor()).stream(), + CodestartLoader.loadExtensionsCodestarts(input.getDescriptor()).stream()).collect(Collectors.toList()); + } + + public static Collection loadBaseCodestarts(final QuarkusPlatformDescriptor descriptor) throws IOException { + return loadCodestarts(descriptor, CODESTARTS_DIR_BASE); + } + + public static Collection loadExtensionsCodestarts(final QuarkusPlatformDescriptor descriptor) + throws IOException { + return loadCodestarts(descriptor, CODESTARTS_DIR_EXTENSIONS); + } + + static Collection loadCodestarts(final QuarkusPlatformDescriptor descriptor, final String directoryName) + throws IOException { + return descriptor.loadResourcePath(directoryName, + path -> toResourceNameWalker(directoryName, path).filter(n -> n.matches(".*/codestart\\.ya?ml$")) + .map(n -> { + try { + final CodestartSpec spec = mapper.readerFor(CodestartSpec.class) + .readValue(descriptor.getTemplate(n)); + return new Codestart(n.replaceAll("/?codestart\\.ya?ml", ""), spec); + } catch (IOException e) { + throw new UncheckedIOException("Failed to parse codestart spec: " + n, e); + } + }).collect(Collectors.toList())); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProcessor.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProcessor.java new file mode 100644 index 00000000000000..044cc6f831c822 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProcessor.java @@ -0,0 +1,148 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static io.quarkus.devtools.project.codegen.codestarts.Codestart.BASE_LANGUAGE; + +import io.fabric8.maven.Maven; +import io.fabric8.maven.merge.SmartModelMerger; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import java.io.IOException; +import java.io.StringReader; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Map; +import java.util.stream.Stream; +import org.apache.maven.model.Model; + +final class CodestartProcessor { + + private CodestartProcessor() { + } + + static void processCodestart(final QuarkusPlatformDescriptor descriptor, final Codestart codestart, + final String languageName, final Path targetDirectory, final Map data) { + try { + descriptor.loadResourcePath(codestart.getResourceName(), p -> { + resolveDirectoriesToProcessAsStream(p, languageName) + .forEach(dirPath -> processCodestartDir(languageName, dirPath, targetDirectory, + CodestartData.mergeData(codestart, languageName, data))); + return null; + }); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + static Stream resolveDirectoriesToProcessAsStream(final Path sourceDirectory, final String languageName) + throws IOException { + if (!Files.isDirectory(sourceDirectory)) { + throw new IllegalStateException("Codestart sourceDirectory is not a directory: " + sourceDirectory); + } + return Stream.of(BASE_LANGUAGE, languageName) + .map(sourceDirectory::resolve) + .filter(Files::isDirectory); + } + + static void processCodestartDir(final String languageName, + final Path sourceDirectory, + final Path targetProjectDirectory, + final Map data) { + try { + Files.walk(sourceDirectory) + .filter(path -> !path.equals(sourceDirectory)) + .forEach(path -> { + try { + final Path relativePath = sourceDirectory.relativize(path); + if (Files.isDirectory(path)) { + return; + } else { + final String fileName = relativePath.getFileName().toString(); + final Path targetPath = targetProjectDirectory.resolve(relativePath.toString()); + if (fileName.contains(".part")) { + // TODO we need some kind of PartCombiner interface with a "matcher" + if (fileName.equals("pom.part.qute.xml")) { + processMavenPart(path, languageName, data, targetPath.getParent().resolve("pom.xml")); + } else if (fileName.equals("README.part.qute.md")) { + processReadmePart(path, languageName, data, + targetPath.getParent().resolve("README.md")); + } else { + throw new IllegalStateException("Unsupported part file: " + path); + } + } else if (fileName.contains(".qute")) { + if (fileName.endsWith(".include.qute")) { + //ignore includes + return; + } + // Template file + processQuteFile(path, languageName, data, + targetPath.getParent().resolve(fileName.replace(".qute", ""))); + } else { + // Static file + processStaticFile(path, targetPath); + } + } + } catch (final IOException e) { + throw new UncheckedIOException(e); + } + }); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + private static void processReadmePart(Path path, String languageName, Map data, Path targetPath) + throws IOException { + if (!Files.exists(targetPath)) { + throw new IllegalStateException( + "Using .part is not possible when the target file does not exist already: " + path + " -> " + targetPath); + } + final String renderedContent = "\n" + CodestartQute.processQuteContent(path, languageName, data); + Files.write(targetPath, renderedContent.getBytes(), StandardOpenOption.APPEND); + } + + private static void processMavenPart(Path path, String languageName, Map data, Path targetPath) + throws IOException { + if (!Files.exists(targetPath)) { + throw new IllegalStateException( + "Using .part is not possible when the target file does not exist already: " + path + " -> " + targetPath); + } + final Model targetModel = Maven.readModel(targetPath); + final SmartModelMerger merger = new SmartModelMerger(); + final String content = CodestartQute.processQuteContent(path, languageName, data); + final Model sourceModel = Maven.readModel(new StringReader(content)); + merger.merge(targetModel, sourceModel, true, null); + Maven.writeModel(targetModel); + } + + private static void processStaticFile(Path path, Path targetPath) throws IOException { + Files.createDirectories(targetPath.getParent()); + Files.copy(path, targetPath); + } + + private static void processQuteFile(Path path, String languageName, Map data, Path targetPath) + throws IOException { + final String renderedContent = CodestartQute.processQuteContent(path, languageName, data); + Files.createDirectories(targetPath.getParent()); + Files.write(targetPath, renderedContent.getBytes(), StandardOpenOption.CREATE_NEW); + } + + static void checkTargetDir(Path targetDirectory) throws IOException { + if (!Files.exists(targetDirectory)) { + boolean mkdirStatus = targetDirectory.toFile().mkdirs(); + if (!mkdirStatus) { + throw new IOException("Failed to create the project directory: " + targetDirectory); + } + return; + } + if (!Files.isDirectory(targetDirectory)) { + throw new IOException("Project path needs to point to a directory: " + targetDirectory); + } + final String[] files = targetDirectory.toFile().list(); + if (files != null && files.length > 0) { + throw new IOException("You can't create a project when the directory is not empty: " + targetDirectory); + } + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProject.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProject.java new file mode 100644 index 00000000000000..b5ee0515ad9a7f --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProject.java @@ -0,0 +1,94 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static io.quarkus.devtools.project.codegen.codestarts.CodestartData.mergeMaps; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class CodestartProject { + + private final Codestart project; + private final Codestart buildTool; + private final Codestart language; + private final Codestart config; + private final List codestarts; + private final CodestartInput codestartInput; + + CodestartProject(Codestart project, Codestart buildTool, Codestart language, Codestart config, List codestarts, + CodestartInput codestartInput) { + this.project = project; + this.buildTool = buildTool; + this.language = language; + this.config = config; + this.codestarts = codestarts; + this.codestartInput = codestartInput; + } + + public Codestart getProject() { + return project; + } + + public Codestart getBuildTool() { + return buildTool; + } + + public Codestart getLanguage() { + return language; + } + + public Codestart getConfig() { + return config; + } + + public List getCodestarts() { + return codestarts; + } + + public CodestartInput getCodestartInput() { + return codestartInput; + } + + public List getDefaultCodestart() { + return Arrays.asList( + this.getProject(), + this.getBuildTool(), + this.getLanguage(), + this.getConfig()); + } + + public Stream getAllCodestartsStream() { + return Stream.concat(getDefaultCodestart().stream(), getCodestarts().stream()); + } + + public String getLanguageName() { + return language.getSpec().getName(); + } + + public Map getSharedData() { + final Stream> codestartsGlobal = getAllCodestartsStream() + .map(c -> c.getSharedData(getLanguageName())); + return mergeMaps(Stream.concat(codestartsGlobal, Stream.of(getCodestartInput().getData()))); + } + + public Map getDepsData() { + final Map> depsData = new HashMap<>(); + final List extensionsAsDeps = codestartInput.getExtensions().stream() + .map(k -> k.getGroupId() + ":" + k.getArtifactId()).map(CodestartSpec.CodestartDep::new) + .collect(Collectors.toList()); + depsData.put("dependencies", new ArrayList<>(extensionsAsDeps)); + depsData.put("testDependencies", new ArrayList<>()); + getAllCodestartsStream() + .flatMap(s -> Stream.of(s.getBaseLanguageSpec(), s.getLanguageSpec(getLanguageName()))) + .forEach(d -> { + depsData.get("dependencies").addAll(d.getDependencies()); + depsData.get("testDependencies").addAll(d.getTestDependencies()); + }); + return Collections.unmodifiableMap(depsData); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartQute.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartQute.java new file mode 100644 index 00000000000000..29d3ffa7c0dc70 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartQute.java @@ -0,0 +1,125 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import io.quarkus.qute.Engine; +import io.quarkus.qute.Expression; +import io.quarkus.qute.ResultMapper; +import io.quarkus.qute.Results; +import io.quarkus.qute.TemplateLocator; +import io.quarkus.qute.TemplateNode; +import io.quarkus.qute.Variant; +import java.io.IOException; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; + +final class CodestartQute { + + private CodestartQute() { + } + + public static Engine newEngine() { + return Engine.builder().addDefaults() + .addResultMapper(new MissingValueMapper()) + .build(); + } + + public static String processQuteContent(Path path, String languageName, Map data) throws IOException { + final String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + final Object preparedData = prepareData(data); + final Engine engine = Engine.builder().addDefaults() + .addResultMapper(new MissingValueMapper()) + .removeStandaloneLines(true) + .addLocator(id -> findIncludeTemplate(path, languageName, id).map(IncludeTemplateLocation::new)) + .build(); + return engine.parse(content).render(preparedData); + } + + private static Optional findIncludeTemplate(Path path, String languageName, String name) { + // FIXME looking at the parent dir is a bit random + final Path codestartPath = path.getParent().getParent(); + final String includeFileName = name + ".include.qute"; + final Path languageIncludeTemplate = codestartPath.resolve(languageName + "/" + includeFileName); + if (Files.isRegularFile(languageIncludeTemplate)) { + return Optional.of(languageIncludeTemplate); + } + final Path baseIncludeTemplate = codestartPath.resolve("base/" + includeFileName); + if (Files.isRegularFile(baseIncludeTemplate)) { + return Optional.of(baseIncludeTemplate); + } + return Optional.empty(); + } + + private static Object prepareData(Map data) { + return unflatten(data); + } + + private static Map unflatten(Map flattened) { + Map unflattened = new HashMap<>(); + for (String key : flattened.keySet()) { + doUnflatten(unflattened, key, flattened.get(key)); + } + return unflattened; + } + + private static void doUnflatten(Map current, String key, Object originalValue) { + String[] parts = StringUtils.split(key, "."); + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + if (i == (parts.length - 1)) { + current.put(part, originalValue); + return; + } + + final Object value = current.get(part); + if (value == null) { + final HashMap map = new HashMap<>(); + current.put(part, map); + current = map; + } else if (value instanceof Map) { + current = (Map) value; + } else { + throw new IllegalStateException("Conflicting data types for key '" + key + "'"); + } + } + } + + private static class IncludeTemplateLocation implements TemplateLocator.TemplateLocation { + + private final Path path; + + private IncludeTemplateLocation(Path path) { + this.path = path; + } + + @Override + public Reader read() { + try { + return Files.newBufferedReader(path); + } catch (IOException e) { + return null; + } + } + + @Override + public Optional getVariant() { + return Optional.empty(); + } + } + + static class MissingValueMapper implements ResultMapper { + + public boolean appliesTo(TemplateNode.Origin origin, Object result) { + return Results.Result.NOT_FOUND.equals(result); + } + + public String map(Object result, Expression expression) { + throw new IllegalStateException("Missing required data: {" + expression.toOriginalString() + "}"); + } + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartSpec.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartSpec.java new file mode 100644 index 00000000000000..8d7010d9a91526 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/CodestartSpec.java @@ -0,0 +1,143 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static java.util.Objects.requireNonNull; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +final class CodestartSpec { + + enum Type { + PROJECT, + BUILDTOOL, + LANGUAGE, + CONFIG, + CODESTART + } + + private final String name; + private final String ref; + private final Type type; + private final boolean isDefault; + private final boolean isExample; + private final Map languagesSpec; + + @JsonCreator + public CodestartSpec(@JsonProperty(value = "name", required = true) String name, + @JsonProperty(value = "ref") String ref, + @JsonProperty(value = "type") Type type, + @JsonProperty("default") boolean isDefault, + @JsonProperty("example") boolean isExample, + @JsonProperty("spec") Map languagesSpec) { + this.name = requireNonNull(name, "name is required"); + this.ref = ref != null ? ref : name; + this.type = type != null ? type : Type.CODESTART; + this.isDefault = isDefault; + this.isExample = isExample; + this.languagesSpec = languagesSpec != null ? languagesSpec : Collections.emptyMap(); + } + + public String getName() { + return name; + } + + public String getRef() { + return ref; + } + + public Type getType() { + return type; + } + + public boolean isDefault() { + return isDefault; + } + + public boolean isExample() { + return isExample; + } + + public Map getLanguagesSpec() { + return languagesSpec; + } + + public static final class LanguageSpec { + private final Map localData; + private final Map sharedData; + private final List dependencies; + private final List testDependencies; + + public LanguageSpec() { + this(null, null, null, null); + } + + @JsonCreator + public LanguageSpec(@JsonProperty("local-data") Map localData, + @JsonProperty("shared-data") Map sharedData, + @JsonProperty("dependencies") List dependencies, + @JsonProperty("test-dependencies") List testDependencies) { + this.localData = localData != null ? localData : Collections.emptyMap(); + this.sharedData = sharedData != null ? sharedData : Collections.emptyMap(); + this.dependencies = dependencies != null ? dependencies : Collections.emptyList(); + this.testDependencies = testDependencies != null ? testDependencies : Collections.emptyList(); + } + + public Map getLocalData() { + return localData; + } + + public Map getSharedData() { + return sharedData; + } + + public List getDependencies() { + return dependencies; + } + + public List getTestDependencies() { + return testDependencies; + } + } + + public static class CodestartDep extends HashMap { + public CodestartDep() { + } + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public CodestartDep(final String expression) { + final String[] split = expression.split(":"); + if (split.length < 2 || split.length > 3) { + throw new IllegalArgumentException("Invalid CodestartDep expression: " + expression); + } + this.put("groupId", split[0]); + this.put("artifactId", split[1]); + if (split.length == 3) { + this.put("version", split[2]); + } + } + + public String getGroupId() { + return this.get("groupId"); + } + + public String getArtifactId() { + return this.get("artifactId"); + } + + public String getVersion() { + return this.get("version"); + } + + @Override + public String toString() { + final String version = Optional.ofNullable(getVersion()).map(v -> ":" + v).orElse(""); + return getGroupId() + ":" + getArtifactId() + version; + } + + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestarts.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestarts.java new file mode 100644 index 00000000000000..8834d22c7a5102 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/codestarts/Codestarts.java @@ -0,0 +1,73 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static io.quarkus.devtools.project.codegen.codestarts.CodestartLoader.loadAddCodestarts; + +import io.quarkus.dependencies.Extension; +import io.quarkus.devtools.project.extensions.Extensions; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Codestarts { + + public static CodestartProject prepareProject(final CodestartInput input) throws IOException { + final String buildToolCodeStart = (String) input.getData().getOrDefault("buildtool.name", "maven"); + final Set enabledCodestarts = Stream.concat(input.getDescriptor().getExtensions().stream() + .filter(e -> input.getExtensions().contains(Extensions.toKey(e))) + .map(Extension::getCodestart), Stream.of(buildToolCodeStart)) + .collect(Collectors.toSet()); + + final Collection allCodestarts = loadAddCodestarts(input); + final Codestart project = findEnabledCodestartOfTypeOrDefault(allCodestarts, enabledCodestarts, + CodestartSpec.Type.PROJECT); + final Codestart buildTool = findEnabledCodestartOfTypeOrDefault(allCodestarts, enabledCodestarts, + CodestartSpec.Type.BUILDTOOL); + final Codestart language = findEnabledCodestartOfTypeOrDefault(allCodestarts, enabledCodestarts, + CodestartSpec.Type.LANGUAGE); + final Codestart config = findEnabledCodestartOfTypeOrDefault(allCodestarts, enabledCodestarts, + CodestartSpec.Type.CONFIG); + final List codestarts = allCodestarts.stream() + .filter(c -> CodestartSpec.Type.CODESTART.equals(c.getSpec().getType())) + .filter(c -> c.getSpec().isDefault() || enabledCodestarts.contains(c.getSpec().getRef())) + .filter(c -> !c.getSpec().isExample() || input.includeExample()) + .collect(Collectors.toList()); + + // Hack for CommandMode activation + if (input.includeExample() && codestarts.stream().noneMatch(c -> c.getSpec().isExample())) { + final Stream commandModeCodestarts = allCodestarts.stream() + .filter(c -> c.getSpec().getRef().equals("commandmode")); + final List codestartsWithCommandMode = Stream.concat(codestarts.stream(), commandModeCodestarts) + .collect(Collectors.toList()); + return new CodestartProject(project, buildTool, language, config, codestartsWithCommandMode, input); + } + + return new CodestartProject(project, buildTool, language, config, codestarts, input); + } + + public static void generateProject(final CodestartProject codestartProject, final Path targetDirectory) throws IOException { + CodestartProcessor.checkTargetDir(targetDirectory); + final String languageName = codestartProject.getLanguageName(); + final Map sharedData = codestartProject.getSharedData(); + final Map data = CodestartData.mergeMaps(Stream.of(sharedData, codestartProject.getDepsData())); + // TODO support yaml config + codestartProject.getAllCodestartsStream() + .forEach(c -> CodestartProcessor.processCodestart(codestartProject.getCodestartInput().getDescriptor(), c, + languageName, targetDirectory, data)); + } + + private static Codestart findEnabledCodestartOfTypeOrDefault(final Collection codestarts, + final Set enabledCodestarts, final CodestartSpec.Type type) { + return codestarts.stream() + .filter(c -> c.getSpec().getType().equals(type) + && (c.getSpec().isDefault() || enabledCodestarts.contains(c.getSpec().getName()))) + .min(Comparator.comparing(c -> c.getSpec().isDefault())) + .orElseThrow(() -> new IllegalStateException("No matching codestart of type " + type + " has been found")); + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ClassPathResourceLoader.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ClassPathResourceLoader.java index 9983b8eb9784a4..076bf3aefbe554 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ClassPathResourceLoader.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ClassPathResourceLoader.java @@ -1,8 +1,11 @@ package io.quarkus.platform.descriptor.loader.json; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; +import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URL; public class ClassPathResourceLoader implements ResourceLoader { @@ -16,6 +19,13 @@ public ClassPathResourceLoader(ClassLoader cl) { this.cl = cl; } + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + final URL url = cl.getResource(name); + final File file = ResourceLoaders.getResourceFile(url, name); + return consumer.consume(file.toPath()); + } + @Override public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { final InputStream stream = cl.getResourceAsStream(name); diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/DirectoryResourceLoader.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/DirectoryResourceLoader.java index c42cc47894791c..46d94953db5533 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/DirectoryResourceLoader.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/DirectoryResourceLoader.java @@ -1,8 +1,7 @@ package io.quarkus.platform.descriptor.loader.json; -import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -18,16 +17,16 @@ public DirectoryResourceLoader(Path dir) { } @Override - public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { - Path resource = dir.resolve(name); - if (!Files.exists(resource)) { - throw new IOException("Failed to locate " + resource); + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + Path path; + if (name == null || name.isEmpty()) { + path = dir; + } else { + path = dir.resolve(name); } - if (Files.isDirectory(resource)) { - throw new IOException("Can't open a stream for path pointing to directory " + resource); - } - try (InputStream is = Files.newInputStream(resource)) { - return consumer.consume(is); + if (!Files.exists(path)) { + throw new IOException("Failed to locate " + name + " dir on the classpath"); } + return consumer.consume(path); } } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoader.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoader.java index a7d67ec4a8c7a4..4451305aba8dd1 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoader.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoader.java @@ -1,9 +1,21 @@ package io.quarkus.platform.descriptor.loader.json; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; public interface ResourceLoader { - T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException; + T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException; + + default T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { + return this.loadResourcePath(name, p -> { + try (InputStream is = Files.newInputStream(p)) { + return consumer.consume(is); + } + }); + } + } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java new file mode 100644 index 00000000000000..bc7f6b94bf3949 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java @@ -0,0 +1,37 @@ +package io.quarkus.platform.descriptor.loader.json; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; +import org.apache.commons.io.FilenameUtils; + +public final class ResourceLoaders { + + private ResourceLoaders() { + } + + public static File getResourceFile(final URL url, final String name) throws IOException { + if (url == null) { + throw new IOException("Failed to locate resource " + name + " on the classpath"); + } + try { + return new File(url.toURI()); + } catch (URISyntaxException | IllegalArgumentException e) { + throw new IOException( + "There were a problem while reading the resource dir '" + name + "' on the classpath with url: '" + + url.toString() + "'"); + } + } + + public static Stream toResourceNameWalker(final String dirName, final Path dirPath) throws IOException { + return Files.walk(dirPath).map(p -> resolveResourceName(dirName, dirPath, p)); + } + + private static String resolveResourceName(final String dirName, final Path dirPath, final Path resourcePath) { + return FilenameUtils.concat(dirName, dirPath.relativize(resourcePath).toString().replace('\\', '/')); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ZipResourceLoader.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ZipResourceLoader.java index 171d4be144e961..d4b372c3169a08 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ZipResourceLoader.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ZipResourceLoader.java @@ -1,8 +1,7 @@ package io.quarkus.platform.descriptor.loader.json; -import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import java.io.IOException; -import java.io.InputStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -17,15 +16,14 @@ public ZipResourceLoader(Path zip) { } @Override - public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { try (FileSystem fs = FileSystems.newFileSystem(zip, (ClassLoader) null)) { - final Path p = fs.getPath("/", name); - if (!Files.exists(p)) { + final Path path = fs.getPath("/", name); + if (!Files.exists(path)) { throw new IOException("Failed to locate " + name + " in " + zip); } - try (InputStream is = Files.newInputStream(p)) { - return consumer.consume(is); - } + return consumer.consume(path); } } + } diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/ProjectTestUtil.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/ProjectTestUtil.java new file mode 100644 index 00000000000000..d6b2d9503ad544 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/ProjectTestUtil.java @@ -0,0 +1,29 @@ +package io.quarkus.devtools; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.stream.Stream; +import org.junit.jupiter.api.Assertions; + +public final class ProjectTestUtil { + + private ProjectTestUtil() { + } + + public static void delete(final File file) throws IOException { + + if (file.exists()) { + try (Stream stream = Files.walk(file.toPath())) { + stream.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + } + + Assertions.assertFalse( + Files.exists(file.toPath()), "Directory still exists"); + } +} diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/CombinedQuarkusPlatformDescriptorTest.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/CombinedQuarkusPlatformDescriptorTest.java index f9da268b93ccc3..8781df78c7dea0 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/CombinedQuarkusPlatformDescriptorTest.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/CombinedQuarkusPlatformDescriptorTest.java @@ -6,7 +6,6 @@ import io.quarkus.dependencies.Category; import io.quarkus.dependencies.Extension; -import io.quarkus.devtools.commands.PlatformAwareTestBase; import io.quarkus.platform.descriptor.CombinedQuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import java.util.List; @@ -50,9 +49,9 @@ public void testDominance() throws Exception { assertManagedDeps(combined); - assertEquals("dominating pom.xml template", combined.getTemplate("templates/basic-rest/java/pom.xml-template.ftl")); - assertEquals(defaultPlatform.getTemplate("templates/dockerfile-jvm.ftl"), - combined.getTemplate("templates/dockerfile-jvm.ftl")); + assertEquals("dominating pom.xml template", combined.getTemplate("dir/some-other-file.template")); + assertEquals(defaultPlatform.getTemplate("dir/some-file.template"), + combined.getTemplate("dir/some-file.template")); } private void assertBom(QuarkusPlatformDescriptor descriptor) { diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/PlatformAwareTestBase.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/PlatformAwareTestBase.java similarity index 97% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/PlatformAwareTestBase.java rename to independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/PlatformAwareTestBase.java index 33b1278cd484df..c04f0fc5539a28 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/PlatformAwareTestBase.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/PlatformAwareTestBase.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.commands; +package io.quarkus.test.platform.descriptor; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.tools.config.QuarkusPlatformConfig; diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/TestDominatingQuarkusPlatformDescriptor.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/TestDominatingQuarkusPlatformDescriptor.java index f2ba040a12c38d..459ede5dc60727 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/TestDominatingQuarkusPlatformDescriptor.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/TestDominatingQuarkusPlatformDescriptor.java @@ -3,10 +3,12 @@ import static io.quarkus.test.platform.descriptor.loader.QuarkusTestPlatformDescriptorLoader.addCategory; import static io.quarkus.test.platform.descriptor.loader.QuarkusTestPlatformDescriptorLoader.addExtension; +import io.quarkus.bootstrap.model.AppArtifactCoords; import io.quarkus.dependencies.Category; import io.quarkus.dependencies.Extension; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -23,8 +25,9 @@ public TestDominatingQuarkusPlatformDescriptor() { addCategory("other", "Other category", categories); addCategory("web", "Dominating Web", categories); - addExtension("io.quarkus", "quarkus-resteasy", "dominating-version", "Dominating RESTEasy", "dominating/guide", - extensions, bomDeps); + addExtension(new AppArtifactCoords("io.quarkus", "quarkus-resteasy", "dominating-version"), "Dominating RESTEasy", + "dominating/guide", + "reasteasy", extensions, bomDeps); } @Override @@ -64,7 +67,7 @@ public List getCategories() { @Override public String getTemplate(String name) { - if ("templates/basic-rest/java/pom.xml-template.ftl".equals(name)) { + if ("dir/some-other-file.template".equals(name)) { return "dominating pom.xml template"; } return null; @@ -74,4 +77,9 @@ public String getTemplate(String name) { public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { return null; } + + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + return null; + } } diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/loader/QuarkusTestPlatformDescriptorLoader.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/loader/QuarkusTestPlatformDescriptorLoader.java index 2f4bc35680a346..604b5659831b3c 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/loader/QuarkusTestPlatformDescriptorLoader.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/test/platform/descriptor/loader/QuarkusTestPlatformDescriptorLoader.java @@ -1,18 +1,24 @@ package io.quarkus.test.platform.descriptor.loader; +import io.quarkus.bootstrap.model.AppArtifactCoords; import io.quarkus.dependencies.Category; import io.quarkus.dependencies.Extension; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import io.quarkus.platform.descriptor.loader.QuarkusPlatformDescriptorLoader; import io.quarkus.platform.descriptor.loader.QuarkusPlatformDescriptorLoaderContext; +import io.quarkus.platform.descriptor.loader.json.ResourceLoaders; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; +import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -39,12 +45,15 @@ private static void addCategories() { private static void addExtensions() { addExtension("quarkus-agroal", "Agroal"); addExtension("quarkus-arc", "Arc"); + addExtension("quarkus-kotlin", "Kotlin", "url://", "kotlin"); + addExtension("quarkus-scala", "Scala", "url://", "scala"); + addExtension("quarkus-config-yaml", "Config Yaml", "url://", "config-yaml"); addExtension("quarkus-hibernate-orm-panache", "Hibernate ORM Panache"); addExtension("quarkus-hibernate-search-elasticsearch", "Elasticsearch"); addExtension("quarkus-hibernate-validator", "Hibernate Validator"); addExtension("quarkus-jdbc-postgresql", "JDBC PostreSQL"); addExtension("quarkus-jdbc-h2", "JDBC H2"); - addExtension("quarkus-resteasy", "RESTEasy", "https://quarkus.io/guides/rest-json"); + addExtension("quarkus-resteasy", "RESTEasy", "https://quarkus.io/guides/rest-json", "resteasy"); addExtension("quarkus-smallrye-reactive-messaging", "SmallRye Reactive Messaging"); addExtension("quarkus-smallrye-reactive-streams-operators", "SmallRye Reactive Streams Operators"); @@ -67,21 +76,26 @@ private static void addExtension(String artifactId, String name) { } private static void addExtension(String artifactId, String name, String guide) { - addExtension("io.quarkus", artifactId, quarkusVersion, name, guide); + addExtension(artifactId, name, guide, null); } - private static void addExtension(String groupId, String artifactId, String version, String name, String guide) { - addExtension(groupId, artifactId, version, name, guide, extensions, bomDeps); + private static void addExtension(String artifactId, String name, String guide, String codestart) { + addExtension(new AppArtifactCoords("io.quarkus", artifactId, quarkusVersion), name, guide, codestart); } - public static void addExtension(String groupId, String artifactId, String version, String name, String guide, + private static void addExtension(AppArtifactCoords coords, String name, String guide, String codestart) { + addExtension(coords, name, guide, codestart, extensions, bomDeps); + } + + public static void addExtension(AppArtifactCoords coords, String name, String guide, String codestart, List extensions, List bomDeps) { - extensions.add(new Extension(groupId, artifactId, version).setName(name).setGuide(guide)); + extensions.add(new Extension(coords.getGroupId(), coords.getArtifactId(), coords.getVersion()).setName(name) + .setGuide(guide).setCodestart(codestart)); final Dependency d = new Dependency(); - d.setGroupId(groupId); - d.setArtifactId(artifactId); - d.setVersion(version); + d.setGroupId(coords.getGroupId()); + d.setArtifactId(coords.getArtifactId()); + d.setVersion(coords.getVersion()); bomDeps.add(d); } @@ -174,6 +188,11 @@ public T loadResource(String name, ResourceInputStreamConsumer consumer) return loadStaticResource(name, consumer); } + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + return loadStaticResourcePath(name, consumer); + } + @Override public List getCategories() { return categories; @@ -192,4 +211,13 @@ private static T loadStaticResource(String name, ResourceInputStreamConsumer is.close(); } } + + private static T loadStaticResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + final URL url = Thread.currentThread().getContextClassLoader().getResource(name); + final File file = ResourceLoaders.getResourceFile(url, name); + if (!Files.exists(file.toPath())) { + throw new IOException("Failed to locate resource " + name + " on the classpath"); + } + return consumer.consume(file.toPath()); + } } diff --git a/independent-projects/tools/devtools-common/src/test/resources/dir/some-file.template b/independent-projects/tools/devtools-common/src/test/resources/dir/some-file.template new file mode 100644 index 00000000000000..93d00322a11ccb --- /dev/null +++ b/independent-projects/tools/devtools-common/src/test/resources/dir/some-file.template @@ -0,0 +1,3 @@ +Humble smack Shirelings tears baby usurper mouthful. Embrace fresh burned oil Wargs regurgitation unheard-of. Brandybucks puppet vines boats familiar prizewinners tunnel leaving riverbank welcome threw 60? Durin's certain washing crawled children? Pouf Dwarvish elected fruity writing. Laughing reserves hinges Barad-dur either troublemakers saw pleased thereof set weren't penny. Hear my voice. Come back to the light. Slight keyhole strong Shirkers 3434 promised? +Water pointy-ear Saruman notion deceived go outer river salted unpredictable slowed. Galadriel strawberries scum surety bolted suffer delaying him lidless achieving killing. I have no memory of this place. Arguing Lake-men scale pon tree falling. Slugs when presses wasteland cousin sing pool Éomund. Resown how shaft wheeled checked dream later Rohan's ago. Famished accustomed you'd Rohan save thicket better plan knife-work becoming ten. Swim solid Ere? Opened clothes filleting devilry struck incident Southrons. +Dancing there wet since sooner contract granny Dunharrow father bless. Easy pipe-weed sweeter talks Kili? Fried raw perfected Dimholt together taught toad child. Avenged cheated fill sigh choking deep biding drown Rabble-rousers very. Smirking adventure exchanged bodyguard Dî courteous. Tries fact merchants Wargs badly. All right, then. Keep your secrets. Fours craft new announce faint Dale beside relic advantage travel cook long-forgotten? Short entire weapons knows Westfold ordered birdsong mustn't? Trousers glory consequence possible poured claim Baggins leg telling squeal. \ No newline at end of file diff --git a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/dependencies/Extension.java b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/dependencies/Extension.java index 1c3eda6389a5c5..f867b080c8561a 100644 --- a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/dependencies/Extension.java +++ b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/dependencies/Extension.java @@ -26,6 +26,8 @@ public class Extension implements Serializable { public static final String MD_SHORT_NAME = "short-name"; + public static final String MD_CODESTART = "codestart"; + public static final String MD_GUIDE = "guide"; /** Key used for keywords in metadata **/ @@ -264,6 +266,15 @@ public Extension setShortName(String shortName) { return this; } + public String getCodestart() { + return (String) getMetadata().get(MD_CODESTART); + } + + public Extension setCodestart(String codestart) { + getMetadata().put(MD_CODESTART, codestart); + return this; + } + public boolean isUnlisted() { Object val = getMetadata().get(MD_UNLISTED); if (val == null) { diff --git a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/CombinedQuarkusPlatformDescriptor.java b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/CombinedQuarkusPlatformDescriptor.java index 55e9f2d8a7bf04..088a93b9159fb8 100644 --- a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/CombinedQuarkusPlatformDescriptor.java +++ b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/CombinedQuarkusPlatformDescriptor.java @@ -153,6 +153,18 @@ public T loadResource(String name, ResourceInputStreamConsumer consumer) throw new IOException("Failed to locate resource " + name); } + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + for (QuarkusPlatformDescriptor platform : platforms) { + try { + return platform.loadResourcePath(name, consumer); + } catch (IOException e) { + // ignore + } + } + throw new IOException("Failed to locate resource " + name); + } + private static class DepKey { final String groupId; final String artifactId; diff --git a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/QuarkusPlatformDescriptor.java b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/QuarkusPlatformDescriptor.java index f13d977975e2b1..8bb5d6f3fe5acf 100644 --- a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/QuarkusPlatformDescriptor.java +++ b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/QuarkusPlatformDescriptor.java @@ -26,6 +26,8 @@ public interface QuarkusPlatformDescriptor { T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException; + T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException; + default String gav() { return String.format("%s:%s:%s", getBomGroupId(), getBomArtifactId(), getBomVersion()); } diff --git a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/ResourcePathConsumer.java b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/ResourcePathConsumer.java new file mode 100644 index 00000000000000..88ccd84c238583 --- /dev/null +++ b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/descriptor/ResourcePathConsumer.java @@ -0,0 +1,9 @@ +package io.quarkus.platform.descriptor; + +import java.io.IOException; +import java.nio.file.Path; + +public interface ResourcePathConsumer { + + T consume(Path is) throws IOException; +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java index 75ea6527ce5ef3..d7c6285b9e0dbb 100644 --- a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java @@ -451,10 +451,11 @@ private QuarkusPlatformDescriptor loadPlatformDescriptor(ArtifactResolver mvn, f // check whether the quarkus-platform-descriptor-json used in the platform is already on the classpath final String pomPropsPath = "META-INF/maven/" + ToolsConstants.IO_QUARKUS + "/" + QUARKUS_PLATFORM_DESCRIPTOR_JSON + "/pom.properties"; - final InputStream is = getCpResourceAsStream(pomPropsPath); - if (is != null) { + final URL url = Thread.currentThread().getContextClassLoader().getResource(pomPropsPath); + // FIXME ia3andy temporary hack to work with jars + if (url != null && !url.toString().startsWith("jar:")) { final Properties props = new Properties(); - try { + try (InputStream is = getCpResourceAsStream(pomPropsPath)) { props.load(is); } catch (IOException e) { throw new PlatformDescriptorLoadingException("Failed to load " + pomPropsPath + " from the classpath", e); diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java index 1e607484cc4a0f..b42ba7f5be6feb 100644 --- a/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java @@ -7,6 +7,7 @@ import io.quarkus.dependencies.Extension; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.ResourcePathConsumer; import io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader; import io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoaderContext; import java.io.IOException; @@ -80,6 +81,11 @@ public String getTemplate(String name) { public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { return null; } + + @Override + public T loadResourcePath(String name, ResourcePathConsumer consumer) throws IOException { + return null; + } }; } diff --git a/independent-projects/tools/pom.xml b/independent-projects/tools/pom.xml index 0dc5f22f52ccaf..41a8e9013644e6 100644 --- a/independent-projects/tools/pom.xml +++ b/independent-projects/tools/pom.xml @@ -52,6 +52,8 @@ 1.6.8 999-SNAPSHOT 3.0.11.Final + 2.10.4 + 14 platform-descriptor-api @@ -81,6 +83,11 @@ quarkus-devtools-utilities ${project.version} + + io.quarkus.qute + qute-generator + ${project.version} + io.quarkus quarkus-devtools-common @@ -102,6 +109,21 @@ + + io.fabric8 + maven-model-helper + ${maven-model-helper.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + org.apache.maven maven-plugin-api diff --git a/integration-tests/devtools/pom.xml b/integration-tests/devtools/pom.xml new file mode 100644 index 00000000000000..a2f5563c8ca431 --- /dev/null +++ b/integration-tests/devtools/pom.xml @@ -0,0 +1,65 @@ + + + + io.quarkus + quarkus-integration-tests-parent + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-integration-test-devtools + Quarkus - Integration Tests - Devtools + + + + + io.quarkus + quarkus-devtools-common + + + io.quarkus + quarkus-platform-descriptor-json + + + io.quarkus + quarkus-platform-descriptor-resolver-json + test + + + io.quarkus + quarkus-junit5-internal + test + + + org.mockito + mockito-core + test + + + org.assertj + assertj-core + test + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/PlatformAwareTestBase.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/PlatformAwareTestBase.java new file mode 100644 index 00000000000000..cf374e267bde11 --- /dev/null +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/PlatformAwareTestBase.java @@ -0,0 +1,62 @@ +package io.quarkus.devtools; + +import java.io.IOException; +import java.util.Properties; + +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; + +public class PlatformAwareTestBase { + + private QuarkusPlatformDescriptor platformDescr; + private Properties quarkusProps; + private String pluginGroupId; + private String pluginArtifactId; + private String pluginVersion; + + protected QuarkusPlatformDescriptor getPlatformDescriptor() { + return platformDescr == null + ? platformDescr = QuarkusJsonPlatformDescriptorResolver.newInstance().resolveBundled() + : platformDescr; + } + + private Properties getQuarkusProperties() { + if (quarkusProps == null) { + try { + quarkusProps = getPlatformDescriptor().loadResource("quarkus.properties", is -> { + final Properties props = new Properties(); + props.load(is); + return props; + }); + } catch (IOException e) { + throw new IllegalStateException("Failed to load quarkus.properties", e); + } + } + return quarkusProps; + } + + protected String getPluginGroupId() { + return pluginGroupId == null ? pluginGroupId = getQuarkusProperties().getProperty("plugin-groupId") : pluginGroupId; + } + + protected String getPluginArtifactId() { + return pluginArtifactId == null ? pluginArtifactId = getQuarkusProperties().getProperty("plugin-artifactId") + : pluginArtifactId; + } + + protected String getPluginVersion() { + return pluginVersion == null ? pluginVersion = getQuarkusProperties().getProperty("plugin-version") : pluginVersion; + } + + protected String getBomGroupId() { + return getPlatformDescriptor().getBomGroupId(); + } + + protected String getBomArtifactId() { + return getPlatformDescriptor().getBomArtifactId(); + } + + protected String getBomVersion() { + return getPlatformDescriptor().getBomVersion(); + } +} diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/ProjectTestUtil.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/ProjectTestUtil.java new file mode 100644 index 00000000000000..241ab1c7fb4b9c --- /dev/null +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/ProjectTestUtil.java @@ -0,0 +1,30 @@ +package io.quarkus.devtools; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Assertions; + +public final class ProjectTestUtil { + + private ProjectTestUtil() { + } + + public static void delete(final File file) throws IOException { + + if (file.exists()) { + try (Stream stream = Files.walk(file.toPath())) { + stream.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + } + + Assertions.assertFalse( + Files.exists(file.toPath()), "Directory still exists"); + } +} diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java similarity index 91% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java index 32c0e4c1aba881..c6cb81792367fe 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractAddExtensionsTest.java @@ -2,16 +2,19 @@ import static java.util.Arrays.asList; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import java.util.List; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; + abstract class AbstractAddExtensionsTest extends PlatformAwareTestBase { private final Path projectPath = Paths.get("target/extensions-test"); @@ -36,12 +39,12 @@ void addSomeValidExtensions() throws Exception { @Test void testPartialMatches() throws Exception { createProject(); - addExtensions(asList("orm-pana", "jdbc-postgre", "arc")); + addExtensions(asList("mongodb-pana", "hibernate-val", "arc")); final T project = readProject(); hasDependency(project, "quarkus-arc"); - hasDependency(project, "quarkus-hibernate-orm-panache"); - hasDependency(project, "quarkus-jdbc-postgresql"); + hasDependency(project, "quarkus-mongodb-panache"); + hasDependency(project, "quarkus-hibernate-validator"); } @Test @@ -61,10 +64,11 @@ void testRegexpMatches() throws Exception { hasDependency(project, "quarkus-smallrye-reactive-messaging-kafka"); hasDependency(project, "quarkus-smallrye-health"); hasDependency(project, "quarkus-smallrye-openapi"); + hasDependency(project, "quarkus-smallrye-graphql"); hasDependency(project, "quarkus-smallrye-jwt"); hasDependency(project, "quarkus-smallrye-context-propagation"); - hasDependency(project, "quarkus-smallrye-reactive-type-converters"); hasDependency(project, "quarkus-smallrye-reactive-messaging-amqp"); + hasDependency(project, "quarkus-smallrye-reactive-messaging-mqtt"); hasDependency(project, "quarkus-smallrye-fault-tolerance"); } @@ -206,10 +210,13 @@ void testVertx() throws Exception { void testVertxWithDot() throws Exception { createProject(); - addExtensions(Collections.singletonList("vert.x")); + // It's not possible anymore to install vert.x this way since there are more than one matching extension + final QuarkusCommandOutcome result = addExtensions(Collections.singletonList("vert.x")); + Assertions.assertFalse(result.isSuccess()); + Assertions.assertFalse(result.valueIs(AddExtensions.OUTCOME_UPDATED, true)); final T project = readProject(); - hasDependency(project, "quarkus-vertx"); + doesNotHaveDependency(project, "quarkus-vertx"); } private void hasDependency(T project, String artifactId) { diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java similarity index 92% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java index 9be4524fa05089..4507624cc19ff6 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AbstractRemoveExtensionsTest.java @@ -2,15 +2,18 @@ import static java.util.Arrays.asList; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; + abstract class AbstractRemoveExtensionsTest extends PlatformAwareTestBase { private final Path projectPath = Paths.get("target/extensions-test"); @@ -44,19 +47,19 @@ void removeSomeValidExtensions() throws Exception { @Test void testPartialMatches() throws Exception { createProject(); - List extensions = asList("orm-pana", "jdbc-postgre", "arc"); + List extensions = asList("mongodb-pana", "hibernate-val", "arc"); addExtensions(extensions); final T project = readProject(); hasDependency(project, "quarkus-arc"); - hasDependency(project, "quarkus-hibernate-orm-panache"); - hasDependency(project, "quarkus-jdbc-postgresql"); + hasDependency(project, "quarkus-mongodb-panache"); + hasDependency(project, "quarkus-hibernate-validator"); removeExtensions(extensions); final T projectAfter = readProject(); hasNoDependency(projectAfter, "quarkus-arc"); - hasNoDependency(projectAfter, "quarkus-hibernate-orm-panache"); - hasNoDependency(projectAfter, "quarkus-jdbc-postgresql"); + hasNoDependency(projectAfter, "quarkus-mongodb-panache"); + hasNoDependency(projectAfter, "quarkus-hibernate-validator"); } @Test diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java similarity index 97% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java index f0e2c3ea201e3a..21ebd05128860d 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java @@ -1,11 +1,5 @@ package io.quarkus.devtools.commands; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile; -import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -14,13 +8,22 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.apache.maven.model.Dependency; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + class AddGradleExtensionsTest extends AbstractAddExtensionsTest> { @Override protected List createProject() throws IOException, QuarkusCommandException { - CreateProjectTest.delete(getProjectPath().toFile()); + ProjectTestUtil.delete(getProjectPath().toFile()); new CreateProject(getProjectPath(), getPlatformDescriptor()) .buildTool(BuildTool.GRADLE) .groupId("org.acme") diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java similarity index 95% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java index 904777bf8917ef..e14cbb7e0b701c 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddMavenExtensionsTest.java @@ -1,23 +1,26 @@ package io.quarkus.devtools.commands; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.maven.utilities.MojoUtils; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Objects; + import org.apache.maven.model.Model; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.maven.utilities.MojoUtils; + class AddMavenExtensionsTest extends AbstractAddExtensionsTest { @Override protected Model createProject() throws IOException, QuarkusCommandException { final File pom = getProjectPath().resolve("pom.xml").toFile(); - CreateProjectTest.delete(getProjectPath().toFile()); + ProjectTestUtil.delete(getProjectPath().toFile()); new CreateProject(getProjectPath(), getPlatformDescriptor()) .buildTool(BuildTool.MAVEN) .groupId("org.acme") diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java similarity index 89% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java index f7a7c993c4821a..cad083d7e5be79 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/CreateProjectTest.java @@ -6,17 +6,10 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.codegen.writer.FileProjectWriter; -import io.quarkus.maven.utilities.MojoUtils; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Comparator; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -24,18 +17,26 @@ import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.IntStream; -import java.util.stream.Stream; + import org.apache.maven.model.Model; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.devtools.project.codegen.writer.FileProjectWriter; +import io.quarkus.maven.utilities.MojoUtils; + public class CreateProjectTest extends PlatformAwareTestBase { @Test public void create() throws Exception { final File file = new File("target/basic-rest"); - delete(file); + ProjectTestUtil.delete(file); createProject(file, "io.quarkus", "basic-rest", "1.0.0-SNAPSHOT"); final File gitignore = new File(file, ".gitignore"); @@ -47,7 +48,7 @@ public void create() throws Exception { @Test public void createGradle() throws Exception { final File file = new File("target/basic-rest-gradle"); - delete(file); + ProjectTestUtil.delete(file); createProject(BuildTool.GRADLE, file, "io.quarkus", "basic-rest", "1.0.0-SNAPSHOT"); final File gitignore = new File(file, ".gitignore"); @@ -64,7 +65,7 @@ public void createGradle() throws Exception { @Test public void createOnTopOfExisting() throws Exception { final File testDir = new File("target/existing"); - delete(testDir); + ProjectTestUtil.delete(testDir); testDir.mkdirs(); Model model = new Model(); @@ -110,20 +111,6 @@ void createMultipleTimes() throws InterruptedException { latch.await(); } - public static void delete(final File file) throws IOException { - - if (file.exists()) { - try (Stream stream = Files.walk(file.toPath())) { - stream.sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } - } - - Assertions.assertFalse( - Files.exists(file.toPath()), "Directory still exists"); - } - private void createProject(final File file, String groupId, String artifactId, String version) throws QuarkusCommandException { createProject(BuildTool.MAVEN, file, groupId, artifactId, version); diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java similarity index 95% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java index 15dde3f7a62379..7f12f0163fe0ed 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/ListExtensionsTest.java @@ -6,12 +6,6 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.quarkus.bootstrap.model.AppArtifactCoords; -import io.quarkus.bootstrap.model.AppArtifactKey; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.maven.utilities.MojoUtils; -import io.quarkus.maven.utilities.QuarkusDependencyPredicate; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -23,10 +17,20 @@ import java.util.HashSet; import java.util.Map; import java.util.function.Function; + import org.apache.maven.model.Model; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.maven.utilities.MojoUtils; +import io.quarkus.maven.utilities.QuarkusDependencyPredicate; + public class ListExtensionsTest extends PlatformAwareTestBase { @Test @@ -95,10 +99,10 @@ public void listWithoutBom() throws Exception { final String output = baos.toString("UTF-8"); boolean checkGuideInLineAfter = false; for (String line : output.split("\r?\n")) { - if (line.contains(" Agroal ")) { + if (line.contains("agroal")) { assertTrue(line.startsWith("default"), "Agroal should list as being default: " + line); agroal = true; - } else if (line.contains(" RESTEasy ")) { + } else if (line.contains("quarkus-resteasy ")) { assertTrue(line.startsWith("custom*"), "RESTEasy should list as being custom*: " + line); assertTrue( line.endsWith( @@ -106,13 +110,13 @@ public void listWithoutBom() throws Exception { "RESTEasy should list as being custom*: " + line); resteasy = true; checkGuideInLineAfter = true; - } else if (line.contains("quarkus-hibernate-orm-panache")) { + } else if (line.contains("quarkus-hibernate-orm-panache ")) { assertTrue(line.startsWith("custom"), "Panache should list as being custom: " + line); assertTrue( line.endsWith(String.format("%-25s", getPluginVersion())), "Panache should list as being custom*: " + line); panache = true; - } else if (line.contains(" Hibernate Validator ")) { + } else if (line.contains("hibernate-validator")) { assertTrue(line.startsWith(" "), "Hibernate Validator should not list as anything: " + line); hibernateValidator = true; } else if (checkGuideInLineAfter) { @@ -124,7 +128,10 @@ public void listWithoutBom() throws Exception { } } - assertTrue(agroal && resteasy && hibernateValidator && panache); + assertTrue(agroal); + assertTrue(resteasy); + assertTrue(hibernateValidator); + assertTrue(panache); } @Test @@ -185,7 +192,7 @@ private void addExtensions(QuarkusProject quarkusProject, String... extensions) } private QuarkusProject createNewProject(final File pom) throws IOException, QuarkusCommandException { - CreateProjectTest.delete(pom.getParentFile()); + ProjectTestUtil.delete(pom.getParentFile()); final Path projectDirPath = pom.getParentFile().toPath(); new CreateProject(projectDirPath, getPlatformDescriptor()) .groupId("org.acme") diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java similarity index 96% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java index 963af786163e6a..f9fcd1689941ea 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveGradleExtensionsTest.java @@ -1,17 +1,20 @@ package io.quarkus.devtools.commands; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashSet; import java.util.List; + import org.junit.jupiter.api.Disabled; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + class RemoveGradleExtensionsTest extends AbstractRemoveExtensionsTest> { @Disabled @@ -21,7 +24,7 @@ void addExtensionTwiceInTwoBatches() throws IOException { @Override protected List createProject() throws IOException, QuarkusCommandException { - CreateProjectTest.delete(getProjectPath().toFile()); + ProjectTestUtil.delete(getProjectPath().toFile()); new CreateProject(getProjectPath(), getPlatformDescriptor()) .buildTool(BuildTool.GRADLE) .groupId("org.acme") diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java similarity index 95% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java index febaba8565c341..33ded3e7e496af 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/RemoveMavenExtensionsTest.java @@ -1,22 +1,25 @@ package io.quarkus.devtools.commands; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.maven.utilities.MojoUtils; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Objects; + import org.apache.maven.model.Model; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.maven.utilities.MojoUtils; + class RemoveMavenExtensionsTest extends AbstractRemoveExtensionsTest { @Override protected Model createProject() throws IOException, QuarkusCommandException { final File pom = getProjectPath().resolve("pom.xml").toFile(); - CreateProjectTest.delete(getProjectPath().toFile()); + ProjectTestUtil.delete(getProjectPath().toFile()); new CreateProject(getProjectPath(), getPlatformDescriptor()) .groupId("org.acme") .artifactId("add-maven-extension-test") diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java similarity index 99% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java index ab9135375aa1c5..2b6f9b51bcabe7 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java @@ -3,13 +3,15 @@ import static io.quarkus.devtools.commands.handlers.QuarkusCommandHandlers.select; import static java.util.Arrays.asList; -import io.quarkus.dependencies.Extension; -import io.quarkus.devtools.commands.data.SelectionResult; import java.util.Collections; import java.util.List; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import io.quarkus.dependencies.Extension; +import io.quarkus.devtools.commands.data.SelectionResult; + class QuarkusCommandHandlersTest { @Test diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProjectTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProjectTest.java new file mode 100644 index 00000000000000..f78d9e7fd3e4c8 --- /dev/null +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartProjectTest.java @@ -0,0 +1,124 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.ProjectTestUtil; + +class CodestartProjectTest extends PlatformAwareTestBase { + + private static final Path projectPath = Paths.get("target/codestarts-test"); + + @BeforeAll + static void setUp() throws IOException { + ProjectTestUtil.delete(projectPath.toFile()); + } + + private Map getTestInputData() { + return getTestInputData(null); + } + + private Map getTestInputData(final Map override) { + final HashMap data = new HashMap<>(); + data.put("project.version", "1.0.0-codestart"); + data.put("quarkus.platform.group-id", getPlatformDescriptor().getBomGroupId()); + data.put("quarkus.platform.artifact-id", getPlatformDescriptor().getBomArtifactId()); + data.put("quarkus.platform.version", "1.5.2.Final"); + data.put("quarkus.plugin.group-id", "io.quarkus"); + data.put("quarkus.plugin.artifact-id", "quarkus-maven-plugin"); + data.put("quarkus.plugin.version", "1.5.2.Final"); + if (override != null) + data.putAll(override); + return data; + } + + @Test + void loadDefaultCodestartsTest() throws IOException { + final Collection codestarts = CodestartLoader.loadBaseCodestarts(getPlatformDescriptor()); + assertThat(codestarts).hasSize(10); + } + + @Test + void generateCodestartProjectEmpty() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject( + new CodestartInput(getPlatformDescriptor(), Collections.emptyList(), false, getTestInputData())); + Codestarts.generateProject(codestartProject, projectPath.resolve("empty")); + } + + @Test + void generateCodestartProjectMavenResteasyJava() throws IOException { + final List extensions = Arrays.asList(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData())); + Codestarts.generateProject(codestartProject, projectPath.resolve("maven-resteasy-java")); + } + + @Test + void generateCodestartProjectMavenResteasyKotlin() throws IOException { + final List extensions = Arrays.asList( + AppArtifactKey.fromString("io.quarkus:quarkus-resteasy"), + AppArtifactKey.fromString("io.quarkus:quarkus-kotlin")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData())); + Codestarts.generateProject(codestartProject, projectPath.resolve("maven-resteasy-kotlin")); + } + + @Test + void generateCodestartProjectMavenResteasyScala() throws IOException { + final List extensions = Arrays.asList( + AppArtifactKey.fromString("io.quarkus:quarkus-resteasy"), + AppArtifactKey.fromString("io.quarkus:quarkus-scala")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData())); + Codestarts.generateProject(codestartProject, projectPath.resolve("maven-resteasy-scala")); + } + + @Test + void generateCodestartProjectGradleResteasyJava() throws IOException { + final List extensions = Arrays.asList(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData(Collections.singletonMap("buildtool.name", "gradle")))); + Codestarts.generateProject(codestartProject, projectPath.resolve("gradle-resteasy-java")); + } + + @Test + void generateCodestartProjectGradleResteasyKotlin() throws IOException { + final List extensions = Arrays.asList( + AppArtifactKey.fromString("io.quarkus:quarkus-resteasy"), + AppArtifactKey.fromString("io.quarkus:quarkus-kotlin")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData(Collections.singletonMap("buildtool.name", "gradle")))); + Codestarts.generateProject(codestartProject, projectPath.resolve("gradle-resteasy-kotlin")); + } + + @Test + void generateCodestartProjectGradleResteasyScala() throws IOException { + final List extensions = Arrays.asList( + AppArtifactKey.fromString("io.quarkus:quarkus-resteasy"), + AppArtifactKey.fromString("io.quarkus:quarkus-scala")); + final CodestartProject codestartProject = Codestarts + .prepareProject(new CodestartInput(getPlatformDescriptor(), extensions, + true, getTestInputData(Collections.singletonMap("buildtool.name", "gradle")))); + Codestarts.generateProject(codestartProject, projectPath.resolve("gradle-resteasy-scala")); + } + +} diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartsTest.java new file mode 100644 index 00000000000000..27df06297d4d2f --- /dev/null +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/codestarts/CodestartsTest.java @@ -0,0 +1,101 @@ +package io.quarkus.devtools.project.codegen.codestarts; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.ProjectTestUtil; + +class CodestartsTest extends PlatformAwareTestBase { + + private final Path projectPath = Paths.get("target/codestarts-test"); + + @BeforeEach + void setUp() throws IOException { + ProjectTestUtil.delete(projectPath.toFile()); + } + + @Test + void loadDefaultCodestartsTest() throws IOException { + final Collection codestarts = CodestartLoader.loadBaseCodestarts(getPlatformDescriptor()); + assertThat(codestarts).hasSize(10); + } + + @Test + void prepareProjectTestEmpty() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject( + new CodestartInput(getPlatformDescriptor(), Collections.emptyList(), false, Collections.emptyMap())); + assertThat(codestartProject.getProject()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/project/quarkus"); + assertThat(codestartProject.getBuildTool()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/buildtool/maven"); + assertThat(codestartProject.getConfig()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/config/config-properties"); + assertThat(codestartProject.getLanguage()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/language/java"); + assertThat(codestartProject.getCodestarts()).extracting(Codestart::getResourceName) + .containsExactly("codestarts/base/codestart/docker"); + } + + @Test + void prepareProjectTestGradle() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.emptyList(), false, Collections.singletonMap("buildtool.name", "gradle"))); + assertThat(codestartProject.getBuildTool()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/buildtool/gradle"); + } + + @Test + void prepareProjectTestKotlin() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.singletonList(AppArtifactKey.fromString("io.quarkus:quarkus-kotlin")), + false, Collections.emptyMap())); + assertThat(codestartProject.getLanguage()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/language/kotlin"); + } + + @Test + void prepareProjectTestScala() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.singletonList(AppArtifactKey.fromString("io.quarkus:quarkus-scala")), + false, Collections.emptyMap())); + assertThat(codestartProject.getLanguage()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/language/scala"); + } + + @Test + void prepareProjectTestConfigYaml() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.singletonList(AppArtifactKey.fromString("io.quarkus:quarkus-config-yaml")), + false, Collections.emptyMap())); + assertThat(codestartProject.getConfig()).extracting(Codestart::getResourceName) + .isEqualTo("codestarts/base/config/config-yaml"); + } + + @Test + void prepareProjectTestResteasy() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.singletonList(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")), + true, Collections.emptyMap())); + assertThat(codestartProject.getCodestarts()).extracting(Codestart::getResourceName) + .containsExactlyInAnyOrder("codestarts/base/codestart/docker", "codestarts/extensions/resteasy-example"); + } + + @Test + void prepareProjectTestCommandMode() throws IOException { + final CodestartProject codestartProject = Codestarts.prepareProject(new CodestartInput(getPlatformDescriptor(), + Collections.emptyList(), + true, Collections.emptyMap())); + assertThat(codestartProject.getCodestarts()).extracting(Codestart::getResourceName) + .containsExactlyInAnyOrder("codestarts/base/codestart/docker", "codestarts/base/codestart/commandmode-example"); + } +} diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java similarity index 99% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java index fbdf838568ac28..a745b1cdb37111 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java @@ -16,13 +16,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import io.quarkus.bootstrap.util.IoUtils; -import io.quarkus.devtools.commands.PlatformAwareTestBase; -import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.devtools.project.codegen.SourceType; -import io.quarkus.devtools.project.codegen.writer.ProjectWriter; -import io.quarkus.maven.utilities.MojoUtils; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -34,11 +27,20 @@ import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.IntStream; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import io.quarkus.bootstrap.util.IoUtils; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.devtools.project.codegen.SourceType; +import io.quarkus.devtools.project.codegen.writer.ProjectWriter; +import io.quarkus.maven.utilities.MojoUtils; + class BasicRestProjectGeneratorTest extends PlatformAwareTestBase { private final Map basicProjectContext = new HashMap<>(); diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java similarity index 95% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java rename to integration-tests/devtools/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java index c3d57ffc3b799c..40b146208ddb5b 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java @@ -6,11 +6,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.quarkus.devtools.commands.CreateProject; -import io.quarkus.devtools.commands.CreateProjectTest; -import io.quarkus.devtools.commands.PlatformAwareTestBase; -import io.quarkus.devtools.commands.data.QuarkusCommandException; -import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -20,15 +15,22 @@ import java.nio.file.Paths; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; + import org.junit.jupiter.api.Test; +import io.quarkus.devtools.PlatformAwareTestBase; +import io.quarkus.devtools.ProjectTestUtil; +import io.quarkus.devtools.commands.CreateProject; +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; + class QuarkusProjectCompressTest extends PlatformAwareTestBase { @Test public void createZip() throws Exception { // Given a Quarkus project final Path testDir = Paths.get("target/zip"); - CreateProjectTest.delete(testDir.toFile()); + ProjectTestUtil.delete(testDir.toFile()); testDir.toFile().mkdirs(); Path zip = testDir.resolve("project.zip"); @@ -49,7 +51,7 @@ public void createZip() throws Exception { public void createZipWithParentFolder() throws Exception { // Given a Quarkus project final Path testDir = Paths.get("target/zip"); - CreateProjectTest.delete(testDir.toFile()); + ProjectTestUtil.delete(testDir.toFile()); testDir.toFile().mkdirs(); Path zip = testDir.resolve("project.zip"); diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index f0258f4b69c738..403d33e4ca0d65 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -29,6 +29,7 @@ common-jpa-entities infinispan-client infinispan-embedded + devtools gradle main kafka