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 0fd7d9abf9c2 CAMEL-26428: camel-jbang - The CLI creates only the
command that the command line runs (#28763)
0fd7d9abf9c2 is described below
commit 0fd7d9abf9c2f500b252fed7f318e1f8e3349aae
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 31 12:12:58 2026 +0100
CAMEL-26428: camel-jbang - The CLI creates only the command that the
command line runs (#28763)
Signed-off-by: Claus Ibsen <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../dsl/jbang/core/commands/CamelJBangMain.java | 430 ++++++++++++++-------
.../camel/dsl/jbang/core/common/PluginHelper.java | 11 +
.../commands/CamelJBangMainOnlyCommandTest.java | 105 +++++
.../core/commands/action/SemanticCommandTest.java | 7 +-
.../dsl/jbang/launcher/CamelLauncherMain.java | 4 +
5 files changed, 407 insertions(+), 150 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 cfb612b807ab..655ba828fe4e 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
@@ -86,6 +86,10 @@ import picocli.CommandLine.Command;
" 70:Internal error: an unexpected exception",
"124:Timed out: no reply from the integration in time" })
public class CamelJBangMain implements Callable<Integer> {
+ // the commands that use the other commands of the CLI, besides the ones
that use the plugins (which may add to any
+ // command, see PluginHelper.isPluginConsumingCommand): the shell and the
completion script
+ private static final Set<String> FULL_COMMANDS = Set.of("shell",
"completion");
+
private static CommandLine commandLine;
private Printer out = new Printer.SystemOutPrinter();
@@ -112,7 +116,14 @@ public class CamelJBangMain implements Callable<Integer> {
// ignore
}
- commandLine = createCommandLine();
+ // the CLI creates only the command that the command line names, as
creating all of them (and loading their
+ // classes) costs more than most commands take to run
+ String only = onlyCommand(args);
+ commandLine = createCommandLine(only);
+ if (only != null && !commandLine.getSubcommands().containsKey(only)) {
+ // not a command of the CLI (such as the command of a plugin, or a
typo, for which picocli suggests others)
+ commandLine = createCommandLine(null);
+ }
postAddCommands(commandLine, args);
@@ -152,155 +163,278 @@ public class CamelJBangMain implements
Callable<Integer> {
quit(exitCode);
}
+ /**
+ * The command of the CLI that a command line runs, when the CLI needs to
create only that command: not for the
+ * help, a command line that starts with an option (such as {@code
--version}), or the commands that use the other
+ * commands ({@link #FULL_COMMANDS}) or the plugins ({@link
PluginHelper#isPluginConsumingCommand(String)}).
+ *
+ * @param args the command line
+ * @return the name of the command, or {@code null} to create all
commands
+ */
+ static String onlyCommand(String... args) {
+ if (args == null || args.length == 0) {
+ return null;
+ }
+ String target = args[0];
+ if (target == null || target.isBlank() || target.startsWith("-") ||
FULL_COMMANDS.contains(target)
+ || PluginHelper.isPluginConsumingCommand(target)) {
+ return null;
+ }
+ for (String arg : args) {
+ if ("--help".equals(arg) || "-h".equals(arg)) {
+ // the help lists the plugins that are not installed, from all
commands
+ return null;
+ }
+ }
+ return target;
+ }
+
+ /**
+ * Whether the command line has only the command of the CLI that it runs
(see {@link #onlyCommand(String...)}), and
+ * not all the commands, so the commands of the plugins are not needed
either.
+ *
+ * @param commandLine the command line
+ * @param args the arguments it runs
+ * @return {@code true} when it has only that command
+ */
+ public static boolean hasOnlyCommand(CommandLine commandLine, String...
args) {
+ String only = onlyCommand(args);
+ return only != null && commandLine.getSubcommands().size() == 1 &&
commandLine.getSubcommands().containsKey(only);
+ }
+
+ private static boolean shouldCreate(String only, String name) {
+ return only == null || only.equals(name);
+ }
+
/**
* The command line with the commands of the CLI.
+ *
+ * @param only the name of the one command to create, or {@code null} for
all commands
*/
- private CommandLine createCommandLine() {
- CommandLine commandLine = new CommandLine(this)
- .addSubcommand("bind", new CommandLine(new Bind(this)))
- .addSubcommand("catalog", new CommandLine(new
CatalogCommand(this))
- .addSubcommand("component", new CommandLine(new
CatalogComponent(this)))
- .addSubcommand("dataformat", new CommandLine(new
CatalogDataFormat(this)))
- .addSubcommand("dev-console", new CommandLine(new
CatalogDevConsole(this)))
- .addSubcommand("kamelet", new CommandLine(new
CatalogKamelet(this)))
- .addSubcommand("transformer", new CommandLine(new
CatalogTransformer(this)))
- .addSubcommand("language", new CommandLine(new
CatalogLanguage(this)))
- .addSubcommand("other", new CommandLine(new
CatalogOther(this))))
- .addSubcommand("cmd", new CommandLine(new CamelAction(this))
- .addSubcommand("browse", new CommandLine(new
CamelBrowseAction(this)))
- .addSubcommand("disable-processor", new
CommandLine(new CamelProcessorDisableAction(this)))
- .addSubcommand("enable-processor", new CommandLine(new
CamelProcessorEnableAction(this)))
- .addSubcommand("gc", new CommandLine(new
CamelGCAction(this)))
- .addSubcommand("heap-dump", new CommandLine(new
CamelHeapDump(this)))
- .addSubcommand("heap-histogram", new CommandLine(new
CamelHeapHistogram(this)))
- .addSubcommand("memory-leak", new CommandLine(new
CamelMemoryLeak(this)))
- .addSubcommand("load", new CommandLine(new
CamelLoadAction(this)))
- .addSubcommand("logger", new CommandLine(new
LoggerAction(this)))
- .addSubcommand("receive", new CommandLine(new
CamelReceiveAction(this)))
- .addSubcommand("reload", new CommandLine(new
CamelReloadAction(this)))
- .addSubcommand("reset-stats", new CommandLine(new
CamelResetStatsAction(this)))
- .addSubcommand("resume-route", new CommandLine(new
CamelRouteResumeAction(this)))
- .addSubcommand("route-diagram", new CommandLine(new
CamelRouteDiagramAction(this)))
- .addSubcommand("route-dump", new CommandLine(new
CamelRouteDumpAction(this)))
- .addSubcommand("route-structure", new CommandLine(new
CamelRouteStructureAction(this)))
- .addSubcommand("route-topology", new CommandLine(new
CamelRouteTopologyAction(this)))
- .addSubcommand("send", new CommandLine(new
CamelSendAction(this)))
- .addSubcommand("sql", new CommandLine(new
CamelSqlQueryAction(this)))
- .addSubcommand("span", new CommandLine(new
CamelSpanAction(this)))
- .addSubcommand("start-group", new CommandLine(new
CamelRouteGroupStartAction(this)))
- .addSubcommand("start-route", new CommandLine(new
CamelRouteStartAction(this)))
- .addSubcommand("stop-group", new CommandLine(new
CamelRouteGroupStopAction(this)))
- .addSubcommand("stop-route", new CommandLine(new
CamelRouteStopAction(this)))
- .addSubcommand("stub", new CommandLine(new
CamelStubAction(this)))
- .addSubcommand("suspend-route", new CommandLine(new
CamelRouteSuspendAction(this)))
- .addSubcommand("thread-dump", new CommandLine(new
CamelThreadDump(this))))
- .addSubcommand("config", new CommandLine(new
ConfigCommand(this))
- .addSubcommand("get", new CommandLine(new
ConfigGet(this)))
- .addSubcommand("list", new CommandLine(new
ConfigList(this)))
- .addSubcommand("set", new CommandLine(new
ConfigSet(this)))
- .addSubcommand("unset", new CommandLine(new
ConfigUnset(this))))
- .addSubcommand("completion", new CommandLine(new
Complete(this)))
- .addSubcommand("doc", new CommandLine(new CatalogDoc(this)))
- .addSubcommand("debug", new CommandLine(new Debug(this)))
- .addSubcommand("dev", new CommandLine(new Dev(this)))
- .addSubcommand("dependency", new CommandLine(new
DependencyCommand(this))
- .addSubcommand("copy", new CommandLine(new
DependencyCopy(this)))
- .addSubcommand("list", new CommandLine(new
DependencyList(this)))
- .addSubcommand("runtime", new CommandLine(new
DependencyRuntime(this)))
- .addSubcommand("update", new CommandLine(new
DependencyUpdate(this))))
- .addSubcommand("dirty", new CommandLine(new Dirty(this)))
- .addSubcommand("doctor", new CommandLine(new Doctor(this)))
- .addSubcommand("eval", new CommandLine(new EvalCommand(this))
- .addSubcommand("expression", new CommandLine(new
EvalExpressionCommand(this))))
- .addSubcommand("export", new CommandLine(new Export(this)))
- .addSubcommand("explain", new CommandLine(new Explain(this)))
- .addSubcommand("overview", new CommandLine(new Overview(this)))
- .addSubcommand("ask", new CommandLine(new Ask(this)))
- .addSubcommand("harden", new CommandLine(new Harden(this)))
- .addSubcommand("get", new CommandLine(new CamelStatus(this))
- .addSubcommand("activity", new CommandLine(new
ListActivity(this)))
- .addSubcommand("bean", new CommandLine(new
CamelBeanDump(this)))
- .addSubcommand("blocked", new CommandLine(new
ListBlocked(this)))
- .addSubcommand("circuit-breaker", new CommandLine(new
ListCircuitBreaker(this)))
- .addSubcommand("consumer", new CommandLine(new
ListConsumer(this)))
- .addSubcommand("context", new CommandLine(new
CamelContextStatus(this)))
- .addSubcommand("count", new CommandLine(new
CamelCount(this)))
- .addSubcommand("datasource", new CommandLine(new
ListDataSource(this)))
- .addSubcommand("endpoint", new CommandLine(new
ListEndpoint(this)))
- .addSubcommand("error", new CommandLine(new
ListError(this)))
- .addSubcommand("event", new CommandLine(new
ListEvent(this)))
- .addSubcommand("groovy", new CommandLine(new
ListGroovy(this)))
- .addSubcommand("group", new CommandLine(new
CamelRouteGroupStatus(this)))
- .addSubcommand("health", new CommandLine(new
ListHealth(this)))
- .addSubcommand("history", new CommandLine(new
CamelHistoryAction(this)))
- .addSubcommand("inflight", new CommandLine(new
ListInflight(this)))
- .addSubcommand("internal-task", new CommandLine(new
ListInternalTask(this)))
- .addSubcommand("kafka", new CommandLine(new
ListKafka(this)))
- .addSubcommand("metric", new CommandLine(new
ListMetric(this)))
- .addSubcommand("platform-http", new CommandLine(new
ListPlatformHttp(this)))
- .addSubcommand("processor", new CommandLine(new
CamelProcessorStatus(this)))
- .addSubcommand("producer", new CommandLine(new
ListProducer(this)))
- .addSubcommand("properties", new CommandLine(new
ListProperties(this)))
- .addSubcommand("rest", new CommandLine(new
ListRest(this)))
- .addSubcommand("route", new CommandLine(new
CamelRouteStatus(this)))
- .addSubcommand("route-controller", new CommandLine(new
RouteControllerAction(this)))
- .addSubcommand("service", new CommandLine(new
ListService(this)))
- .addSubcommand("source", new CommandLine(new
CamelSourceAction(this)))
- .addSubcommand("sql-trace", new CommandLine(new
ListSqlTrace(this)))
- .addSubcommand("startup-recorder", new CommandLine(new
CamelStartupRecorderAction(this)))
- .addSubcommand("transformer", new CommandLine(new
ListTransformer(this)))
- .addSubcommand("variable", new CommandLine(new
ListVariable(this)))
- .addSubcommand("vault", new CommandLine(new
ListVault(this))))
- .addSubcommand("hawtio", new CommandLine(new Hawtio(this)))
- .addSubcommand("infra", new CommandLine(new InfraCommand(this))
- .addSubcommand("get", new CommandLine(new
InfraGet(this)))
- .addSubcommand("list", new CommandLine(new
InfraList(this)))
- .addSubcommand("log", new CommandLine(new
InfraLog(this)))
- .addSubcommand("ps", new CommandLine(new
InfraPs(this)))
- .addSubcommand("restart", new CommandLine(new
InfraRestart(this)))
- .addSubcommand("run", new CommandLine(new
InfraRun(this)))
- .addSubcommand("stop", new CommandLine(new
InfraStop(this))))
- .addSubcommand("init", new CommandLine(new Init(this)))
- .addSubcommand("jolokia", new CommandLine(new Jolokia(this)))
- .addSubcommand("log", new CommandLine(new
CamelLogAction(this)))
- .addSubcommand("nano", new CommandLine(new Nano(this)))
- .addSubcommand("plugin", new CommandLine(new
PluginCommand(this))
- .addSubcommand("add", new CommandLine(new
PluginAdd(this)))
- .addSubcommand("delete", new CommandLine(new
PluginDelete(this)))
- .addSubcommand("get", new CommandLine(new
PluginGet(this)))
- .addSubcommand("list", new CommandLine(new
PluginList(this))))
- .addSubcommand("ps", new CommandLine(new ListProcess(this)))
- .addSubcommand("restart", new CommandLine(new
RestartProcess(this)))
- .addSubcommand("run", new CommandLine(new Run(this)))
- .addSubcommand("sbom", new CommandLine(new
SBOMGenerator(this)))
- .addSubcommand("script", new CommandLine(new Script(this)))
- .addSubcommand("semantic", new CommandLine(new
CamelSemantic(this))
- .addSubcommand("get", new CommandLine(new
SemanticGet(this)))
- .addSubcommand("eval", new CommandLine(new
SemanticEvaluate(this)))
- .addSubcommand("audit", new CommandLine(new
SemanticAudit(this)))
- .addSubcommand("monitoring", new CommandLine(new
SemanticMonitoring(this))))
- .addSubcommand("shell", new CommandLine(new Shell(this)))
- .addSubcommand("stop", new CommandLine(new StopProcess(this)))
- .addSubcommand("top", new CommandLine(new CamelTop(this))
- .addSubcommand("context", new CommandLine(new
CamelContextTop(this)))
- .addSubcommand("group", new CommandLine(new
CamelRouteGroupTop(this)))
- .addSubcommand("processor", new CommandLine(new
CamelProcessorTop(this)))
- .addSubcommand("route", new CommandLine(new
CamelRouteTop(this)))
- .addSubcommand("source", new CommandLine(new
CamelSourceTop(this))))
- .addSubcommand("trace", new CommandLine(new
CamelTraceAction(this)))
- .addSubcommand("transform", new CommandLine(new
TransformCommand(this))
- .addSubcommand("dataweave", new CommandLine(new
TransformDataWeave(this)))
- .addSubcommand("message", new CommandLine(new
TransformMessageAction(this)))
- .addSubcommand("route", new CommandLine(new
TransformRoute(this))))
- .addSubcommand("update", new CommandLine(new
UpdateCommand(this))
- .addSubcommand("list", new CommandLine(new
UpdateList(this)))
- .addSubcommand("run", new CommandLine(new
UpdateRun(this))))
- .addSubcommand("version", new CommandLine(new
VersionCommand(this))
- .addSubcommand("get", new CommandLine(new
VersionGet(this)))
- .addSubcommand("list", new CommandLine(new
VersionList(this)))
- .addSubcommand("set", new CommandLine(new
VersionSet(this))))
- .addSubcommand("wrapper", new CommandLine(new
WrapperCommand(this)))
- .setParameterExceptionHandler(new
MissingPluginParameterExceptionHandler(this));
+ private CommandLine createCommandLine(String only) {
+ CommandLine commandLine = new CommandLine(this);
+ if (shouldCreate(only, "bind")) {
+ commandLine.addSubcommand("bind", new CommandLine(new Bind(this)));
+ }
+ if (shouldCreate(only, "catalog")) {
+ commandLine.addSubcommand("catalog", new CommandLine(new
CatalogCommand(this))
+ .addSubcommand("component", new CommandLine(new
CatalogComponent(this)))
+ .addSubcommand("dataformat", new CommandLine(new
CatalogDataFormat(this)))
+ .addSubcommand("dev-console", new CommandLine(new
CatalogDevConsole(this)))
+ .addSubcommand("kamelet", new CommandLine(new
CatalogKamelet(this)))
+ .addSubcommand("transformer", new CommandLine(new
CatalogTransformer(this)))
+ .addSubcommand("language", new CommandLine(new
CatalogLanguage(this)))
+ .addSubcommand("other", new CommandLine(new
CatalogOther(this))));
+ }
+ if (shouldCreate(only, "cmd")) {
+ commandLine.addSubcommand("cmd", new CommandLine(new
CamelAction(this))
+ .addSubcommand("browse", new CommandLine(new
CamelBrowseAction(this)))
+ .addSubcommand("disable-processor", new CommandLine(new
CamelProcessorDisableAction(this)))
+ .addSubcommand("enable-processor", new CommandLine(new
CamelProcessorEnableAction(this)))
+ .addSubcommand("gc", new CommandLine(new
CamelGCAction(this)))
+ .addSubcommand("heap-dump", new CommandLine(new
CamelHeapDump(this)))
+ .addSubcommand("heap-histogram", new CommandLine(new
CamelHeapHistogram(this)))
+ .addSubcommand("memory-leak", new CommandLine(new
CamelMemoryLeak(this)))
+ .addSubcommand("load", new CommandLine(new
CamelLoadAction(this)))
+ .addSubcommand("logger", new CommandLine(new
LoggerAction(this)))
+ .addSubcommand("receive", new CommandLine(new
CamelReceiveAction(this)))
+ .addSubcommand("reload", new CommandLine(new
CamelReloadAction(this)))
+ .addSubcommand("reset-stats", new CommandLine(new
CamelResetStatsAction(this)))
+ .addSubcommand("resume-route", new CommandLine(new
CamelRouteResumeAction(this)))
+ .addSubcommand("route-diagram", new CommandLine(new
CamelRouteDiagramAction(this)))
+ .addSubcommand("route-dump", new CommandLine(new
CamelRouteDumpAction(this)))
+ .addSubcommand("route-structure", new CommandLine(new
CamelRouteStructureAction(this)))
+ .addSubcommand("route-topology", new CommandLine(new
CamelRouteTopologyAction(this)))
+ .addSubcommand("send", new CommandLine(new
CamelSendAction(this)))
+ .addSubcommand("sql", new CommandLine(new
CamelSqlQueryAction(this)))
+ .addSubcommand("span", new CommandLine(new
CamelSpanAction(this)))
+ .addSubcommand("start-group", new CommandLine(new
CamelRouteGroupStartAction(this)))
+ .addSubcommand("start-route", new CommandLine(new
CamelRouteStartAction(this)))
+ .addSubcommand("stop-group", new CommandLine(new
CamelRouteGroupStopAction(this)))
+ .addSubcommand("stop-route", new CommandLine(new
CamelRouteStopAction(this)))
+ .addSubcommand("stub", new CommandLine(new
CamelStubAction(this)))
+ .addSubcommand("suspend-route", new CommandLine(new
CamelRouteSuspendAction(this)))
+ .addSubcommand("thread-dump", new CommandLine(new
CamelThreadDump(this))));
+ }
+ if (shouldCreate(only, "config")) {
+ commandLine.addSubcommand("config", new CommandLine(new
ConfigCommand(this))
+ .addSubcommand("get", new CommandLine(new ConfigGet(this)))
+ .addSubcommand("list", new CommandLine(new
ConfigList(this)))
+ .addSubcommand("set", new CommandLine(new ConfigSet(this)))
+ .addSubcommand("unset", new CommandLine(new
ConfigUnset(this))));
+ }
+ if (shouldCreate(only, "completion")) {
+ commandLine.addSubcommand("completion", new CommandLine(new
Complete(this)));
+ }
+ if (shouldCreate(only, "doc")) {
+ commandLine.addSubcommand("doc", new CommandLine(new
CatalogDoc(this)));
+ }
+ if (shouldCreate(only, "debug")) {
+ commandLine.addSubcommand("debug", new CommandLine(new
Debug(this)));
+ }
+ if (shouldCreate(only, "dev")) {
+ commandLine.addSubcommand("dev", new CommandLine(new Dev(this)));
+ }
+ if (shouldCreate(only, "dependency")) {
+ commandLine.addSubcommand("dependency", new CommandLine(new
DependencyCommand(this))
+ .addSubcommand("copy", new CommandLine(new
DependencyCopy(this)))
+ .addSubcommand("list", new CommandLine(new
DependencyList(this)))
+ .addSubcommand("runtime", new CommandLine(new
DependencyRuntime(this)))
+ .addSubcommand("update", new CommandLine(new
DependencyUpdate(this))));
+ }
+ if (shouldCreate(only, "dirty")) {
+ commandLine.addSubcommand("dirty", new CommandLine(new
Dirty(this)));
+ }
+ if (shouldCreate(only, "doctor")) {
+ commandLine.addSubcommand("doctor", new CommandLine(new
Doctor(this)));
+ }
+ if (shouldCreate(only, "eval")) {
+ commandLine.addSubcommand("eval", new CommandLine(new
EvalCommand(this))
+ .addSubcommand("expression", new CommandLine(new
EvalExpressionCommand(this))));
+ }
+ if (shouldCreate(only, "export")) {
+ commandLine.addSubcommand("export", new CommandLine(new
Export(this)));
+ }
+ if (shouldCreate(only, "explain")) {
+ commandLine.addSubcommand("explain", new CommandLine(new
Explain(this)));
+ }
+ if (shouldCreate(only, "overview")) {
+ commandLine.addSubcommand("overview", new CommandLine(new
Overview(this)));
+ }
+ if (shouldCreate(only, "ask")) {
+ commandLine.addSubcommand("ask", new CommandLine(new Ask(this)));
+ }
+ if (shouldCreate(only, "harden")) {
+ commandLine.addSubcommand("harden", new CommandLine(new
Harden(this)));
+ }
+ if (shouldCreate(only, "get")) {
+ commandLine.addSubcommand("get", new CommandLine(new
CamelStatus(this))
+ .addSubcommand("activity", new CommandLine(new
ListActivity(this)))
+ .addSubcommand("bean", new CommandLine(new
CamelBeanDump(this)))
+ .addSubcommand("blocked", new CommandLine(new
ListBlocked(this)))
+ .addSubcommand("circuit-breaker", new CommandLine(new
ListCircuitBreaker(this)))
+ .addSubcommand("consumer", new CommandLine(new
ListConsumer(this)))
+ .addSubcommand("context", new CommandLine(new
CamelContextStatus(this)))
+ .addSubcommand("count", new CommandLine(new
CamelCount(this)))
+ .addSubcommand("datasource", new CommandLine(new
ListDataSource(this)))
+ .addSubcommand("endpoint", new CommandLine(new
ListEndpoint(this)))
+ .addSubcommand("error", new CommandLine(new
ListError(this)))
+ .addSubcommand("event", new CommandLine(new
ListEvent(this)))
+ .addSubcommand("groovy", new CommandLine(new
ListGroovy(this)))
+ .addSubcommand("group", new CommandLine(new
CamelRouteGroupStatus(this)))
+ .addSubcommand("health", new CommandLine(new
ListHealth(this)))
+ .addSubcommand("history", new CommandLine(new
CamelHistoryAction(this)))
+ .addSubcommand("inflight", new CommandLine(new
ListInflight(this)))
+ .addSubcommand("internal-task", new CommandLine(new
ListInternalTask(this)))
+ .addSubcommand("kafka", new CommandLine(new
ListKafka(this)))
+ .addSubcommand("metric", new CommandLine(new
ListMetric(this)))
+ .addSubcommand("platform-http", new CommandLine(new
ListPlatformHttp(this)))
+ .addSubcommand("processor", new CommandLine(new
CamelProcessorStatus(this)))
+ .addSubcommand("producer", new CommandLine(new
ListProducer(this)))
+ .addSubcommand("properties", new CommandLine(new
ListProperties(this)))
+ .addSubcommand("rest", new CommandLine(new ListRest(this)))
+ .addSubcommand("route", new CommandLine(new
CamelRouteStatus(this)))
+ .addSubcommand("route-controller", new CommandLine(new
RouteControllerAction(this)))
+ .addSubcommand("service", new CommandLine(new
ListService(this)))
+ .addSubcommand("source", new CommandLine(new
CamelSourceAction(this)))
+ .addSubcommand("sql-trace", new CommandLine(new
ListSqlTrace(this)))
+ .addSubcommand("startup-recorder", new CommandLine(new
CamelStartupRecorderAction(this)))
+ .addSubcommand("transformer", new CommandLine(new
ListTransformer(this)))
+ .addSubcommand("variable", new CommandLine(new
ListVariable(this)))
+ .addSubcommand("vault", new CommandLine(new
ListVault(this))));
+ }
+ if (shouldCreate(only, "hawtio")) {
+ commandLine.addSubcommand("hawtio", new CommandLine(new
Hawtio(this)));
+ }
+ if (shouldCreate(only, "infra")) {
+ commandLine.addSubcommand("infra", new CommandLine(new
InfraCommand(this))
+ .addSubcommand("get", new CommandLine(new InfraGet(this)))
+ .addSubcommand("list", new CommandLine(new
InfraList(this)))
+ .addSubcommand("log", new CommandLine(new InfraLog(this)))
+ .addSubcommand("ps", new CommandLine(new InfraPs(this)))
+ .addSubcommand("restart", new CommandLine(new
InfraRestart(this)))
+ .addSubcommand("run", new CommandLine(new InfraRun(this)))
+ .addSubcommand("stop", new CommandLine(new
InfraStop(this))));
+ }
+ if (shouldCreate(only, "init")) {
+ commandLine.addSubcommand("init", new CommandLine(new Init(this)));
+ }
+ if (shouldCreate(only, "jolokia")) {
+ commandLine.addSubcommand("jolokia", new CommandLine(new
Jolokia(this)));
+ }
+ if (shouldCreate(only, "log")) {
+ commandLine.addSubcommand("log", new CommandLine(new
CamelLogAction(this)));
+ }
+ if (shouldCreate(only, "nano")) {
+ commandLine.addSubcommand("nano", new CommandLine(new Nano(this)));
+ }
+ if (shouldCreate(only, "plugin")) {
+ commandLine.addSubcommand("plugin", new CommandLine(new
PluginCommand(this))
+ .addSubcommand("add", new CommandLine(new PluginAdd(this)))
+ .addSubcommand("delete", new CommandLine(new
PluginDelete(this)))
+ .addSubcommand("get", new CommandLine(new PluginGet(this)))
+ .addSubcommand("list", new CommandLine(new
PluginList(this))));
+ }
+ if (shouldCreate(only, "ps")) {
+ commandLine.addSubcommand("ps", new CommandLine(new
ListProcess(this)));
+ }
+ if (shouldCreate(only, "restart")) {
+ commandLine.addSubcommand("restart", new CommandLine(new
RestartProcess(this)));
+ }
+ if (shouldCreate(only, "run")) {
+ commandLine.addSubcommand("run", new CommandLine(new Run(this)));
+ }
+ if (shouldCreate(only, "sbom")) {
+ commandLine.addSubcommand("sbom", new CommandLine(new
SBOMGenerator(this)));
+ }
+ if (shouldCreate(only, "script")) {
+ commandLine.addSubcommand("script", new CommandLine(new
Script(this)));
+ }
+ if (shouldCreate(only, "semantic")) {
+ commandLine.addSubcommand("semantic", new CommandLine(new
CamelSemantic(this))
+ .addSubcommand("get", new CommandLine(new
SemanticGet(this)))
+ .addSubcommand("eval", new CommandLine(new
SemanticEvaluate(this)))
+ .addSubcommand("audit", new CommandLine(new
SemanticAudit(this)))
+ .addSubcommand("monitoring", new CommandLine(new
SemanticMonitoring(this))));
+ }
+ if (shouldCreate(only, "shell")) {
+ commandLine.addSubcommand("shell", new CommandLine(new
Shell(this)));
+ }
+ if (shouldCreate(only, "stop")) {
+ commandLine.addSubcommand("stop", new CommandLine(new
StopProcess(this)));
+ }
+ if (shouldCreate(only, "top")) {
+ commandLine.addSubcommand("top", new CommandLine(new
CamelTop(this))
+ .addSubcommand("context", new CommandLine(new
CamelContextTop(this)))
+ .addSubcommand("group", new CommandLine(new
CamelRouteGroupTop(this)))
+ .addSubcommand("processor", new CommandLine(new
CamelProcessorTop(this)))
+ .addSubcommand("route", new CommandLine(new
CamelRouteTop(this)))
+ .addSubcommand("source", new CommandLine(new
CamelSourceTop(this))));
+ }
+ if (shouldCreate(only, "trace")) {
+ commandLine.addSubcommand("trace", new CommandLine(new
CamelTraceAction(this)));
+ }
+ if (shouldCreate(only, "transform")) {
+ commandLine.addSubcommand("transform", new CommandLine(new
TransformCommand(this))
+ .addSubcommand("dataweave", new CommandLine(new
TransformDataWeave(this)))
+ .addSubcommand("message", new CommandLine(new
TransformMessageAction(this)))
+ .addSubcommand("route", new CommandLine(new
TransformRoute(this))));
+ }
+ if (shouldCreate(only, "update")) {
+ commandLine.addSubcommand("update", new CommandLine(new
UpdateCommand(this))
+ .addSubcommand("list", new CommandLine(new
UpdateList(this)))
+ .addSubcommand("run", new CommandLine(new
UpdateRun(this))));
+ }
+ if (shouldCreate(only, "version")) {
+ commandLine.addSubcommand("version", new CommandLine(new
VersionCommand(this))
+ .addSubcommand("get", new CommandLine(new
VersionGet(this)))
+ .addSubcommand("list", new CommandLine(new
VersionList(this)))
+ .addSubcommand("set", new CommandLine(new
VersionSet(this))));
+ }
+ if (shouldCreate(only, "wrapper")) {
+ commandLine.addSubcommand("wrapper", new CommandLine(new
WrapperCommand(this)));
+ }
+ commandLine.setParameterExceptionHandler(new
MissingPluginParameterExceptionHandler(this));
commandLine.getHelpSectionMap().put(
CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST,
@@ -314,7 +448,7 @@ public class CamelJBangMain implements Callable<Integer> {
* {@link CliRunner} runs each command on a new command line.
*/
public CommandLine newCommandLine() {
- CommandLine answer = createCommandLine();
+ CommandLine answer = createCommandLine(null);
postAddCommands(answer, new String[0]);
for (Plugin plugin : plugins) {
plugin.customize(answer, this);
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 f331f8a39598..cf05692f8090 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
@@ -114,6 +114,17 @@ public final class PluginHelper {
return !commandLine.getSubcommands().containsKey(target);
}
+ /**
+ * Whether the command of the CLI uses the plugins, so they are loaded
when it runs (see
+ * {@link #shouldDiscoverPlugins(CommandLine, String...)}).
+ *
+ * @param command the name of the command
+ * @return {@code true} for shell, run, export and cmd
+ */
+ public static boolean isPluginConsumingCommand(String command) {
+ return PLUGIN_CONSUMING_BUILTINS.contains(command);
+ }
+
/**
* Loads the plugin Json configuration from the user home and goes through
all configured plugins adding the plugin
* commands to the current command line. Tries to resolve each plugin from
the classpath with the factory finder
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
new file mode 100644
index 000000000000..39939ab2b169
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import java.util.List;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CamelJBangMainOnlyCommandTest extends CamelCommandBaseTestSupport {
+
+ @BeforeEach
+ public void setup() throws Exception {
+ super.setup();
+
+ useTestHomeDir();
+ }
+
+ @Test
+ public void aCommandOfTheCliCreatesOnlyItself() {
+ CommandLine commandLine = execute("config", "list");
+
+ assertEquals(Set.of("config"), commandLine.getSubcommands().keySet());
+ assertEquals(Set.of("get", "list", "set", "unset"),
+
commandLine.getSubcommands().get("config").getSubcommands().keySet());
+ assertTrue(CamelJBangMain.hasOnlyCommand(commandLine, "config",
"list"));
+ }
+
+ @Test
+ public void theHelpCreatesAllCommands() {
+ assertAllCommands(execute("--help"));
+ assertAllCommands(execute());
+ assertAllCommands(execute("config", "--help"));
+ }
+
+ @Test
+ public void aCommandThatIsNotOfTheCliCreatesAllCommands() {
+ // the command of a plugin that is not installed, or a typo, for which
picocli suggests the commands it knows
+ CommandLine commandLine = execute("confg", "list");
+
+ assertAllCommands(commandLine);
+ assertFalse(CamelJBangMain.hasOnlyCommand(commandLine, "confg",
"list"));
+ }
+
+ @Test
+ public void
theCommandsThatUseTheOtherCommandsOrThePluginsCreateAllCommands() {
+ for (String command : List.of("shell", "completion", "run", "export",
"cmd")) {
+ assertNull(CamelJBangMain.onlyCommand(command, "--foo"), command);
+ }
+ assertNull(CamelJBangMain.onlyCommand("--verbose", "version"));
+ assertEquals("version", CamelJBangMain.onlyCommand("version", "get"));
+ }
+
+ @Test
+ public void aNewCommandLineHasAllCommands() {
+ // camel ask, camel shell and the monitor run any command on a new
command line
+ CamelJBangMain main = new CamelJBangMain().withPrinter(printer);
+
+ assertAllCommands(main.newCommandLine());
+ }
+
+ private CommandLine execute(String... args) {
+ CommandLine[] executed = new CommandLine[1];
+ CamelJBangMain main = new CamelJBangMain() {
+ @Override
+ public void postExecute(CommandLine commandLine, String[] args,
int exitCode) {
+ executed[0] = commandLine;
+ }
+
+ @Override
+ public void quit(int exitCode) {
+ // noop
+ }
+ }.withPrinter(printer);
+ main.setDiscoverPlugins(false);
+ main.execute(args);
+ return executed[0];
+ }
+
+ private static void assertAllCommands(CommandLine commandLine) {
+
assertTrue(commandLine.getSubcommands().keySet().containsAll(List.of("config",
"get", "run", "shell", "version")),
+ () -> "All commands of the CLI, but was: " +
commandLine.getSubcommands().keySet());
+ }
+}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
index 1eb6c98a7310..d5ee5fa1f712 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
@@ -488,8 +488,6 @@ class SemanticCommandTest {
assertNotNull(semantic.getSubcommands().get("get"));
assertNotNull(semantic.getSubcommands().get("eval"));
assertNotNull(semantic.getSubcommands().get("audit"));
-
assertFalse(command.getSubcommands().get("get").getSubcommands().containsKey("semantic"));
-
assertFalse(command.getSubcommands().get("cmd").getSubcommands().containsKey("semantic-evaluate"));
}
@Override
@@ -505,6 +503,11 @@ class SemanticCommandTest {
main.withPrinter(printer);
main.execute("semantic", "eval", "--bad-option", "--json");
assertError(2, "Unknown option");
+
+ // the command line of camel semantic has only that command: all of
them are on a new command line
+ CommandLine all = main.newCommandLine();
+
assertFalse(all.getSubcommands().get("get").getSubcommands().containsKey("semantic"));
+
assertFalse(all.getSubcommands().get("cmd").getSubcommands().containsKey("semantic-evaluate"));
}
@ParameterizedTest
diff --git
a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
index 71f5c17d2ab3..2ab0a379fc67 100644
---
a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
+++
b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
@@ -41,6 +41,10 @@ public class CamelLauncherMain extends CamelJBangMain {
@Override
public void postAddCommands(CommandLine commandLine, String[] args) {
+ if (hasOnlyCommand(commandLine, args)) {
+ // a command of the CLI, which needs none of the commands of the
plugins
+ return;
+ }
// Install embedded plugins. Each plugin must be given the classloader
that loaded it (this
// class's classloader, i.e. the fat-jar classloader) so that plugins
relying on ServiceLoader
// discovery can see the dependencies bundled in the launcher. The TUI
plugin installs this