diff --git a/cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java b/cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java index 15c5cdbe0..d79afdf33 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java @@ -25,6 +25,7 @@ import com.devonfw.tools.ide.tool.node.Node; import com.devonfw.tools.ide.tool.oc.Oc; import com.devonfw.tools.ide.tool.quarkus.Quarkus; +import com.devonfw.tools.ide.tool.sonar.Sonar; import com.devonfw.tools.ide.tool.terraform.Terraform; import com.devonfw.tools.ide.tool.vscode.Vscode; @@ -83,6 +84,7 @@ public CommandletManagerImpl(IdeContext context) { add(new Aws(context)); add(new Cobigen(context)); add(new Jmc(context)); + add(new Sonar(context)); } private void add(Commandlet commandlet) { diff --git a/cli/src/main/java/com/devonfw/tools/ide/property/EnumProperty.java b/cli/src/main/java/com/devonfw/tools/ide/property/EnumProperty.java new file mode 100644 index 000000000..d1db549e0 --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/property/EnumProperty.java @@ -0,0 +1,59 @@ +package com.devonfw.tools.ide.property; + +import java.util.Locale; + +import com.devonfw.tools.ide.commandlet.Commandlet; +import com.devonfw.tools.ide.completion.CompletionCandidateCollector; +import com.devonfw.tools.ide.context.IdeContext; + +/** + * {@link Property} with {@link #getValueType() value type} {@link Boolean}. + */ +public class EnumProperty> extends Property { + + private final Class valueType; + + /** + * The constructor. + * + * @param name the {@link #getName() property name}. + * @param required the {@link #isRequired() required flag}. + * @param alias the {@link #getAlias() property alias}. + */ + public EnumProperty(String name, boolean required, String alias, Class valueType) { + + super(name, required, alias, null); + this.valueType = valueType; + } + + @Override + public Class getValueType() { + + return this.valueType; + } + + @Override + public V parse(String valueAsString, IdeContext context) { + + for (V enumConstant : this.valueType.getEnumConstants()) { + String name = enumConstant.name().toLowerCase(Locale.ROOT); + if (name.equals(valueAsString)) { + return enumConstant; + } + } + + throw new IllegalArgumentException(String.format("Invalid Enum option: %s", valueAsString)); + } + + @Override + protected void completeValue(String arg, IdeContext context, Commandlet commandlet, + CompletionCandidateCollector collector) { + + for (V enumConstant : this.valueType.getEnumConstants()) { + String name = enumConstant.name().toLowerCase(Locale.ROOT); + if (name.startsWith(arg)) { + collector.add(name, null, this, commandlet); + } + } + } +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java index b5d8d4df6..ea9f7656b 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java @@ -48,7 +48,16 @@ public ToolCommandlet(IdeContext context, String tool, Set tags) { this.tool = tool; this.tags = tags; addKeyword(tool); - this.arguments = add(new StringListProperty("", false, "args")); + this.arguments = new StringListProperty("", false, "args"); + initProperties(); + } + + /** + * Add initial Properties to the tool + */ + protected void initProperties() { + + add(this.arguments); } /** diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/Sonar.java b/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/Sonar.java new file mode 100644 index 000000000..e3f77051a --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/Sonar.java @@ -0,0 +1,105 @@ +package com.devonfw.tools.ide.tool.sonar; + +import java.nio.file.Path; +import java.util.Properties; +import java.util.Set; + +import com.devonfw.tools.ide.common.Tag; +import com.devonfw.tools.ide.context.IdeContext; +import com.devonfw.tools.ide.property.EnumProperty; +import com.devonfw.tools.ide.tool.LocalToolCommandlet; +import com.devonfw.tools.ide.tool.java.Java; +import com.devonfw.tools.ide.tool.mvn.Mvn; +import com.devonfw.tools.ide.util.PropertiesFileUtil; + +public class Sonar extends LocalToolCommandlet { + + public final EnumProperty command; + + /** + * The constructor. + * + * @param context the {@link IdeContext}. method. + */ + public Sonar(IdeContext context) { + + super(context, "sonar", Set.of(Tag.CODE_QA)); + + this.command = add(new EnumProperty<>("", true, "command", SonarCommand.class)); + add(this.arguments); + } + + @Override + protected void initProperties() { + + // Empty on purpose + } + + @Override + public boolean install(boolean silent) { + + getCommandlet(Java.class).install(); + return super.install(silent); + } + + @Override + public void run() { + + SonarCommand command = this.command.getValue(); + + Path toolPath = getToolPath(); + if (!toolPath.toFile().exists()) { + super.install(true); + } + + switch (command) { + case ANALYZE: + getCommandlet(Mvn.class).runTool(null, "sonar:sonar"); + break; + case START: + printSonarWebPort(); + arguments.setValueAsString("start", context); + super.run(); + break; + case STOP: + arguments.setValueAsString("stop", context); + super.run(); + break; + default: + } + } + + @Override + protected String getBinaryName() { + + SonarCommand command = this.command.getValue(); + + Path toolBinPath = getToolBinPath(); + String sonarLocation = null; + + if (this.context.getSystemInfo().isWindows()) { + if (command.equals(SonarCommand.START)) { + sonarLocation = "windows-x86-64/StartSonar.bat"; + } else if (command.equals(SonarCommand.STOP)) { + sonarLocation = "windows-x86-64/SonarService.bat"; + } + } else if (this.context.getSystemInfo().isMac()) { + sonarLocation = "macosx-universal-64/sonar.sh"; + } else { + sonarLocation = "linux-x86-64/sonar.sh"; + } + return toolBinPath.resolve(sonarLocation).toString(); + } + + private void printSonarWebPort() { + + this.context.info("SonarQube is running at localhost on the following port (default 9000):"); + Path sonarPropertiesPath = getToolPath().resolve("conf/sonar.properties"); + + Properties sonarProperties = PropertiesFileUtil.loadProperties(sonarPropertiesPath); + String sonarWebPort = sonarProperties.getProperty("sonar.web.port"); + if (sonarWebPort != null) { + this.context.info(sonarWebPort); + } + } +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/SonarCommand.java b/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/SonarCommand.java new file mode 100644 index 000000000..1ec15148e --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/sonar/SonarCommand.java @@ -0,0 +1,8 @@ +package com.devonfw.tools.ide.tool.sonar; + +/** + * Represents commands for controlling a sonar operation in The{@link Sonar} Tool. + */ +public enum SonarCommand { + START, STOP, ANALYZE +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/util/PropertiesFileUtil.java b/cli/src/main/java/com/devonfw/tools/ide/util/PropertiesFileUtil.java new file mode 100644 index 000000000..b0525639b --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/util/PropertiesFileUtil.java @@ -0,0 +1,27 @@ +package com.devonfw.tools.ide.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; + +public class PropertiesFileUtil { + + /** + * Loads properties from a file at the given path. + * + * @param path the path to the properties file + * @return a Properties object loaded with properties from the file + */ + public static Properties loadProperties(Path path) { + + Properties properties = new Properties(); + + try (var inputStream = Files.newInputStream(path)) { + properties.load(inputStream); + } catch (IOException e) { + throw new IllegalArgumentException(String.format("Cannot read Properties File at %s", path.toString()), e); + } + return properties; + } +} diff --git a/cli/src/main/resources/nls/Ide.properties b/cli/src/main/resources/nls/Ide.properties index ef6b3eda7..297ae29de 100644 --- a/cli/src/main/resources/nls/Ide.properties +++ b/cli/src/main/resources/nls/Ide.properties @@ -32,8 +32,10 @@ cmd-shell=Commandlet to start built-in shell with advanced auto-completion. cmd-terraform=Tool commandlet for Terraform cmd-vscode=Tool commandlet for Visual Studio Code (IDE) cmd-cobigen=Tool commandlet for Cobigen +cmd-sonar=Tool commandlet for SonarQube val-args=The commandline arguments to pass to the tool. val-edition=The tool edition. +val-sonar-command=START|STOP|ANALYZE val-tool=The tool commandlet to select. val-version=The tool version val-set-version-version=The tool version to set. diff --git a/cli/src/main/resources/nls/Ide_de.properties b/cli/src/main/resources/nls/Ide_de.properties index 688bd923a..d7bb5ebb5 100644 --- a/cli/src/main/resources/nls/Ide_de.properties +++ b/cli/src/main/resources/nls/Ide_de.properties @@ -29,6 +29,7 @@ cmd-set-version=Setzt die Version des selektierten Werkzeugs. cmd-terraform=Werkzeug Kommando für Terraform. cmd-vscode=Werkzeug Kommando für Visual Studio Code (IDE) cmd-cobigen=Werkzeug Kommando für Cobigen. +cmd-sonar=Werkzeug Kommando für SonarQube. val-args=Die Kommandozeilen-Argumente zur Übergabe an das Werkzeug. val-edition=Die Werkzeug Edition. val-tool=Das zu selektierende Werkzeug Kommando. diff --git a/documentation/IDEasy-usage.asciidoc b/documentation/IDEasy-usage.asciidoc index 7917902c1..95b182c73 100644 --- a/documentation/IDEasy-usage.asciidoc +++ b/documentation/IDEasy-usage.asciidoc @@ -1,39 +1,39 @@ -= Usage - -include::usage.asciidoc[leveloffset=2] - -<<<< - -include::configuration.asciidoc[leveloffset=2] - -<<<< - -include::variables.asciidoc[leveloffset=2] - -<<<< - -include::cli.asciidoc[leveloffset=2] - -include::docker-desktop-alternative.asciidoc[leveloffset=3] - -<<<< - -include::structure.asciidoc[leveloffset=2] - -include::conf.asciidoc[leveloffset=3] - -include::log.asciidoc[leveloffset=3] - -include::scripts.asciidoc[leveloffset=3] - -include::settings.asciidoc[leveloffset=3] - -include::software.asciidoc[leveloffset=3] - -include::system.asciidoc[leveloffset=3] - -include::updates.asciidoc[leveloffset=3] - -include::workspaces.asciidoc[leveloffset=3] - -include::projects.asciidoc[leveloffset=3] += Usage + +include::usage.asciidoc[leveloffset=2] + +<<<< + +include::configuration.asciidoc[leveloffset=2] + +<<<< + +include::variables.asciidoc[leveloffset=2] + +<<<< + +include::cli.asciidoc[leveloffset=2] + +include::docker-desktop-alternative.asciidoc[leveloffset=3] + +<<<< + +include::structure.asciidoc[leveloffset=2] + +include::conf.asciidoc[leveloffset=3] + +include::log.asciidoc[leveloffset=3] + +include::scripts.asciidoc[leveloffset=3] + +include::settings.asciidoc[leveloffset=3] + +include::software.asciidoc[leveloffset=3] + +include::system.asciidoc[leveloffset=3] + +include::updates.asciidoc[leveloffset=3] + +include::workspaces.asciidoc[leveloffset=3] + +include::projects.asciidoc[leveloffset=3] diff --git a/documentation/cli.asciidoc b/documentation/cli.asciidoc index d73866633..cc79c8001 100644 --- a/documentation/cli.asciidoc +++ b/documentation/cli.asciidoc @@ -45,49 +45,3 @@ The benefit when using `ide` as wrapper is that it will even work when the comma We see the main benefit in this for writing portable scripts that you may commit to your git repository and that will then run everywhere and will lazily install the required tools on the fly. In your daily usage you can and surely should avoid to always type `ide` as prefix to every command. However, when you automate and want to avoid "command not found" errors, you can simply prefix the command with `ide`. - -=== Commandlet overview - -The following commandlets are currently available: - -* link:android-studio.asciidoc[android-studio] -* link:aws.asciidoc[aws] -* link:az.asciidoc[az] -* link:build.asciidoc[build] -* link:cobigen.asciidoc[cobigen] -* link:docker.asciidoc[docker] -* link:dotnet.asciidoc[dotnet] -* link:eclipse.asciidoc[eclipse] -* link:gcloud.asciidoc[gcloud] -* link:gcviewer.asciidoc[gcviewer] -* link:gh.asciidoc[gh] -* link:graalvm.asciidoc[graalvm] -* link:gradle.asciidoc[gradle] -* link:helm.asciidoc[helm] -* link:help.asciidoc[help] -* link:ide.asciidoc[ide] -* link:intellij.asciidoc[intellij] -* link:ionic.asciidoc[ionic] -* link:jasypt.asciidoc[jasypt] -* link:java.asciidoc[java] -* link:jenkins.asciidoc[jenkins] -* link:jmc.asciidoc[jmc] -* link:kotlinc.asciidoc[kotlinc] -* link:kotlinc-native.asciidoc[kotlinc-native] -* link:kubectl.asciidoc[kubectl] -* link:lazydocker.asciidoc[lazydocker] -* link:mvn.asciidoc[mvn] -* link:ng.asciidoc[ng] -* link:node.asciidoc[node] -* link:npm.asciidoc[npm] -* link:oc.asciidoc[oc] -* link:python.asciidoc[python] -* link:pip.asciidoc[pip] -* link:quarkus.asciidoc[quarkus] -* link:release.asciidoc[release] -* link:rewrite.asciidoc[rewrite] -* link:sonar.asciidoc[sonar] -* link:terraform.asciidoc[terraform] -* link:tomcat.asciidoc[tomcat] -* link:vscode.asciidoc[vscode] -* link:yarn.asciidoc[yarn]