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 5edb5c262f38 CAMEL-22765: camel-jbang - Loading custom jbang plugins
should suppor… (#20459)
5edb5c262f38 is described below
commit 5edb5c262f38159febcc402e96f41b7d1b6124de
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Dec 16 20:15:22 2025 +0100
CAMEL-22765: camel-jbang - Loading custom jbang plugins should suppor…
(#20459)
* CAMEL-22765: camel-jbang - Loading custom jbang plugins should support
downloading from 3rd party maven repositories specified via --repos. Also camel
add plugin can now declare --repos to specify where to download the plugin
---
.../dsl/jbang/core/commands/CamelCommand.java | 3 +-
.../dsl/jbang/core/commands/ExportBaseCommand.java | 6 +--
.../dsl/jbang/core/commands/plugin/PluginAdd.java | 23 +++++++----
.../jbang/core/commands/plugin/PluginCommand.java | 2 +-
.../jbang/core/commands/plugin/PluginDelete.java | 4 +-
.../dsl/jbang/core/commands/plugin/PluginGet.java | 17 +++++---
.../camel/dsl/jbang/core/common/PluginHelper.java | 45 ++++++++++++++++++----
.../camel/dsl/jbang/core/common/PluginType.java | 16 +++++---
8 files changed, 83 insertions(+), 33 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
index 583658b41383..95b70b0979df 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
@@ -20,6 +20,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.Properties;
import java.util.Stack;
import java.util.concurrent.Callable;
@@ -141,7 +142,7 @@ public abstract class CamelCommand implements
Callable<Integer> {
// name starts with --
configProperties.containsKey(name.substring(2)))) {
lines.add(String.format(" %s=%s",
- opt.longestName(), opt.getValue().toString()));
+ opt.longestName(),
Optional.ofNullable(opt.getValue()).orElse("")));
}
});
if (!lines.isEmpty()) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index 823c7c59087d..8783e4e3a4a7 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -399,7 +399,7 @@ public abstract class ExportBaseCommand extends
CamelCommand {
Properties properties = mapBuildProperties();
if (!skipPlugins) {
- Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain()).values()
+ Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain(), repositories).values()
.stream()
.map(Plugin::getExporter)
.filter(Optional::isPresent)
@@ -597,7 +597,7 @@ public abstract class ExportBaseCommand extends
CamelCommand {
}
if (!skipPlugins) {
- Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain()).values()
+ Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain(), repositories).values()
.stream()
.map(Plugin::getExporter)
.filter(Optional::isPresent)
@@ -777,7 +777,7 @@ public abstract class ExportBaseCommand extends
CamelCommand {
}
if (!skipPlugins) {
- Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain()).values()
+ Set<PluginExporter> exporters =
PluginHelper.getActivePlugins(getMain(), repositories).values()
.stream()
.map(Plugin::getExporter)
.filter(Optional::isPresent)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginAdd.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginAdd.java
index 70694564b399..a1ad1998f9ad 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginAdd.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginAdd.java
@@ -26,38 +26,42 @@ import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
@CommandLine.Command(name = "add",
- description = "Add new plugin.", sortOptions = false,
showDefaultValues = true)
+ description = "Add new plugin", sortOptions = false,
showDefaultValues = true)
public class PluginAdd extends PluginBaseCommand {
- @CommandLine.Parameters(description = "The Camel plugin to add.",
+ @CommandLine.Parameters(description = "The Camel plugin to add",
paramLabel = "<name>")
String name;
@CommandLine.Option(names = { "--command" },
- description = "The command that the plugin uses.")
+ description = "The command that the plugin uses")
String command;
@CommandLine.Option(names = { "--description" },
- description = "A short description of the plugin.")
+ description = "A short description of the plugin")
String description;
+ @CommandLine.Option(names = { "--repo", "--repos" },
+ description = "Additional maven repositories to use
for downloading the plugin (Use commas to separate multiple repositories)")
+ String repositories;
+
@CommandLine.Option(names = { "--artifactId" },
- description = "Maven artifactId.")
+ description = "Maven artifactId")
String artifactId;
@CommandLine.Option(names = { "--groupId" },
defaultValue = "org.apache.camel",
- description = "Maven groupId.")
+ description = "Maven groupId")
String groupId = "org.apache.camel";
@CommandLine.Option(names = { "--version" },
defaultValue = "${camel-version}",
- description = "Maven artifact version.")
+ description = "Maven artifact version")
String version;
@CommandLine.Option(names = { "--first-version" },
defaultValue = "${camel-version}",
- description = "First version of this plugin.")
+ description = "First version of this plugin")
String firstVersion;
@CommandLine.Option(names = { "--gav" },
@@ -117,6 +121,9 @@ public class PluginAdd extends PluginBaseCommand {
if (gav != null) {
plugin.put("dependency", gav);
}
+ if (repositories != null) {
+ plugin.put("repos", repositories);
+ }
plugins.put(name, plugin);
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginCommand.java
index 4de9c444cfc4..3a1129d128ac 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginCommand.java
@@ -20,7 +20,7 @@ import
org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import picocli.CommandLine;
@CommandLine.Command(name = "plugin",
- description = "Manage plugins that add sub-commands to
this CLI.")
+ description = "Manage plugins that add sub-commands to
this CLI")
public class PluginCommand extends PluginBaseCommand {
public PluginCommand(CamelJBangMain main) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginDelete.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginDelete.java
index 3d4123c10c38..dfbc3d909a57 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginDelete.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginDelete.java
@@ -21,10 +21,10 @@ import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
@CommandLine.Command(name = "delete",
- description = "Removes a plugin.", sortOptions = false,
showDefaultValues = true)
+ description = "Removes a plugin", sortOptions = false,
showDefaultValues = true)
public class PluginDelete extends PluginBaseCommand {
- @CommandLine.Parameters(description = "The Camel plugin to remove.",
+ @CommandLine.Parameters(description = "The Camel plugin to remove",
paramLabel = "<plugin>")
String name;
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGet.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGet.java
index 593690a8e4f6..9e17ae314ec7 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGet.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGet.java
@@ -30,12 +30,15 @@ import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
@CommandLine.Command(name = "get",
- description = "Display available plugins.", sortOptions =
false, showDefaultValues = true)
+ description = "Display available plugins", sortOptions =
false, showDefaultValues = true)
public class PluginGet extends PluginBaseCommand {
- @CommandLine.Option(names = { "--all" }, defaultValue = "false",
description = "Display all available plugins.")
+ @CommandLine.Option(names = { "--all" }, defaultValue = "false",
description = "Display all available plugins")
public boolean all;
+ @CommandLine.Option(names = { "--repos" }, defaultValue = "false",
description = "Display maven repository column")
+ public boolean repos;
+
public PluginGet(CamelJBangMain main) {
super(main);
}
@@ -54,8 +57,9 @@ public class PluginGet extends PluginBaseCommand {
"org.apache.camel:camel-jbang-plugin-%s".formatted(command));
String description
= details.getStringOrDefault("description", "Plugin %s
called with command %s".formatted(name, command));
+ String repos = details.getString("repos");
- rows.add(new Row(name, command, dependency, description));
+ rows.add(new Row(name, command, dependency, description, repos));
});
printRows(rows);
@@ -67,7 +71,7 @@ public class PluginGet extends PluginBaseCommand {
String dependency =
"org.apache.camel:camel-jbang-plugin-%s".formatted(camelPlugin.getCommand());
rows.add(new Row(
camelPlugin.getName(), camelPlugin.getCommand(),
dependency,
- camelPlugin.getDescription()));
+ camelPlugin.getDescription(),
camelPlugin.getRepos()));
}
}
@@ -92,12 +96,15 @@ public class PluginGet extends PluginBaseCommand {
.with(r -> r.command),
new
Column().header("DEPENDENCY").headerAlign(HorizontalAlign.LEFT).dataAlign(HorizontalAlign.LEFT)
.with(r -> r.dependency),
+ new
Column().visible(repos).header("REPOSITORY").headerAlign(HorizontalAlign.LEFT)
+ .dataAlign(HorizontalAlign.LEFT)
+ .with(r -> r.repos),
new
Column().header("DESCRIPTION").headerAlign(HorizontalAlign.LEFT).dataAlign(HorizontalAlign.LEFT)
.maxWidth(50, OverflowBehaviour.ELLIPSIS_RIGHT)
.with(r -> r.description))));
}
}
- private record Row(String name, String command, String dependency, String
description) {
+ private record Row(String name, String command, String dependency, String
description, String repos) {
}
}
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 76281564eb1c..b212b647e21d 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
@@ -84,6 +84,30 @@ public final class PluginHelper {
// Ignore errors in embedded plugin loading
}
+ // allow to download plugins from 3rd party maven repositories by
--repos argument
+ String repos = null;
+ try {
+ for (String a : args) {
+ if (a.startsWith("--repos=")) {
+ repos = a.substring(8).trim();
+ } else if (a.startsWith("--repo=")) {
+ repos = a.substring(7).trim();
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (repos == null) {
+ // fallback to load user configuration
+ Properties configProperties = new Properties();
+ CommandLineHelper.loadProperties(configProperties::putAll);
+ repos = configProperties.getProperty("repos");
+ if (repos == null) {
+ repos = configProperties.getProperty("repo");
+ }
+ }
+
// If we found embedded plugins, and we're looking for a specific
target,
// check if it was satisfied by embedded plugins
if (foundEmbeddedPlugins && target != null && !"shell".equals(target))
{
@@ -94,7 +118,7 @@ public final class PluginHelper {
}
// Fall back to JSON configuration for additional or missing plugins
- Map<String, Plugin> plugins = getActivePlugins(main);
+ Map<String, Plugin> plugins = getActivePlugins(main, repos);
for (Map.Entry<String, Plugin> plugin : plugins.entrySet()) {
// only load the plugin if the command-line is calling this plugin
if (target != null && !"shell".equals(target) &&
!target.equals(plugin.getKey())) {
@@ -114,10 +138,11 @@ public final class PluginHelper {
* Gets the active plugins according to the local plugin configuration
file. Performs version check to make sure
* that the current Camel JBang version is able to execute the plugin.
*
- * @param main to exit the CLI process in case of error
- * @return map of plugins where key represents the plugin command and
value the plugin instance.
+ * @param main to exit the CLI process in case of error
+ * @param repos custom maven repositories
+ * @return map of plugins where key represents the plugin command
and value the plugin instance.
*/
- public static Map<String, Plugin> getActivePlugins(CamelJBangMain main) {
+ public static Map<String, Plugin> getActivePlugins(CamelJBangMain main,
String repos) {
Map<String, Plugin> activePlugins = new HashMap<>();
JsonObject config = getPluginConfig();
if (config != null) {
@@ -138,7 +163,7 @@ public final class PluginHelper {
versionCheck(main, version, firstVersion, command);
}
- Optional<Plugin> plugin = getPlugin(command, version, gav,
main.getOut());
+ Optional<Plugin> plugin = getPlugin(command, version, gav,
repos, main.getOut());
if (plugin.isPresent()) {
activePlugins.put(command, plugin.get());
} else {
@@ -151,14 +176,14 @@ public final class PluginHelper {
return activePlugins;
}
- public static Optional<Plugin> getPlugin(String name, String
defaultVersion, String gav, Printer printer) {
+ public static Optional<Plugin> getPlugin(String name, String
defaultVersion, String gav, String repos, Printer printer) {
Optional<Plugin> plugin =
FACTORY_FINDER.newInstance("camel-jbang-plugin-" + name, Plugin.class);
if (plugin.isEmpty()) {
final MavenGav mavenGav = dependencyAsMavenGav(gav);
final String group = extractGroup(mavenGav, "org.apache.camel");
final String depVersion = extractVersion(mavenGav, defaultVersion);
- plugin = downloadPlugin(name, depVersion, group, printer);
+ plugin = downloadPlugin(name, depVersion, group, repos, printer);
}
return plugin;
@@ -186,10 +211,14 @@ public final class PluginHelper {
}
}
- private static Optional<Plugin> downloadPlugin(String command, String
version, String group, Printer printer) {
+ private static Optional<Plugin> downloadPlugin(
+ String command, String version, String group, String repos,
Printer printer) {
DependencyDownloader downloader = new MavenDependencyDownloader();
DependencyDownloaderClassLoader ddlcl = new
DependencyDownloaderClassLoader(PluginHelper.class.getClassLoader());
downloader.setClassLoader(ddlcl);
+ if (repos != null && !repos.isBlank()) {
+ downloader.setRepositories(repos);
+ }
downloader.start();
// downloads and adds to the classpath
downloader.downloadDependencyWithParent("org.apache.camel:camel-jbang-parent:"
+ version, group,
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java
index f87ddf31c1eb..98c0b081e897 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java
@@ -24,21 +24,23 @@ import java.util.Optional;
*/
public enum PluginType {
- KUBERNETES("kubernetes", "kubernetes", "Run Camel applications on
Kubernetes", "4.8.0"),
- GENERATE("generate", "generate", "Generate code such as DTOs", "4.8.0"),
- EDIT("edit", "edit", "Edit Camel files with suggestions", "4.12.0"),
- TEST("test", "test", "Manage tests for Camel applications", "4.14.0");
+ KUBERNETES("kubernetes", "kubernetes", "Run Camel applications on
Kubernetes", "4.8.0", null),
+ GENERATE("generate", "generate", "Generate code such as DTOs", "4.8.0",
null),
+ EDIT("edit", "edit", "Edit Camel files with suggestions", "4.12.0", null),
+ TEST("test", "test", "Manage tests for Camel applications", "4.14.0",
null);
private final String name;
private final String command;
private final String description;
private final String firstVersion;
+ private final String repos;
- PluginType(String name, String command, String description, String
firstVersion) {
+ PluginType(String name, String command, String description, String
firstVersion, String repos) {
this.name = name;
this.command = command;
this.description = description;
this.firstVersion = firstVersion;
+ this.repos = repos;
}
public static Optional<PluginType> findByName(String name) {
@@ -62,4 +64,8 @@ public enum PluginType {
public String getFirstVersion() {
return firstVersion;
}
+
+ public String getRepos() {
+ return repos;
+ }
}