diff --git a/devtools/aesh/src/main/java/io/quarkus/cli/QuarkusCli.java b/devtools/aesh/src/main/java/io/quarkus/cli/QuarkusCli.java
index 97d3da8324c9c0..a4e491f3fc1ad8 100644
--- a/devtools/aesh/src/main/java/io/quarkus/cli/QuarkusCli.java
+++ b/devtools/aesh/src/main/java/io/quarkus/cli/QuarkusCli.java
@@ -12,18 +12,18 @@
import org.aesh.command.validator.CommandValidatorException;
import org.aesh.command.validator.OptionValidatorException;
-import io.quarkus.cli.commands.QuarkusCommand;
+import io.quarkus.cli.commands.QuarkusCommandHandler;
public class QuarkusCli {
public static void main(String[] args) throws CommandRegistryException {
CommandRuntime runtime = AeshCommandRuntimeBuilder
.builder()
- .commandRegistry(AeshCommandRegistryBuilder.builder().command(QuarkusCommand.class).create())
+ .commandRegistry(AeshCommandRegistryBuilder.builder().command(QuarkusCommandHandler.class).create())
.build();
if (args.length > 0) {
- StringBuilder sb = new StringBuilder(QuarkusCommand.COMMAND_NAME).append(" ");
+ StringBuilder sb = new StringBuilder(QuarkusCommandHandler.COMMAND_NAME).append(" ");
if (args.length == 1) {
sb.append(args[0]);
} else {
@@ -54,6 +54,6 @@ private static void showHelpIfNeeded(CommandRuntime runtime, Exception e) {
if (e != null) {
System.err.println(e.getMessage());
}
- System.err.println(runtime.commandInfo(QuarkusCommand.COMMAND_NAME));
+ System.err.println(runtime.commandInfo(QuarkusCommandHandler.COMMAND_NAME));
}
}
diff --git a/devtools/aesh/src/main/java/io/quarkus/cli/commands/AddExtensionCommand.java b/devtools/aesh/src/main/java/io/quarkus/cli/commands/AddExtensionCommand.java
index f28858c67e830d..b877068cc47a1c 100644
--- a/devtools/aesh/src/main/java/io/quarkus/cli/commands/AddExtensionCommand.java
+++ b/devtools/aesh/src/main/java/io/quarkus/cli/commands/AddExtensionCommand.java
@@ -5,6 +5,7 @@
import java.util.Collections;
import java.util.List;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import org.aesh.command.Command;
import org.aesh.command.CommandDefinition;
import org.aesh.command.CommandException;
diff --git a/devtools/aesh/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java b/devtools/aesh/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java
index 1fec3661741939..280d3559f069de 100644
--- a/devtools/aesh/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java
+++ b/devtools/aesh/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java
@@ -10,7 +10,7 @@
/**
* @author Ståle Pedersen
*/
-@GroupCommandDefinition(name = QuarkusCommand.COMMAND_NAME, groupCommands = { ListExtensionsCommand.class,
+@GroupCommandDefinition(name = QuarkusCommandHandler.COMMAND_NAME, groupCommands = { ListExtensionsCommand.class,
AddExtensionCommand.class,
CreateProjectCommand.class }, description = " [] \n\nThese are the common quarkus commands used in various situations")
public class QuarkusCommand implements Command {
diff --git a/devtools/aesh/src/main/java/io/quarkus/cli/commands/RemoveExtensionCommand.java b/devtools/aesh/src/main/java/io/quarkus/cli/commands/RemoveExtensionCommand.java
index cc3b718276cfcc..943af1b480b2c8 100644
--- a/devtools/aesh/src/main/java/io/quarkus/cli/commands/RemoveExtensionCommand.java
+++ b/devtools/aesh/src/main/java/io/quarkus/cli/commands/RemoveExtensionCommand.java
@@ -5,6 +5,7 @@
import java.util.Collections;
import java.util.List;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import org.aesh.command.Command;
import org.aesh.command.CommandDefinition;
import org.aesh.command.CommandException;
diff --git a/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleProjectTest.java b/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleProjectTest.java
index 00b55e2260616b..c992eef547c623 100644
--- a/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleProjectTest.java
+++ b/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/AddExtensionToModuleInMultiModuleProjectTest.java
@@ -19,7 +19,6 @@ public class AddExtensionToModuleInMultiModuleProjectTest extends QuarkusGradleT
public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("add-extension-multi-module");
-
BuildResult build = GradleRunner.create()
.forwardOutput()
.withPluginClasspath()
diff --git a/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java b/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
index 38cfcc6d75e9e5..c1c0248b223d8c 100644
--- a/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
+++ b/devtools/gradle/src/functionalTest/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
@@ -23,7 +23,7 @@
import io.quarkus.cli.commands.CreateProject;
import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.generators.SourceType;
+import io.quarkus.devtools.project.codegen.SourceType;
import io.quarkus.platform.tools.config.QuarkusPlatformConfig;
import io.quarkus.test.devmode.util.DevModeTestUtils;
diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java b/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java
index 01c4102868f7bc..3a2e41a15eae63 100644
--- a/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java
+++ b/devtools/gradle/src/main/java/io/quarkus/gradle/GradleBuildFileFromConnector.java
@@ -1,6 +1,7 @@
package io.quarkus.gradle;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -13,16 +14,20 @@
import org.gradle.tooling.model.eclipse.EclipseExternalDependency;
import org.gradle.tooling.model.eclipse.EclipseProject;
-import io.quarkus.devtools.buildfile.GradleBuildFile;
-import io.quarkus.devtools.writer.ProjectWriter;
+import io.quarkus.devtools.buildfile.AbstractGradleBuildFile;
+import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
-public class GradleBuildFileFromConnector extends GradleBuildFile {
+public class GradleBuildFileFromConnector extends AbstractGradleBuildFile {
private List dependencies = null;
- public GradleBuildFileFromConnector(ProjectWriter writer) {
- super(writer);
- // we need to initialize here since there is no other single point of entry
+ public GradleBuildFileFromConnector(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor) {
+ super(projectFolderPath, platformDescriptor);
+ }
+
+ public GradleBuildFileFromConnector(Path projectFolderPath, QuarkusPlatformDescriptor platformDescriptor,
+ Path rootProjectPath) {
+ super(projectFolderPath, platformDescriptor, rootProjectPath);
}
@Override
@@ -30,16 +35,14 @@ public List getDependencies() throws IOException {
if (dependencies == null) {
EclipseProject eclipseProject = null;
if (getBuildContent() != null) {
- if (getWriter().hasFile()) {
- try {
- ProjectConnection connection = GradleConnector.newConnector()
- .forProjectDirectory(getWriter().getProjectFolder())
- .connect();
- eclipseProject = connection.getModel(EclipseProject.class);
- } catch (BuildException e) {
- // ignore this error.
- e.printStackTrace();
- }
+ try {
+ ProjectConnection connection = GradleConnector.newConnector()
+ .forProjectDirectory(getProjectFolderPath().toFile())
+ .connect();
+ eclipseProject = connection.getModel(EclipseProject.class);
+ } catch (BuildException e) {
+ // ignore this error.
+ e.printStackTrace();
}
}
if (eclipseProject != null) {
diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusListExtensions.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusListExtensions.java
index 833679f5c61dd8..35bb017c74dc18 100644
--- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusListExtensions.java
+++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusListExtensions.java
@@ -7,9 +7,6 @@
import org.gradle.api.tasks.options.Option;
import io.quarkus.cli.commands.ListExtensions;
-import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.devtools.writer.FileProjectWriter;
-import io.quarkus.gradle.GradleBuildFileFromConnector;
public class QuarkusListExtensions extends QuarkusPlatformTask {
@@ -58,11 +55,7 @@ public QuarkusListExtensions() {
@TaskAction
public void listExtensions() {
try {
- final GradleBuildFileFromConnector buildFileFromConnector = new GradleBuildFileFromConnector(
- new FileProjectWriter(getProject().getProjectDir()));
- QuarkusProject quarkusProject = QuarkusProject.of(getProject().getProjectDir().toPath(), platformDescriptor(),
- buildFileFromConnector);
- new ListExtensions(quarkusProject)
+ new ListExtensions(getQuarkusProject())
.all(isAll())
.format(getFormat())
.search(getSearchPattern())
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 3433f111bb2cea..467acad3a3872c 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
@@ -10,10 +10,9 @@
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.Internal;
-import io.quarkus.devtools.buildfile.GradleBuildFile;
import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.devtools.writer.FileProjectWriter;
-import io.quarkus.devtools.writer.ProjectWriter;
+import io.quarkus.devtools.buildfile.BuildFile;
+import io.quarkus.gradle.GradleBuildFileFromConnector;
import io.quarkus.platform.descriptor.CombinedQuarkusPlatformDescriptor;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver;
@@ -66,12 +65,11 @@ protected QuarkusPlatformDescriptor platformDescriptor() {
}
@Internal
- protected GradleBuildFile getGradleBuildFile() {
- final ProjectWriter writer = new FileProjectWriter(getProject().getProjectDir());
+ protected BuildFile getGradleBuildFile() {
return getProject().getParent() == null
- ? new GradleBuildFile(writer)
- : new GradleBuildFile(writer,
- new FileProjectWriter(getProject().getRootProject().getProjectDir()));
+ ? new GradleBuildFileFromConnector(getProject().getProjectDir().toPath(), platformDescriptor())
+ : new GradleBuildFileFromConnector(getProject().getProjectDir().toPath(), platformDescriptor(),
+ getProject().getRootProject().getProjectDir().toPath());
}
@Internal
diff --git a/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java b/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java
index 899513bec48f52..74fdb9c7532724 100644
--- a/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java
+++ b/devtools/gradle/src/test/java/io/quarkus/gradle/GradleBuildFileTest.java
@@ -20,7 +20,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-import io.quarkus.devtools.writer.FileProjectWriter;
+import io.quarkus.devtools.project.codegen.writer.FileProjectWriter;
class GradleBuildFileTest {
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/AddExtensionMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/AddExtensionMojo.java
index 115d681b095af0..411eae8d27eb12 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/AddExtensionMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/AddExtensionMojo.java
@@ -11,7 +11,7 @@
import org.apache.maven.plugins.annotations.Parameter;
import io.quarkus.cli.commands.AddExtensions;
-import io.quarkus.cli.commands.QuarkusCommandOutcome;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.platform.tools.MessageWriter;
@@ -22,7 +22,7 @@
* parameters.
*/
@Mojo(name = "add-extension")
-public class AddExtensionMojo extends BuildFileMojoBase {
+public class AddExtensionMojo extends QuarkusProjectMojoBase {
/**
* The list of extensions to be added.
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 b560894b9ac450..9749d058286ce5 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
@@ -46,11 +46,9 @@
import io.quarkus.bootstrap.resolver.AppModelResolverException;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
-import io.quarkus.cli.commands.AddExtensions;
import io.quarkus.cli.commands.CreateProject;
import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.generators.SourceType;
+import io.quarkus.devtools.project.codegen.SourceType;
import io.quarkus.maven.components.MavenVersionEnforcer;
import io.quarkus.maven.components.Prompter;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
@@ -214,11 +212,6 @@ public void execute() throws MojoExecutionException {
success = createProject.execute().isSuccess();
File createdDependenciesBuildFile = new File(projectRoot, buildToolEnum.getDependenciesFile());
- if (success) {
- success = new AddExtensions(QuarkusProject.of(projectFolderPath, platform, buildToolEnum))
- .extensions(extensions).execute()
- .isSuccess();
- }
if (BuildTool.MAVEN.equals(buildToolEnum)) {
createMavenWrapper(createdDependenciesBuildFile, ToolsUtils.readQuarkusProperties(platform));
} else if (BuildTool.GRADLE.equals(buildToolEnum)) {
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/ListExtensionsMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/ListExtensionsMojo.java
index 64486a685a6fa1..6de18e4f6c021e 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/ListExtensionsMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/ListExtensionsMojo.java
@@ -15,7 +15,7 @@
* You can list all extension or just installable. Choose between 3 output formats: name, concise and full.
*/
@Mojo(name = "list-extensions", requiresProject = false)
-public class ListExtensionsMojo extends BuildFileMojoBase {
+public class ListExtensionsMojo extends QuarkusProjectMojoBase {
/**
* List all extensions or just the installable.
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusProjectMojoBase.java
similarity index 75%
rename from devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java
rename to devtools/maven/src/main/java/io/quarkus/maven/QuarkusProjectMojoBase.java
index 961abc3440c53e..c3fdcbb89d463d 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusProjectMojoBase.java
@@ -1,11 +1,13 @@
package io.quarkus.maven;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
@@ -19,11 +21,8 @@
import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
-import io.quarkus.devtools.buildfile.BuildFile;
-import io.quarkus.devtools.buildfile.MavenBuildFile;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.devtools.writer.FileProjectWriter;
import io.quarkus.platform.descriptor.CombinedQuarkusPlatformDescriptor;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver;
@@ -31,7 +30,7 @@
import io.quarkus.platform.tools.ToolsConstants;
import io.quarkus.platform.tools.maven.MojoMessageWriter;
-public abstract class BuildFileMojoBase extends AbstractMojo {
+public abstract class QuarkusProjectMojoBase extends AbstractMojo {
@Parameter(defaultValue = "${project}")
protected MavenProject project;
@@ -60,37 +59,31 @@ public void execute() throws MojoExecutionException {
// Validate Mojo parameters
validateParameters();
+ final MessageWriter log = new MojoMessageWriter(getLog());
+ final Path projectFolderPath = project.getBasedir().toPath();
+ final BuildTool buildTool = QuarkusProject.resolveExistingProjectBuildTool(projectFolderPath);
+ final QuarkusPlatformDescriptor platformDescriptor = resolvePlatformDescriptor(log);
+
+ doExecute(QuarkusProject.of(project.getBasedir().toPath(), platformDescriptor, buildTool), log);
+ }
+
+ private QuarkusPlatformDescriptor resolvePlatformDescriptor(final MessageWriter log) throws MojoExecutionException {
// Resolve and setup the platform descriptor
- final MavenArtifactResolver mvn;
try {
- mvn = MavenArtifactResolver.builder().setRepositorySystem(repoSystem).setRepositorySystemSession(repoSession)
+ final MavenArtifactResolver mvn = MavenArtifactResolver.builder().setRepositorySystem(repoSystem)
+ .setRepositorySystemSession(repoSession)
.setRemoteRepositories(repos).build();
- } catch (Exception e) {
- throw new MojoExecutionException("Failed to initialize maven artifact resolver", e);
- }
-
- final MessageWriter log = new MojoMessageWriter(getLog());
-
- QuarkusPlatformDescriptor platformDescr = null;
- BuildTool buildTool = null;
- BuildFile buildFile = null;
- try (FileProjectWriter fileProjectWriter = new FileProjectWriter(project.getBasedir())) {
if (project.getFile() != null) {
- // Maven project
- final MavenBuildFile mvnBuild = new MavenBuildFile(fileProjectWriter);
- buildTool = BuildTool.MAVEN;
- buildFile = new MavenBuildFile(fileProjectWriter);
-
final List descrArtifactList = new ArrayList<>(2);
- for (Dependency dep : mvnBuild.getManagedDependencies()) {
+ for (Dependency dep : getManagedDependencies()) {
if ((dep.getScope() == null || !dep.getScope().equals("import"))
&& (dep.getType() == null || !dep.getType().equals("pom"))) {
continue;
}
// We don't know which BOM is the platform one, so we are trying every BOM here
- final String bomVersion = resolveValue(dep.getVersion(), buildFile);
- final String bomGroupId = resolveValue(dep.getGroupId(), buildFile);
- final String bomArtifactId = resolveValue(dep.getArtifactId(), buildFile);
+ final String bomVersion = resolveValue(dep.getVersion());
+ final String bomGroupId = resolveValue(dep.getGroupId());
+ final String bomArtifactId = resolveValue(dep.getArtifactId());
if (bomVersion == null || bomGroupId == null || bomArtifactId == null) {
continue;
}
@@ -102,28 +95,19 @@ public void execute() throws MojoExecutionException {
}
if (!descrArtifactList.isEmpty()) {
if (descrArtifactList.size() == 1) {
- platformDescr = loadPlatformDescriptor(mvn, log, descrArtifactList.get(0));
+ return loadPlatformDescriptor(mvn, log, descrArtifactList.get(0));
} else {
final CombinedQuarkusPlatformDescriptor.Builder builder = CombinedQuarkusPlatformDescriptor.builder();
for (Artifact descrArtifact : descrArtifactList) {
builder.addPlatform(loadPlatformDescriptor(mvn, log, descrArtifact));
}
- platformDescr = builder.build();
+ return builder.build();
}
}
- } else if (new File(project.getBasedir(), "build.gradle").exists()
- || new File(project.getBasedir(), "build.gradle.kts").exists()) {
- // Gradle project
- buildTool = BuildTool.GRADLE;
}
-
- if (platformDescr == null) {
- platformDescr = CreateUtils.resolvePlatformDescriptor(bomGroupId, bomArtifactId, bomVersion, mvn, getLog());
- }
-
- doExecute(QuarkusProject.of(project.getBasedir().toPath(), platformDescr, buildTool), log);
- } catch (IOException e) {
- throw new MojoExecutionException("Failed to initialize project reading tools", e);
+ return CreateUtils.resolvePlatformDescriptor(bomGroupId, bomArtifactId, bomVersion, mvn, getLog());
+ } catch (Exception e) {
+ throw new MojoExecutionException("Failed to initialize maven artifact resolver", e);
}
}
@@ -166,10 +150,10 @@ protected void validateParameters() throws MojoExecutionException {
protected abstract void doExecute(QuarkusProject quarkusProject, MessageWriter log)
throws MojoExecutionException;
- private String resolveValue(String expr, BuildFile buildFile) throws IOException {
+ private String resolveValue(String expr) throws IOException {
if (expr.startsWith("${") && expr.endsWith("}")) {
final String name = expr.substring(2, expr.length() - 1);
- final String v = buildFile.getProperty(name);
+ final String v = project.getModel().getProperties().getProperty(name);
if (v == null) {
if (getLog().isDebugEnabled()) {
getLog().debug("Failed to resolve property " + name);
@@ -179,4 +163,10 @@ private String resolveValue(String expr, BuildFile buildFile) throws IOException
}
return expr;
}
+
+ private List getManagedDependencies() throws IOException {
+ final DependencyManagement managed = project.getModel().getDependencyManagement();
+ return managed != null ? managed.getDependencies()
+ : Collections.emptyList();
+ }
}
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/RemoveExtensionMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/RemoveExtensionMojo.java
index 827f258f592432..4caa81b4a89a3f 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/RemoveExtensionMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/RemoveExtensionMojo.java
@@ -10,8 +10,8 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
-import io.quarkus.cli.commands.QuarkusCommandOutcome;
import io.quarkus.cli.commands.RemoveExtensions;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.platform.tools.MessageWriter;
@@ -22,7 +22,7 @@
* parameters.
*/
@Mojo(name = "remove-extension")
-public class RemoveExtensionMojo extends BuildFileMojoBase {
+public class RemoveExtensionMojo extends QuarkusProjectMojoBase {
/**
* The list of extensions to be removed.
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensions.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensions.java
index b0b1462bae823f..914de39f67963a 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensions.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensions.java
@@ -1,6 +1,12 @@
package io.quarkus.cli.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import io.quarkus.platform.tools.ToolsConstants;
import io.quarkus.platform.tools.ToolsUtils;
import java.util.Set;
@@ -13,19 +19,26 @@ public class AddExtensions {
public static final String NAME = "add-extensions";
public static final String EXTENSIONS = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "extensions");
public static final String OUTCOME_UPDATED = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "outcome", "updated");
+ public static final String EXTENSIONS_MANAGER = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "extensions-manager");
private final QuarkusCommandInvocation invocation;
+ private final AddExtensionsCommandHandler handler = new AddExtensionsCommandHandler();
public AddExtensions(final QuarkusProject quarkusProject) {
this.invocation = new QuarkusCommandInvocation(quarkusProject);
}
+ public AddExtensions extensionsManager(ExtensionsManager extensionsManager) {
+ invocation.setValue(EXTENSIONS_MANAGER, checkNotNull(extensionsManager, "extensionsManager is required"));
+ return this;
+ }
+
public AddExtensions extensions(Set extensions) {
invocation.setValue(EXTENSIONS, extensions);
return this;
}
public QuarkusCommandOutcome execute() throws QuarkusCommandException {
- return new AddExtensionsCommandHandler().execute(invocation);
+ return handler.execute(invocation);
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensionsCommandHandler.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensionsCommandHandler.java
index 6541aa6992b7ce..f8317904de786e 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensionsCommandHandler.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/AddExtensionsCommandHandler.java
@@ -1,232 +1,45 @@
package io.quarkus.cli.commands;
+import static io.quarkus.cli.commands.AddExtensions.EXTENSIONS_MANAGER;
+import static io.quarkus.cli.commands.QuarkusCommandHandlers.computeExtensionsFromQuery;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.dependencies.Extension;
-import io.quarkus.devtools.buildfile.BuildFile;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import java.io.IOException;
import java.util.Collections;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.util.stream.Collectors;
/**
* This class is thread-safe. It extracts extensions to be added to the project from an instance of
* {@link QuarkusCommandInvocation}.
*/
-public class AddExtensionsCommandHandler implements QuarkusCommand {
-
- final static Printer PRINTER = new Printer();
+public class AddExtensionsCommandHandler implements QuarkusCommandHandler {
@Override
public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException {
-
- final Set extensions = invocation.getValue(AddExtensions.EXTENSIONS, Collections.emptySet());
- if (extensions.isEmpty()) {
+ final Set extensionsQuery = invocation.getValue(AddExtensions.EXTENSIONS, Collections.emptySet());
+ if (extensionsQuery.isEmpty()) {
return QuarkusCommandOutcome.success().setValue(AddExtensions.OUTCOME_UPDATED, false);
}
- boolean updated = false;
- boolean success = true;
-
- final List registry = invocation.getPlatformDescriptor().getExtensions();
-
- final BuildFile buildFile = invocation.getBuildFile();
+ final List extensionsToAdd = computeExtensionsFromQuery(invocation, extensionsQuery);
+ final ExtensionsManager extensionsManager = invocation.getValue(EXTENSIONS_MANAGER,
+ invocation.getQuarkusProject().getExtensionsManager());
try {
- for (String query : extensions) {
- if (query.contains(":")) {
- // GAV case.
- updated = buildFile.addExtensionAsGAV(query) || updated;
- } else {
- SelectionResult result = select(query, registry, false);
- if (!result.matches()) {
- StringBuilder sb = new StringBuilder();
- // We have 3 cases, we can still have a single candidate, but the match is on label
- // or we have several candidates, or none
- Set candidates = result.getExtensions();
- if (candidates.isEmpty()) {
- // No matches at all.
- PRINTER.nok(" Cannot find a dependency matching '" + query + "', maybe a typo?");
- success = false;
- } else {
- sb.append(Printer.NOK).append(" Multiple extensions matching '").append(query).append("'");
- result.getExtensions()
- .forEach(extension -> sb.append(System.lineSeparator()).append(" * ")
- .append(extension.managementKey()));
- sb.append(System.lineSeparator())
- .append(" Be more specific e.g using the exact name or the full GAV.");
- PRINTER.print(sb.toString());
- success = false;
- }
- } else { // Matches.
- for (Extension extension : result) {
- // Don't set success to false even if the dependency is not added; as it's should be idempotent.
- updated = buildFile.addDependency(invocation.getPlatformDescriptor(), extension) || updated;
- }
- }
- }
+ if (extensionsToAdd != null) {
+ final int added = extensionsManager.install(extensionsToAdd);
+ return new QuarkusCommandOutcome(true).setValue(AddExtensions.OUTCOME_UPDATED, added > 0);
}
+
} catch (IOException e) {
throw new QuarkusCommandException("Failed to add extensions", e);
}
- if (buildFile != null && updated) {
- try {
- buildFile.close();
- } catch (IOException e) {
- throw new QuarkusCommandException("Failed to update the project", e);
- }
- }
-
- return new QuarkusCommandOutcome(success).setValue(AddExtensions.OUTCOME_UPDATED, updated);
+ return new QuarkusCommandOutcome(false).setValue(AddExtensions.OUTCOME_UPDATED, false);
}
- /**
- * Selection algorithm.
- *
- * @param query the query
- * @param extensions the extension list
- * @param labelLookup whether or not the query must be tested against the labels of the extensions. Should
- * be {@code false} by default.
- * @return the list of matching candidates and whether or not a match has been found.
- */
- static SelectionResult select(String query, List extensions, boolean labelLookup) {
- String q = query.trim().toLowerCase();
-
- // Try exact matches
- Set matchesNameOrArtifactId = extensions.stream()
- .filter(extension -> extension.getName().equalsIgnoreCase(q) || matchesArtifactId(extension.getArtifactId(), q))
- .collect(Collectors.toSet());
- if (matchesNameOrArtifactId.size() == 1) {
- return new SelectionResult(matchesNameOrArtifactId, true);
- }
-
- extensions = extensions.stream().filter(e -> !e.isUnlisted()).collect(Collectors.toList());
-
- // Try short names
- Set matchesShortName = extensions.stream().filter(extension -> matchesShortName(extension, q))
- .collect(Collectors.toSet());
-
- if (matchesShortName.size() == 1 && matchesNameOrArtifactId.isEmpty()) {
- return new SelectionResult(matchesShortName, true);
- }
-
- // Partial matches on name, artifactId and short names
- Set partialMatches = extensions.stream().filter(extension -> extension.getName().toLowerCase().contains(q)
- || extension.getArtifactId().toLowerCase().contains(q)
- || extension.getShortName().toLowerCase().contains(q)).collect(Collectors.toSet());
- // Even if we have a single partial match, if the name, artifactId and short names are ambiguous, so not
- // consider it as a match.
- if (partialMatches.size() == 1 && matchesNameOrArtifactId.isEmpty() && matchesShortName.isEmpty()) {
- return new SelectionResult(partialMatches, true);
- }
-
- // find by labels
- List matchesLabels;
- if (labelLookup) {
- matchesLabels = extensions.stream()
- .filter(extension -> extension.labelsForMatching().contains(q)).collect(Collectors.toList());
- } else {
- matchesLabels = Collections.emptyList();
- }
-
- // find by pattern
- Set matchesPatterns;
- Pattern pattern = toRegex(q);
- if (pattern != null) {
- matchesPatterns = extensions.stream()
- .filter(extension -> pattern.matcher(extension.getName().toLowerCase()).matches()
- || pattern.matcher(extension.getArtifactId().toLowerCase()).matches()
- || pattern.matcher(extension.getShortName().toLowerCase()).matches()
- || matchLabels(pattern, extension.getKeywords()))
- .collect(Collectors.toSet());
- return new SelectionResult(matchesPatterns, true);
- } else {
- matchesPatterns = Collections.emptySet();
- }
-
- Set candidates = new LinkedHashSet<>();
- candidates.addAll(matchesNameOrArtifactId);
- candidates.addAll(matchesShortName);
- candidates.addAll(partialMatches);
- candidates.addAll(matchesLabels);
- candidates.addAll(matchesPatterns);
- return new SelectionResult(candidates, false);
- }
-
- private static boolean matchLabels(Pattern pattern, List labels) {
- boolean matches = false;
- // if any label match it's ok
- for (String label : labels) {
- matches = matches || pattern.matcher(label.toLowerCase()).matches();
- }
- return matches;
- }
-
- private static Pattern toRegex(final String str) {
- try {
- String wildcardToRegex = wildcardToRegex(str);
- if (wildcardToRegex != null && !wildcardToRegex.isEmpty()) {
- return Pattern.compile(wildcardToRegex);
- }
- } catch (PatternSyntaxException e) {
- //ignore it
- }
- return null;
- }
-
- private static String wildcardToRegex(String wildcard) {
- if (wildcard == null || wildcard.isEmpty()) {
- return null;
- }
- // don't try with file match char in pattern
- if (!(wildcard.contains("*") || wildcard.contains("?"))) {
- return null;
- }
- StringBuffer s = new StringBuffer(wildcard.length());
- s.append("^.*");
- for (int i = 0, is = wildcard.length(); i < is; i++) {
- char c = wildcard.charAt(i);
- switch (c) {
- case '*':
- s.append(".*");
- break;
- case '?':
- s.append(".");
- break;
- case '^': // escape character in cmd.exe
- s.append("\\");
- break;
- // escape special regexp-characters
- case '(':
- case ')':
- case '[':
- case ']':
- case '$':
- case '.':
- case '{':
- case '}':
- case '|':
- case '\\':
- s.append("\\");
- s.append(c);
- break;
- default:
- s.append(c);
- break;
- }
- }
- s.append(".*$");
- return (s.toString());
- }
-
- private static boolean matchesShortName(Extension extension, String q) {
- return q.equalsIgnoreCase(extension.getShortName());
- }
-
- private static boolean matchesArtifactId(String artifactId, String q) {
- return artifactId.equalsIgnoreCase(q) ||
- artifactId.equalsIgnoreCase("quarkus-" + q);
- }
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProject.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProject.java
index 0f01b9bc452fc8..e9f49eb51e3113 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProject.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProject.java
@@ -1,17 +1,21 @@
package io.quarkus.cli.commands;
import static com.google.common.base.Preconditions.checkNotNull;
-import static io.quarkus.generators.ProjectGenerator.CLASS_NAME;
-import static io.quarkus.generators.ProjectGenerator.IS_SPRING;
-import static io.quarkus.generators.ProjectGenerator.JAVA_TARGET;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_ARTIFACT_ID;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_GROUP_ID;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_VERSION;
-import static io.quarkus.generators.ProjectGenerator.SOURCE_TYPE;
-
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.CLASS_NAME;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.EXTENSIONS;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.IS_SPRING;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.JAVA_TARGET;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_ARTIFACT_ID;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_GROUP_ID;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_VERSION;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.SOURCE_TYPE;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.generators.SourceType;
+import io.quarkus.devtools.project.codegen.SourceType;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import java.io.IOException;
import java.nio.file.Path;
@@ -81,14 +85,11 @@ public CreateProject className(String className) {
return this;
}
- /**
- * @deprecated in 1.3.0.CR
- */
- @Deprecated
public CreateProject extensions(Set extensions) {
if (isSpringStyle(extensions)) {
setValue(IS_SPRING, true);
}
+ setValue(EXTENSIONS, extensions);
return this;
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProjectCommandHandler.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProjectCommandHandler.java
index 3bd04bea6cd843..705b3086cf3bb6 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProjectCommandHandler.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/CreateProjectCommandHandler.java
@@ -1,42 +1,45 @@
package io.quarkus.cli.commands;
-import static io.quarkus.generators.ProjectGenerator.*;
+import static io.quarkus.cli.commands.QuarkusCommandHandlers.computeExtensionsFromQuery;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.*;
-import io.quarkus.devtools.buildfile.BuildFile;
-import io.quarkus.devtools.writer.FileProjectWriter;
-import io.quarkus.devtools.writer.ProjectWriter;
-import io.quarkus.generators.ProjectGeneratorRegistry;
-import io.quarkus.generators.SourceType;
-import io.quarkus.generators.rest.BasicRestProjectGenerator;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
+import io.quarkus.dependencies.Extension;
+import io.quarkus.devtools.buildfile.GradleBuildFilesCreator;
+import io.quarkus.devtools.project.BuildTool;
+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.rest.BasicRestProjectGenerator;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import io.quarkus.platform.tools.ToolsUtils;
import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
import java.util.Properties;
+import java.util.Set;
/**
* Instances of this class are thread-safe. They create a new project extracting all the necessary properties from an instance
* of {@link QuarkusCommandInvocation}.
*/
-public class CreateProjectCommandHandler implements QuarkusCommand {
+public class CreateProjectCommandHandler implements QuarkusCommandHandler {
@Override
public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException {
- final ProjectWriter projectWriter = new FileProjectWriter(
- invocation.getQuarkusProject().getProjectFolderPath().toFile());
- if (!projectWriter.init()) {
- return QuarkusCommandOutcome.failure();
- }
-
final QuarkusPlatformDescriptor platformDescr = invocation.getPlatformDescriptor();
invocation.setValue(BOM_GROUP_ID, platformDescr.getBomGroupId());
invocation.setValue(BOM_ARTIFACT_ID, platformDescr.getBomArtifactId());
invocation.setValue(QUARKUS_VERSION, platformDescr.getQuarkusVersion());
invocation.setValue(BOM_VERSION, platformDescr.getBomVersion());
+ final Set extensionsQuery = invocation.getValue(ProjectGenerator.EXTENSIONS, Collections.emptySet());
final Properties quarkusProps = ToolsUtils.readQuarkusProperties(platformDescr);
quarkusProps.forEach((k, v) -> invocation.setValue(k.toString().replace("-", "_"), v.toString()));
- try (BuildFile buildFile = invocation.getBuildFile()) {
+ try {
String className = invocation.getStringValue(CLASS_NAME);
if (className != null) {
className = invocation.getValue(SOURCE_TYPE, SourceType.JAVA).stripExtensionFrom(className);
@@ -50,13 +53,27 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws
}
invocation.setValue(CLASS_NAME, className);
}
- ProjectGeneratorRegistry.get(BasicRestProjectGenerator.NAME).generate(projectWriter, invocation);
- // call close at the end to save file
- buildFile.completeFile(invocation.getStringValue(PROJECT_GROUP_ID),
- invocation.getStringValue(PROJECT_ARTIFACT_ID),
- invocation.getStringValue(PROJECT_VERSION),
- platformDescr, quarkusProps);
+ final List extensionsToAdd = computeExtensionsFromQuery(invocation, extensionsQuery);
+
+ // extensionsToAdd is null when an error occurred while matching extensions
+ if (extensionsToAdd != null) {
+ ProjectGeneratorRegistry.get(BasicRestProjectGenerator.NAME).generate(invocation);
+
+ //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(
+ invocation.getStringValue(PROJECT_GROUP_ID),
+ invocation.getStringValue(PROJECT_ARTIFACT_ID),
+ invocation.getStringValue(PROJECT_VERSION),
+ quarkusProps,
+ extensionsToAdd);
+ } else {
+ invocation.getQuarkusProject().getExtensionsManager().install(extensionsToAdd);
+ }
+ }
+
} catch (IOException e) {
throw new QuarkusCommandException("Failed to create project", e);
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensions.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensions.java
index 6f9fd3adbc4382..b22f23e2b145cc 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensions.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensions.java
@@ -1,11 +1,14 @@
package io.quarkus.cli.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import io.quarkus.platform.tools.ToolsConstants;
import io.quarkus.platform.tools.ToolsUtils;
-import java.io.IOException;
-import java.util.Map;
-import org.apache.maven.model.Dependency;
/**
* Instances of this class are not thread-safe. They are created per single invocation.
@@ -16,6 +19,7 @@ public class ListExtensions {
public static final String ALL = ToolsUtils.dotJoin(PARAM_PREFIX, "all");
public static final String FORMAT = ToolsUtils.dotJoin(PARAM_PREFIX, "format");
public static final String SEARCH = ToolsUtils.dotJoin(PARAM_PREFIX, "search");
+ public static final String EXTENSIONS_MANAGER = ToolsUtils.dotJoin(PARAM_PREFIX, "extensions-manager");
private final QuarkusCommandInvocation invocation;
private final ListExtensionsCommandHandler handler = new ListExtensionsCommandHandler();
@@ -34,32 +38,17 @@ public ListExtensions format(String format) {
return this;
}
- public ListExtensions search(String search) {
- invocation.setValue(SEARCH, search);
+ public ListExtensions extensionsManager(ExtensionsManager extensionsManager) {
+ invocation.setValue(EXTENSIONS_MANAGER, checkNotNull(extensionsManager, "extensionsManager is required"));
return this;
}
- /**
- * @deprecated in 1.3.0.CR1
- * Please use {@link #all(boolean)}, {@link #format(String)} and {@link #search(String)} respectively.
- */
- @Deprecated
- public void listExtensions(boolean all, String format, String search) throws IOException {
- all(all);
- format(format);
- search(search);
- try {
- execute();
- } catch (QuarkusCommandException e) {
- throw new IOException("Failed to list extensions", e);
- }
+ public ListExtensions search(String search) {
+ invocation.setValue(SEARCH, search);
+ return this;
}
public QuarkusCommandOutcome execute() throws QuarkusCommandException {
return handler.execute(invocation);
}
-
- public Map findInstalled() throws IOException {
- return handler.findInstalled(invocation);
- }
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensionsCommandHandler.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensionsCommandHandler.java
index 4f5f1fe82ea248..4c39c07250737f 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensionsCommandHandler.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ListExtensionsCommandHandler.java
@@ -1,23 +1,29 @@
package io.quarkus.cli.commands;
+import static java.util.stream.Collectors.toMap;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.dependencies.Extension;
-import io.quarkus.devtools.buildfile.BuildFile;
-import io.quarkus.devtools.buildfile.GradleBuildFile;
+import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
+import io.quarkus.platform.tools.MessageWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.function.Consumer;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.apache.maven.model.Dependency;
/**
* Instances of this class are thread-safe. It lists extensions according to the options passed in as properties of
* {@link QuarkusCommandInvocation}
*/
-public class ListExtensionsCommandHandler implements QuarkusCommand {
+public class ListExtensionsCommandHandler implements QuarkusCommandHandler {
private static final String FULL_FORMAT = "%-8s %-50s %-50s %-25s%n%s";
private static final String CONCISE_FORMAT = "%-50s %-50s";
@@ -29,72 +35,71 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws
final boolean all = invocation.getValue(ListExtensions.ALL, true);
final String format = invocation.getValue(ListExtensions.FORMAT, "concise");
final String search = invocation.getValue(ListExtensions.SEARCH, "*");
+ final ExtensionsManager extensionsManager = invocation.getValue(ListExtensions.EXTENSIONS_MANAGER,
+ invocation.getQuarkusProject().getExtensionsManager());
- Map installed;
+ Map installedByGA;
try {
- installed = findInstalled(invocation);
+ installedByGA = extensionsManager.getInstalled().stream()
+ .collect(toMap(Extension::managementKey, Function.identity()));
} catch (IOException e) {
throw new QuarkusCommandException("Failed to determine the list of installed extensions", e);
}
- Stream extensionsStream = invocation.getPlatformDescriptor().getExtensions().stream();
- extensionsStream = extensionsStream.filter(e -> filterUnlisted(e));
+ Stream platformExtensionsStream = invocation.getPlatformDescriptor().getExtensions().stream();
+ platformExtensionsStream = platformExtensionsStream.filter(this::filterUnlisted);
if (search != null && !"*".equalsIgnoreCase(search)) {
final Pattern searchPattern = Pattern.compile(".*" + search + ".*", Pattern.CASE_INSENSITIVE);
- extensionsStream = extensionsStream.filter(e -> filterBySearch(searchPattern, e));
+ platformExtensionsStream = platformExtensionsStream.filter(e -> filterBySearch(searchPattern, e));
}
- List loadedExtensions = extensionsStream.collect(Collectors.toList());
+ List platformExtensions = platformExtensionsStream.collect(Collectors.toList());
- if (loadedExtensions.isEmpty()) {
- System.out.println("No extension found with this pattern");
+ if (platformExtensions.isEmpty()) {
+ invocation.log().info("No extension found with this pattern");
} else {
String extensionStatus = all ? "available" : "installable";
- System.out.println(String.format("%nCurrent Quarkus extensions %s: ", extensionStatus));
+ invocation.log().info(String.format("%nCurrent Quarkus extensions %s: ", extensionStatus));
- Consumer currentFormatter;
+ BiConsumer currentFormatter;
switch (format.toLowerCase()) {
case "name":
currentFormatter = this::nameFormatter;
break;
case "full":
currentFormatter = this::fullFormatter;
- currentFormatter.accept(new String[] { "Status", "Extension", "ArtifactId", "Updated Version", "Guide" });
+ currentFormatter.accept(invocation.log(),
+ new String[] { "Status", "Extension", "ArtifactId", "Updated Version", "Guide" });
break;
case "concise":
default:
currentFormatter = this::conciseFormatter;
}
- final BuildFile buildFile = invocation.getBuildFile();
- loadedExtensions.forEach(extension -> display(extension, installed, all, currentFormatter, buildFile));
-
- if (buildFile != null) {
- if ("concise".equalsIgnoreCase(format)) {
- if (buildFile instanceof GradleBuildFile) {
- System.out.println("\nTo get more information, append --format=full to your command line.");
- } else {
- System.out.println(
- "\nTo get more information, append -Dquarkus.extension.format=full to your command line.");
- }
- }
-
- if (buildFile instanceof GradleBuildFile) {
- System.out.println("\nAdd an extension to your project by adding the dependency to your " +
- "build.gradle or use `./gradlew addExtension --extensions=\"artifactId\"`");
+ platformExtensions.forEach(platformExtension -> display(invocation.log(), platformExtension,
+ installedByGA.get(platformExtension.managementKey()), all, currentFormatter));
+ final BuildTool buildTool = invocation.getQuarkusProject().getBuildTool();
+ if ("concise".equalsIgnoreCase(format)) {
+ if (BuildTool.GRADLE.equals(buildTool)) {
+ invocation.log().info("\nTo get more information, append --format=full to your command line.");
} else {
- System.out.println("\nAdd an extension to your project by adding the dependency to your " +
- "pom.xml or use `./mvnw quarkus:add-extension -Dextensions=\"artifactId\"`");
+ invocation.log().info(
+ "\nTo get more information, append -Dquarkus.extension.format=full to your command line.");
}
}
+
+ if (BuildTool.GRADLE.equals(buildTool)) {
+ invocation.log().info("\nAdd an extension to your project by adding the dependency to your " +
+ "build.gradle or use `./gradlew addExtension --extensions=\"artifactId\"`");
+ } else {
+ invocation.log().info("\nAdd an extension to your project by adding the dependency to your " +
+ "pom.xml or use `./mvnw quarkus:add-extension -Dextensions=\"artifactId\"`");
+ }
+
}
return QuarkusCommandOutcome.success();
}
- Map findInstalled(QuarkusCommandInvocation invocation) throws IOException {
- return invocation.getBuildFile().findInstalled();
- }
-
private boolean filterUnlisted(Extension e) {
return !e.getMetadata().containsKey("unlisted");
}
@@ -103,65 +108,46 @@ private boolean filterBySearch(final Pattern searchPattern, Extension e) {
return searchPattern.matcher(e.getName()).matches();
}
- private void conciseFormatter(String[] cols) {
- System.out.println(String.format(CONCISE_FORMAT, cols[1], cols[2], cols[4]));
+ private void conciseFormatter(MessageWriter writer, String[] cols) {
+ writer.info(String.format(CONCISE_FORMAT, cols[1], cols[2], cols[4]));
}
- private void fullFormatter(String[] cols) {
- System.out.println(String.format(FULL_FORMAT, cols[0], cols[1], cols[2], cols[3], cols[4]));
+ private void fullFormatter(MessageWriter writer, String[] cols) {
+ writer.info(String.format(FULL_FORMAT, cols[0], cols[1], cols[2], cols[3], cols[4]));
}
- private void nameFormatter(String[] cols) {
- System.out.println(String.format(NAME_FORMAT, cols[2]));
+ private void nameFormatter(MessageWriter writer, String[] cols) {
+ writer.info(String.format(NAME_FORMAT, cols[2]));
}
- private void display(Extension extension, final Map installed, boolean all,
- Consumer formatter, BuildFile buildFile) {
- final Dependency dependency = installed.get(extension.getGroupId() + ":" + extension.getArtifactId());
- if (!all && dependency != null) {
+ private void display(MessageWriter messageWriter, final Extension platformExtension, final Extension installed, boolean all,
+ BiConsumer formatter) {
+ if (!all && installed != null) {
return;
}
String label = "";
String version = "";
- final String extracted = extractVersion(dependency, buildFile);
- if (extracted != null) {
- if (extracted.equalsIgnoreCase(extension.getVersion())) {
+ final String installedVersion = installed != null ? installed.getVersion() : null;
+ if (installedVersion != null) {
+ if (installedVersion.equalsIgnoreCase(platformExtension.getVersion())) {
label = "current";
- version = String.format("%s", extracted);
+ version = String.format("%s", installedVersion);
} else {
label = "update";
- version = String.format("%s <> %s", extracted, extension.getVersion());
+ version = String.format("%s <> %s", installedVersion, platformExtension.getVersion());
}
}
- String[] result = new String[] { label, extension.getName(), extension.getArtifactId(), version, extension.getGuide() };
+ String[] result = new String[] { label, platformExtension.getName(), platformExtension.getArtifactId(), version,
+ platformExtension.getGuide() };
for (int i = 0; i < result.length; i++) {
result[i] = Objects.toString(result[i], "");
}
- formatter.accept(result);
+ formatter.accept(messageWriter, result);
}
- private String extractVersion(final Dependency dependency, BuildFile buildFile) {
- String version = dependency != null ? dependency.getVersion() : null;
- if (version != null && version.startsWith("$") && buildFile != null) {
- String value = null;
- try {
- value = (String) buildFile.getProperty(propertyName(version));
- } catch (IOException e) {
- // ignore this error.
- }
- if (value != null) {
- version = value;
- }
- }
- return version;
- }
-
- private String propertyName(final String variable) {
- return variable.substring(2, variable.length() - 1);
- }
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/Printer.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/Printer.java
deleted file mode 100644
index 1b74c43ca230b0..00000000000000
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/Printer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.quarkus.cli.commands;
-
-public class Printer {
- private static final String OK = "\u2705";
- static final String NOK = "\u274c";
- private static final String NOOP = "\uD83D\uDC4D";
-
- public void nok(String content) {
- print(NOK + content);
- }
-
- public void ok(String content) {
- print(OK + content);
- }
-
- public void noop(String content) {
- print(NOOP + content);
- }
-
- void print(String message) {
- System.out.println(message);
- }
-
-}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java
deleted file mode 100644
index 31025343198fd1..00000000000000
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommand.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.quarkus.cli.commands;
-
-public interface QuarkusCommand {
-
- QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException;
-}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandler.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandler.java
new file mode 100644
index 00000000000000..8f8279be0aa74c
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandler.java
@@ -0,0 +1,10 @@
+package io.quarkus.cli.commands;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
+
+public interface QuarkusCommandHandler {
+
+ QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException;
+}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandlers.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandlers.java
new file mode 100644
index 00000000000000..e10c46f29b5724
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandHandlers.java
@@ -0,0 +1,213 @@
+package io.quarkus.cli.commands;
+
+import static io.quarkus.platform.tools.ConsoleMessageFormat.NOK;
+import static io.quarkus.platform.tools.ConsoleMessageFormat.nok;
+
+import com.google.common.collect.ImmutableList;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.SelectionResult;
+import io.quarkus.dependencies.Extension;
+import io.quarkus.devtools.project.extensions.Extensions;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import java.util.stream.Collectors;
+
+final class QuarkusCommandHandlers {
+
+ private QuarkusCommandHandlers() {
+ }
+
+ static List computeExtensionsFromQuery(final QuarkusCommandInvocation invocation,
+ final Set extensionsQuery) {
+ final ImmutableList.Builder builder = ImmutableList. builder();
+ for (String query : extensionsQuery) {
+ if (query.contains(":")) {
+ builder.add(Extensions.parse(query));
+ } else {
+ SelectionResult result = select(invocation.getPlatformDescriptor().getExtensions(), query, false);
+ if (!result.matches()) {
+ StringBuilder sb = new StringBuilder();
+ // We have 3 cases, we can still have a single candidate, but the match is on label
+ // or we have several candidates, or none
+ Set candidates = result.getExtensions();
+ if (candidates.isEmpty()) {
+ // No matches at all.
+ invocation.log().info(nok(" Cannot find a dependency matching '" + query + "', maybe a typo?"));
+ return null;
+ } else {
+ sb.append(NOK).append(" Multiple extensions matching '").append(query).append("'");
+ result.getExtensions()
+ .forEach(extension -> sb.append(System.lineSeparator()).append(" * ")
+ .append(extension.managementKey()));
+ sb.append(System.lineSeparator())
+ .append(" Be more specific e.g using the exact name or the full GAV.");
+ invocation.log().info(sb.toString());
+ return null;
+ }
+ } else { // Matches.
+ for (Extension extension : result) {
+ // Don't set success to false even if the dependency is not added; as it's should be idempotent.
+ builder.add(extension);
+ }
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Selection algorithm.
+ *
+ * @param allPlatformExtensions the list of all platform extensions
+ * @param query the query
+ * @param labelLookup whether or not the query must be tested against the labels of the extensions. Should
+ * be {@code false} by default.
+ * @return the list of matching candidates and whether or not a match has been found.
+ */
+ static SelectionResult select(final List allPlatformExtensions, final String query, final boolean labelLookup) {
+ String q = query.trim().toLowerCase();
+
+ // Try exact matches
+ Set matchesNameOrArtifactId = allPlatformExtensions.stream()
+ .filter(extension -> extension.getName().equalsIgnoreCase(q) || matchesArtifactId(extension.getArtifactId(), q))
+ .collect(Collectors.toSet());
+ if (matchesNameOrArtifactId.size() == 1) {
+ return new SelectionResult(matchesNameOrArtifactId, true);
+ }
+
+ final List listedPlatformExtensions = allPlatformExtensions.stream()
+ .filter(e -> !e.isUnlisted()).collect(Collectors.toList());
+
+ // Try short names
+ Set matchesShortName = listedPlatformExtensions.stream().filter(extension -> matchesShortName(extension, q))
+ .collect(Collectors.toSet());
+
+ if (matchesShortName.size() == 1 && matchesNameOrArtifactId.isEmpty()) {
+ return new SelectionResult(matchesShortName, true);
+ }
+
+ // Partial matches on name, artifactId and short names
+ Set partialMatches = listedPlatformExtensions.stream()
+ .filter(extension -> extension.getName().toLowerCase().contains(q)
+ || extension.getArtifactId().toLowerCase().contains(q)
+ || extension.getShortName().toLowerCase().contains(q))
+ .collect(Collectors.toSet());
+ // Even if we have a single partial match, if the name, artifactId and short names are ambiguous, so not
+ // consider it as a match.
+ if (partialMatches.size() == 1 && matchesNameOrArtifactId.isEmpty() && matchesShortName.isEmpty()) {
+ return new SelectionResult(partialMatches, true);
+ }
+
+ // find by labels
+ List matchesLabels;
+ if (labelLookup) {
+ matchesLabels = listedPlatformExtensions.stream()
+ .filter(extension -> extension.labelsForMatching().contains(q)).collect(Collectors.toList());
+ } else {
+ matchesLabels = Collections.emptyList();
+ }
+
+ // find by pattern
+ Set matchesPatterns;
+ Pattern pattern = toRegex(q);
+ if (pattern != null) {
+ matchesPatterns = listedPlatformExtensions.stream()
+ .filter(extension -> pattern.matcher(extension.getName().toLowerCase()).matches()
+ || pattern.matcher(extension.getArtifactId().toLowerCase()).matches()
+ || pattern.matcher(extension.getShortName().toLowerCase()).matches()
+ || matchLabels(pattern, extension.getKeywords()))
+ .collect(Collectors.toSet());
+ return new SelectionResult(matchesPatterns, true);
+ } else {
+ matchesPatterns = Collections.emptySet();
+ }
+
+ Set candidates = new LinkedHashSet<>();
+ candidates.addAll(matchesNameOrArtifactId);
+ candidates.addAll(matchesShortName);
+ candidates.addAll(partialMatches);
+ candidates.addAll(matchesLabels);
+ candidates.addAll(matchesPatterns);
+ return new SelectionResult(candidates, false);
+ }
+
+ private static boolean matchLabels(Pattern pattern, List labels) {
+ boolean matches = false;
+ // if any label match it's ok
+ for (String label : labels) {
+ matches = matches || pattern.matcher(label.toLowerCase()).matches();
+ }
+ return matches;
+ }
+
+ private static Pattern toRegex(final String str) {
+ try {
+ String wildcardToRegex = wildcardToRegex(str);
+ if (wildcardToRegex != null && !wildcardToRegex.isEmpty()) {
+ return Pattern.compile(wildcardToRegex);
+ }
+ } catch (PatternSyntaxException e) {
+ //ignore it
+ }
+ return null;
+ }
+
+ private static String wildcardToRegex(String wildcard) {
+ if (wildcard == null || wildcard.isEmpty()) {
+ return null;
+ }
+ // don't try with file match char in pattern
+ if (!(wildcard.contains("*") || wildcard.contains("?"))) {
+ return null;
+ }
+ StringBuffer s = new StringBuffer(wildcard.length());
+ s.append("^.*");
+ for (int i = 0, is = wildcard.length(); i < is; i++) {
+ char c = wildcard.charAt(i);
+ switch (c) {
+ case '*':
+ s.append(".*");
+ break;
+ case '?':
+ s.append(".");
+ break;
+ case '^': // escape character in cmd.exe
+ s.append("\\");
+ break;
+ // escape special regexp-characters
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '$':
+ case '.':
+ case '{':
+ case '}':
+ case '|':
+ case '\\':
+ s.append("\\");
+ s.append(c);
+ break;
+ default:
+ s.append(c);
+ break;
+ }
+ }
+ s.append(".*$");
+ return (s.toString());
+ }
+
+ private static boolean matchesShortName(Extension extension, String q) {
+ return q.equalsIgnoreCase(extension.getShortName());
+ }
+
+ private static boolean matchesArtifactId(String artifactId, String q) {
+ return artifactId.equalsIgnoreCase(q) ||
+ artifactId.equalsIgnoreCase("quarkus-" + q);
+ }
+
+}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensions.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensions.java
index 5e6c2b6de8ed5c..e44af4d6c6b871 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensions.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensions.java
@@ -1,6 +1,12 @@
package io.quarkus.cli.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import io.quarkus.platform.tools.ToolsConstants;
import io.quarkus.platform.tools.ToolsUtils;
import java.util.Set;
@@ -13,6 +19,7 @@ public class RemoveExtensions {
public static final String NAME = "remove-extensions";
public static final String EXTENSIONS = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "extensions");
public static final String OUTCOME_UPDATED = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "outcome", "updated");
+ public static final String EXTENSIONS_MANAGER = ToolsUtils.dotJoin(ToolsConstants.QUARKUS, NAME, "extensions-manager");
private final QuarkusCommandInvocation invocation;
@@ -25,6 +32,11 @@ public RemoveExtensions extensions(Set extensions) {
return this;
}
+ public RemoveExtensions extensionsManager(ExtensionsManager extensionsManager) {
+ invocation.setValue(EXTENSIONS_MANAGER, checkNotNull(extensionsManager, "extensionsManager is required"));
+ return this;
+ }
+
public QuarkusCommandOutcome execute() throws QuarkusCommandException {
return new RemoveExtensionsCommandHandler().execute(invocation);
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensionsCommandHandler.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensionsCommandHandler.java
index 24aea2fa73a71b..4f41ab28d73921 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensionsCommandHandler.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/RemoveExtensionsCommandHandler.java
@@ -1,7 +1,14 @@
package io.quarkus.cli.commands;
+import static io.quarkus.cli.commands.QuarkusCommandHandlers.computeExtensionsFromQuery;
+import static io.quarkus.cli.commands.RemoveExtensions.EXTENSIONS_MANAGER;
+
+import com.google.common.collect.ImmutableSet;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.dependencies.Extension;
-import io.quarkus.devtools.buildfile.BuildFile;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
@@ -11,69 +18,27 @@
* This class is thread-safe. It extracts extensions to be removed from the project from an instance of
* {@link QuarkusCommandInvocation}.
*/
-public class RemoveExtensionsCommandHandler implements QuarkusCommand {
-
- final static Printer PRINTER = new Printer();
+public class RemoveExtensionsCommandHandler implements QuarkusCommandHandler {
@Override
public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException {
- final Set extensions = invocation.getValue(RemoveExtensions.EXTENSIONS, Collections.emptySet());
- if (extensions.isEmpty()) {
+ final Set extensionsQuery = invocation.getValue(RemoveExtensions.EXTENSIONS, Collections.emptySet());
+ if (extensionsQuery.isEmpty()) {
return QuarkusCommandOutcome.success().setValue(RemoveExtensions.OUTCOME_UPDATED, false);
}
- boolean updated = false;
- boolean success = true;
-
- final List registry = invocation.getPlatformDescriptor().getExtensions();
- final BuildFile buildFile = invocation.getBuildFile();
-
+ final List extensionsToRemove = computeExtensionsFromQuery(invocation, extensionsQuery);
+ final ExtensionsManager extensionsManager = invocation.getValue(EXTENSIONS_MANAGER,
+ invocation.getQuarkusProject().getExtensionsManager());
try {
- for (String query : extensions) {
-
- if (query.contains(":")) {
- // GAV case.
- updated = buildFile.removeExtensionAsGAV(query) || updated;
- } else {
- SelectionResult result = AddExtensionsCommandHandler.select(query, registry, false);
- if (!result.matches()) {
- StringBuilder sb = new StringBuilder();
- // We have 3 cases, we can still have a single candidate, but the match is on label
- // or we have several candidates, or none
- Set candidates = result.getExtensions();
- if (candidates.isEmpty()) {
- // No matches at all.
- PRINTER.nok(" Cannot find a dependency matching '" + query + "', maybe a typo?");
- success = false;
- } else {
- sb.append(Printer.NOK).append(" Multiple extensions matching '").append(query).append("'");
- result.getExtensions()
- .forEach(extension -> sb.append(System.lineSeparator()).append(" * ")
- .append(extension.managementKey()));
- sb.append(System.lineSeparator())
- .append(" Be more specific e.g using the exact name");
- PRINTER.print(sb.toString());
- success = false;
- }
- } else { // Matches.
- for (Extension extension : result) {
- updated = buildFile.removeDependency(invocation.getPlatformDescriptor(), extension) || updated;
- }
- }
- }
+ if (extensionsToRemove != null) {
+ final int removed = extensionsManager.uninstall(ImmutableSet.copyOf(extensionsToRemove));
+ return new QuarkusCommandOutcome(true).setValue(RemoveExtensions.OUTCOME_UPDATED, removed > 0);
}
} catch (IOException e) {
throw new QuarkusCommandException("Failed to add extensions", e);
}
- if (updated) {
- try {
- buildFile.close();
- } catch (IOException e) {
- throw new QuarkusCommandException("Failed to update the project", e);
- }
- }
-
- return new QuarkusCommandOutcome(success).setValue(RemoveExtensions.OUTCOME_UPDATED, updated);
+ return new QuarkusCommandOutcome(true).setValue(RemoveExtensions.OUTCOME_UPDATED, false);
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandException.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandException.java
similarity index 88%
rename from independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandException.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandException.java
index e9545c28ae89f8..cc85487df14ee8 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandException.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandException.java
@@ -1,4 +1,4 @@
-package io.quarkus.cli.commands;
+package io.quarkus.cli.commands.data;
public class QuarkusCommandException extends Exception {
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandInvocation.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandInvocation.java
similarity index 87%
rename from independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandInvocation.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandInvocation.java
index 3f2de476c5a9e3..75abaefc6f2e6b 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandInvocation.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandInvocation.java
@@ -1,8 +1,7 @@
-package io.quarkus.cli.commands;
+package io.quarkus.cli.commands.data;
import static com.google.common.base.Preconditions.checkNotNull;
-import io.quarkus.devtools.buildfile.BuildFile;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import io.quarkus.platform.tools.DefaultMessageWriter;
@@ -43,11 +42,7 @@ public MessageWriter log() {
}
public QuarkusPlatformDescriptor getPlatformDescriptor() {
- return quarkusProject.getDescriptor();
- }
-
- public BuildFile getBuildFile() {
- return quarkusProject.getBuildFile();
+ return quarkusProject.getPlatformDescriptor();
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandOutcome.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandOutcome.java
similarity index 92%
rename from independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandOutcome.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandOutcome.java
index be8747ea3d9df5..8e8ee3f3a8d980 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/QuarkusCommandOutcome.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/QuarkusCommandOutcome.java
@@ -1,4 +1,4 @@
-package io.quarkus.cli.commands;
+package io.quarkus.cli.commands.data;
public class QuarkusCommandOutcome extends ValueMap {
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/SelectionResult.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/SelectionResult.java
similarity index 95%
rename from independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/SelectionResult.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/SelectionResult.java
index 3b51911a5794ed..d96119d97fd799 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/SelectionResult.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/SelectionResult.java
@@ -1,4 +1,4 @@
-package io.quarkus.cli.commands;
+package io.quarkus.cli.commands.data;
import io.quarkus.dependencies.Extension;
import java.util.Collections;
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ValueMap.java b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/ValueMap.java
similarity index 83%
rename from independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ValueMap.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/ValueMap.java
index 7636d9a88b5c6e..e2f100d06a3f2f 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/ValueMap.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/cli/commands/data/ValueMap.java
@@ -1,4 +1,4 @@
-package io.quarkus.cli.commands;
+package io.quarkus.cli.commands.data;
import java.util.HashMap;
import java.util.Map;
@@ -48,6 +48,18 @@ public String getStringValue(String name) {
throw new IllegalStateException("value for '" + name + "' must be a String");
}
+ public boolean getBooleanValue(String name) {
+ final Object value = getValue(name, null);
+ if (value == null) {
+ throw new IllegalStateException("value for '" + name + "' must be defined");
+ }
+
+ if (Boolean.class.equals(value.getClass())) {
+ return ((Boolean) value).booleanValue();
+ }
+ return Boolean.parseBoolean(value.toString());
+ }
+
public boolean getValue(String name, boolean defaultValue) {
final Object value = getValue(name, null);
if (value == null) {
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/AbstractGradleBuildFile.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/AbstractGradleBuildFile.java
new file mode 100644
index 00000000000000..582b1a9882c787
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/AbstractGradleBuildFile.java
@@ -0,0 +1,242 @@
+package io.quarkus.devtools.buildfile;
+
+import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import org.apache.maven.model.Dependency;
+
+// We keep it here to take advantage of the abstract tests
+public 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 Optional rootProjectPath;
+
+ private AtomicReference modelReference = new AtomicReference<>();
+
+ public AbstractGradleBuildFile(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor) {
+ super(projectFolderPath, platformDescriptor);
+ this.rootProjectPath = Optional.empty();
+ }
+
+ public AbstractGradleBuildFile(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor,
+ Path rootProjectPath) {
+ super(projectFolderPath, platformDescriptor);
+ this.rootProjectPath = Optional.ofNullable(rootProjectPath);
+ }
+
+ @Override
+ public void writeToDisk() throws IOException {
+ if (rootProjectPath.isPresent()) {
+ Files.write(rootProjectPath.get().resolve(SETTINGS_GRADLE_PATH), getModel().getRootSettingsContent().getBytes());
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ getModel().getRootPropertiesContent().store(out, "Gradle properties");
+ Files.write(rootProjectPath.get().resolve(GRADLE_PROPERTIES_PATH),
+ getModel().getRootSettingsContent().getBytes());
+ }
+ } else {
+ writeToProjectFile(SETTINGS_GRADLE_PATH, 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 void addDependencyInBuildFile(Dependency dependency) throws IOException {
+ StringBuilder newBuildContent = new StringBuilder();
+ readLineByLine(getModel().getBuildContent(), currentLine -> {
+ newBuildContent.append(currentLine).append(System.lineSeparator());
+ if (currentLine.startsWith("dependencies {")) {
+ newBuildContent.append(" implementation '")
+ .append(dependency.getGroupId())
+ .append(":")
+ .append(dependency.getArtifactId());
+ if (dependency.getVersion() != null && !dependency.getVersion().isEmpty()) {
+ newBuildContent.append(":")
+ .append(dependency.getVersion());
+ }
+ newBuildContent.append("'")
+ .append(System.lineSeparator());
+ }
+ });
+ getModel().setBuildContent(newBuildContent.toString());
+ }
+
+ @Override
+ protected void removeDependencyFromBuildFile(Dependency dependency) throws IOException {
+ String depString = new StringBuilder("'").append(dependency.getGroupId()).append(":")
+ .append(dependency.getArtifactId()).toString();
+ StringBuilder newBuildContent = new StringBuilder();
+ Scanner scanner = new Scanner(getModel().getBuildContent());
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ if (!line.contains(depString)) {
+ newBuildContent.append(line).append(System.lineSeparator());
+ }
+ }
+ scanner.close();
+ getModel().setBuildContent(newBuildContent.toString());
+ }
+
+ @Override
+ protected boolean containsBOM(String groupId, String artifactId) throws IOException {
+ String buildContent = getModel().getBuildContent();
+ return buildContent.contains("enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:")
+ || buildContent.contains("enforcedPlatform(\"" + groupId + ":" + artifactId + ":");
+ }
+
+ @Override
+ public String getProperty(String propertyName) throws IOException {
+ final String property = getModel().getPropertiesContent().getProperty(propertyName);
+ if (property != null || getModel().getRootPropertiesContent() == null) {
+ return property;
+ }
+ return getModel().getRootPropertiesContent().getProperty(propertyName);
+ }
+
+ @Override
+ public BuildTool getBuildTool() {
+ return BuildTool.GRADLE;
+ }
+
+ private void readLineByLine(String content, Consumer lineConsumer) {
+ try (Scanner scanner = new Scanner(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)),
+ StandardCharsets.UTF_8.name())) {
+ while (scanner.hasNextLine()) {
+ String currentLine = scanner.nextLine();
+ lineConsumer.accept(currentLine);
+ }
+ }
+ }
+
+ private Model getModel() throws IOException {
+ return modelReference.updateAndGet(model -> {
+ if (model == null) {
+ try {
+ return readModel();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ return model;
+ });
+ }
+
+ @Override
+ protected void refreshData() {
+ this.modelReference.set(null);
+ }
+
+ private boolean hasRootProjectFile(final String fileName) throws IOException {
+ if (!rootProjectPath.isPresent()) {
+ return false;
+ }
+ final Path filePath = rootProjectPath.get().resolve(fileName);
+ return Files.exists(filePath);
+ }
+
+ private byte[] readRootProjectFile(final String fileName) throws IOException {
+ final Path filePath = rootProjectPath
+ .orElseThrow(() -> new IllegalStateException("There is no rootProject defined in this GradleBuildFile"))
+ .resolve(fileName);
+ return Files.readAllBytes(filePath);
+ }
+
+ private Model readModel() throws IOException {
+ String settingsContent = "";
+ String buildContent = "";
+ Properties propertiesContent = new Properties();
+ String rootSettingsContent = null;
+ Properties rootPropertiesContent = null;
+ if (hasProjectFile(SETTINGS_GRADLE_PATH)) {
+ final byte[] settings = readProjectFile(SETTINGS_GRADLE_PATH);
+ settingsContent = new String(settings, StandardCharsets.UTF_8);
+ }
+ if (hasRootProjectFile(SETTINGS_GRADLE_PATH)) {
+ final byte[] settings = readRootProjectFile(SETTINGS_GRADLE_PATH);
+ rootSettingsContent = new String(settings, StandardCharsets.UTF_8);
+ }
+ if (hasProjectFile(BUILD_GRADLE_PATH)) {
+ final byte[] build = readProjectFile(BUILD_GRADLE_PATH);
+ buildContent = new String(build, StandardCharsets.UTF_8);
+ }
+ if (hasProjectFile(GRADLE_PROPERTIES_PATH)) {
+ final byte[] properties = readProjectFile(GRADLE_PROPERTIES_PATH);
+ propertiesContent.load(new ByteArrayInputStream(properties));
+ }
+ if (hasRootProjectFile(GRADLE_PROPERTIES_PATH)) {
+ final byte[] properties = readRootProjectFile(GRADLE_PROPERTIES_PATH);
+ rootPropertiesContent = new Properties();
+ rootPropertiesContent.load(new ByteArrayInputStream(properties));
+ }
+ return new Model(settingsContent, buildContent, propertiesContent, rootSettingsContent, rootPropertiesContent);
+ }
+
+ protected String getBuildContent() throws IOException {
+ return getModel().getBuildContent();
+ }
+
+ private static class Model {
+ private String settingsContent;
+ private String buildContent;
+ private Properties propertiesContent;
+
+ private String rootSettingsContent;
+ private Properties rootPropertiesContent;
+
+ public Model(String settingsContent, String buildContent, Properties propertiesContent, String rootSettingsContent,
+ Properties rootPropertiesContent) {
+ this.settingsContent = settingsContent;
+ this.buildContent = buildContent;
+ this.propertiesContent = propertiesContent;
+ this.rootSettingsContent = rootSettingsContent;
+ this.rootPropertiesContent = rootPropertiesContent;
+ }
+
+ public String getSettingsContent() {
+ return settingsContent;
+ }
+
+ public String getBuildContent() {
+ return buildContent;
+ }
+
+ public Properties getPropertiesContent() {
+ return propertiesContent;
+ }
+
+ public String getRootSettingsContent() {
+ return rootSettingsContent;
+ }
+
+ public Properties getRootPropertiesContent() {
+ return rootPropertiesContent;
+ }
+
+ public void setSettingsContent(String settingsContent) {
+ this.settingsContent = settingsContent;
+ }
+
+ public void setBuildContent(String buildContent) {
+ this.buildContent = buildContent;
+ }
+
+ }
+
+}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/BuildFile.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/BuildFile.java
index 725e0a2e5e8d1a..a8ee8303745fbc 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/BuildFile.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/BuildFile.java
@@ -1,170 +1,163 @@
package io.quarkus.devtools.buildfile;
import static com.google.common.base.Preconditions.checkNotNull;
-import static io.quarkus.maven.utilities.MojoUtils.credentials;
+import static io.quarkus.devtools.project.extensions.Extensions.key;
import static java.util.stream.Collectors.toList;
-import io.quarkus.cli.commands.Printer;
import io.quarkus.dependencies.Extension;
-import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.writer.ProjectWriter;
-import io.quarkus.maven.utilities.MojoUtils;
-import io.quarkus.maven.utilities.QuarkusDependencyPredicate;
+import io.quarkus.devtools.project.extensions.Extensions;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
-import java.io.Closeable;
import java.io.IOException;
-import java.util.Collections;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeMap;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.stream.Collectors;
import org.apache.maven.model.Dependency;
-public abstract class BuildFile implements Closeable {
+public abstract class BuildFile implements ExtensionsManager {
- protected final static Printer PRINTER = new Printer();
+ private final Path projectFolderPath;
+ private final QuarkusPlatformDescriptor platformDescriptor;
- private final ProjectWriter writer;
-
- private final BuildTool buildTool;
-
- public BuildFile(final ProjectWriter writer, BuildTool buildTool) {
- this.writer = checkNotNull(writer, "writer is required");
- this.buildTool = checkNotNull(buildTool, "buildTool is required");
+ public BuildFile(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor) {
+ this.projectFolderPath = checkNotNull(projectFolderPath, "projectPath is required");
+ this.platformDescriptor = checkNotNull(platformDescriptor, "platformDescriptor is required");
}
- protected void write(String fileName, String content) throws IOException {
- writer.write(fileName, content);
+ @Override
+ public final boolean hasQuarkusPlatformBom() throws IOException {
+ return containsBOM(platformDescriptor.getBomGroupId(), platformDescriptor.getBomArtifactId());
}
- public boolean addDependency(QuarkusPlatformDescriptor platform, Extension extension) throws IOException {
- if (!hasDependency(extension)) {
- PRINTER.ok(" Adding extension " + extension.managementKey());
- Dependency dep;
- if (containsBOM(platform.getBomGroupId(), platform.getBomArtifactId())
- && isDefinedInBom(platform.getManagedDependencies(), extension)) {
- dep = extension.toDependency(true);
- } else {
- dep = extension.toDependency(false);
- if (getProperty(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_NAME) != null) {
- dep.setVersion(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_VALUE);
- }
- }
- addDependencyInBuildFile(dep);
- return true;
- } else {
- PRINTER.noop(" Skipping already present extension " + extension.managementKey());
- return false;
+ @Override
+ public final int install(List extensions) throws IOException {
+ if (!hasQuarkusPlatformBom()) {
+ throw new IllegalStateException("The Quarkus BOM is required to add a Quarkus extension");
}
+ this.refreshData();
+ final Set existingKeys = getDependenciesManagementKeys();
+ final LongAdder counter = new LongAdder();
+ extensions.stream()
+ .filter(a -> !existingKeys.contains(a.managementKey()))
+ .forEach(e -> {
+ try {
+ final boolean isInPlatformBom = isDefinedInRegistry(platformDescriptor.getExtensions(),
+ e.managementKey());
+ // We hardcode the version when it is already defined in the platform bom
+ addDependencyInBuildFile(e.toDependency(isInPlatformBom));
+ counter.increment();
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+ this.writeToDisk();
+ return counter.intValue();
}
- public boolean removeDependency(QuarkusPlatformDescriptor platform, Extension extension) throws IOException {
- if (hasDependency(extension)) {
- PRINTER.ok(" Removing extension " + extension.managementKey());
- Dependency dep;
- if (containsBOM(platform.getBomGroupId(), platform.getBomArtifactId())
- && isDefinedInBom(platform.getManagedDependencies(), extension)) {
- dep = extension.toDependency(true);
- } else {
- dep = extension.toDependency(false);
- if (getProperty(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_NAME) != null) {
- dep.setVersion(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_VALUE);
- }
- }
- removeDependencyFromBuildFile(dep);
- return true;
- } else {
- PRINTER.noop(" Skipping extension that does not exists " + extension.managementKey());
- return false;
- }
+ @Override
+ public final List getInstalled() throws IOException {
+ this.refreshData();
+ return this.getDependencies().stream().filter(d -> this.isRegisteredQuarkusExtension(key(d)))
+ .map(d -> new Extension(d.getGroupId(), d.getArtifactId(), extractVersion(d)))
+ .collect(toList());
+ }
+
+ @Override
+ public final int uninstall(Set extensions) throws IOException {
+ this.refreshData();
+ final Set existingKeys = getDependenciesManagementKeys();
+ final LongAdder counter = new LongAdder();
+ extensions.stream()
+ .filter(a -> existingKeys.contains(a.managementKey()))
+ .forEach(e -> {
+ try {
+ removeDependencyFromBuildFile(e.toDependency(true));
+ counter.increment();
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+ this.writeToDisk();
+ return counter.intValue();
}
protected abstract void addDependencyInBuildFile(Dependency dependency) throws IOException;
protected abstract void removeDependencyFromBuildFile(Dependency dependency) throws IOException;
- protected abstract boolean hasDependency(Extension extension) throws IOException;
-
- public boolean addExtensionAsGAV(String query) throws IOException {
- Dependency parsed = MojoUtils.parse(query.trim());
- boolean alreadyThere = getDependencies().stream()
- .anyMatch(d -> d.getManagementKey().equalsIgnoreCase(parsed.getManagementKey()));
- if (!alreadyThere) {
- PRINTER.ok(" Adding dependency " + parsed.getManagementKey());
- addDependencyInBuildFile(parsed);
- return true;
- } else {
- PRINTER.noop(" Skipping already present dependency " + parsed.getManagementKey());
- return false;
- }
- }
+ protected abstract List getDependencies() throws IOException;
- public boolean removeExtensionAsGAV(String query) throws IOException {
- Dependency parsed = MojoUtils.parse(query.trim());
- PRINTER.ok(" Removing dependency " + parsed.getManagementKey());
- removeDependencyFromBuildFile(parsed);
- return true;
- }
+ protected abstract void writeToDisk() throws IOException;
- protected boolean isDefinedInBom(List dependencies, Extension extension) {
- return dependencies.stream().anyMatch(dependency -> dependency.getGroupId().equalsIgnoreCase(extension.getGroupId())
- && dependency.getArtifactId().equalsIgnoreCase(extension.getArtifactId()));
- }
+ protected abstract String getProperty(String propertyName) throws IOException;
protected abstract boolean containsBOM(String groupId, String artifactId) throws IOException;
- public abstract List getDependencies() throws IOException;
+ protected abstract void refreshData();
- public Map findInstalled() throws IOException {
- return mapDependencies(getDependencies(), loadManaged());
+ protected Path getProjectFolderPath() {
+ return projectFolderPath;
}
- private Map loadManaged() throws IOException {
- final List managedDependencies = getManagedDependencies();
- return managedDependencies.isEmpty() ? Collections.emptyMap()
- : mapDependencies(managedDependencies, Collections.emptyMap());
+ protected boolean hasProjectFile(final String fileName) throws IOException {
+ final Path filePath = projectFolderPath.resolve(fileName);
+ return Files.exists(filePath);
}
- protected Map mapDependencies(final List dependencies,
- final Map managed) {
- final Map map = new TreeMap<>();
-
- if (dependencies != null) {
- final List listed = dependencies.stream()
- // THIS ASSUMES EXTENSIONS' groupId is always 'io.quarkus' which is wrong
- .filter(new QuarkusDependencyPredicate())
- .collect(toList());
-
- listed.forEach(d -> {
- if (d.getVersion() == null) {
- final Dependency managedDep = managed.get(credentials(d));
- if (managedDep != null) {
- final String version = managedDep.getVersion();
- if (version != null) {
- d.setVersion(version);
- }
- }
- }
+ protected byte[] readProjectFile(final String fileName) throws IOException {
+ final Path filePath = projectFolderPath.resolve(fileName);
+ return Files.readAllBytes(filePath);
+ }
- map.put(credentials(d), d);
- });
- }
- return map;
+ protected void writeToProjectFile(final String fileName, final byte[] content) throws IOException {
+ Files.write(projectFolderPath.resolve(fileName), content);
}
- public abstract String getProperty(String propertyName) throws IOException;
+ private boolean isRegisteredQuarkusExtension(final String managementKey) {
+ // This will not always be true as the platform descriptor does not contain the list of all available extensions
+ return isDefinedInRegistry(platformDescriptor.getExtensions(), managementKey);
+ }
- protected abstract List getManagedDependencies() throws IOException;
+ private Set getDependenciesManagementKeys() throws IOException {
+ return getDependencies().stream().map(Extensions::key).collect(Collectors.toSet());
+ }
- public abstract void completeFile(String groupId, String artifactId, String version, QuarkusPlatformDescriptor platform,
- Properties props) throws IOException;
+ private String extractVersion(final Dependency d) {
+ String version = d != null ? d.getVersion() : null;
+ if (version != null && version.startsWith("$")) {
+ String value = null;
+ try {
+ value = (String) this.getProperty(propertyName(version));
+ if (value != null) {
+ return value;
+ }
+ } catch (IOException e) {
+ // ignore this error.
+ }
+ }
+ if (version != null) {
+ return version;
+ }
+ return mapToExtensionFromRegistry(platformDescriptor.getExtensions(), key(d))
+ .map(Extension::getVersion)
+ .orElse(null);
+ }
- public BuildTool getBuildTool() {
- return buildTool;
+ private String propertyName(final String variable) {
+ return variable.substring(2, variable.length() - 1);
}
- protected ProjectWriter getWriter() {
- return writer;
+ public static boolean isDefinedInRegistry(List registry, final String managementKey) {
+ return mapToExtensionFromRegistry(registry, managementKey).isPresent();
}
+ public static Optional mapToExtensionFromRegistry(List registry, final String managementKey) {
+ return registry.stream().filter(k -> Objects.equals(k.managementKey(), managementKey)).findFirst();
+ }
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GenericGradleBuildFile.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GenericGradleBuildFile.java
new file mode 100644
index 00000000000000..688cdf731a1f21
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GenericGradleBuildFile.java
@@ -0,0 +1,39 @@
+package io.quarkus.devtools.buildfile;
+
+import io.quarkus.dependencies.Extension;
+import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * TODO We need to find a way to use the gradle api outside of a gradle plugin
+ */
+public class GenericGradleBuildFile implements ExtensionsManager {
+
+ @Override
+ public BuildTool getBuildTool() {
+ return BuildTool.GRADLE;
+ }
+
+ @Override
+ public List getInstalled() throws IOException {
+ throw new IllegalStateException("This feature is not yet implemented outside of the Gradle Plugin.");
+ }
+
+ @Override
+ public boolean hasQuarkusPlatformBom() throws IOException {
+ throw new IllegalStateException("This feature is not yet implemented outside of the Gradle Plugin.");
+ }
+
+ @Override
+ public int install(List extensions) throws IOException {
+ throw new IllegalStateException("This feature is not yet implemented outside of the Gradle Plugin.");
+ }
+
+ @Override
+ public int uninstall(Set extensions) throws IOException {
+ throw new IllegalStateException("This feature is not yet implemented outside of the Gradle Plugin.");
+ }
+}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFile.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFilesCreator.java
similarity index 52%
rename from independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFile.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFilesCreator.java
index e148e30bfe82ee..87e9bba54d075f 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFile.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/GradleBuildFilesCreator.java
@@ -1,77 +1,153 @@
package io.quarkus.devtools.buildfile;
+import static io.quarkus.devtools.buildfile.BuildFile.isDefinedInRegistry;
+
import io.quarkus.dependencies.Extension;
-import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.writer.ProjectWriter;
-import io.quarkus.maven.utilities.MojoUtils;
+import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import io.quarkus.platform.tools.ToolsUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
-import java.util.Collections;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import org.apache.maven.model.Dependency;
-public class GradleBuildFile extends BuildFile {
+public final class GradleBuildFilesCreator {
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<>();
- private final ProjectWriter rootWriter;
+ public GradleBuildFilesCreator(QuarkusProject quarkusProject) {
+ this.quarkusProject = quarkusProject;
+ }
- private Model model;
+ public void create(String groupId, String artifactId, String version,
+ Properties properties, List extensions) throws IOException {
+ createSettingsContent(artifactId);
+ createBuildContent(groupId, version);
+ createProperties();
+ extensions.stream()
+ .forEach(e -> {
+ try {
+ final boolean isInPlatformBom = isDefinedInRegistry(
+ quarkusProject.getPlatformDescriptor().getExtensions(), e.managementKey());
+ // We hardcode the version when it is already defined in the platform bom
+ addDependencyInBuildFile(e.toDependency(isInPlatformBom));
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+ this.writeToDisk();
+ }
- public GradleBuildFile(ProjectWriter writer) {
- super(writer, BuildTool.GRADLE);
- rootWriter = writer;
+ private void writeToDisk() throws IOException {
+ writeToProjectFile(SETTINGS_GRADLE_PATH, getModel().getSettingsContent().getBytes());
+ writeToProjectFile(BUILD_GRADLE_PATH, getModel().getBuildContent().getBytes());
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ getModel().getPropertiesContent().store(out, "Gradle properties");
+ writeToProjectFile(GRADLE_PROPERTIES_PATH, out.toByteArray());
+ }
}
- public GradleBuildFile(ProjectWriter writer, ProjectWriter rootWriter) {
- super(writer, BuildTool.GRADLE);
- this.rootWriter = rootWriter;
+ private void addDependencyInBuildFile(Dependency dependency) throws IOException {
+ StringBuilder newBuildContent = new StringBuilder();
+ readLineByLine(getModel().getBuildContent(), currentLine -> {
+ newBuildContent.append(currentLine).append(System.lineSeparator());
+ if (currentLine.startsWith("dependencies {")) {
+ newBuildContent.append(" implementation '")
+ .append(dependency.getGroupId())
+ .append(":")
+ .append(dependency.getArtifactId());
+ if (dependency.getVersion() != null && !dependency.getVersion().isEmpty()) {
+ newBuildContent.append(":")
+ .append(dependency.getVersion());
+ }
+ newBuildContent.append("'")
+ .append(System.lineSeparator());
+ }
+ });
+ getModel().setBuildContent(newBuildContent.toString());
}
- protected void rootWrite(String fileName, String content) throws IOException {
- rootWriter.write(fileName, content);
+ protected boolean containsBOM(String groupId, String artifactId) throws IOException {
+ String buildContent = getModel().getBuildContent();
+ return buildContent.contains("enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:")
+ || buildContent.contains("enforcedPlatform(\"" + groupId + ":" + artifactId + ":");
}
- protected ProjectWriter getRootWriter() {
- return rootWriter;
+ public String getProperty(String propertyName) throws IOException {
+ return getModel().getPropertiesContent().getProperty(propertyName);
}
- @Override
- public void close() throws IOException {
- if (getWriter() == getRootWriter()) {
- write(SETTINGS_GRADLE_PATH, getModel().getSettingsContent());
- } else {
- rootWrite(SETTINGS_GRADLE_PATH, getModel().getSettingsContent());
+ private void readLineByLine(String content, Consumer lineConsumer) {
+ try (Scanner scanner = new Scanner(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)),
+ StandardCharsets.UTF_8.name())) {
+ while (scanner.hasNextLine()) {
+ String currentLine = scanner.nextLine();
+ lineConsumer.accept(currentLine);
+ }
}
- write(BUILD_GRADLE_PATH, getModel().getBuildContent());
- try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- getModel().getPropertiesContent().store(out, "Gradle properties");
- if (getModel().isRootProperties()) {
- rootWrite(GRADLE_PROPERTIES_PATH, out.toString(StandardCharsets.UTF_8.toString()));
- } else {
- write(GRADLE_PROPERTIES_PATH, out.toString(StandardCharsets.UTF_8.toString()));
+ }
+
+ private Model getModel() throws IOException {
+ return modelReference.updateAndGet(model -> {
+ if (model == null) {
+ try {
+ return readModel();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
+ return model;
+ });
+ }
+
+ 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);
+ settingsContent = new String(settings, StandardCharsets.UTF_8);
+ }
+ if (hasProjectFile(BUILD_GRADLE_PATH)) {
+ final byte[] build = readProjectFile(BUILD_GRADLE_PATH);
+ buildContent = new String(build, StandardCharsets.UTF_8);
}
+ if (hasProjectFile(GRADLE_PROPERTIES_PATH)) {
+ final byte[] properties = readProjectFile(GRADLE_PROPERTIES_PATH);
+ propertiesContent.load(new ByteArrayInputStream(properties));
+ }
+ return new Model(settingsContent, buildContent, propertiesContent);
+ }
+
+ protected boolean hasProjectFile(final String fileName) throws IOException {
+ final Path filePath = quarkusProject.getProjectFolderPath().resolve(fileName);
+ return Files.exists(filePath);
}
- @Override
- public void completeFile(String groupId, String artifactId, String version, QuarkusPlatformDescriptor platform,
- Properties props) throws IOException {
- completeSettingsContent(artifactId);
- completeBuildContent(groupId, version, platform, props);
- completeProperties(platform);
+ protected byte[] readProjectFile(final String fileName) throws IOException {
+ final Path filePath = quarkusProject.getProjectFolderPath().resolve(fileName);
+ return Files.readAllBytes(filePath);
}
- private void completeBuildContent(String groupId, String version, QuarkusPlatformDescriptor platform, Properties props)
+ protected void writeToProjectFile(final String fileName, final byte[] content) throws IOException {
+ Files.write(quarkusProject.getProjectFolderPath().resolve(fileName), content);
+ }
+
+ private void createBuildContent(String groupId, String version)
throws IOException {
final String buildContent = getModel().getBuildContent();
StringBuilder res = new StringBuilder(buildContent);
@@ -81,7 +157,8 @@ private void completeBuildContent(String groupId, String version, QuarkusPlatfor
res.append(System.lineSeparator()).append(" id 'io.quarkus'").append(System.lineSeparator());
res.append("}");
}
- if (!containsBOM(platform.getBomGroupId(), platform.getBomArtifactId())) {
+ if (!containsBOM(quarkusProject.getPlatformDescriptor().getBomGroupId(),
+ quarkusProject.getPlatformDescriptor().getBomArtifactId())) {
res.append(System.lineSeparator());
res.append("dependencies {").append(System.lineSeparator());
res.append(
@@ -113,7 +190,7 @@ private void completeBuildContent(String groupId, String version, QuarkusPlatfor
getModel().setBuildContent(res.toString());
}
- private void completeSettingsContent(String artifactId) throws IOException {
+ private void createSettingsContent(String artifactId) throws IOException {
final String settingsContent = getModel().getSettingsContent();
final StringBuilder res = new StringBuilder();
if (!settingsContent.contains("id 'io.quarkus'")) {
@@ -137,7 +214,8 @@ private void completeSettingsContent(String artifactId) throws IOException {
getModel().setSettingsContent(res.toString());
}
- private void completeProperties(QuarkusPlatformDescriptor platform) throws IOException {
+ private void createProperties() throws IOException {
+ final QuarkusPlatformDescriptor platform = quarkusProject.getPlatformDescriptor();
Properties props = getModel().getPropertiesContent();
if (props.getProperty("quarkusPluginVersion") == null) {
props.setProperty("quarkusPluginVersion", ToolsUtils.getPluginVersion(ToolsUtils.readQuarkusProperties(platform)));
@@ -153,174 +231,15 @@ private void completeProperties(QuarkusPlatformDescriptor platform) throws IOExc
}
}
- @Override
- protected void addDependencyInBuildFile(Dependency dependency) throws IOException {
- StringBuilder newBuildContent = new StringBuilder();
- readLineByLine(getModel().getBuildContent(), new AppendDependency(newBuildContent, dependency));
- getModel().setBuildContent(newBuildContent.toString());
- }
-
- @Override
- public boolean removeDependency(QuarkusPlatformDescriptor platform, Extension extension) throws IOException {
- PRINTER.ok(" Removing extension " + extension.managementKey());
- Dependency dep;
- if (containsBOM(platform.getBomGroupId(), platform.getBomArtifactId())
- && isDefinedInBom(platform.getManagedDependencies(), extension)) {
- dep = extension.toDependency(true);
- } else {
- dep = extension.toDependency(false);
- if (getProperty(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_NAME) != null) {
- dep.setVersion(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_VERSION_VALUE);
- }
- }
- removeDependencyFromBuildFile(dep);
- return true;
- }
-
- @Override
- protected void removeDependencyFromBuildFile(Dependency dependency) throws IOException {
- String depString = new StringBuilder("'").append(dependency.getGroupId()).append(":")
- .append(dependency.getArtifactId()).toString();
- StringBuilder newBuildContent = new StringBuilder();
- Scanner scanner = new Scanner(getModel().getBuildContent());
- while (scanner.hasNextLine()) {
- String line = scanner.nextLine();
- if (!line.contains(depString)) {
- newBuildContent.append(line).append(System.lineSeparator());
- }
- }
- scanner.close();
- getModel().setBuildContent(newBuildContent.toString());
- }
-
- private void readLineByLine(String content, Consumer lineConsumer) {
- try (Scanner scanner = new Scanner(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)),
- StandardCharsets.UTF_8.name())) {
- while (scanner.hasNextLine()) {
- String currentLine = scanner.nextLine();
- lineConsumer.accept(currentLine);
- }
- }
- }
-
- private static class AppendDependency implements Consumer {
-
- private StringBuilder newContent;
- private Dependency dependency;
-
- public AppendDependency(StringBuilder newContent, Dependency dependency) {
- this.newContent = newContent;
- this.dependency = dependency;
- }
-
- @Override
- public void accept(String currentLine) {
- newContent.append(currentLine).append(System.lineSeparator());
- if (currentLine.startsWith("dependencies {")) {
- newContent.append(" implementation '")
- .append(dependency.getGroupId())
- .append(":")
- .append(dependency.getArtifactId());
- if (dependency.getVersion() != null && !dependency.getVersion().isEmpty()) {
- newContent.append(":")
- .append(dependency.getVersion());
- }
- newContent.append("'")
- .append(System.lineSeparator());
- }
- }
-
- }
-
- @Override
- protected boolean hasDependency(Extension extension) throws IOException {
- return getDependencies().stream()
- .anyMatch(d -> extension.getGroupId().equals(d.getGroupId())
- && extension.getArtifactId().equals(d.getArtifactId()));
- }
-
- @Override
- protected boolean containsBOM(String groupId, String artifactId) throws IOException {
- String buildContent = getModel().getBuildContent();
- return buildContent.contains("enforcedPlatform(\"${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:")
- || buildContent.contains("enforcedPlatform(\"" + groupId + ":" + artifactId + ":");
- }
-
- @Override
- public List getDependencies() throws IOException {
- return Collections.emptyList();
- }
-
- @Override
- public String getProperty(String propertyName) throws IOException {
- return getModel().getPropertiesContent().getProperty(propertyName);
- }
-
- @Override
- protected List getManagedDependencies() {
- // Gradle tooling API only provide resolved dependencies.
- return Collections.emptyList();
- }
-
- private Model getModel() throws IOException {
- if (model == null) {
- initModel();
- }
- return model;
- }
-
- protected void initModel() throws IOException {
- String settingsContent = "";
- String buildContent = "";
- Properties propertiesContent = new Properties();
- boolean isRootProperties = false;
- if (getWriter() == getRootWriter()) {
- if (getWriter().exists(SETTINGS_GRADLE_PATH)) {
- final byte[] settings = getWriter().getContent(SETTINGS_GRADLE_PATH);
- settingsContent = new String(settings, StandardCharsets.UTF_8);
- }
- } else {
- if (getRootWriter().exists(SETTINGS_GRADLE_PATH)) {
- final byte[] settings = getRootWriter().getContent(SETTINGS_GRADLE_PATH);
- settingsContent = new String(settings, StandardCharsets.UTF_8);
- }
- }
- if (getWriter().exists(BUILD_GRADLE_PATH)) {
- final byte[] build = getWriter().getContent(BUILD_GRADLE_PATH);
- buildContent = new String(build, StandardCharsets.UTF_8);
- }
- if (getWriter().exists(GRADLE_PROPERTIES_PATH)) {
- final byte[] properties = getWriter().getContent(GRADLE_PROPERTIES_PATH);
- propertiesContent.load(new ByteArrayInputStream(properties));
- }
- if (!propertiesContent.containsKey("quarkusPluginVersion") &&
- !propertiesContent.containsKey("quarkusPlatformGroupId") &&
- !propertiesContent.containsKey("quarkusPlatformArtifactId") &&
- !propertiesContent.containsKey("quarkusPlatformVersion")) {
- if (getRootWriter().exists(GRADLE_PROPERTIES_PATH)) {
- final byte[] properties = getRootWriter().getContent(GRADLE_PROPERTIES_PATH);
- propertiesContent.load(new ByteArrayInputStream(properties));
- }
- isRootProperties = true;
- }
- this.model = new Model(settingsContent, buildContent, propertiesContent, isRootProperties);
- }
-
- protected String getBuildContent() throws IOException {
- return getModel().getBuildContent();
- }
-
private static class Model {
private String settingsContent;
private String buildContent;
private Properties propertiesContent;
- private boolean rootProperties;
- public Model(String settingsContent, String buildContent, Properties propertiesContent, boolean rootProperties) {
+ public Model(String settingsContent, String buildContent, Properties propertiesContent) {
this.settingsContent = settingsContent;
this.buildContent = buildContent;
this.propertiesContent = propertiesContent;
- this.rootProperties = rootProperties;
}
public String getSettingsContent() {
@@ -343,8 +262,5 @@ public void setBuildContent(String buildContent) {
this.buildContent = buildContent;
}
- public boolean isRootProperties() {
- return rootProperties;
- }
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/MavenBuildFile.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/MavenBuildFile.java
index df55a72c8e6bd9..902edc2a7aa647 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/MavenBuildFile.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/buildfile/MavenBuildFile.java
@@ -1,57 +1,35 @@
package io.quarkus.devtools.buildfile;
-import static io.quarkus.maven.utilities.MojoUtils.configuration;
-import static io.quarkus.maven.utilities.MojoUtils.plugin;
-
-import io.quarkus.dependencies.Extension;
import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.writer.ProjectWriter;
import io.quarkus.maven.utilities.MojoUtils;
-import io.quarkus.maven.utilities.MojoUtils.Element;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
-import io.quarkus.platform.tools.ToolsUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.ArrayList;
+import java.io.UncheckedIOException;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
-import java.util.Properties;
-import org.apache.maven.model.Activation;
-import org.apache.maven.model.ActivationProperty;
-import org.apache.maven.model.Build;
-import org.apache.maven.model.BuildBase;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.maven.model.Dependency;
-import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Model;
-import org.apache.maven.model.Plugin;
-import org.apache.maven.model.PluginExecution;
-import org.apache.maven.model.PluginManagement;
-import org.apache.maven.model.Profile;
public class MavenBuildFile extends BuildFile {
- private Model model;
-
- public MavenBuildFile(ProjectWriter writer) {
- super(writer, BuildTool.MAVEN);
- }
+ private AtomicReference modelRef = new AtomicReference<>();
- private void initModel() throws IOException {
- if (getWriter().exists(BuildTool.MAVEN.getDependenciesFile())) {
- byte[] content = getWriter().getContent(BuildTool.MAVEN.getDependenciesFile());
- this.model = MojoUtils.readPom(new ByteArrayInputStream(content));
- }
+ public MavenBuildFile(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor) {
+ super(projectFolderPath, platformDescriptor);
}
@Override
- public void close() throws IOException {
+ public void writeToDisk() throws IOException {
if (getModel() == null) {
return;
}
try (ByteArrayOutputStream pomOutputStream = new ByteArrayOutputStream()) {
MojoUtils.write(getModel(), pomOutputStream);
- write(BuildTool.MAVEN.getDependenciesFile(), pomOutputStream.toString("UTF-8"));
+ writeToProjectFile(BuildTool.MAVEN.getDependenciesFile(), pomOutputStream.toByteArray());
}
}
@@ -71,11 +49,6 @@ protected void removeDependencyFromBuildFile(Dependency dependency) throws IOExc
}
}
- @Override
- protected boolean hasDependency(Extension extension) throws IOException {
- return getModel() != null && MojoUtils.hasDependency(getModel(), extension.getGroupId(), extension.getArtifactId());
- }
-
@Override
public List getDependencies() throws IOException {
return getModel() == null ? Collections.emptyList() : getModel().getDependencies();
@@ -98,150 +71,8 @@ protected boolean containsBOM(String groupId, String artifactId) throws IOExcept
}
@Override
- public void completeFile(String groupId, String artifactId, String version, QuarkusPlatformDescriptor platform,
- Properties props) throws IOException {
- addQuarkusProperties(platform);
- addBom(platform);
- final String pluginGroupId = ToolsUtils.getPluginGroupId(props);
- final String pluginArtifactId = ToolsUtils.getPluginArtifactId(props);
- addMainPluginConfig(pluginGroupId, pluginArtifactId);
- addNativeProfile(pluginGroupId, pluginArtifactId);
- }
-
- private void addBom(QuarkusPlatformDescriptor platform) throws IOException {
- boolean hasBom = false;
- DependencyManagement dm = getModel().getDependencyManagement();
- if (dm == null) {
- dm = new DependencyManagement();
- getModel().setDependencyManagement(dm);
- } else {
- hasBom = containsBOM(platform.getBomGroupId(), platform.getBomArtifactId());
- }
-
- if (!hasBom) {
- Dependency bom = new Dependency();
- bom.setGroupId(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_GROUP_ID_VALUE);
- bom.setArtifactId(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_ARTIFACT_ID_VALUE);
- bom.setVersion(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_VERSION_VALUE);
- bom.setType("pom");
- bom.setScope("import");
-
- dm.addDependency(bom);
- }
- }
-
- private void addNativeProfile(String pluginGroupId, String pluginArtifactId) throws IOException {
- final boolean match = getModel().getProfiles().stream().anyMatch(p -> p.getId().equals("native"));
- if (!match) {
- PluginExecution exec = new PluginExecution();
- exec.addGoal("native-image");
- exec.setConfiguration(configuration(new Element("enableHttpUrlHandler", "true")));
-
- Plugin plg = plugin(pluginGroupId, pluginArtifactId, MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE);
- plg.addExecution(exec);
-
- BuildBase buildBase = new BuildBase();
- buildBase.addPlugin(plg);
-
- Profile profile = new Profile();
- profile.setId("native");
- profile.setBuild(buildBase);
-
- final Activation activation = new Activation();
- final ActivationProperty property = new ActivationProperty();
- property.setName("native");
-
- activation.setProperty(property);
- profile.setActivation(activation);
- getModel().addProfile(profile);
- }
- }
-
- private void addMainPluginConfig(String groupId, String artifactId) throws IOException {
- if (!hasPlugin(groupId, artifactId)) {
- Build build = createBuildSectionIfRequired();
- Plugin plugin = plugin(groupId, artifactId, MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE);
- if (isParentPom()) {
- addPluginManagementSection(plugin);
- //strip the quarkusVersion off
- plugin = plugin(groupId, artifactId);
- }
- PluginExecution pluginExec = new PluginExecution();
- pluginExec.addGoal("build");
- plugin.addExecution(pluginExec);
- build.getPlugins().add(plugin);
- }
- }
-
- private boolean hasPlugin(String groupId, String artifactId) throws IOException {
- if (getModel() == null) {
- return false;
- }
- List plugins = null;
- final Build build = getModel().getBuild();
- if (build != null) {
- if (isParentPom()) {
- final PluginManagement management = build.getPluginManagement();
- if (management != null) {
- plugins = management.getPlugins();
- }
- } else {
- plugins = build.getPlugins();
- }
- }
- return plugins != null && build.getPlugins()
- .stream()
- .anyMatch(p -> p.getGroupId().equalsIgnoreCase(groupId) &&
- p.getArtifactId().equalsIgnoreCase(artifactId));
- }
-
- private void addPluginManagementSection(Plugin plugin) throws IOException {
- final Build build = getModel().getBuild();
- if (build != null && build.getPluginManagement() != null) {
- if (build.getPluginManagement().getPlugins() == null) {
- build.getPluginManagement().setPlugins(new ArrayList<>());
- }
- build.getPluginManagement().getPlugins().add(plugin);
- }
- }
-
- private Build createBuildSectionIfRequired() throws IOException {
- Build build = getModel().getBuild();
- if (build == null) {
- build = new Build();
- getModel().setBuild(build);
- }
- if (build.getPlugins() == null) {
- build.setPlugins(new ArrayList<>());
- }
- return build;
- }
-
- private void addQuarkusProperties(QuarkusPlatformDescriptor platform) throws IOException {
- Properties properties = getModel().getProperties();
- if (properties == null) {
- properties = new Properties();
- getModel().setProperties(properties);
- }
- properties.putIfAbsent(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_NAME,
- ToolsUtils.getPluginVersion(ToolsUtils.readQuarkusProperties(platform)));
- properties.putIfAbsent(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_GROUP_ID_NAME, platform.getBomGroupId());
- properties.putIfAbsent(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_ARTIFACT_ID_NAME, platform.getBomArtifactId());
- properties.putIfAbsent(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_VERSION_NAME, platform.getBomVersion());
- }
-
- private boolean isParentPom() throws IOException {
- return getModel() != null && "pom".equals(getModel().getPackaging());
- }
-
- @Override
- public List getManagedDependencies() throws IOException {
- if (getModel() == null) {
- return Collections.emptyList();
- }
- final DependencyManagement managed = getModel().getDependencyManagement();
- return managed != null ? managed.getDependencies()
- : Collections.emptyList();
+ protected void refreshData() {
+ this.modelRef.set(null);
}
@Override
@@ -252,10 +83,26 @@ public String getProperty(String propertyName) throws IOException {
return getModel().getProperties().getProperty(propertyName);
}
+ @Override
+ public BuildTool getBuildTool() {
+ return BuildTool.MAVEN;
+ }
+
private Model getModel() throws IOException {
- if (model == null) {
- initModel();
- }
- return model;
+ return modelRef.updateAndGet(model -> {
+ if (model == null) {
+ try {
+ return initModel();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ return model;
+ });
+ }
+
+ private Model initModel() throws IOException {
+ byte[] content = readProjectFile(BuildTool.MAVEN.getDependenciesFile());
+ return MojoUtils.readPom(new ByteArrayInputStream(content));
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/BuildTool.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/BuildTool.java
index 0987465b3c1b3f..8ebd65de5ab662 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/BuildTool.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/BuildTool.java
@@ -1,11 +1,10 @@
package io.quarkus.devtools.project;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import io.quarkus.devtools.buildfile.BuildFile;
-import io.quarkus.devtools.buildfile.GradleBuildFile;
+import io.quarkus.devtools.buildfile.GenericGradleBuildFile;
import io.quarkus.devtools.buildfile.MavenBuildFile;
-import io.quarkus.devtools.writer.ProjectWriter;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
+import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
+import java.nio.file.Path;
/**
* An enum of build tools, such as Maven and Gradle.
@@ -53,14 +52,14 @@ public String getBuildDirectory() {
return buildDirectory;
}
- public BuildFile createBuildFile(final ProjectWriter writer) {
- checkNotNull(writer, "writer is required");
+ public ExtensionsManager createExtensionManager(final Path projectFolderPath,
+ final QuarkusPlatformDescriptor platformDescriptor) {
switch (this) {
case GRADLE:
- return new GradleBuildFile(writer);
+ return new GenericGradleBuildFile();
case MAVEN:
default:
- return new MavenBuildFile(writer);
+ return new MavenBuildFile(projectFolderPath, platformDescriptor);
}
}
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java
index 8d6ef03e40831a..abfa56f1f30628 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/QuarkusProject.java
@@ -2,33 +2,38 @@
import static com.google.common.base.Preconditions.checkNotNull;
-import io.quarkus.devtools.buildfile.BuildFile;
-import io.quarkus.devtools.writer.FileProjectWriter;
+import io.quarkus.devtools.buildfile.MavenBuildFile;
+import io.quarkus.devtools.project.extensions.ExtensionsManager;
import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor;
import java.nio.file.Path;
public final class QuarkusProject {
private final Path projectFolderPath;
- private final BuildFile buildFile;
- private final QuarkusPlatformDescriptor descriptor;
+ private final QuarkusPlatformDescriptor platformDescriptor;
+ private final ExtensionsManager extensionsManager;
- private QuarkusProject(final Path projectFolderPath, final QuarkusPlatformDescriptor descriptor,
- final BuildFile buildFile) {
+ private QuarkusProject(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor,
+ final ExtensionsManager extensionsManager) {
this.projectFolderPath = checkNotNull(projectFolderPath, "projectFolderPath is required");
- this.descriptor = checkNotNull(descriptor, "descriptor is required");
- this.buildFile = checkNotNull(buildFile, "buildFile is required");
+ this.platformDescriptor = checkNotNull(platformDescriptor, "platformDescriptor is required");
+ this.extensionsManager = checkNotNull(extensionsManager, "extensionsManager is required");
}
- public static QuarkusProject of(final Path projectFolderPath, final QuarkusPlatformDescriptor descriptor,
+ public static QuarkusProject of(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor,
+ final ExtensionsManager extensionsManager) {
+ return new QuarkusProject(projectFolderPath, platformDescriptor, extensionsManager);
+ }
+
+ public static QuarkusProject of(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor,
final BuildTool buildTool) {
- final BuildFile buildFile = buildTool.createBuildFile(new FileProjectWriter(projectFolderPath.toFile()));
- return of(projectFolderPath, descriptor, buildFile);
+ return new QuarkusProject(projectFolderPath, platformDescriptor,
+ buildTool.createExtensionManager(projectFolderPath, platformDescriptor));
}
- public static QuarkusProject of(final Path projectFolderPath, final QuarkusPlatformDescriptor descriptor,
- final BuildFile buildFile) {
- return new QuarkusProject(projectFolderPath, descriptor, buildFile);
+ public static QuarkusProject maven(final Path projectFolderPath, final QuarkusPlatformDescriptor platformDescriptor) {
+ return new QuarkusProject(projectFolderPath, platformDescriptor,
+ new MavenBuildFile(projectFolderPath, platformDescriptor));
}
public static QuarkusProject resolveExistingProject(final Path projectFolderPath,
@@ -44,19 +49,19 @@ public Path getProjectFolderPath() {
return projectFolderPath;
}
- public BuildFile getBuildFile() {
- return buildFile;
+ public BuildTool getBuildTool() {
+ return extensionsManager.getBuildTool();
}
- public BuildTool getBuildTool() {
- return buildFile.getBuildTool();
+ public ExtensionsManager getExtensionsManager() {
+ return extensionsManager;
}
- public QuarkusPlatformDescriptor getDescriptor() {
- return descriptor;
+ public QuarkusPlatformDescriptor getPlatformDescriptor() {
+ return platformDescriptor;
}
- private static BuildTool resolveExistingProjectBuildTool(Path projectFolderPath) {
+ public static BuildTool resolveExistingProjectBuildTool(Path projectFolderPath) {
if (projectFolderPath.resolve("pom.xml").toFile().exists()) {
return BuildTool.MAVEN;
} else if (projectFolderPath.resolve("build.gradle").toFile().exists()
@@ -65,4 +70,5 @@ private static BuildTool resolveExistingProjectBuildTool(Path projectFolderPath)
}
return null;
}
+
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGenerator.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGenerator.java
similarity index 77%
rename from independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGenerator.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGenerator.java
index 518e86f0505c24..825f09499361d8 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGenerator.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGenerator.java
@@ -1,7 +1,6 @@
-package io.quarkus.generators;
+package io.quarkus.devtools.project.codegen;
-import io.quarkus.cli.commands.QuarkusCommandInvocation;
-import io.quarkus.devtools.writer.ProjectWriter;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
import java.io.IOException;
public interface ProjectGenerator {
@@ -18,11 +17,12 @@ public interface ProjectGenerator {
String BUILD_DIRECTORY = "build_dir";
String ADDITIONAL_GITIGNORE_ENTRIES = "additional_gitignore_entries";
String CLASS_NAME = "class_name";
+ String EXTENSIONS = "extensions";
String IS_SPRING = "is_spring";
String RESOURCE_PATH = "path";
String JAVA_TARGET = "java_target";
String getName();
- void generate(ProjectWriter writer, QuarkusCommandInvocation invocation) throws IOException;
+ void generate(QuarkusCommandInvocation invocation) throws IOException;
}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGeneratorRegistry.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGeneratorRegistry.java
similarity index 96%
rename from independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGeneratorRegistry.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGeneratorRegistry.java
index 14e50d3f9b847b..4090c600ef7b54 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/generators/ProjectGeneratorRegistry.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/ProjectGeneratorRegistry.java
@@ -1,4 +1,4 @@
-package io.quarkus.generators;
+package io.quarkus.devtools.project.codegen;
import java.util.Map;
import java.util.NoSuchElementException;
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/generators/SourceType.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/SourceType.java
similarity index 98%
rename from independent-projects/tools/common/src/main/java/io/quarkus/generators/SourceType.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/SourceType.java
index be92d2f2be6b24..3044f4992d3726 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/generators/SourceType.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/SourceType.java
@@ -1,4 +1,4 @@
-package io.quarkus.generators;
+package io.quarkus.devtools.project.codegen;
import io.quarkus.maven.utilities.MojoUtils;
import java.util.Arrays;
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/generators/rest/BasicRestProjectGenerator.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java
similarity index 92%
rename from independent-projects/tools/common/src/main/java/io/quarkus/generators/rest/BasicRestProjectGenerator.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java
index 9578e9be6f54f4..70bde46bc7534b 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/generators/rest/BasicRestProjectGenerator.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGenerator.java
@@ -1,12 +1,13 @@
-package io.quarkus.generators.rest;
+package io.quarkus.devtools.project.codegen.rest;
import static java.lang.String.format;
-import io.quarkus.cli.commands.QuarkusCommandInvocation;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.writer.ProjectWriter;
-import io.quarkus.generators.ProjectGenerator;
-import io.quarkus.generators.SourceType;
+import io.quarkus.devtools.project.codegen.ProjectGenerator;
+import io.quarkus.devtools.project.codegen.SourceType;
+import io.quarkus.devtools.project.codegen.writer.FileProjectWriter;
+import io.quarkus.devtools.project.codegen.writer.ProjectWriter;
import io.quarkus.maven.utilities.MojoUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -25,7 +26,13 @@ public String getName() {
}
@Override
- public void generate(final ProjectWriter writer, QuarkusCommandInvocation invocation) throws IOException {
+ public void generate(QuarkusCommandInvocation invocation) throws IOException {
+ final FileProjectWriter writer = new FileProjectWriter(invocation.getQuarkusProject().getProjectFolderPath().toFile());
+ writer.init();
+ generate(writer, invocation);
+ }
+
+ void generate(ProjectWriter writer, QuarkusCommandInvocation invocation) throws IOException {
final BasicRestProject project = new BasicRestProject(writer, invocation);
project.initProject();
@@ -122,7 +129,7 @@ private boolean initBuildTool() throws IOException {
}
private BuildTool getBuildTool() {
- return invocation.getBuildFile().getBuildTool();
+ return invocation.getQuarkusProject().getBuildTool();
}
private void generate(final String templateName, QuarkusCommandInvocation invocation, final String outputFilePath,
@@ -141,7 +148,7 @@ 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.getBuildFile().getBuildTool())) {
+ if (BuildTool.GRADLE.equals(invocation.getQuarkusProject().getBuildTool())) {
template = template.replace("JavaVersion.VERSION_1_8", "JavaVersion.VERSION_11");
} else {
template = template.replace("1.8",
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/FileProjectWriter.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/FileProjectWriter.java
similarity index 73%
rename from independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/FileProjectWriter.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/FileProjectWriter.java
index 35e4a2d4e1e52a..da284ca0f50c05 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/FileProjectWriter.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/FileProjectWriter.java
@@ -1,7 +1,7 @@
/**
*
*/
-package io.quarkus.devtools.writer;
+package io.quarkus.devtools.project.codegen.writer;
import java.io.File;
import java.io.IOException;
@@ -19,21 +19,21 @@ public FileProjectWriter(final File file) {
}
@Override
- public boolean init() {
- if (root.exists() && !root.isDirectory()) {
- System.out.println("Project root needs to either not exist or be a directory");
- return false;
- } else if (!root.exists()) {
+ public void init() throws IOException {
+ if (!root.exists()) {
boolean mkdirStatus = root.mkdirs();
if (!mkdirStatus) {
- System.out.println("Failed to create root directory");
- return false;
+ throw new IOException("Failed to create root directory");
}
+ return;
+ }
+ if (!root.isDirectory()) {
+ throw new IOException("Project root needs to either not exist or be a directory");
+ }
+ final String[] files = root.list();
+ if (files != null && files.length > 0) {
+ throw new IOException("You can't create a project when the folder is not empty.");
}
-
- System.out.println("Creating a new project in " + root.getAbsolutePath());
-
- return true;
}
@Override
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/ProjectWriter.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/ProjectWriter.java
similarity index 84%
rename from independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/ProjectWriter.java
rename to independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/ProjectWriter.java
index 45e75607edac79..4b9ecdea8cf5d3 100644
--- a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/writer/ProjectWriter.java
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/codegen/writer/ProjectWriter.java
@@ -1,7 +1,7 @@
/**
*
*/
-package io.quarkus.devtools.writer;
+package io.quarkus.devtools.project.codegen.writer;
import java.io.Closeable;
import java.io.File;
@@ -12,9 +12,7 @@
*/
public interface ProjectWriter extends Closeable {
- default boolean init() {
- return true;
- }
+ void init() throws IOException;
void write(String path, String content) throws IOException;
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/Extensions.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/Extensions.java
new file mode 100644
index 00000000000000..34af541b140b2b
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/Extensions.java
@@ -0,0 +1,40 @@
+package io.quarkus.devtools.project.extensions;
+
+import io.quarkus.dependencies.Extension;
+import java.util.Objects;
+import org.apache.maven.model.Dependency;
+
+public final class Extensions {
+ private Extensions() {
+ }
+
+ public static String key(final Extension extension) {
+ return extension.managementKey();
+ }
+
+ public static String key(final Dependency dependency) {
+ return dependency.getGroupId() + ":" + dependency.getArtifactId();
+ }
+
+ public static boolean equalsIgnoringVersions(final Extension a, final Extension b) {
+ return Objects.equals(a.getGroupId(), b.getGroupId()) && Objects.equals(a.getArtifactId(), b.getArtifactId());
+ }
+
+ public static Extension parse(String gav) {
+ final Extension res = new Extension();
+ String[] segments = gav.split(":");
+ if (segments.length >= 2) {
+ res.setGroupId(segments[0].toLowerCase());
+ res.setArtifactId(segments[1].toLowerCase());
+ if (segments.length >= 3 && !segments[2].isEmpty()) {
+ res.setVersion(segments[2]);
+ }
+ if (segments.length >= 4) {
+ res.setClassifier(segments[3].toLowerCase());
+ }
+ return res;
+ } else {
+ throw new IllegalArgumentException("Invalid GAV '" + gav + "'");
+ }
+ }
+}
diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionsManager.java b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionsManager.java
new file mode 100644
index 00000000000000..06900c1a924519
--- /dev/null
+++ b/independent-projects/tools/common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionsManager.java
@@ -0,0 +1,71 @@
+package io.quarkus.devtools.project.extensions;
+
+import static io.quarkus.devtools.project.extensions.Extensions.equalsIgnoringVersions;
+
+import io.quarkus.dependencies.Extension;
+import io.quarkus.devtools.project.BuildTool;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This interface defines a high level way of managing (read/write) extensions in any QuarkusProject
+ */
+public interface ExtensionsManager {
+
+ /**
+ * @return the {@link BuildTool} of this extension manager
+ */
+ BuildTool getBuildTool();
+
+ /**
+ * Read the build file(s) to get the list of installed extensions in this Quarkus project.
+ *
+ * @return The list of extensions installed in the project build file(s).
+ * @throws IOException if a problem occurs while reading the project build file(s)
+ */
+ List getInstalled() throws IOException;
+
+ /**
+ * Read build file(s) to check if an extension is installed in this Quarkus project.
+ *
+ * @param e the extensions to check
+ * @return true if it's installed
+ * @throws IOException if a problem occurs while reading the project build file(s)
+ */
+ default boolean isInstalled(Extension e) throws IOException {
+ return getInstalled().stream().anyMatch(i -> equalsIgnoringVersions(i, e));
+ }
+
+ /**
+ * Check that the Quarkus Platform bom is defined in the project.
+ * The Quarkus Platform Bom role is to define version to use for Quarkus extensions.
+ *
+ * @return true if it's defined, false else
+ * @throws IOException if a problem occurs while reading the project build file(s)
+ */
+ boolean hasQuarkusPlatformBom() throws IOException;
+
+ /**
+ * This is going to install/add all the specified extensions to the project build file(s).
+ *
+ * Extensions which are already installed are ignored.
+ *
+ * @param extensions the list of extensions to add
+ * @return the number of added extensions (excluding already installed)
+ * @throws IOException if a problem occurs while reading/writing the project build file(s)
+ */
+ int install(List extensions) throws IOException;
+
+ /**
+ * This is going to uninstall/remove all the specified extensions from the project build file(s).
+ *
+ * This is ignoring the {@link Extension} version
+ *
+ * @param extensions the set of extensions to remove
+ * @return the number of removed extensions (excluding already not installed)
+ * @throws IOException if a problem occurs while reading/writing the project build file(s)
+ */
+ int uninstall(Set extensions) throws IOException;
+
+}
diff --git a/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.devtools.project.codegen.ProjectGenerator b/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.devtools.project.codegen.ProjectGenerator
new file mode 100644
index 00000000000000..41ba05fc1a3e40
--- /dev/null
+++ b/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.devtools.project.codegen.ProjectGenerator
@@ -0,0 +1 @@
+io.quarkus.devtools.project.codegen.rest.BasicRestProjectGenerator
diff --git a/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.generators.ProjectGenerator b/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.generators.ProjectGenerator
deleted file mode 100644
index 481f77c230b6bc..00000000000000
--- a/independent-projects/tools/common/src/main/resources/META-INF/services/io.quarkus.generators.ProjectGenerator
+++ /dev/null
@@ -1 +0,0 @@
-io.quarkus.generators.rest.BasicRestProjectGenerator
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractAddExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractAddExtensionsTest.java
index 2e38ffa5b54cab..d0d377c1a8975e 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractAddExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractAddExtensionsTest.java
@@ -2,6 +2,8 @@
import static java.util.Arrays.asList;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -135,25 +137,25 @@ void testPartialMatchConflict() throws Exception {
}
@Test
- void addExistingAndMissingExtensions() throws Exception {
+ void addExistingAndMissingExtensionsWillFailForBoth() throws Exception {
createProject();
final QuarkusCommandOutcome result = addExtensions(asList("missing", "agroal"));
final T project = readProject();
doesNotHaveDependency(project, "quarkus-missing");
- hasDependency(project, "quarkus-agroal");
+ doesNotHaveDependency(project, "quarkus-agroal");
Assertions.assertFalse(result.isSuccess());
- Assertions.assertTrue(result.valueIs(AddExtensions.OUTCOME_UPDATED, true));
+ Assertions.assertFalse(result.valueIs(AddExtensions.OUTCOME_UPDATED, true));
}
@Test
- void addDuplicatedExtension() throws Exception {
+ void doNotAddExtensionWhenMultipleMatch() throws Exception {
createProject();
- addExtensions(asList("agroal", "jdbc", "non-exist-ent"));
+ addExtensions(asList("agroal", "jdbc"));
final T project = readProject();
- hasDependency(project, "quarkus-agroal");
+ doesNotHaveDependency(project, "quarkus-agroal");
doesNotHaveDependency(project, "quarkus-jdbc-postgresql");
doesNotHaveDependency(project, "quarkus-jdbc-h2");
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractRemoveExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractRemoveExtensionsTest.java
index 1acfd547df7188..364acafb599225 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractRemoveExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AbstractRemoveExtensionsTest.java
@@ -2,6 +2,8 @@
import static java.util.Arrays.asList;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -64,12 +66,12 @@ void testRegexpMatches() throws Exception {
final QuarkusCommandOutcome result = addExtensions(asList("Sm??lRye**"));
Assertions.assertTrue(result.isSuccess());
- Assertions.assertTrue(result.valueIs(AddExtensions.OUTCOME_UPDATED, true));
+ Assertions.assertTrue(result.getBooleanValue(AddExtensions.OUTCOME_UPDATED));
final QuarkusCommandOutcome result2 = removeExtensions(asList("Sm??lRye**"));
Assertions.assertTrue(result2.isSuccess());
- Assertions.assertTrue(result2.valueIs(RemoveExtensions.OUTCOME_UPDATED, true));
+ Assertions.assertTrue(result2.getBooleanValue(RemoveExtensions.OUTCOME_UPDATED));
final T project = readProject();
hasNoDependency(project, "quarkus-smallrye-reactive-messaging");
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddGradleExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddGradleExtensionsTest.java
index f080c5fffff4a0..574f9e7d039142 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddGradleExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddGradleExtensionsTest.java
@@ -1,20 +1,23 @@
package io.quarkus.cli.commands;
+import com.google.common.collect.ImmutableList;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
+import io.quarkus.devtools.buildfile.AbstractGradleBuildFile;
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 java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.maven.model.Dependency;
class AddGradleExtensionsTest extends AbstractAddExtensionsTest> {
- @Disabled
- void addExtensionTwiceInTwoBatches() throws IOException {
- //FIXME This is currently not working
- }
-
@Override
protected List createProject() throws IOException, QuarkusCommandException {
CreateProjectTest.delete(getProjectPath().toFile());
@@ -53,6 +56,30 @@ private static String getBuildFileDependencyString(final String groupId, final S
}
private QuarkusProject getQuarkusProject() {
- return QuarkusProject.of(getProjectPath(), getPlatformDescriptor(), BuildTool.GRADLE);
+ final Path projectPath = getProjectPath();
+ final QuarkusPlatformDescriptor platformDescriptor = getPlatformDescriptor();
+ return QuarkusProject.of(projectPath, platformDescriptor, new TestingGradleBuildFile(projectPath, platformDescriptor));
+ }
+
+ static class TestingGradleBuildFile extends AbstractGradleBuildFile {
+
+ public TestingGradleBuildFile(Path projectFolderPath, QuarkusPlatformDescriptor platformDescriptor) {
+ super(projectFolderPath, platformDescriptor);
+ }
+
+ @Override
+ protected List getDependencies() throws IOException {
+ final Matcher matcher = Pattern.compile("\\s*implementation\\s+'([^\\v:]+):([^\\v:]+)(:[^:\\v]+)?'")
+ .matcher(getBuildContent());
+ final ImmutableList.Builder builder = ImmutableList.builder();
+ while (matcher.find()) {
+ final Dependency dep = new Dependency();
+ dep.setGroupId(matcher.group(1));
+ dep.setArtifactId(matcher.group(2));
+ dep.setVersion(matcher.group(3));
+ builder.add(dep);
+ }
+ return builder.build();
+ }
}
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddMavenExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddMavenExtensionsTest.java
index 57ee06f7052467..ed42efcf0e9782 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddMavenExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddMavenExtensionsTest.java
@@ -1,5 +1,7 @@
package io.quarkus.cli.commands;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.maven.utilities.MojoUtils;
@@ -46,6 +48,6 @@ protected long countDependencyOccurrences(final Model project, final String grou
}
private QuarkusProject getQuarkusProject() {
- return QuarkusProject.of(getProjectPath(), getPlatformDescriptor(), BuildTool.MAVEN);
+ return QuarkusProject.maven(getProjectPath(), getPlatformDescriptor());
}
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/CreateProjectTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/CreateProjectTest.java
index 44cbd56da51ea4..75953171e3f406 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/CreateProjectTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/CreateProjectTest.java
@@ -1,22 +1,23 @@
package io.quarkus.cli.commands;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.contentOf;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.BuildTool;
-import io.quarkus.devtools.writer.FileProjectWriter;
-import io.quarkus.generators.ProjectGenerator;
+import io.quarkus.devtools.project.codegen.writer.FileProjectWriter;
import io.quarkus.maven.utilities.MojoUtils;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
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.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@@ -61,126 +62,7 @@ public void createGradle() throws Exception {
}
@Test
- public void createGradleOnExisting() throws Exception {
- final File testDir = new File("target/existing");
- delete(testDir);
- testDir.mkdirs();
-
- final File buildGradle = new File(testDir, "build.gradle");
- buildGradle.createNewFile();
- final File settingsGradle = new File(testDir, "settings.gradle");
- settingsGradle.createNewFile();
-
- createProject(BuildTool.GRADLE, testDir, "io.quarkus", "basic-rest", "1.0.0-SNAPSHOT");
-
- final File gitignore = new File(testDir, ".gitignore");
- assertTrue(gitignore.exists());
- final String gitignoreContent = new String(Files.readAllBytes(gitignore.toPath()), StandardCharsets.UTF_8);
- Assertions.assertFalse(gitignoreContent.contains("\ntarget/\n"));
- assertTrue(gitignoreContent.contains("\nbuild/"));
- assertTrue(gitignoreContent.contains("\n.gradle/\n"));
-
- assertThat(contentOf(new File(testDir, "build.gradle"), "UTF-8"))
- .contains("id 'io.quarkus'")
- .contains("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}");
-
- final Properties props = new Properties();
- try (InputStream is = Files.newInputStream(testDir.toPath().resolve("gradle.properties"))) {
- props.load(is);
- }
- Assertions.assertEquals(getBomGroupId(), props.get("quarkusPlatformGroupId"));
- Assertions.assertEquals(getBomArtifactId(), props.get("quarkusPlatformArtifactId"));
- Assertions.assertEquals(getBomVersion(), props.get("quarkusPlatformVersion"));
-
- assertThat(new File(testDir, "README.md")).exists();
- assertThat(contentOf(new File(testDir, "README.md"), "UTF-8")).contains("./gradlew");
- }
-
- @Test
- public void createOnTopPomWithoutResource() throws Exception {
- final File testDir = new File("target/existing");
- delete(testDir);
- testDir.mkdirs();
-
- Model model = new Model();
- model.setModelVersion("4.0.0");
- model.setGroupId("org.acme");
- model.setArtifactId("foobar");
- model.setVersion("10.1.2");
- final File pom = new File(testDir, "pom.xml");
- MojoUtils.write(model, pom);
- createProject(testDir, "something.is", "wrong", "1.0.0-SNAPSHOT");
-
- assertThat(contentOf(pom, "UTF-8"))
- .contains(getPluginArtifactId(), MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE, getPluginGroupId());
-
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java")).isDirectory();
-
- assertThat(new File(testDir, "README.md")).exists();
- assertThat(contentOf(new File(testDir, "README.md"), "UTF-8")).contains("./mvnw");
- assertThat(new File(testDir, "src/main/resources/application.properties")).exists();
- assertThat(new File(testDir, "src/main/resources/META-INF/resources/index.html")).isFile();
- assertThat(new File(testDir, "src/main/java")).isDirectory().matches(f -> {
- String[] list = f.list();
- return list != null && list.length == 0;
- });
- assertThat(new File(testDir, "src/test/java")).isDirectory().matches(f -> {
- String[] list = f.list();
- return list != null && list.length == 0;
- });
-
- assertThat(contentOf(new File(testDir, "pom.xml"), "UTF-8"))
- .contains(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_ARTIFACT_ID_VALUE);
-
- }
-
- @Test
- public void createOnTopPomWithResource() throws Exception {
- final File testDir = new File("target/existing");
- delete(testDir);
- testDir.mkdirs();
-
- Model model = new Model();
- model.setModelVersion("4.0.0");
- model.setGroupId("org.acme");
- model.setArtifactId("foobar");
- model.setVersion("10.1.2");
- final File pom = new File(testDir, "pom.xml");
- MojoUtils.write(model, pom);
-
- final QuarkusCommandOutcome result = new CreateProject(testDir.toPath(), getPlatformDescriptor())
- .groupId("something.is")
- .artifactId("wrong")
- .version("1.0.0-SNAPSHOT")
- .className("org.foo.MyResource")
- .execute();
- assertTrue(result.isSuccess());
-
- assertThat(contentOf(pom, "UTF-8"))
- .contains(getPluginArtifactId(), MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE, getPluginGroupId());
-
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java")).isDirectory();
-
- assertThat(new File(testDir, "README.md")).exists();
- assertThat(contentOf(new File(testDir, "README.md"), "UTF-8")).contains("./mvnw");
- assertThat(new File(testDir, "src/main/resources/application.properties")).exists();
- assertThat(new File(testDir, "src/main/resources/META-INF/resources/index.html")).exists();
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/main/java/org/foo/MyResource.java")).isFile();
- assertThat(contentOf(new File(testDir, "src/main/java/org/foo/MyResource.java"), "UTF-8"))
- .contains("@Path", "@GET", "@Produces");
- assertThat(new File(testDir, "src/test/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java/org/foo/MyResourceTest.java")).isFile();
- assertThat(new File(testDir, "src/test/java/org/foo/NativeMyResourceIT.java")).isFile();
-
- assertThat(contentOf(new File(testDir, "pom.xml"))).contains(getBomArtifactId());
-
- }
-
- @Test
- public void createOnTopPomWithSpringController() throws Exception {
+ public void createOnTopOfExisting() throws Exception {
final File testDir = new File("target/existing");
delete(testDir);
testDir.mkdirs();
@@ -192,68 +74,14 @@ public void createOnTopPomWithSpringController() throws Exception {
model.setVersion("10.1.2");
final File pom = new File(testDir, "pom.xml");
MojoUtils.write(model, pom);
-
- final QuarkusCommandOutcome result = new CreateProject(testDir.toPath(), getPlatformDescriptor())
- .groupId("something.is")
- .artifactId("wrong")
- .version("1.0.0-SNAPSHOT")
- .className("org.foo.MyResource")
- .setValue(ProjectGenerator.IS_SPRING, true)
- .execute();
- assertTrue(result.isSuccess());
-
- assertThat(contentOf(pom, "UTF-8"))
- .contains(getPluginArtifactId(), MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE, getPluginGroupId());
-
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java")).isDirectory();
-
- assertThat(new File(testDir, "README.md")).exists();
- assertThat(contentOf(new File(testDir, "README.md"), "UTF-8")).contains("./mvnw");
- assertThat(new File(testDir, "src/main/resources/application.properties")).exists();
- assertThat(new File(testDir, "src/main/resources/META-INF/resources/index.html")).exists();
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/main/java/org/foo/MyResource.java")).isFile();
- assertThat(contentOf(new File(testDir, "src/main/java/org/foo/MyResource.java"), "UTF-8"))
- .contains("@RestController", "@RequestMapping", "@GetMapping");
- assertThat(new File(testDir, "src/test/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java/org/foo/MyResourceTest.java")).isFile();
- assertThat(new File(testDir, "src/test/java/org/foo/NativeMyResourceIT.java")).isFile();
-
- assertThat(contentOf(new File(testDir, "pom.xml"))).contains(getBomArtifactId());
-
- }
-
- @Test
- public void createNewWithCustomizations() throws Exception {
- final File testDir = new File("target/existing");
- delete(testDir);
- testDir.mkdirs();
-
- final QuarkusCommandOutcome result = new CreateProject(testDir.toPath(), getPlatformDescriptor())
- .groupId("org.acme")
- .artifactId("acme")
- .version("1.0.0-SNAPSHOT")
- .className("org.acme.MyResource")
- .execute();
- assertTrue(result.isSuccess());
-
- assertThat(new File(testDir, "pom.xml")).isFile();
- assertThat(new File(testDir, "src/main/java/org/acme/MyResource.java")).isFile();
- assertThat(new File(testDir, "src/main/java/org/acme/MyApplication.java")).doesNotExist();
-
- assertThat(contentOf(new File(testDir, "pom.xml"), "UTF-8"))
- .contains(getPluginArtifactId(), MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLUGIN_VERSION_VALUE, getPluginGroupId());
-
- assertThat(new File(testDir, "src/main/java")).isDirectory();
- assertThat(new File(testDir, "src/test/java")).isDirectory();
-
- assertThat(new File(testDir, "src/main/resources/application.properties")).exists();
- assertThat(new File(testDir, "src/main/resources/META-INF/resources/index.html")).exists();
-
- assertThat(contentOf(new File(testDir, "pom.xml"), "UTF-8"))
- .contains(MojoUtils.TEMPLATE_PROPERTY_QUARKUS_PLATFORM_VERSION_VALUE);
-
+ assertThatExceptionOfType(QuarkusCommandException.class).isThrownBy(() -> {
+ new CreateProject(testDir.toPath(), getPlatformDescriptor())
+ .groupId("something.is")
+ .artifactId("wrong")
+ .version("1.0.0-SNAPSHOT")
+ .className("org.foo.MyResource")
+ .execute();
+ }).withRootCauseInstanceOf(IOException.class);
}
@Test
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/ListExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/ListExtensionsTest.java
index cd039e61c49a67..27feada00ec7d6 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/ListExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/ListExtensionsTest.java
@@ -2,10 +2,12 @@
import static io.quarkus.maven.utilities.MojoUtils.readPom;
import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
+import static java.util.stream.Collectors.toMap;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.dependencies.Extension;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.maven.utilities.MojoUtils;
import io.quarkus.maven.utilities.QuarkusDependencyPredicate;
@@ -13,11 +15,13 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
+import java.io.UncheckedIOException;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Map;
-import org.apache.maven.model.Dependency;
+import java.util.function.Function;
import org.apache.maven.model.Model;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -31,7 +35,7 @@ public void listWithBom() throws Exception {
final ListExtensions listExtensions = new ListExtensions(project);
- final Map installed = listExtensions.findInstalled();
+ final Map installed = readByManagementKey(project);
Assertions.assertNotNull(installed.get(getPluginGroupId() + ":quarkus-agroal"));
}
@@ -49,7 +53,7 @@ public void listWithBomExtensionWithSpaces() throws Exception {
final ListExtensions listExtensions = new ListExtensions(quarkusProject);
- final Map installed = listExtensions.findInstalled();
+ final Map installed = readByManagementKey(quarkusProject);
Assertions.assertNotNull(installed.get(getPluginGroupId() + ":quarkus-resteasy"));
Assertions.assertNotNull(installed.get(getPluginGroupId() + ":quarkus-hibernate-validator"));
@@ -59,10 +63,8 @@ public void listWithBomExtensionWithSpaces() throws Exception {
public void listWithoutBom() throws Exception {
final File pom = new File("target/list-extensions-test", "pom.xml");
final QuarkusProject quarkusProject = createNewProject(pom);
-
Model model = readPom(pom);
- model.setDependencyManagement(null);
model.getDependencies().stream()
.filter(new QuarkusDependencyPredicate())
.forEach(d -> d.setVersion("0.0.1"));
@@ -162,9 +164,9 @@ public void searchRest() throws Exception {
@Test
void testListExtensionsWithoutAPomFile() throws IOException {
final Path tempDirectory = Files.createTempDirectory("proj");
- ListExtensions listExtensions = new ListExtensions(
- QuarkusProject.of(tempDirectory, getPlatformDescriptor(), BuildTool.MAVEN));
- assertThat(listExtensions.findInstalled()).isEmpty();
+ final QuarkusProject project = QuarkusProject.maven(tempDirectory, getPlatformDescriptor());
+ assertThatExceptionOfType(UncheckedIOException.class).isThrownBy(() -> readByManagementKey(project))
+ .withRootCauseInstanceOf(NoSuchFileException.class);
}
private void addExtensions(QuarkusProject quarkusProject, String... extensions) throws Exception {
@@ -181,6 +183,11 @@ private QuarkusProject createNewProject(final File pom) throws IOException, Quar
.artifactId("add-extension-test")
.version("0.0.1-SNAPSHOT")
.execute();
- return QuarkusProject.of(projectFolderPath, getPlatformDescriptor(), BuildTool.MAVEN);
+ return QuarkusProject.maven(projectFolderPath, getPlatformDescriptor());
+ }
+
+ private static Map readByManagementKey(QuarkusProject project) throws IOException {
+ return project.getExtensionsManager().getInstalled().stream()
+ .collect(toMap(Extension::managementKey, Function.identity()));
}
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddExtensionsSelectTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/QuarkusCommandHandlersTest.java
similarity index 86%
rename from independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddExtensionsSelectTest.java
rename to independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/QuarkusCommandHandlersTest.java
index 633d796491b688..476bdf7d6a0f1f 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/AddExtensionsSelectTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/QuarkusCommandHandlersTest.java
@@ -1,14 +1,16 @@
package io.quarkus.cli.commands;
+import static io.quarkus.cli.commands.QuarkusCommandHandlers.select;
import static java.util.Arrays.asList;
+import io.quarkus.cli.commands.data.SelectionResult;
import io.quarkus.dependencies.Extension;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-class AddExtensionsSelectTest {
+class QuarkusCommandHandlersTest {
@Test
void testMultiMatchByLabels() {
@@ -24,11 +26,11 @@ void testMultiMatchByLabels() {
List extensions = asList(e1, e2, e3);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("foo", extensions, true);
+ SelectionResult matches = select(extensions, "foo", true);
Assertions.assertFalse(matches.matches());
Assertions.assertEquals(2, matches.getExtensions().size());
- matches = AddExtensionsCommandHandler.select("foo", extensions, false);
+ matches = select(extensions, "foo", false);
Assertions.assertFalse(matches.matches());
Assertions.assertEquals(0, matches.getExtensions().size());
}
@@ -44,7 +46,7 @@ void testThatSingleLabelMatchIsNotAMatch() {
List extensions = asList(e1, e2);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("foo", extensions, true);
+ SelectionResult matches = select(extensions, "foo", true);
Assertions.assertFalse(matches.matches());
Assertions.assertEquals(1, matches.getExtensions().size());
}
@@ -63,11 +65,11 @@ void testMultiMatchByArtifactIdsAndNames() {
List extensions = asList(e1, e2, e3);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("foo", extensions, false);
+ SelectionResult matches = select(extensions, "foo", false);
Assertions.assertFalse(matches.matches());
Assertions.assertEquals(2, matches.getExtensions().size());
- matches = AddExtensionsCommandHandler.select("foo", extensions, true);
+ matches = select(extensions, "foo", true);
Assertions.assertFalse(matches.matches());
Assertions.assertEquals(3, matches.getExtensions().size());
@@ -88,7 +90,7 @@ void testShortNameSelection() {
List extensions = asList(e1, e2, e3);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("foo", extensions, false);
+ SelectionResult matches = select(extensions, "foo", false);
Assertions.assertTrue(matches.matches());
Assertions.assertEquals(1, matches.getExtensions().size());
Assertions.assertTrue(matches.iterator().hasNext());
@@ -111,7 +113,7 @@ void testArtifactIdSelectionWithQuarkusPrefix() {
List extensions = asList(e1, e2, e3);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("foo", extensions, false);
+ SelectionResult matches = select(extensions, "foo", false);
Assertions.assertEquals(1, matches.getExtensions().size());
Assertions.assertTrue(matches.iterator().hasNext());
Assertions.assertTrue(matches.iterator().next().getArtifactId().equalsIgnoreCase("quarkus-foo"));
@@ -133,12 +135,11 @@ void testListedVsUnlisted() {
List extensions = asList(e1, e2, e3);
Collections.shuffle(extensions);
- SelectionResult matches = AddExtensionsCommandHandler.select("quarkus-foo", extensions, true);
+ SelectionResult matches = select(extensions, "quarkus-foo", true);
Assertions.assertEquals(2, matches.getExtensions().size());
- matches = AddExtensionsCommandHandler.select("quarkus-foo-unlisted", extensions, true);
+ matches = select(extensions, "quarkus-foo-unlisted", true);
Assertions.assertEquals(1, matches.getExtensions().size());
}
-
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveGradleExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveGradleExtensionsTest.java
index 2348a72ba33615..07eacd18b5f4c9 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveGradleExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveGradleExtensionsTest.java
@@ -1,9 +1,13 @@
package io.quarkus.cli.commands;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.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;
@@ -56,7 +60,10 @@ protected long countDependencyOccurrences(final List buildFile, final St
}
private QuarkusProject getQuarkusProject() {
- return QuarkusProject.of(getProjectPath(), getPlatformDescriptor(), BuildTool.GRADLE);
+ final Path projectPath = getProjectPath();
+ final QuarkusPlatformDescriptor platformDescriptor = getPlatformDescriptor();
+ return QuarkusProject.of(projectPath, platformDescriptor,
+ new AddGradleExtensionsTest.TestingGradleBuildFile(projectPath, platformDescriptor));
}
private static String getBuildFileDependencyString(final String groupId, final String artifactId, final String version) {
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveMavenExtensionsTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveMavenExtensionsTest.java
index 57971f118a4ed0..6a6b3d173b92b9 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveMavenExtensionsTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/cli/commands/RemoveMavenExtensionsTest.java
@@ -1,6 +1,7 @@
package io.quarkus.cli.commands;
-import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.maven.utilities.MojoUtils;
import java.io.File;
@@ -52,6 +53,6 @@ protected long countDependencyOccurrences(final Model project, final String grou
}
private QuarkusProject getQuarkusProject() {
- return QuarkusProject.of(getProjectPath(), getPlatformDescriptor(), BuildTool.MAVEN);
+ return QuarkusProject.maven(getProjectPath(), getPlatformDescriptor());
}
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/generators/rest/BasicRestProjectGeneratorTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java
similarity index 85%
rename from independent-projects/tools/common/src/test/java/io/quarkus/generators/rest/BasicRestProjectGeneratorTest.java
rename to independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java
index 1ca8d1441dc64c..dfd1997904c033 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/generators/rest/BasicRestProjectGeneratorTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/codegen/rest/BasicRestProjectGeneratorTest.java
@@ -1,13 +1,13 @@
-package io.quarkus.generators.rest;
-
-import static io.quarkus.generators.ProjectGenerator.BOM_VERSION;
-import static io.quarkus.generators.ProjectGenerator.CLASS_NAME;
-import static io.quarkus.generators.ProjectGenerator.IS_SPRING;
-import static io.quarkus.generators.ProjectGenerator.PACKAGE_NAME;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_ARTIFACT_ID;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_GROUP_ID;
-import static io.quarkus.generators.ProjectGenerator.PROJECT_VERSION;
-import static io.quarkus.generators.ProjectGenerator.SOURCE_TYPE;
+package io.quarkus.devtools.project.codegen.rest;
+
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.BOM_VERSION;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.CLASS_NAME;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.IS_SPRING;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PACKAGE_NAME;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_ARTIFACT_ID;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_GROUP_ID;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.PROJECT_VERSION;
+import static io.quarkus.devtools.project.codegen.ProjectGenerator.SOURCE_TYPE;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -20,12 +20,10 @@
import com.google.common.collect.Maps;
import io.quarkus.bootstrap.util.IoUtils;
import io.quarkus.cli.commands.PlatformAwareTestBase;
-import io.quarkus.cli.commands.QuarkusCommandInvocation;
-import io.quarkus.devtools.project.BuildTool;
+import io.quarkus.cli.commands.data.QuarkusCommandInvocation;
import io.quarkus.devtools.project.QuarkusProject;
-import io.quarkus.devtools.writer.FileProjectWriter;
-import io.quarkus.devtools.writer.ProjectWriter;
-import io.quarkus.generators.SourceType;
+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;
@@ -63,9 +61,8 @@ void generateMultipleTimes() throws InterruptedException {
final BasicRestProjectGenerator basicRestProjectGenerator = new BasicRestProjectGenerator();
List> collect = IntStream.range(0, 20).boxed().map(i -> (Callable) () -> {
final Path path = Files.createTempDirectory("test");
- try (FileProjectWriter writer = new FileProjectWriter(path.toFile())) {
- basicRestProjectGenerator.generate(writer,
- createQuarkusCommandInvocation(path));
+ try {
+ basicRestProjectGenerator.generate(createQuarkusCommandInvocation(path));
} finally {
IoUtils.recursiveDelete(path);
}
@@ -138,7 +135,7 @@ void generateFilesWithSpringControllerResource() throws Exception {
}
private QuarkusCommandInvocation createQuarkusCommandInvocation(Path projectPath) {
- return new QuarkusCommandInvocation(QuarkusProject.of(projectPath, getPlatformDescriptor(), BuildTool.MAVEN),
+ return new QuarkusCommandInvocation(QuarkusProject.maven(projectPath, getPlatformDescriptor()),
BASIC_PROJECT_CONTEXT);
}
diff --git a/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java b/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java
index 33b014420a00c7..8416a0c77cd600 100644
--- a/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java
+++ b/independent-projects/tools/common/src/test/java/io/quarkus/devtools/project/compress/QuarkusProjectCompressTest.java
@@ -9,8 +9,8 @@
import io.quarkus.cli.commands.CreateProject;
import io.quarkus.cli.commands.CreateProjectTest;
import io.quarkus.cli.commands.PlatformAwareTestBase;
-import io.quarkus.cli.commands.QuarkusCommandException;
-import io.quarkus.cli.commands.QuarkusCommandOutcome;
+import io.quarkus.cli.commands.data.QuarkusCommandException;
+import io.quarkus.cli.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.QuarkusProject;
import java.io.File;
import java.io.FileInputStream;
diff --git a/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/tools/ConsoleMessageFormat.java b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/tools/ConsoleMessageFormat.java
new file mode 100644
index 00000000000000..d4dc80af5c314b
--- /dev/null
+++ b/independent-projects/tools/platform-descriptor-api/src/main/java/io/quarkus/platform/tools/ConsoleMessageFormat.java
@@ -0,0 +1,23 @@
+package io.quarkus.platform.tools;
+
+public final class ConsoleMessageFormat {
+
+ public static final String OK = "\u2705";
+ public static final String NOK = "\u274c";
+ public static final String NOOP = "\uD83D\uDC4D";
+
+ private ConsoleMessageFormat() {
+ }
+
+ public static String nok(String content) {
+ return NOK + content;
+ }
+
+ public static String ok(String content) {
+ return OK + content;
+ }
+
+ public static String noop(String content) {
+ return NOOP + content;
+ }
+}
diff --git a/integration-tests/maven/src/test/resources/projects/simple-pom-it/pom.xml b/integration-tests/maven/src/test/resources/projects/simple-pom-it/pom.xml
index 1dc185b7a89403..5147ef26527776 100644
--- a/integration-tests/maven/src/test/resources/projects/simple-pom-it/pom.xml
+++ b/integration-tests/maven/src/test/resources/projects/simple-pom-it/pom.xml
@@ -5,4 +5,21 @@
io.acme.it
acme-empty-pom
0.0.1.BUILD-SNAPSHOT
+
+ io.quarkus
+ quarkus-bom
+ @project.version@
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ ${quarkus.platform.artifact-id}
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+