This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-23653 in repository https://gitbox.apache.org/repos/asf/camel.git
commit cc1c242c018dd3d8bc65c60f012f77569aba677c Author: Claus Ibsen <[email protected]> AuthorDate: Sun May 31 18:27:55 2026 +0200 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]> --- .../dsl/jbang/core/commands/CamelJBangMain.java | 61 ++++++++++++++++++++++ .../MissingPluginParameterExceptionHandler.java | 16 +++++- .../camel/dsl/jbang/core/common/PluginHelper.java | 6 ++- 3 files changed, 81 insertions(+), 2 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)) {
