This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new e59b852914f7 CAMEL-23653: camel-jbang - Make it easy to use plugins
(#23657)
e59b852914f7 is described below
commit e59b852914f7b46795387bf208280259d2c0efb5
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jun 1 11:25:15 2026 +0200
CAMEL-23653: camel-jbang - Make it easy to use plugins (#23657)
* CAMEL-23653: camel-jbang - Make it easy to use plugins
Auto-install bundled plugins on first use and show available plugins in
help output.
Co-Authored-By: Claude <[email protected]>
* CAMEL-23653: Fix test to match corrected quote in error message
Co-Authored-By: Claude <[email protected]>
---------
Co-authored-by: Claude <[email protected]>
---
.../dsl/jbang/core/commands/CamelJBangMain.java | 61 ++++++++++++++++++++++
.../MissingPluginParameterExceptionHandler.java | 16 +++++-
.../camel/dsl/jbang/core/common/PluginHelper.java | 6 ++-
.../ParameterExceptionHandlerTest.java | 2 +-
4 files changed, 82 insertions(+), 3 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index 5ffd1ecd473a..04a0f9d39a6a 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -16,6 +16,10 @@
*/
package org.apache.camel.dsl.jbang.core.commands;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;
import org.apache.camel.catalog.CamelCatalog;
@@ -59,7 +63,9 @@ import
org.apache.camel.dsl.jbang.core.commands.version.VersionList;
import org.apache.camel.dsl.jbang.core.commands.version.VersionSet;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
import org.apache.camel.dsl.jbang.core.common.PluginHelper;
+import org.apache.camel.dsl.jbang.core.common.PluginType;
import org.apache.camel.dsl.jbang.core.common.Printer;
+import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
import picocli.CommandLine.Command;
@@ -232,6 +238,9 @@ public class CamelJBangMain implements Callable<Integer> {
CommandLineHelper.augmentWithUserConfiguration(commandLine);
preExecute(commandLine, args);
int exitCode = commandLine.execute(args);
+ if (isHelpRequest(args)) {
+ printAvailablePlugins();
+ }
postExecute(commandLine, args, exitCode);
quit(exitCode);
}
@@ -271,6 +280,58 @@ public class CamelJBangMain implements Callable<Integer> {
return 0;
}
+ private static boolean isHelpRequest(String[] args) {
+ if (args == null || args.length == 0) {
+ return true;
+ }
+ for (String arg : args) {
+ if ("--help".equals(arg) || "-h".equals(arg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void printAvailablePlugins() {
+ Set<String> installed = new HashSet<>();
+ JsonObject config = PluginHelper.getPluginConfig();
+ if (config != null) {
+ JsonObject plugins = config.getMap("plugins");
+ if (plugins != null) {
+ installed.addAll(plugins.keySet());
+ }
+ }
+ // also consider already registered subcommands as installed
+ Set<String> registered = commandLine.getSubcommands().keySet();
+
+ List<String[]> rows = new ArrayList<>();
+ for (PluginType pt : PluginType.values()) {
+ if (!installed.contains(pt.getName()) &&
!registered.contains(pt.getCommand())) {
+ rows.add(new String[] { pt.getCommand(), pt.getDescription()
});
+ }
+ }
+ for (JsonObject kp : PluginHelper.loadKnownPlugins()) {
+ String name = kp.getString("name");
+ String command = kp.getStringOrDefault("command", name);
+ if (!installed.contains(name) && !registered.contains(command)
+ && PluginType.findByName(name).isEmpty()) {
+ rows.add(new String[] { command,
kp.getStringOrDefault("description", "") });
+ }
+ }
+
+ if (!rows.isEmpty()) {
+ int maxCmd = rows.stream().mapToInt(r ->
r[0].length()).max().orElse(0);
+ out.println();
+ out.println("Plugins (not installed):");
+ for (String[] row : rows) {
+ out.printf(" %-" + maxCmd + "s %s%n", row[0], row[1]);
+ }
+ out.println();
+ out.println("Tip: Install with: camel plugin add <name>");
+ out.println(" Bundled plugins are auto-installed on first
use.");
+ }
+ }
+
/**
* Gets the main output printer to write command output.
*
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/MissingPluginParameterExceptionHandler.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/MissingPluginParameterExceptionHandler.java
index 9f930aceeb6e..6b131ad9b1ef 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/MissingPluginParameterExceptionHandler.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/MissingPluginParameterExceptionHandler.java
@@ -17,7 +17,10 @@
package org.apache.camel.dsl.jbang.core.commands.exceptionhandler;
import java.io.PrintWriter;
+import java.util.Optional;
+import org.apache.camel.dsl.jbang.core.common.PluginHelper;
+import org.apache.camel.dsl.jbang.core.common.PluginType;
import picocli.CommandLine;
import picocli.CommandLine.IParameterExceptionHandler;
import picocli.CommandLine.Model.CommandSpec;
@@ -31,6 +34,17 @@ public class MissingPluginParameterExceptionHandler
implements IParameterExcepti
CommandLine cmd = ex.getCommandLine();
PrintWriter err = cmd.getErr();
+ if (ex.getMessage().startsWith("Unmatched argument at index 0") &&
args.length > 0) {
+ Optional<PluginType> pluginType = PluginType.findByName(args[0]);
+ if (pluginType.isPresent()) {
+ PluginHelper.enable(pluginType.get());
+ PrintWriter out = cmd.getOut();
+ out.printf("Installed plugin: %s%n",
pluginType.get().getName());
+ out.println("Please re-run the command.");
+ return 0;
+ }
+ }
+
if ("DEBUG".equalsIgnoreCase(System.getProperty("picocli.trace"))) {
err.println(cmd.getColorScheme().stackTraceText(ex));
}
@@ -44,7 +58,7 @@ public class MissingPluginParameterExceptionHandler
implements IParameterExcepti
if (ex.getMessage().startsWith("Unmatched argument at index 0")) {
err.println(cmd.getColorScheme().errorText(
- "Maybe a specific Camel JBang plugin must be installed?
(Try camel plugin --help' for more information)"));
+ "Maybe a specific Camel JBang plugin must be installed?
(Try 'camel plugin --help' for more information)"));
}
return cmd.getExitCodeExceptionMapper() != null
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
index 0fa2eb0a1f55..a71d7c888717 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
@@ -118,7 +118,11 @@ public final class PluginHelper {
*/
public static void addPlugins(CommandLine commandLine, CamelJBangMain
main, String... args) {
// first arg is the command name (ie camel generate xxx)
+ // if the first arg is a flag (e.g. --help), treat as no target so all
plugins load
String target = args != null && args.length > 0 ? args[0] : null;
+ if (target != null && target.startsWith("-")) {
+ target = null;
+ }
// First, try to load embedded plugins from classpath (fat-jar
scenario)
boolean foundEmbeddedPlugins = false;
@@ -536,7 +540,7 @@ public final class PluginHelper {
return
Optional.ofNullable(getPluginConfig()).orElseGet(PluginHelper::createPluginConfig);
}
- static JsonObject getPluginConfig() {
+ public static JsonObject getPluginConfig() {
try {
Path f = CommandLineHelper.getHomeDir().resolve(PLUGIN_CONFIG);
if (Files.exists(f)) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/ParameterExceptionHandlerTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/ParameterExceptionHandlerTest.java
index a6ec85d69c6c..210773167f0b 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/ParameterExceptionHandlerTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/exceptionhandler/ParameterExceptionHandlerTest.java
@@ -37,7 +37,7 @@ class ParameterExceptionHandlerTest {
Assertions.assertEquals("Did you mean: camel eval or camel stop or
camel infra?", lines[1],
"Second line with suggestion in case it is a typo");
Assertions.assertEquals(
- "Maybe a specific Camel JBang plugin must be installed? (Try
camel plugin --help' for more information)",
+ "Maybe a specific Camel JBang plugin must be installed? (Try
'camel plugin --help' for more information)",
lines[4], "Last line suggesting new plugin");
}