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;
+    }
 }

Reply via email to