diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 391733f60c..e26eb92e8f 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -21,6 +21,7 @@ Release with new features and bugfixes: * https://github.com/devonfw/IDEAsy/issues/2181[#2181]: Merged the VsCode and VsCodium plugin folder and added excluded-editions as an option for plugins * https://github.com/devonfw/IDEasy/issues/2145[#2145]: Improve documentation on symlink regarding ide ln * https://github.com/devonfw/IDEasy/issues/2235[#2235]: Language flag in cli dosn't take effect in some terminals +* https://github.com/devonfw/IDEasy/issues/825[#825]: Add commandlet for GC Log Analyzer The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/48?closed=1[milestone 2026.08.001]. 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 49f59bdcd0..0f3aa2b6ab 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 @@ -29,6 +29,7 @@ import com.devonfw.tools.ide.tool.docker.Docker; import com.devonfw.tools.ide.tool.dotnet.DotNet; import com.devonfw.tools.ide.tool.eclipse.Eclipse; +import com.devonfw.tools.ide.tool.gcloganalyzer.GcLogAnalyzer; import com.devonfw.tools.ide.tool.gcviewer.GcViewer; import com.devonfw.tools.ide.tool.gh.Gh; import com.devonfw.tools.ide.tool.go.Go; @@ -137,6 +138,7 @@ public CommandletManagerImpl(IdeContext context) { add(new Npm(context)); add(new Mvn(context)); add(new Msvc(context)); + add(new GcLogAnalyzer(context)); add(new GcViewer(context)); add(new Gradle(context)); add(new Eclipse(context)); diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzer.java b/cli/src/main/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzer.java new file mode 100644 index 0000000000..53b780e7a7 --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzer.java @@ -0,0 +1,64 @@ +package com.devonfw.tools.ide.tool.gcloganalyzer; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import com.devonfw.tools.ide.common.Tag; +import com.devonfw.tools.ide.context.IdeContext; +import com.devonfw.tools.ide.process.ProcessContext; +import com.devonfw.tools.ide.process.ProcessMode; +import com.devonfw.tools.ide.process.ProcessResult; +import com.devonfw.tools.ide.tool.LocalToolCommandlet; +import com.devonfw.tools.ide.tool.ToolCommandlet; + +/** + * {@link ToolCommandlet} for GC Log Analyzer by Azul Systems. + */ +public class GcLogAnalyzer extends LocalToolCommandlet { + + /** + * The constructor. + * + * @param context the {@link IdeContext}. + */ + public GcLogAnalyzer(IdeContext context) { + + super(context, "gcloganalyzer", Set.of(Tag.JAVA, Tag.ANALYSE)); + } + + @Override + public ProcessResult runTool(List args) { + + return runTool(ProcessMode.BACKGROUND, null, args); + } + + @Override + public ProcessResult runTool(ProcessContext pc, ProcessMode processMode, List args) { + + pc.directory(getToolPath()); + pc.executable("java"); + pc.addArg("-jar"); + pc.addArg(resolveGcLogAnalyzerJarPath().getFileName().toString()); + pc.addArgs(args); + return pc.run(processMode); + } + + private Path resolveGcLogAnalyzerJarPath() { + + List jarFiles = this.context.getFileAccess().listChildren( + getToolPath(), + path -> Files.isRegularFile(path) && path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar") + ); + + if (jarFiles.size() == 1) { + return jarFiles.getFirst(); + } + + return jarFiles.stream().filter(path -> path.getFileName().toString() + .regionMatches(true, 0, "GCLogAnalyzer-", 0, "GCLogAnalyzer-".length())).findFirst() + .orElseThrow(() -> new IllegalStateException("Could not find GC Log Analyzer JAR in " + getToolPath())); + } +} diff --git a/cli/src/main/resources/nls/Help.properties b/cli/src/main/resources/nls/Help.properties index 2efa03eae2..1ec96e468e 100644 --- a/cli/src/main/resources/nls/Help.properties +++ b/cli/src/main/resources/nls/Help.properties @@ -34,6 +34,8 @@ cmd.env.opt.--bash=Convert Windows path syntax to bash for usage in git-bash. cmd.fix-vpn-tls-problem=Commandlet to fix the VPN TLS problem on Windows. cmd.fix-vpn-tls-problem.detail=If you are using a VPN on Windows and encounter TLS problems, this commandlet can help you fix the issue by adding the necessary certificates to your Java keystore. Simply run the following command:\nide fix-vpn-tls-problem cmd.fix-vpn-tls-problem.val.url=The URL that is affected by the VPN TLS problem (e.g. 'https://api.azul.com'), if not provided the commandlet will test 'https://github.com' by default. +cmd.gcloganalyzer=Tool commandlet for GC Log Analyzer (Analyze and visualize garbage collection logs of Java). +cmd.gcloganalyzer.detail=GC Log Analyzer by Azul Systems is a tool for analyzing and visualizing Java garbage collection logs. Detailed documentation can be found at https://docs.azul.com/prime/gcla/about-gcla cmd.gcviewer=Tool commandlet for GC Viewer (View garbage collector logs of Java). cmd.gcviewer.detail=GCViewer is a tool for analyzing and visualizing Java garbage collection logs. Detailed documentation can be found at https://github.com/chewiebug/GCViewer cmd.get-edition=Get the edition of the selected tool. diff --git a/cli/src/main/resources/nls/Help_de.properties b/cli/src/main/resources/nls/Help_de.properties index 53d7d7002e..27bd6ca322 100644 --- a/cli/src/main/resources/nls/Help_de.properties +++ b/cli/src/main/resources/nls/Help_de.properties @@ -34,6 +34,8 @@ cmd.env.opt.--bash=Konvertiert Windows-Pfad-Syntax nach Bash zur Verwendung in g cmd.fix-vpn-tls-problem=Wekzeug Kommando zum Beheben von VPN TLS Problemen auf Windows cmd.fix-vpn-tls-problem.detail=Auf einigen Windows-Systemen kann es zu Problemen mit der TLS-Verbindung kommen, wenn eine VPN-Verbindung aktiv ist. Dieses Werkzeug Kommando bietet eine Lösung für dieses Problem, indem es die TLS-Einstellungen anpasst, um die Kompatibilität mit VPN-Verbindungen zu verbessern. Um dieses Problem zu beheben, führen Sie einfach den folgenden Befehl aus:\nide fix-vpn-tls-problem cmd.fix-vpn-tls-problem.val.url=Die URL, die von dem VPN TLS Problem betroffen ist (e.g. 'https://api.azul.com'). Ohne eingabe einer URL wird standardmäßig: 'https://github.com' angefragt. +cmd.gcloganalyzer=Werkzeug Kommando für GC Log Analyzer (Analyse und Visualisierung von Garbage-Collector Logs von Java). +cmd.gcloganalyzer.detail=GC Log Analyzer von Azul Systems ist ein Tool zur Analyse und Visualisierung von Java-Garbage-Collection-Protokollen. Detaillierte Dokumentation ist zu finden unter https://docs.azul.com/prime/gcla/about-gcla cmd.gcviewer=Werkzeug Kommando für GC Viewer (Anzeige von Garbage-Collector Logs von Java). cmd.gcviewer.detail=GCViewer ist ein Tool zur Analyse und Visualisierung von Java-Garbage-Collection-Protokollen. Detaillierte Dokumentation ist zu finden unter https://github.com/chewiebug/GCViewer cmd.get-edition=Zeigt die Edition des selektierten Werkzeugs an. diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzerTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzerTest.java new file mode 100644 index 0000000000..d42db51743 --- /dev/null +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/gcloganalyzer/GcLogAnalyzerTest.java @@ -0,0 +1,89 @@ +package com.devonfw.tools.ide.tool.gcloganalyzer; + +import org.junit.jupiter.api.Test; + +import com.devonfw.tools.ide.context.AbstractIdeContextTest; +import com.devonfw.tools.ide.context.IdeTestContext; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + +/** + * Test of {@link GcLogAnalyzer}. + */ +@WireMockTest +class GcLogAnalyzerTest extends AbstractIdeContextTest { + + private static final String PROJECT_GCLOGANALYZER = "gcloganalyzer"; + + private static final String VERSION = "24.10.0.0"; + + private static final String ARTIFACT_VERSION = "24.10.0"; + + @Test + void testGcLogAnalyzerInstall(WireMockRuntimeInfo wireMockRuntimeInfo) { + + // arrange + IdeTestContext context = + newContext(PROJECT_GCLOGANALYZER, wireMockRuntimeInfo); + GcLogAnalyzer commandlet = new GcLogAnalyzer(context); + + // act + commandlet.install(); + + // assert + assertInstallation(context, commandlet); + } + + @Test + void testGcLogAnalyzerRunWithArguments( + WireMockRuntimeInfo wireMockRuntimeInfo) { + + // arrange + IdeTestContext context = + newContext(PROJECT_GCLOGANALYZER, wireMockRuntimeInfo); + GcLogAnalyzer commandlet = new GcLogAnalyzer(context); + + commandlet.arguments.addValue("--generate-html"); + commandlet.arguments.addValue("output"); + commandlet.arguments.addValue("gc.log"); + + // act + commandlet.run(); + + // assert + assertThat(context.getSoftwarePath().resolve("java/bin/java")) + .exists(); + + assertThat(context).logAtInfo().hasMessageContaining( + "java -jar GCLogAnalyzer-" + ARTIFACT_VERSION + + "-ca.jar --generate-html output gc.log"); + } + + private void assertInstallation( + IdeTestContext context, GcLogAnalyzer commandlet) { + + assertThat(commandlet.getInstalledVersion().toString()) + .isEqualTo(VERSION); + + assertThat(context.getSoftwarePath() + .resolve("java/bin/java")) + .exists(); + + assertThat(context.getSoftwarePath() + .resolve("gcloganalyzer/.ide.software.version")) + .hasContent(VERSION); + + assertThat(context.getSoftwarePath() + .resolve("gcloganalyzer/GCLogAnalyzer-" + + ARTIFACT_VERSION + "-ca.jar")) + .hasContent("This is a fake GC Log Analyzer jar file.\n"); + + assertThat(context.getSoftwarePath() + .resolve("gcloganalyzer/GCLogAnalyzer-" + + ARTIFACT_VERSION + "-ca")) + .doesNotExist(); + + assertThat(context).logAtSuccess().hasMessageContaining( + "Successfully installed gcloganalyzer in version " + VERSION); + } +} diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/24.10.0.0/urls b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/24.10.0.0/urls new file mode 100644 index 0000000000..3c44b47bec --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/24.10.0.0/urls @@ -0,0 +1 @@ +${testbaseurl}/download/gcloganalyzer/gcloganalyzer/24.10.0.0/GCLogAnalyzer-24.10.0-ca.zip \ No newline at end of file diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/dependencies.json b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/dependencies.json new file mode 100644 index 0000000000..8b376ba251 --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/gcloganalyzer/gcloganalyzer/dependencies.json @@ -0,0 +1,8 @@ +{ + "[24.0.0,25.0.0)": [ + { + "tool": "java", + "versionRange": "[11,)" + } + ] +} diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/java/java/17.0.10_7/urls b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/java/java/17.0.10_7/urls new file mode 100644 index 0000000000..22eab573d1 --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/_ide/urls/java/java/17.0.10_7/urls @@ -0,0 +1 @@ +${testbaseurl}/download/java/java/17.0.10_7/java-17.0.10_7.tgz \ No newline at end of file diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/project/settings/ide.properties b/cli/src/test/resources/ide-projects/gcloganalyzer/project/settings/ide.properties new file mode 100644 index 0000000000..291c74a7f1 --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/project/settings/ide.properties @@ -0,0 +1,2 @@ +JAVA_VERSION=17.0.10_7 +GCLOGANALYZER_VERSION=24.10.0.0 \ No newline at end of file diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/project/workspaces/main/.gitkeep b/cli/src/test/resources/ide-projects/gcloganalyzer/project/workspaces/main/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/repository/gcloganalyzer/gcloganalyzer/default/GCLogAnalyzer-24.10.0-ca/GCLogAnalyzer-24.10.0-ca.jar b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/gcloganalyzer/gcloganalyzer/default/GCLogAnalyzer-24.10.0-ca/GCLogAnalyzer-24.10.0-ca.jar new file mode 100644 index 0000000000..4972ebb4eb --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/gcloganalyzer/gcloganalyzer/default/GCLogAnalyzer-24.10.0-ca/GCLogAnalyzer-24.10.0-ca.jar @@ -0,0 +1 @@ +This is a fake GC Log Analyzer jar file. \ No newline at end of file diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java new file mode 100755 index 0000000000..0aa8af9dc5 --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java @@ -0,0 +1,2 @@ +#!/bin/bash +echo "java $*" \ No newline at end of file diff --git a/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java.cmd b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java.cmd new file mode 100644 index 0000000000..bbaac38028 --- /dev/null +++ b/cli/src/test/resources/ide-projects/gcloganalyzer/repository/java/java/default/bin/java.cmd @@ -0,0 +1,2 @@ +@echo off +echo java %* \ No newline at end of file diff --git a/documentation/LICENSE.adoc b/documentation/LICENSE.adoc index f6257d260c..5b38abce54 100644 --- a/documentation/LICENSE.adoc +++ b/documentation/LICENSE.adoc @@ -49,6 +49,7 @@ The column `inclusion` indicates the way the component is included: |https://logback.qos.ch/[logback-classic]|Directly included|https://logback.qos.ch/license.html[LGPL 2.1] |https://openjdk.java.net/[OpenJDK] / https://adoptopenjdk.net/[AdoptOpenJDK] (Java)|Default Setup|https://openjdk.java.net/legal/gplv2+ce.html[GPLv2] |https://go.dev[GO]|Optional|https://go.dev/LICENSE[BSD 3-Clause] +|https://docs.azul.com/gc-log-analyzer/[GC Log Analyzer]|Optional|https://opensource.org/license/BSD-3-clause[BSD 3-Clause] |https://github.com/github/copilot-cli[GitHub Copilot CLI]|Optional|https://github.com/github/copilot-cli/blob/main/LICENSE.md[Proprietary] |https://github.com/anthropics/claude-code/tree/main[Claude Code CLI]|Optional|https://github.com/anthropics/claude-code/blob/main/LICENSE.md[Proprietary] |https://maven.apache.org/[Maven]|Default Setup|https://www.apache.org/licenses/LICENSE-2.0[Apache 2.0]