diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java b/devtools/gradle/src/main/java/io/quarkus/gradle/ConnectorDependencyResolver.java similarity index 68% rename from devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java rename to devtools/gradle/src/main/java/io/quarkus/gradle/ConnectorDependencyResolver.java index 4b3e864bdbbe6..e7feb01cc9dea 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/ConnectorDependencyResolver.java @@ -1,6 +1,5 @@ package io.quarkus.gradle; -import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -14,30 +13,17 @@ import org.gradle.tooling.model.eclipse.EclipseExternalDependency; import org.gradle.tooling.model.eclipse.EclipseProject; -import io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile; -import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; - -public class GradleBuildFileFromConnector extends AbstractGradleBuildFile { +public final class ConnectorDependencyResolver { private List dependencies = null; - public GradleBuildFileFromConnector(final Path projectDirPath, final QuarkusPlatformDescriptor platformDescriptor) { - super(projectDirPath, platformDescriptor); - } - - public GradleBuildFileFromConnector(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor, - Path rootProjectPath) { - super(projectDirPath, platformDescriptor, rootProjectPath); - } - - @Override - public List getDependencies() throws IOException { + List getDependencies(String buildContent, Path projectDirPath) { if (dependencies == null) { EclipseProject eclipseProject = null; - if (getBuildContent() != null) { + if (buildContent != null) { try { ProjectConnection connection = GradleConnector.newConnector() - .forProjectDirectory(getProjectDirPath().toFile()) + .forProjectDirectory(projectDirPath.toFile()) .connect(); eclipseProject = connection.getModel(EclipseProject.class); } catch (BuildException e) { @@ -61,7 +47,6 @@ private Dependency gradleModuleVersionToDependency(EclipseExternalDependency eed Dependency dependency = new Dependency(); if (eed == null || eed.getGradleModuleVersion() == null) { // local dependencies are ignored - System.err.println("Found null dependency:" + eed); return null; } dependency.setGroupId(eed.getGradleModuleVersion().getGroup()); @@ -69,5 +54,4 @@ private Dependency gradleModuleVersionToDependency(EclipseExternalDependency eed dependency.setVersion(eed.getGradleModuleVersion().getVersion()); return dependency; } - } diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/GroovyBuildFileFromConnector.java b/devtools/gradle/src/main/java/io/quarkus/gradle/GroovyBuildFileFromConnector.java new file mode 100644 index 0000000000000..02d0e69316d9f --- /dev/null +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/GroovyBuildFileFromConnector.java @@ -0,0 +1,30 @@ +package io.quarkus.gradle; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +import org.apache.maven.model.Dependency; + +import io.quarkus.devtools.project.buildfile.AbstractGroovyGradleBuildFile; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + +public class GroovyBuildFileFromConnector extends AbstractGroovyGradleBuildFile { + + private final ConnectorDependencyResolver dependencyResolver = new ConnectorDependencyResolver(); + + public GroovyBuildFileFromConnector(final Path projectDirPath, final QuarkusPlatformDescriptor platformDescriptor) { + super(projectDirPath, platformDescriptor); + } + + public GroovyBuildFileFromConnector(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor, + Path rootProjectPath) { + super(projectDirPath, platformDescriptor, rootProjectPath); + } + + @Override + public List getDependencies() throws IOException { + return dependencyResolver.getDependencies(getBuildContent(), getProjectDirPath()); + } + +} diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/KotlinBuildFileFromConnector.java b/devtools/gradle/src/main/java/io/quarkus/gradle/KotlinBuildFileFromConnector.java new file mode 100644 index 0000000000000..75968d6b9d9d8 --- /dev/null +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/KotlinBuildFileFromConnector.java @@ -0,0 +1,29 @@ +package io.quarkus.gradle; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +import org.apache.maven.model.Dependency; + +import io.quarkus.devtools.project.buildfile.AbstractKotlinGradleBuildFile; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + +public class KotlinBuildFileFromConnector extends AbstractKotlinGradleBuildFile { + + private final ConnectorDependencyResolver dependencyResolver = new ConnectorDependencyResolver(); + + public KotlinBuildFileFromConnector(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor) { + super(projectDirPath, platformDescriptor); + } + + public KotlinBuildFileFromConnector(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor, + Path rootProjectPath) { + super(projectDirPath, platformDescriptor, rootProjectPath); + } + + @Override + public List getDependencies() throws IOException { + return dependencyResolver.getDependencies(getBuildContent(), getProjectDirPath()); + } +} diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusPlatformTask.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusPlatformTask.java index f85ac2ebe0efd..116f5a1ee9f96 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusPlatformTask.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusPlatformTask.java @@ -2,6 +2,7 @@ import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -15,7 +16,8 @@ import io.quarkus.devtools.project.QuarkusProject; import io.quarkus.devtools.project.buildfile.BuildFile; -import io.quarkus.gradle.GradleBuildFileFromConnector; +import io.quarkus.gradle.GroovyBuildFileFromConnector; +import io.quarkus.gradle.KotlinBuildFileFromConnector; import io.quarkus.platform.descriptor.CombinedQuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; @@ -71,9 +73,16 @@ protected QuarkusPlatformDescriptor platformDescriptor() { protected BuildFile getGradleBuildFile() { final Path projectDirPath = getProject().getProjectDir().toPath(); final Path rootProjectPath = getProject().getParent() != null ? getProject().getRootProject().getProjectDir().toPath() - : null; - return new GradleBuildFileFromConnector(projectDirPath, platformDescriptor(), - rootProjectPath); + : projectDirPath; + if (Files.exists(rootProjectPath.resolve("settings.gradle.kts")) + && Files.exists(projectDirPath.resolve("build.gradle.kts"))) { + return new KotlinBuildFileFromConnector(projectDirPath, platformDescriptor(), rootProjectPath); + } else if (Files.exists(rootProjectPath.resolve("settings.gradle")) + && Files.exists(projectDirPath.resolve("build.gradle"))) { + return new GroovyBuildFileFromConnector(projectDirPath, platformDescriptor(), rootProjectPath); + } + throw new GradleException( + "Mixed DSL is not supported. Both build and settings file need to use either Kotlin or Groovy DSL"); } @Internal diff --git a/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java b/devtools/gradle/src/test/java/io/quarkus/gradle/AbstractBuildFileTest.java similarity index 55% rename from devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java rename to devtools/gradle/src/test/java/io/quarkus/gradle/AbstractBuildFileTest.java index ea7457f191337..791f03c2fd3e0 100644 --- a/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java +++ b/devtools/gradle/src/test/java/io/quarkus/gradle/AbstractBuildFileTest.java @@ -5,38 +5,22 @@ import static org.junit.jupiter.api.Assertions.assertNull; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.maven.model.Dependency; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +abstract class AbstractBuildFileTest { -class GradleBuildFileTest { + abstract String getProperty(String propertyName) throws IOException; - private static GradleBuildFileFromConnector buildFile; - - @BeforeAll - public static void beforeAll() throws URISyntaxException { - URL url = GradleBuildFileTest.class.getClassLoader().getResource("gradle-project"); - URI uri = url.toURI(); - Path gradleProjectPath = Paths.get(uri); - final QuarkusPlatformDescriptor descriptor = Mockito.mock(QuarkusPlatformDescriptor.class); - buildFile = new GradleBuildFileFromConnector(gradleProjectPath, descriptor); - } + abstract List getDependencies() throws IOException; @Test void testGetDependencies() throws IOException { - List dependencies = buildFile.getDependencies(); + List dependencies = getDependencies(); assertThat(dependencies).isNotEmpty(); List depsString = new ArrayList<>(); for (Iterator depIter = dependencies.iterator(); depIter.hasNext();) { @@ -53,13 +37,13 @@ void testGetDependencies() throws IOException { @Test void testGetProperty() throws IOException { - assertNull(buildFile.getProperty("toto")); - assertEquals("0.23.2", buildFile.getProperty("quarkusVersion")); + assertNull(getProperty("toto")); + assertEquals("0.23.2", getProperty("quarkusVersion")); } @Test void testGetTestClosure() throws IOException { - assertNull(buildFile.getProperty("test")); + assertNull(getProperty("test")); } } diff --git a/devtools/gradle/src/test/java/io/quarkus/gradle/GroovyBuildFileTest.java b/devtools/gradle/src/test/java/io/quarkus/gradle/GroovyBuildFileTest.java new file mode 100644 index 0000000000000..7b6ae1482eb29 --- /dev/null +++ b/devtools/gradle/src/test/java/io/quarkus/gradle/GroovyBuildFileTest.java @@ -0,0 +1,40 @@ +package io.quarkus.gradle; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.model.Dependency; +import org.junit.jupiter.api.BeforeAll; +import org.mockito.Mockito; + +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + +class GroovyBuildFileTest extends AbstractBuildFileTest { + + private static GroovyBuildFileFromConnector buildFile; + + @BeforeAll + public static void beforeAll() throws URISyntaxException { + URL url = GroovyBuildFileTest.class.getClassLoader().getResource("gradle-project"); + URI uri = url.toURI(); + Path gradleProjectPath = Paths.get(uri); + final QuarkusPlatformDescriptor descriptor = Mockito.mock(QuarkusPlatformDescriptor.class); + buildFile = new GroovyBuildFileFromConnector(gradleProjectPath, descriptor); + } + + @Override + String getProperty(String propertyName) throws IOException { + return buildFile.getProperty(propertyName); + } + + @Override + List getDependencies() throws IOException { + return buildFile.getDependencies(); + } + +} diff --git a/devtools/gradle/src/test/java/io/quarkus/gradle/KotlinBuildFileTest.java b/devtools/gradle/src/test/java/io/quarkus/gradle/KotlinBuildFileTest.java new file mode 100644 index 0000000000000..a77b514cc2742 --- /dev/null +++ b/devtools/gradle/src/test/java/io/quarkus/gradle/KotlinBuildFileTest.java @@ -0,0 +1,40 @@ +package io.quarkus.gradle; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.model.Dependency; +import org.junit.jupiter.api.BeforeAll; +import org.mockito.Mockito; + +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; + +class KotlinBuildFileTest extends AbstractBuildFileTest { + + private static KotlinBuildFileFromConnector buildFile; + + @BeforeAll + public static void beforeAll() throws URISyntaxException { + URL url = KotlinBuildFileTest.class.getClassLoader().getResource("gradle-kts-project"); + URI uri = url.toURI(); + Path gradleProjectPath = Paths.get(uri); + final QuarkusPlatformDescriptor descriptor = Mockito.mock(QuarkusPlatformDescriptor.class); + buildFile = new KotlinBuildFileFromConnector(gradleProjectPath, descriptor); + } + + @Override + String getProperty(String propertyName) throws IOException { + return buildFile.getProperty(propertyName); + } + + @Override + List getDependencies() throws IOException { + return buildFile.getDependencies(); + } + +} diff --git a/devtools/gradle/src/test/resources/gradle-kts-project/build.gradle.kts b/devtools/gradle/src/test/resources/gradle-kts-project/build.gradle.kts new file mode 100644 index 0000000000000..a31be9ccd97d4 --- /dev/null +++ b/devtools/gradle/src/test/resources/gradle-kts-project/build.gradle.kts @@ -0,0 +1,35 @@ +plugins { + java +} + +repositories { + mavenLocal() + mavenCentral() +} + +val quarkusVersion: String by project + +dependencies { + implementation("io.quarkus:quarkus-jsonp") + implementation("io.quarkus:quarkus-jsonb") + constraints { + implementation("io.quarkus:quarkus-jsonb:0.10.0") { + because("to test constraints") + } + } + implementation(enforcedPlatform("io.quarkus:quarkus-bom:${quarkusVersion}")) + implementation("io.quarkus:quarkus-resteasy") + + testImplementation("io.quarkus:quarkus-junit5") + testImplementation("io.rest-assured:rest-assured") +} + +tasks { + test { + dependsOn("cleanTest") + useJUnitPlatform() + + // @NativeImageTest and JVM mode tests can't be mixed in the same run + setForkEvery(1) + } +} diff --git a/devtools/gradle/src/test/resources/gradle-kts-project/gradle.properties b/devtools/gradle/src/test/resources/gradle-kts-project/gradle.properties new file mode 100644 index 0000000000000..cc038fb4df04c --- /dev/null +++ b/devtools/gradle/src/test/resources/gradle-kts-project/gradle.properties @@ -0,0 +1 @@ +quarkusVersion = 0.23.2 \ No newline at end of file diff --git a/devtools/gradle/src/test/resources/gradle-kts-project/settings.gradle.kts b/devtools/gradle/src/test/resources/gradle-kts-project/settings.gradle.kts new file mode 100644 index 0000000000000..e69de29bb2d1d 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 d3f3f9a848f81..561553527c2b8 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java @@ -183,7 +183,7 @@ public void execute() throws MojoExecutionException { BuildTool buildToolEnum; try { - buildToolEnum = BuildTool.valueOf(buildTool.toUpperCase()); + buildToolEnum = BuildTool.findTool(buildTool); } catch (IllegalArgumentException e) { String validBuildTools = String.join(",", Arrays.asList(BuildTool.values()).stream().map(BuildTool::toString).collect(Collectors.toList())); @@ -204,11 +204,12 @@ public void execute() throws MojoExecutionException { } success = createProject.execute().isSuccess(); + if (!codestartsEnabled) { File createdDependenciesBuildFile = new File(projectRoot, buildToolEnum.getDependenciesFile()); if (BuildTool.MAVEN.equals(buildToolEnum)) { createMavenWrapper(createdDependenciesBuildFile, ToolsUtils.readQuarkusProperties(platform)); - } else if (BuildTool.GRADLE.equals(buildToolEnum)) { + } else if (BuildTool.GRADLE.equals(buildToolEnum) || BuildTool.GRADLE_KOTLIN_DSL.equals(buildToolEnum)) { createGradleWrapper(platform, projectDirPath); } } diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/..gitignore b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/..gitignore new file mode 100644 index 0000000000000..ace4d3dd9713d --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/..gitignore @@ -0,0 +1,3 @@ +# Gradle +.gradle/ +build/ \ No newline at end of file diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/build-layout.include.qute b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/build-layout.include.qute new file mode 100644 index 0000000000000..77fb62af899b4 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/build-layout.include.qute @@ -0,0 +1,46 @@ +{#insert plugins} +plugins { + id("{quarkus.plugin.id}") +} +{/} + +{#insert repositories} +repositories { + mavenLocal() + mavenCentral() +} +{/} + +{#insert dependencies} +val quarkusPlatformGroupId: String by project +val quarkusPlatformArtifactId: String by project +val quarkusPlatformVersion: String by project + +dependencies { + implementation(enforcedPlatform("$\{quarkusPlatformGroupId}:$\{quarkusPlatformArtifactId}:$\{quarkusPlatformVersion}")) +{#for dep in dependencies} + implementation("{dep}") +{/for} + testImplementation("io.quarkus:quarkus-junit5") +{#for dep in test-dependencies} + testImplementation("{dep}") +{/for} +} +{/} + +{#insert project} +group = "{project.group-id}" +version = "{project.version}" +{/} + +{#insert java} +java { + {#if java.version == "11"} + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + {#else} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {/if} +} +{/} diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/gradle.tpl.qute.properties b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/gradle.tpl.qute.properties new file mode 100644 index 0000000000000..72c7052dddd09 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/gradle.tpl.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/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/settings.tpl.qute.gradle.kts b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/settings.tpl.qute.gradle.kts new file mode 100644 index 0000000000000..0c69b3f424cb4 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/base/settings.tpl.qute.gradle.kts @@ -0,0 +1,12 @@ +pluginManagement { + val quarkusPluginVersion: String by settings + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + plugins { + id("io.quarkus") version quarkusPluginVersion + } +} +rootProject.name="{project.artifact-id}" diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/codestart.yml b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/codestart.yml new file mode 100644 index 0000000000000..df9e122c8d577 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/codestart.yml @@ -0,0 +1,28 @@ +name: gradle-kotlin-dsl +type: buildtool +language: + base: + data: + quarkus: + plugin: + id: io.quarkus + version: + kotlin: 1.3.72 + scala: 2.12.8 + shared-data: + buildtool: + build-dir: build + guide: https://quarkus.io/guides/gradle-tooling + guide-native: https://quarkus.io/guides/gradle-tooling#building-a-native-executable + cmd: + dev: ./gradlew quarkusDev + package: ./gradlew quarkusBuild + package-uberjar: ./gradlew quarkusBuild --uber-jar + package-native: ./gradlew build -Dquarkus.package.type=native + package-native-container: ./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true + kotlin: + dependencies: + - org.jetbrains.kotlin:kotlin-stdlib-jdk8 + scala: + dependencies: + - org.scala-lang:scala-library diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/java/build.tpl.qute.gradle.kts b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/java/build.tpl.qute.gradle.kts new file mode 100644 index 0000000000000..1fa940f2319bb --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/java/build.tpl.qute.gradle.kts @@ -0,0 +1,13 @@ +{#include build-layout} +{#plugins} +plugins { + java + id("{quarkus.plugin.id}") +} +{/plugins} +{/include} + +tasks.withType { + options.encoding = "UTF-8" + options.compilerArgs.add("-parameters") +} diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/kotlin/build.tpl.qute.gradle.kts b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/kotlin/build.tpl.qute.gradle.kts new file mode 100644 index 0000000000000..553970c74acd2 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/kotlin/build.tpl.qute.gradle.kts @@ -0,0 +1,32 @@ +{#include build-layout} +{#plugins} +plugins { + kotlin("jvm") version "{version.kotlin}" + kotlin("plugin.allopen") version "{version.kotlin}" + id("{quarkus.plugin.id}") +} +{/plugins} +{/include} + +quarkus { + setOutputDirectory("$projectDir/build/classes/kotlin/main") +} + +tasks.withType { + setSourceDir("$projectDir/src/main/kotlin") +} + +allOpen { + annotation("javax.ws.rs.Path") + annotation("javax.enterprise.context.ApplicationScoped") + annotation("io.quarkus.test.junit.QuarkusTest") +} + +tasks.withType { + {#if java.version == "11"} + kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString() + {#else} + kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() + {/if} + kotlinOptions.javaParameters = true +} diff --git a/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/scala/build.tpl.qute.gradle.kts b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/scala/build.tpl.qute.gradle.kts new file mode 100644 index 0000000000000..9564058a8f960 --- /dev/null +++ b/devtools/platform-descriptor-json/src/main/resources/bundled-codestarts/buildtool/gradle-kotlin-dsl/scala/build.tpl.qute.gradle.kts @@ -0,0 +1,19 @@ +{#include build-layout} +{#plugins} +plugins { + scala + id("{quarkus.plugin.id}") +} + {/plugins} +{/include} + +tasks.withType { + scalaCompileOptions.encoding = "UTF-8" + {#if java.version == "11"} + sourceCompatibility = JavaVersion.VERSION_11.toString() + targetCompatibility = JavaVersion.VERSION_11.toString() + {#else} + sourceCompatibility = JavaVersion.VERSION_1_8.toString() + targetCompatibility = JavaVersion.VERSION_1_8.toString() + {/if} +} 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 da587172367ad..17ffde09d9b23 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 @@ -16,7 +16,8 @@ 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.buildfile.GroovyGradleBuildFilesCreator; +import io.quarkus.devtools.project.buildfile.KotlinGradleBuildFilesCreator; import io.quarkus.devtools.project.codegen.ProjectGenerator; import io.quarkus.devtools.project.codegen.ProjectGeneratorRegistry; import io.quarkus.devtools.project.codegen.SourceType; @@ -65,7 +66,7 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws .addExtensions(extensionsToAdd) .addData(CodestartData.LegacySupport.convertFromLegacy(invocation.getValues())) .putData(CodestartData.DataKey.BUILDTOOL.getKey(), - invocation.getQuarkusProject().getBuildTool().toString().toLowerCase()) + invocation.getQuarkusProject().getBuildTool().toString().toLowerCase().replace("_", "-")) .includeExamples(invocation.getValue("codestarts.with-example-code", true)) .build(); invocation.log().info("Generating Quarkus Codestart Project with data: " + input.getData().toString()); @@ -103,7 +104,17 @@ 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 generator = new GradleBuildFilesCreator(invocation.getQuarkusProject()); + final GroovyGradleBuildFilesCreator generator = new GroovyGradleBuildFilesCreator( + invocation.getQuarkusProject()); + generator.create( + invocation.getStringValue(PROJECT_GROUP_ID), + invocation.getStringValue(PROJECT_ARTIFACT_ID), + invocation.getStringValue(PROJECT_VERSION), + quarkusProps, + extensionsToAdd); + } else if (invocation.getQuarkusProject().getBuildTool().equals(BuildTool.GRADLE_KOTLIN_DSL)) { + final KotlinGradleBuildFilesCreator generator = new KotlinGradleBuildFilesCreator( + invocation.getQuarkusProject()); generator.create( invocation.getStringValue(PROJECT_GROUP_ID), invocation.getStringValue(PROJECT_ARTIFACT_ID), diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java index 76ff92b02ee4b..6b042a433f2cd 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java @@ -78,8 +78,10 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws platformExtensions.forEach(platformExtension -> display(log, platformExtension, installedByKey.get(toKey(platformExtension)), all, currentFormatter)); final BuildTool buildTool = invocation.getQuarkusProject().getBuildTool(); + boolean isGradle = BuildTool.GRADLE.equals(buildTool) || BuildTool.GRADLE_KOTLIN_DSL.equals(buildTool); + if ("concise".equalsIgnoreCase(format)) { - if (BuildTool.GRADLE.equals(buildTool)) { + if (isGradle) { log.info("\nTo get more information, append --format=full to your command line."); } else { log.info( @@ -87,7 +89,7 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws } } - if (BuildTool.GRADLE.equals(buildTool)) { + if (isGradle) { log.info("\nAdd an extension to your project by adding the dependency to your " + "build.gradle or use `./gradlew addExtension --extensions=\"artifactId\"`"); } else { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/BuildTool.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/BuildTool.java index f4bb1b3d98a5f..fd45b6642c4b5 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/BuildTool.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/BuildTool.java @@ -1,6 +1,7 @@ package io.quarkus.devtools.project; -import io.quarkus.devtools.project.buildfile.GenericGradleBuildFile; +import io.quarkus.devtools.project.buildfile.GroovyGradleBuildFile; +import io.quarkus.devtools.project.buildfile.KotlinGradleBuildFile; import io.quarkus.devtools.project.buildfile.MavenBuildFile; import io.quarkus.devtools.project.extensions.ExtensionManager; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; @@ -19,7 +20,12 @@ public enum BuildTool { /** Gradle build tool */ GRADLE("\n# Gradle\n.gradle/\nbuild/", "build", - new String[] { "build.gradle", "settings.gradle", "gradle.properties" }); + new String[] { "build.gradle", "settings.gradle", "gradle.properties" }), + + /** Gradle build tool with Kotlin DSL */ + GRADLE_KOTLIN_DSL("\n# Gradle\n.gradle/\nbuild/", + "build", + new String[] { "build.gradle.kts", "settings.gradle.kts", "gradle.properties" }); private final String gitIgnoreEntries; @@ -56,7 +62,9 @@ public ExtensionManager createExtensionManager(final Path projectDirPath, final QuarkusPlatformDescriptor platformDescriptor) { switch (this) { case GRADLE: - return new GenericGradleBuildFile(); + return new GroovyGradleBuildFile(); + case GRADLE_KOTLIN_DSL: + return new KotlinGradleBuildFile(); case MAVEN: default: return new MavenBuildFile(projectDirPath, platformDescriptor); @@ -70,6 +78,8 @@ public static BuildTool resolveExistingProject(Path path) { public static BuildTool findTool(String tool) { if ("GRADLE".equalsIgnoreCase(tool)) return GRADLE; + else if ("GRADLE_KOTLIN_DSL".equalsIgnoreCase(tool) || "gradle-kotlin-dsl".equalsIgnoreCase(tool)) + return GRADLE_KOTLIN_DSL; else if ("MAVEN".equalsIgnoreCase(tool)) return MAVEN; else diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java index dac22e0692daa..976040c3a961e 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java @@ -64,9 +64,10 @@ public QuarkusPlatformDescriptor getPlatformDescriptor() { public static BuildTool resolveExistingProjectBuildTool(Path projectDirPath) { if (projectDirPath.resolve("pom.xml").toFile().exists()) { return BuildTool.MAVEN; - } else if (projectDirPath.resolve("build.gradle").toFile().exists() - || projectDirPath.resolve("build.gradle.kts").toFile().exists()) { + } else if (projectDirPath.resolve("build.gradle").toFile().exists()) { return BuildTool.GRADLE; + } else if (projectDirPath.resolve("build.gradle.kts").toFile().exists()) { + return BuildTool.GRADLE_KOTLIN_DSL; } return null; } 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 bde532c250b06..5a0e051ca1602 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 @@ -2,7 +2,6 @@ import io.quarkus.bootstrap.model.AppArtifactCoords; import io.quarkus.bootstrap.model.AppArtifactKey; -import io.quarkus.devtools.project.BuildTool; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -11,15 +10,14 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Objects; import java.util.Properties; import java.util.Scanner; import java.util.concurrent.atomic.AtomicReference; // We keep it here to take advantage of the abstract tests -public abstract class AbstractGradleBuildFile extends BuildFile { +abstract class AbstractGradleBuildFile extends BuildFile { - private static final String BUILD_GRADLE_PATH = "build.gradle"; - private static final String SETTINGS_GRADLE_PATH = "settings.gradle"; private static final String GRADLE_PROPERTIES_PATH = "gradle.properties"; private final Path rootProjectPath; @@ -36,74 +34,64 @@ public AbstractGradleBuildFile(final Path projectDirPath, final QuarkusPlatformD this.rootProjectPath = rootProjectPath; } + abstract String getSettingsGradlePath(); + + abstract String getBuildGradlePath(); + @Override public void writeToDisk() throws IOException { if (rootProjectPath != null) { - Files.write(rootProjectPath.resolve(SETTINGS_GRADLE_PATH), getModel().getRootSettingsContent().getBytes()); + Files.write(rootProjectPath.resolve(getSettingsGradlePath()), getModel().getRootSettingsContent().getBytes()); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { getModel().getRootPropertiesContent().store(out, "Gradle properties"); Files.write(rootProjectPath.resolve(GRADLE_PROPERTIES_PATH), out.toByteArray()); } } else { - writeToProjectFile(SETTINGS_GRADLE_PATH, getModel().getSettingsContent().getBytes()); + writeToProjectFile(getSettingsGradlePath(), getModel().getSettingsContent().getBytes()); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { getModel().getPropertiesContent().store(out, "Gradle properties"); writeToProjectFile(GRADLE_PROPERTIES_PATH, out.toByteArray()); } } - writeToProjectFile(BUILD_GRADLE_PATH, getModel().getBuildContent().getBytes()); - } - - @Override - protected boolean addDependency(AppArtifactCoords coords, boolean managed) { - return addDependencyInModel(getModel(), coords, managed); + writeToProjectFile(getBuildGradlePath(), getModel().getBuildContent().getBytes()); } - static boolean addDependencyInModel(Model model, AppArtifactCoords coords, boolean managed) { + static String createDependencyCoordinatesString(Model model, AppArtifactCoords coords, boolean managed, char quoteChar) { boolean isBOM = "pom".equals(coords.getType()); - StringBuilder newDependency; - if (isBOM) { - // Check if BOM is not included already - String resolvedPlatform = String - .format("%s:%s", getProperty(model, "quarkusPlatformGroupId"), - getProperty(model, "quarkusPlatformArtifactId")); - String thisBOM = String.format("%s:%s", coords.getGroupId(), coords.getArtifactId()); - if (thisBOM.equals(resolvedPlatform)) { - // BOM matches the platform, no need to do anything - return false; - } - newDependency = new StringBuilder() - .append(" implementation enforcedPlatform(\"") - .append(thisBOM).append(":").append(coords.getVersion()) - .append("\")'"); - } else { - newDependency = new StringBuilder() - .append(" implementation '") - .append(coords.getGroupId()) - .append(":") - .append(coords.getArtifactId()); - } + // Special case for platform dependency. We will create properties based dependency string. + // It will be ignored if it is already in "dependencies" section. + // Note that we ignore version here - if someone tries to add platform with different version, we will still use + // version from properties. + if (isBOM && !managed + && Objects.equals(coords.getGroupId(), getProperty(model, "quarkusPlatformGroupId")) + && Objects.equals(coords.getArtifactId(), getProperty(model, "quarkusPlatformArtifactId"))) { + return "enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}\")"; + } + StringBuilder newDependency = new StringBuilder().append(quoteChar) + .append(coords.getGroupId()).append(":").append(coords.getArtifactId()); if (!managed && (coords.getVersion() != null && !coords.getVersion().isEmpty())) { newDependency.append(":").append(coords.getVersion()); } - newDependency.append("'").append(System.lineSeparator()); - String newDependencyString = newDependency.toString(); + return newDependency.append(quoteChar).toString(); + } + + static boolean addDependencyInModel(Model model, String newDependency) { StringBuilder buildContent = new StringBuilder(model.getBuildContent()); boolean changed = false; - if (buildContent.indexOf(newDependencyString) == -1) { + if (buildContent.indexOf(newDependency) == -1) { changed = true; // Add dependency after "dependencies {" int indexOfDeps = buildContent.indexOf("dependencies {"); if (indexOfDeps > -1) { // The line below fails on Windows if System.lineSeparator() is used int nextLine = buildContent.indexOf("\n", indexOfDeps) + 1; - buildContent.insert(nextLine, newDependencyString); + buildContent.insert(nextLine, newDependency); } else { // if no "dependencies {" found, add one buildContent.append("dependencies {").append(System.lineSeparator()) - .append(newDependencyString) + .append(newDependency) .append("}").append(System.lineSeparator()); } model.setBuildContent(buildContent.toString()); @@ -111,6 +99,14 @@ static boolean addDependencyInModel(Model model, AppArtifactCoords coords, boole return changed; } + static String getProperty(Model model, String propertyName) { + final String property = model.getPropertiesContent().getProperty(propertyName); + if (property != null || model.getRootPropertiesContent() == null) { + return property; + } + return model.getRootPropertiesContent().getProperty(propertyName); + } + @Override protected void removeDependency(AppArtifactKey key) { StringBuilder newBuildContent = new StringBuilder(); @@ -130,20 +126,7 @@ public String getProperty(String propertyName) { return getProperty(getModel(), propertyName); } - @Override - public BuildTool getBuildTool() { - return BuildTool.GRADLE; - } - - static String getProperty(Model model, String propertyName) { - final String property = model.getPropertiesContent().getProperty(propertyName); - if (property != null || model.getRootPropertiesContent() == null) { - return property; - } - return model.getRootPropertiesContent().getProperty(propertyName); - } - - private Model getModel() { + Model getModel() { return modelReference.updateAndGet(model -> { if (model == null) { try { @@ -183,16 +166,16 @@ private Model readModel() throws IOException { Properties propertiesContent = new Properties(); String rootSettingsContent = null; Properties rootPropertiesContent = null; - if (hasProjectFile(SETTINGS_GRADLE_PATH)) { - final byte[] settings = readProjectFile(SETTINGS_GRADLE_PATH); + if (hasProjectFile(getSettingsGradlePath())) { + final byte[] settings = readProjectFile(getSettingsGradlePath()); settingsContent = new String(settings, StandardCharsets.UTF_8); } - if (hasRootProjectFile(SETTINGS_GRADLE_PATH)) { - final byte[] settings = readRootProjectFile(SETTINGS_GRADLE_PATH); + if (hasRootProjectFile(getSettingsGradlePath())) { + final byte[] settings = readRootProjectFile(getSettingsGradlePath()); rootSettingsContent = new String(settings, StandardCharsets.UTF_8); } - if (hasProjectFile(BUILD_GRADLE_PATH)) { - final byte[] build = readProjectFile(BUILD_GRADLE_PATH); + if (hasProjectFile(getBuildGradlePath())) { + final byte[] build = readProjectFile(getBuildGradlePath()); buildContent = new String(build, StandardCharsets.UTF_8); } if (hasProjectFile(GRADLE_PROPERTIES_PATH)) { 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/buildfile/AbstractGradleBuildFilesCreator.java similarity index 50% 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/buildfile/AbstractGradleBuildFilesCreator.java index 83488c6549bb7..d9d0c6faee1f6 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/buildfile/AbstractGradleBuildFilesCreator.java @@ -1,7 +1,5 @@ package io.quarkus.devtools.project.buildfile; -import static io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile.addDependencyInModel; - import io.quarkus.bootstrap.model.AppArtifactCoords; import io.quarkus.devtools.project.QuarkusProject; import io.quarkus.devtools.project.buildfile.AbstractGradleBuildFile.Model; @@ -18,19 +16,27 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; -public final class GradleBuildFilesCreator { +abstract class AbstractGradleBuildFilesCreator { - private static final String BUILD_GRADLE_PATH = "build.gradle"; - private static final String SETTINGS_GRADLE_PATH = "settings.gradle"; private static final String GRADLE_PROPERTIES_PATH = "gradle.properties"; private final QuarkusProject quarkusProject; private AtomicReference modelReference = new AtomicReference<>(); - public GradleBuildFilesCreator(QuarkusProject quarkusProject) { + public AbstractGradleBuildFilesCreator(QuarkusProject quarkusProject) { this.quarkusProject = quarkusProject; } + abstract String getSettingsGradlePath(); + + abstract String getBuildGradlePath(); + + abstract void createBuildContent(String groupId, String version) throws IOException; + + abstract void createSettingsContent(String artifactId) throws IOException; + + abstract void addDependencyInBuildFile(AppArtifactCoords coords) throws IOException; + public void create(String groupId, String artifactId, String version, Properties properties, List extensions) throws IOException { createSettingsContent(artifactId); @@ -47,18 +53,14 @@ public void create(String groupId, String artifactId, String version, } private void writeToDisk() throws IOException { - writeToProjectFile(SETTINGS_GRADLE_PATH, getModel().getSettingsContent().getBytes()); - writeToProjectFile(BUILD_GRADLE_PATH, getModel().getBuildContent().getBytes()); + writeToProjectFile(getSettingsGradlePath(), getModel().getSettingsContent().getBytes()); + writeToProjectFile(getBuildGradlePath(), getModel().getBuildContent().getBytes()); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { getModel().getPropertiesContent().store(out, "Gradle properties"); writeToProjectFile(GRADLE_PROPERTIES_PATH, out.toByteArray()); } } - private void addDependencyInBuildFile(AppArtifactCoords coords) throws IOException { - addDependencyInModel(getModel(), coords, false); - } - protected boolean containsBOM(String groupId, String artifactId) throws IOException { String buildContent = getModel().getBuildContent(); return buildContent.contains("enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:") @@ -69,7 +71,11 @@ public String getProperty(String propertyName) throws IOException { return getModel().getPropertiesContent().getProperty(propertyName); } - private Model getModel() throws IOException { + QuarkusProject getQuarkusProject() { + return quarkusProject; + } + + Model getModel() throws IOException { return modelReference.updateAndGet(model -> { if (model == null) { try { @@ -86,12 +92,12 @@ private Model readModel() throws IOException { String settingsContent = ""; String buildContent = ""; Properties propertiesContent = new Properties(); - if (hasProjectFile(SETTINGS_GRADLE_PATH)) { - final byte[] settings = readProjectFile(SETTINGS_GRADLE_PATH); + if (hasProjectFile(getSettingsGradlePath())) { + final byte[] settings = readProjectFile(getSettingsGradlePath()); settingsContent = new String(settings, StandardCharsets.UTF_8); } - if (hasProjectFile(BUILD_GRADLE_PATH)) { - final byte[] build = readProjectFile(BUILD_GRADLE_PATH); + if (hasProjectFile(getBuildGradlePath())) { + final byte[] build = readProjectFile(getBuildGradlePath()); buildContent = new String(build, StandardCharsets.UTF_8); } if (hasProjectFile(GRADLE_PROPERTIES_PATH)) { @@ -115,73 +121,6 @@ protected void writeToProjectFile(final String fileName, final byte[] content) t Files.write(quarkusProject.getProjectDirPath().resolve(fileName), content); } - private void createBuildContent(String groupId, String version) - throws IOException { - final String buildContent = getModel().getBuildContent(); - StringBuilder res = new StringBuilder(buildContent); - if (!buildContent.contains("id 'io.quarkus'")) { - res.append("plugins {"); - res.append(System.lineSeparator()).append(" id 'java'").append(System.lineSeparator()); - res.append(System.lineSeparator()).append(" id 'io.quarkus'").append(System.lineSeparator()); - res.append("}"); - } - if (!containsBOM(quarkusProject.getPlatformDescriptor().getBomGroupId(), - quarkusProject.getPlatformDescriptor().getBomArtifactId())) { - res.append(System.lineSeparator()); - res.append("dependencies {").append(System.lineSeparator()); - res.append( - " implementation enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}\")") - .append(System.lineSeparator()); - res.append(" implementation 'io.quarkus:quarkus-resteasy'").append(System.lineSeparator()); - res.append(" testImplementation 'io.quarkus:quarkus-junit5'").append(System.lineSeparator()); - res.append(" testImplementation 'io.rest-assured:rest-assured'").append(System.lineSeparator()); - res.append("}").append(System.lineSeparator()); - - } - String groupLine = "group '" + groupId + "'"; - if (!buildContent.contains(groupLine)) { - res.append(System.lineSeparator()).append(groupLine) - .append(System.lineSeparator()); - } - String versionLine = "version '" + version + "'"; - if (!buildContent.contains(versionLine)) { - res.append(System.lineSeparator()).append(versionLine) - .append(System.lineSeparator()); - } - - res.append(System.lineSeparator()) - .append("test {").append(System.lineSeparator()) - .append(" systemProperty \"java.util.logging.manager\", \"org.jboss.logmanager.LogManager\"") - .append(System.lineSeparator()) - .append("}"); - - getModel().setBuildContent(res.toString()); - } - - private void createSettingsContent(String artifactId) throws IOException { - final String settingsContent = getModel().getSettingsContent(); - final StringBuilder res = new StringBuilder(); - if (!settingsContent.contains("id 'io.quarkus'")) { - res.append(System.lineSeparator()); - res.append("pluginManagement {").append(System.lineSeparator()); - res.append(" repositories {").append(System.lineSeparator()); - res.append(" mavenLocal()").append(System.lineSeparator()); - res.append(" mavenCentral()").append(System.lineSeparator()); - res.append(" gradlePluginPortal()").append(System.lineSeparator()); - res.append(" }").append(System.lineSeparator()); - res.append(" plugins {").append(System.lineSeparator()); - res.append(" id 'io.quarkus' version \"${quarkusPluginVersion}\"").append(System.lineSeparator()); - res.append(" }").append(System.lineSeparator()); - res.append("}").append(System.lineSeparator()); - } - if (!settingsContent.contains("rootProject.name")) { - res.append(System.lineSeparator()).append("rootProject.name='").append(artifactId).append("'") - .append(System.lineSeparator()); - } - res.append(settingsContent); - getModel().setSettingsContent(res.toString()); - } - private void createProperties() throws IOException { final QuarkusPlatformDescriptor platform = quarkusProject.getPlatformDescriptor(); Properties props = getModel().getPropertiesContent(); diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGroovyGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGroovyGradleBuildFile.java new file mode 100644 index 0000000000000..ba090e6867dfe --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractGroovyGradleBuildFile.java @@ -0,0 +1,46 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import java.nio.file.Path; + +public abstract class AbstractGroovyGradleBuildFile extends AbstractGradleBuildFile { + + static final String BUILD_GRADLE_PATH = "build.gradle"; + static final String SETTINGS_GRADLE_PATH = "settings.gradle"; + + public AbstractGroovyGradleBuildFile(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor) { + super(projectDirPath, platformDescriptor); + } + + public AbstractGroovyGradleBuildFile(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor, + Path rootProjectPath) { + super(projectDirPath, platformDescriptor, rootProjectPath); + } + + @Override + String getSettingsGradlePath() { + return SETTINGS_GRADLE_PATH; + } + + @Override + String getBuildGradlePath() { + return BUILD_GRADLE_PATH; + } + + @Override + protected boolean addDependency(AppArtifactCoords coords, boolean managed) { + return addDependencyInModel(getModel(), coords, managed); + } + + @Override + public BuildTool getBuildTool() { + return BuildTool.GRADLE; + } + + static boolean addDependencyInModel(Model model, AppArtifactCoords coords, boolean managed) { + return addDependencyInModel(model, + String.format(" implementation %s%n", createDependencyCoordinatesString(model, coords, managed, '\''))); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractKotlinGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractKotlinGradleBuildFile.java new file mode 100644 index 0000000000000..f8056c8855819 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/AbstractKotlinGradleBuildFile.java @@ -0,0 +1,47 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import java.nio.file.Path; + +public abstract class AbstractKotlinGradleBuildFile extends AbstractGradleBuildFile { + + static final String BUILD_GRADLE_PATH = "build.gradle.kts"; + static final String SETTINGS_GRADLE_PATH = "settings.gradle.kts"; + + public AbstractKotlinGradleBuildFile(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor) { + super(projectDirPath, platformDescriptor); + } + + public AbstractKotlinGradleBuildFile(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor, + Path rootProjectPath) { + super(projectDirPath, platformDescriptor, rootProjectPath); + } + + @Override + String getSettingsGradlePath() { + return SETTINGS_GRADLE_PATH; + } + + @Override + String getBuildGradlePath() { + return BUILD_GRADLE_PATH; + } + + @Override + protected boolean addDependency(AppArtifactCoords coords, boolean managed) { + return addDependencyInModel(getModel(), coords, managed); + } + + @Override + public BuildTool getBuildTool() { + return BuildTool.GRADLE_KOTLIN_DSL; + } + + static boolean addDependencyInModel(Model model, AppArtifactCoords coords, boolean managed) { + return addDependencyInModel(model, + String.format(" implementation(%s)%n", createDependencyCoordinatesString(model, coords, managed, '"'))); + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GenericGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GenericGradleBuildFile.java index 9a07d5ef77d1d..3a4c239aa4461 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GenericGradleBuildFile.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GenericGradleBuildFile.java @@ -2,7 +2,6 @@ import io.quarkus.bootstrap.model.AppArtifactCoords; import io.quarkus.bootstrap.model.AppArtifactKey; -import io.quarkus.devtools.project.BuildTool; import io.quarkus.devtools.project.extensions.ExtensionInstallPlan; import io.quarkus.devtools.project.extensions.ExtensionManager; import java.io.IOException; @@ -11,12 +10,7 @@ /** * TODO We need to find a way to use the gradle api outside of a gradle plugin */ -public class GenericGradleBuildFile implements ExtensionManager { - - @Override - public BuildTool getBuildTool() { - return BuildTool.GRADLE; - } +abstract class GenericGradleBuildFile implements ExtensionManager { @Override public Collection getInstalled() throws IOException { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFile.java new file mode 100644 index 0000000000000..3f3e57522f8f7 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFile.java @@ -0,0 +1,12 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.devtools.project.BuildTool; + +public class GroovyGradleBuildFile extends GenericGradleBuildFile { + + @Override + public BuildTool getBuildTool() { + return BuildTool.GRADLE; + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFilesCreator.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFilesCreator.java new file mode 100644 index 0000000000000..e825a78b299c3 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/GroovyGradleBuildFilesCreator.java @@ -0,0 +1,96 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.devtools.project.QuarkusProject; +import java.io.IOException; + +public final class GroovyGradleBuildFilesCreator extends AbstractGradleBuildFilesCreator { + + public GroovyGradleBuildFilesCreator(QuarkusProject quarkusProject) { + super(quarkusProject); + } + + @Override + String getSettingsGradlePath() { + return AbstractGroovyGradleBuildFile.SETTINGS_GRADLE_PATH; + } + + @Override + String getBuildGradlePath() { + return AbstractGroovyGradleBuildFile.BUILD_GRADLE_PATH; + } + + @Override + void createBuildContent(String groupId, String version) throws IOException { + final String buildContent = getModel().getBuildContent(); + StringBuilder res = new StringBuilder(buildContent); + if (!buildContent.contains("id 'io.quarkus'")) { + res.append("plugins {"); + res.append(System.lineSeparator()).append(" id 'java'").append(System.lineSeparator()); + res.append(System.lineSeparator()).append(" id 'io.quarkus'").append(System.lineSeparator()); + res.append("}"); + } + if (!containsBOM(getQuarkusProject().getPlatformDescriptor().getBomGroupId(), + getQuarkusProject().getPlatformDescriptor().getBomArtifactId())) { + res.append(System.lineSeparator()); + res.append("dependencies {").append(System.lineSeparator()); + res.append( + " implementation enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}\")") + .append(System.lineSeparator()); + res.append(" implementation 'io.quarkus:quarkus-resteasy'").append(System.lineSeparator()); + res.append(" testImplementation 'io.quarkus:quarkus-junit5'").append(System.lineSeparator()); + res.append(" testImplementation 'io.rest-assured:rest-assured'").append(System.lineSeparator()); + res.append("}").append(System.lineSeparator()); + + } + String groupLine = "group '" + groupId + "'"; + if (!buildContent.contains(groupLine)) { + res.append(System.lineSeparator()).append(groupLine) + .append(System.lineSeparator()); + } + String versionLine = "version '" + version + "'"; + if (!buildContent.contains(versionLine)) { + res.append(System.lineSeparator()).append(versionLine) + .append(System.lineSeparator()); + } + + res.append(System.lineSeparator()) + .append("test {").append(System.lineSeparator()) + .append(" systemProperty \"java.util.logging.manager\", \"org.jboss.logmanager.LogManager\"") + .append(System.lineSeparator()) + .append("}"); + + getModel().setBuildContent(res.toString()); + } + + @Override + void createSettingsContent(String artifactId) throws IOException { + final String settingsContent = getModel().getSettingsContent(); + final StringBuilder res = new StringBuilder(); + if (!settingsContent.contains("id 'io.quarkus'")) { + res.append(System.lineSeparator()); + res.append("pluginManagement {").append(System.lineSeparator()); + res.append(" repositories {").append(System.lineSeparator()); + res.append(" mavenLocal()").append(System.lineSeparator()); + res.append(" mavenCentral()").append(System.lineSeparator()); + res.append(" gradlePluginPortal()").append(System.lineSeparator()); + res.append(" }").append(System.lineSeparator()); + res.append(" plugins {").append(System.lineSeparator()); + res.append(" id 'io.quarkus' version \"${quarkusPluginVersion}\"").append(System.lineSeparator()); + res.append(" }").append(System.lineSeparator()); + res.append("}").append(System.lineSeparator()); + } + if (!settingsContent.contains("rootProject.name")) { + res.append(System.lineSeparator()).append("rootProject.name='").append(artifactId).append("'") + .append(System.lineSeparator()); + } + res.append(settingsContent); + getModel().setSettingsContent(res.toString()); + } + + @Override + void addDependencyInBuildFile(AppArtifactCoords coords) throws IOException { + AbstractGroovyGradleBuildFile.addDependencyInModel(getModel(), coords, false); + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFile.java new file mode 100644 index 0000000000000..059c6b029aaf1 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFile.java @@ -0,0 +1,12 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.devtools.project.BuildTool; + +public class KotlinGradleBuildFile extends GenericGradleBuildFile { + + @Override + public BuildTool getBuildTool() { + return BuildTool.GRADLE_KOTLIN_DSL; + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFilesCreator.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFilesCreator.java new file mode 100644 index 0000000000000..679a9d2792745 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/KotlinGradleBuildFilesCreator.java @@ -0,0 +1,96 @@ +package io.quarkus.devtools.project.buildfile; + +import io.quarkus.bootstrap.model.AppArtifactCoords; +import io.quarkus.devtools.project.QuarkusProject; +import java.io.IOException; + +public class KotlinGradleBuildFilesCreator extends AbstractGradleBuildFilesCreator { + + public KotlinGradleBuildFilesCreator(QuarkusProject quarkusProject) { + super(quarkusProject); + } + + @Override + String getSettingsGradlePath() { + return AbstractKotlinGradleBuildFile.SETTINGS_GRADLE_PATH; + } + + @Override + String getBuildGradlePath() { + return AbstractKotlinGradleBuildFile.BUILD_GRADLE_PATH; + } + + @Override + void createBuildContent(String groupId, String version) throws IOException { + final String buildContent = getModel().getBuildContent(); + StringBuilder res = new StringBuilder(buildContent); + if (!buildContent.contains("id(\"io.quarkus\")")) { + res.append("plugins {"); + res.append(System.lineSeparator()).append(" java").append(System.lineSeparator()); + res.append(System.lineSeparator()).append(" id(\"io.quarkus\")").append(System.lineSeparator()); + res.append("}"); + } + if (!containsBOM(getQuarkusProject().getPlatformDescriptor().getBomGroupId(), + getQuarkusProject().getPlatformDescriptor().getBomArtifactId())) { + res.append(System.lineSeparator()); + res.append("dependencies {").append(System.lineSeparator()); + res.append( + " implementation(enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}\"))") + .append(System.lineSeparator()); + res.append(" implementation(\"io.quarkus:quarkus-resteasy\")").append(System.lineSeparator()); + res.append(" testImplementation(\"io.quarkus:quarkus-junit5\")").append(System.lineSeparator()); + res.append(" testImplementation(\"io.rest-assured:rest-assured\")").append(System.lineSeparator()); + res.append("}").append(System.lineSeparator()); + + } + String groupLine = "group = \"" + groupId + "\""; + if (!buildContent.contains(groupLine)) { + res.append(System.lineSeparator()).append(groupLine) + .append(System.lineSeparator()); + } + String versionLine = "version = \"" + version + "\""; + if (!buildContent.contains(versionLine)) { + res.append(System.lineSeparator()).append(versionLine) + .append(System.lineSeparator()); + } + + res.append(System.lineSeparator()) + .append("tasks.withType {").append(System.lineSeparator()) + .append(" systemProperty(\"java.util.logging.manager\", \"org.jboss.logmanager.LogManager\")") + .append(System.lineSeparator()) + .append("}"); + + getModel().setBuildContent(res.toString()); + } + + @Override + void createSettingsContent(String artifactId) throws IOException { + final String settingsContent = getModel().getSettingsContent(); + final StringBuilder res = new StringBuilder(); + if (!settingsContent.contains("id(\"io.quarkus\")")) { + res.append(System.lineSeparator()); + res.append("pluginManagement {").append(System.lineSeparator()); + res.append(" val quarkusPluginVersion: String by settings"); + res.append(" repositories {").append(System.lineSeparator()); + res.append(" mavenLocal()").append(System.lineSeparator()); + res.append(" mavenCentral()").append(System.lineSeparator()); + res.append(" gradlePluginPortal()").append(System.lineSeparator()); + res.append(" }").append(System.lineSeparator()); + res.append(" plugins {").append(System.lineSeparator()); + res.append(" id(\"io.quarkus\") version quarkusPluginVersion").append(System.lineSeparator()); + res.append(" }").append(System.lineSeparator()); + res.append("}").append(System.lineSeparator()); + } + if (!settingsContent.contains("rootProject.name")) { + res.append(System.lineSeparator()).append("rootProject.name=\"").append(artifactId).append("\"") + .append(System.lineSeparator()); + } + res.append(settingsContent); + getModel().setSettingsContent(res.toString()); + } + + @Override + void addDependencyInBuildFile(AppArtifactCoords coords) throws IOException { + AbstractKotlinGradleBuildFile.addDependencyInModel(getModel(), coords, false); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java index e21454bed2d76..599be80e173bf 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java @@ -78,12 +78,14 @@ private boolean initProject() throws IOException { testMainPath = writer.mkdirs(type.getTestSrcDir()); // for gradle we want to place the native tests in under 'src/native-test/java' // since gradle's idiomatic way of running integration tests is to create a new source set - if (getBuildTool() == BuildTool.GRADLE) { - nativeTestMainPath = writer.mkdirs(type.getTestSrcDir().replace("test", "native-test")); - } else { - nativeTestMainPath = testMainPath; + switch (getBuildTool()) { + case GRADLE: + case GRADLE_KOTLIN_DSL: + nativeTestMainPath = writer.mkdirs(type.getTestSrcDir().replace("test", "native-test")); + break; + default: + nativeTestMainPath = testMainPath; } - return newProject; } @@ -154,7 +156,8 @@ private void generate(final String templateName, QuarkusCommandInvocation invoca // do some nasty replacements for Java target if we want to generate Java 11 projects if ("11".equals(invocation.getValue(JAVA_TARGET))) { - if (BuildTool.GRADLE.equals(invocation.getQuarkusProject().getBuildTool())) { + if (BuildTool.GRADLE.equals(invocation.getQuarkusProject().getBuildTool()) + || BuildTool.GRADLE_KOTLIN_DSL.equals(invocation.getQuarkusProject().getBuildTool())) { template = template.replace("JavaVersion.VERSION_1_8", "JavaVersion.VERSION_11"); } else { template = template.replace("1.8", @@ -201,6 +204,7 @@ private void createReadme() throws IOException { generate("templates/README.maven.ftl", invocation, readme, "read me"); break; case GRADLE: + case GRADLE_KOTLIN_DSL: generate("templates/README.gradle.ftl", invocation, readme, "read me"); break; default: diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartProjectGenerationTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartProjectGenerationTest.java index ef7da2dbadbe3..18fb26d7662c0 100644 --- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartProjectGenerationTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartProjectGenerationTest.java @@ -210,6 +210,68 @@ void generateCodestartProjectGradleResteasyScala() throws IOException { assertThat(projectDir.resolve("src/main/scala/org/acme/resteasy/ExampleResource.scala")).exists(); } + @Test + void generateCodestartProjectGradleWithKotlinDslResteasyJava() throws IOException { + final CodestartInput input = inputBuilder(getPlatformDescriptor()) + .includeExamples() + .addExtension(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")) + .addData(getTestInputData()) + .putData("buildtool.name", "gradle-kotlin-dsl") + .build(); + final CodestartProject codestartProject = Codestarts.prepareProject(input); + final Path projectDir = testDirPath.resolve("gradle-kotlin-dsl-resteasy-java"); + Codestarts.generateProject(codestartProject, projectDir); + + checkGradleWithKotlinDsl(projectDir); + checkReadme(projectDir); + checkDockerfiles(projectDir); + checkConfigProperties(projectDir); + + assertThat(projectDir.resolve("src/main/java/org/acme/resteasy/ExampleResource.java")).exists(); + } + + @Test + void generateCodestartProjectGradleWithKotlinDslResteasyKotlin() throws IOException { + final CodestartInput input = inputBuilder(getPlatformDescriptor()) + .includeExamples() + .addExtension(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")) + .addExtension(AppArtifactKey.fromString("io.quarkus:quarkus-kotlin")) + .putData("buildtool.name", "gradle-kotlin-dsl") + .addData(getTestInputData()) + .build(); + final CodestartProject codestartProject = Codestarts.prepareProject(input); + final Path projectDir = testDirPath.resolve("gradle-kotlin-dsl-resteasy-kotlin"); + Codestarts.generateProject(codestartProject, projectDir); + + checkGradleWithKotlinDsl(projectDir); + checkReadme(projectDir); + checkDockerfiles(projectDir); + checkConfigProperties(projectDir); + + assertThat(projectDir.resolve("src/main/kotlin/org/acme/resteasy/ExampleResource.kt")).exists(); + } + + @Test + void generateCodestartProjectGradleWithKotlinDslResteasyScala() throws IOException { + final CodestartInput input = inputBuilder(getPlatformDescriptor()) + .includeExamples() + .addExtension(AppArtifactKey.fromString("io.quarkus:quarkus-resteasy")) + .addExtension(AppArtifactKey.fromString("io.quarkus:quarkus-scala")) + .addData(getTestInputData()) + .putData("buildtool.name", "gradle-kotlin-dsl") + .build(); + final CodestartProject codestartProject = Codestarts.prepareProject(input); + final Path projectDir = testDirPath.resolve("gradle-kotlin-dsl-resteasy-scala"); + Codestarts.generateProject(codestartProject, projectDir); + + checkGradleWithKotlinDsl(projectDir); + checkReadme(projectDir); + checkDockerfiles(projectDir); + checkConfigProperties(projectDir); + + assertThat(projectDir.resolve("src/main/scala/org/acme/resteasy/ExampleResource.scala")).exists(); + } + @Test void generateCodestartProjectQute() throws IOException { final CodestartInput input = inputBuilder(getPlatformDescriptor()) @@ -271,6 +333,8 @@ private void checkMaven(Path projectDir) { private void checkGradle(Path projectDir) { assertThat(projectDir.resolve("pom.xml")).doesNotExist(); + assertThat(projectDir.resolve("build.gradle.kts")).doesNotExist(); + assertThat(projectDir.resolve("settings.gradle.kts")).doesNotExist(); assertThat(projectDir.resolve("build.gradle")) .exists() .satisfies(checkContains("group 'org.test'")) @@ -281,6 +345,20 @@ private void checkGradle(Path projectDir) { .satisfies(checkContains("rootProject.name='test-codestart'")); } + private void checkGradleWithKotlinDsl(Path projectDir) { + assertThat(projectDir.resolve("pom.xml")).doesNotExist(); + assertThat(projectDir.resolve("build.gradle")).doesNotExist(); + assertThat(projectDir.resolve("settings.gradle")).doesNotExist(); + assertThat(projectDir.resolve("build.gradle.kts")) + .exists() + .satisfies(checkContains("group = \"org.test\"")) + .satisfies(checkContains("version = \"1.0.0-codestart\"")); + assertThat(projectDir.resolve("gradle.properties")).exists(); + assertThat(projectDir.resolve("settings.gradle.kts")) + .exists() + .satisfies(checkContains("rootProject.name=\"test-codestart\"")); + } + private Consumer checkContains(String s) { return (p) -> assertThat(Files.contentOf(p.toFile(), StandardCharsets.UTF_8)).contains(s); } diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartsTest.java index 36c47740f0ea3..772b232aff781 100644 --- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/CodestartsTest.java @@ -29,7 +29,7 @@ void setUp() throws IOException { void loadBundledCodestartsTest() throws IOException { final Collection codestarts = CodestartLoader .loadBundledCodestarts(inputBuilder(getPlatformDescriptor()).build()); - assertThat(codestarts).hasSize(10); + assertThat(codestarts).hasSize(11); assertThat(codestarts) .filteredOn(c -> c.getType().isBase()) .extracting(Codestart::getImplementedLanguages) diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java index 21ebd05128860..58ae9674a77a5 100644 --- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/AddGradleExtensionsTest.java @@ -16,7 +16,7 @@ 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.devtools.project.buildfile.AbstractGroovyGradleBuildFile; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; class AddGradleExtensionsTest extends AbstractAddExtensionsTest> { @@ -64,7 +64,7 @@ private QuarkusProject getQuarkusProject() { return QuarkusProject.of(projectPath, platformDescriptor, new TestingGradleBuildFile(projectPath, platformDescriptor)); } - static class TestingGradleBuildFile extends AbstractGradleBuildFile { + static class TestingGradleBuildFile extends AbstractGroovyGradleBuildFile { public TestingGradleBuildFile(Path projectDirPath, QuarkusPlatformDescriptor platformDescriptor) { super(projectDirPath, platformDescriptor); diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleKtsProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleKtsProjectTest.java new file mode 100644 index 0000000000000..a1f591e2afd4c --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleKtsProjectTest.java @@ -0,0 +1,52 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class AddExtensionToModuleInMultiModuleKtsProjectTest extends QuarkusGradleWrapperTestBase { + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + @Test + public void testBasicMultiModuleBuild() throws Exception { + + final File projectDir = getProjectDir("add-extension-multi-module-kts"); + + runGradleWrapper(projectDir, ":application:addExtension", "--extensions=hibernate-orm"); + + final Path applicationLib = projectDir.toPath().resolve("application").resolve("settings.gradle"); + assertThat(applicationLib).doesNotExist(); + final Path applicationLibKts = projectDir.toPath().resolve("application").resolve("settings.gradle.kts"); + assertThat(applicationLibKts).doesNotExist(); + + final Path appBuild = projectDir.toPath().resolve("application").resolve("build.gradle"); + assertThat(appBuild).doesNotExist(); + + final Path appBuildKts = projectDir.toPath().resolve("application").resolve("build.gradle.kts"); + assertThat(appBuildKts).exists(); + assertThat(readFile(appBuildKts)).contains("implementation(\"io.quarkus:quarkus-hibernate-orm\")"); + + runGradleWrapper(projectDir, ":application:removeExtension", "--extensions=hibernate-orm"); + assertThat(readFile(appBuildKts)).doesNotContain("implementation(\"io.quarkus:quarkus-hibernate-orm\")"); + } + + private static String readFile(Path file) throws IOException { + final char[] charBuffer = new char[DEFAULT_BUFFER_SIZE]; + int n = 0; + final StringWriter output = new StringWriter(); + try (BufferedReader input = Files.newBufferedReader(file)) { + while ((n = input.read(charBuffer)) != -1) { + output.write(charBuffer, 0, n); + } + } + return output.getBuffer().toString(); + } +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java new file mode 100644 index 0000000000000..41d71a43bee79 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java @@ -0,0 +1,56 @@ +package io.quarkus.gradle; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +public class AddExtensionToSingleModuleKtsProjectTest extends QuarkusGradleWrapperTestBase { + + @Test + public void testAddAndRemoveExtension() throws IOException, URISyntaxException, InterruptedException { + + final File projectDir = getProjectDir("add-remove-extension-single-module-kts"); + + runGradleWrapper(projectDir, ":addExtension", "--extensions=hibernate-orm"); + + final Path buildKts = projectDir.toPath().resolve("build.gradle.kts"); + assertThat(buildKts).exists(); + assertThat(new String(Files.readAllBytes(buildKts))) + .contains("implementation(\"io.quarkus:quarkus-hibernate-orm\")") + .doesNotContain("implementation(enforcedPlatform(\"io.quarkus:quarkus-bom:") + .doesNotContain("implementation(\"io.quarkus:quarkus-bom:"); + + runGradleWrapper(projectDir, ":removeExtension", "--extensions=hibernate-orm"); + assertThat(new String(Files.readAllBytes(buildKts))) + .doesNotContain("implementation(\"io.quarkus:quarkus-hibernate-orm\")"); + + assertThat(projectDir.toPath().resolve("build.gradle")).doesNotExist(); + } + + @Test + public void testRemoveNonExistentExtension() throws IOException, URISyntaxException, InterruptedException { + + final File projectDir = getProjectDir("add-remove-extension-single-module-kts"); + + runGradleWrapper(projectDir, "clean", "build"); + + final Path buildKts = projectDir.toPath().resolve("build.gradle.kts"); + assertThat(buildKts).exists(); + assertThat(new String(Files.readAllBytes(buildKts))) + .doesNotContain("implementation(\"io.quarkus:quarkus-hibernate-orm\")"); + + runGradleWrapper(projectDir, ":removeExtension", "--extensions=hibernate-orm"); + + assertThat(new String(Files.readAllBytes(buildKts))) + .doesNotContain("implementation(\"io.quarkus:quarkus-hibernate-orm\")"); + + assertThat(projectDir.toPath().resolve("build.gradle")).doesNotExist(); + } + +} diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/build.gradle.kts b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/build.gradle.kts new file mode 100644 index 0000000000000..3b8089e95f69d --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("io.quarkus") +} + +val quarkusPlatformGroupId: String by project +val quarkusPlatformArtifactId: String by project +val quarkusPlatformVersion: String by project + +dependencies { + implementation(project(":common")) + implementation("io.quarkus:quarkus-resteasy") + + testImplementation("io.quarkus:quarkus-junit5") + testImplementation("io.rest-assured:rest-assured") + + implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")) +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/java/org/acme/quarkus/sample/HelloResource.java b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/java/org/acme/quarkus/sample/HelloResource.java new file mode 100644 index 0000000000000..092d251dc1ebb --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/java/org/acme/quarkus/sample/HelloResource.java @@ -0,0 +1,22 @@ +package org.acme.quarkus.sample; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.acme.common.CommonBean; + +@Path("/hello") +public class HelloResource { + + @Inject + CommonBean common; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello " + common.getName(); + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/META-INF/resources/index.html b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/META-INF/resources/index.html new file mode 100644 index 0000000000000..77e09dffb5088 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,155 @@ + + + + + my-quarkus-project - 1.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.quarkus.sample
  • +
  • ArtifactId: my-quarkus-project
  • +
  • Version: 1.0-SNAPSHOT
  • +
  • Quarkus Version: 999-SNAPSHOT
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/application.properties b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/application.properties new file mode 100644 index 0000000000000..3c1ac56a1ad0a --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/application/src/main/resources/application.properties @@ -0,0 +1,2 @@ +# Configuration file +# key = value \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/build.gradle.kts b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/build.gradle.kts new file mode 100644 index 0000000000000..dab45043d88d6 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/build.gradle.kts @@ -0,0 +1,42 @@ +buildscript { + + repositories { + jcenter() + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + +} + +plugins { + java +} + +group = "com.quarkus.demo" +version = "1.0" + + +subprojects { + + apply(plugin = "java") + + java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + tasks { + test { + dependsOn("cleanTest") + useJUnitPlatform() + setForkEvery(1) + } + } + + repositories { + jcenter() + mavenLocal() + mavenCentral() + } +} diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/build.gradle.kts b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/build.gradle.kts new file mode 100644 index 0000000000000..bcf58d676e495 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `java-library` +} + +dependencies { + +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/java/org/acme/common/CommonBean.java b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/java/org/acme/common/CommonBean.java new file mode 100644 index 0000000000000..ace88a5b0e415 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/java/org/acme/common/CommonBean.java @@ -0,0 +1,11 @@ +package org.acme.common; + +import javax.enterprise.context.RequestScoped; + +@RequestScoped +public class CommonBean { + + public String getName() { + return "common"; + } +} diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/resources/META-INF/beans.xml b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000000..ddcbaf4800eb9 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/common/src/main/resources/META-INF/beans.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/gradle.properties b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/gradle.properties new file mode 100644 index 0000000000000..8f063b7d88ba4 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/settings.gradle.kts b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/settings.gradle.kts new file mode 100644 index 0000000000000..65328f5555e18 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-extension-multi-module-kts/settings.gradle.kts @@ -0,0 +1,16 @@ +pluginManagement { + val quarkusPluginVersion: String by settings + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + plugins { + id("io.quarkus") version quarkusPluginVersion + } +} +rootProject.name="quarkus-basic-multi-module-build" + +include(":common") +include(":application") + diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/build.gradle.kts b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/build.gradle.kts new file mode 100644 index 0000000000000..6c14e2e562fe3 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + java + id("io.quarkus") +} + +repositories { + mavenLocal() + mavenCentral() +} + +val quarkusPlatformGroupId: String by project +val quarkusPlatformArtifactId: String by project +val quarkusPlatformVersion: String by project + +dependencies { + implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")) + implementation("io.quarkus:quarkus-resteasy") + + testImplementation("io.quarkus:quarkus-junit5") + testImplementation("io.rest-assured:rest-assured") +} + +group = "org.acme" +version = "1.0.0-SNAPSHOT" + +tasks.withType { + options.encoding = "UTF-8" + options.compilerArgs.add("-parameters") +} diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/gradle.properties b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/settings.gradle.kts b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/settings.gradle.kts new file mode 100644 index 0000000000000..42c5272356d1e --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/settings.gradle.kts @@ -0,0 +1,12 @@ +pluginManagement { + val quarkusPluginVersion: String by settings + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + plugins { + id("io.quarkus") version quarkusPluginVersion + } +} +rootProject.name="code-with-quarkus" \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/java/org/acme/ExampleResource.java b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/java/org/acme/ExampleResource.java new file mode 100644 index 0000000000000..d01ef472250e2 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/java/org/acme/ExampleResource.java @@ -0,0 +1,24 @@ +package org.acme; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@Path("/hello") +public class ExampleResource { + + @ConfigProperty(name = "my-app-name") + String appName; + @ConfigProperty(name = "quarkus.application.version") + String appVersion; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return appName + " " + appVersion; + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/resources/application.properties b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/resources/application.properties new file mode 100644 index 0000000000000..b18c72feda9df --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/main/resources/application.properties @@ -0,0 +1,3 @@ +# Configuration file +# key = value +my-app-name=${quarkus.application.name} diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/java/org/acme/ExampleResourceTest.java b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/java/org/acme/ExampleResourceTest.java new file mode 100644 index 0000000000000..9b92351468aa0 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/java/org/acme/ExampleResourceTest.java @@ -0,0 +1,29 @@ +package org.acme; + +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("/hello") + .then() + .statusCode(200) + .body(is("Hello from Test")); + } + + @Test + public void testTestOnly() { + given() + .when().get("test-only") + .then() + .statusCode(200) + .body(is("Test only")); + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/resources/application.properties b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/resources/application.properties new file mode 100644 index 0000000000000..b2340b5f9173f --- /dev/null +++ b/integration-tests/gradle/src/test/resources/add-remove-extension-single-module-kts/src/test/resources/application.properties @@ -0,0 +1,5 @@ +# Configuration file +# key = value +example.message=Hello from Test +test-only=Test only +