You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by cd...@apache.org on 2024/03/15 13:18:00 UTC

(camel) branch camel-4.4.x updated: CAMEL-20517 camel-jbang-plugin-k doesn't recognize command (#13397)

This is an automated email from the ASF dual-hosted git repository.

cdeppisch pushed a commit to branch camel-4.4.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.4.x by this push:
     new 22bd4374faf CAMEL-20517 camel-jbang-plugin-k doesn't recognize command (#13397)
22bd4374faf is described below

commit 22bd4374fafd3043f22e212061a21679f3c4938a
Author: Claudio Miranda <cl...@claudius.com.br>
AuthorDate: Tue Mar 12 11:26:17 2024 -0300

    CAMEL-20517 camel-jbang-plugin-k doesn't recognize command (#13397)
    
    (cherry picked from commit cc8a3f85356a535e2a5dc2c6c5326607c30aea24)
---
 .../camel/dsl/jbang/core/common/PluginHelper.java  | 127 +++++++--------------
 1 file changed, 43 insertions(+), 84 deletions(-)

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 303cbce1574..0470aad1cc2 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
@@ -20,19 +20,22 @@ package org.apache.camel.dsl.jbang.core.common;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Optional;
+import java.util.Properties;
 
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.catalog.CamelCatalog;
-import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.VersionHelper;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import org.apache.camel.impl.engine.DefaultClassResolver;
 import org.apache.camel.impl.engine.DefaultFactoryFinder;
+import org.apache.camel.main.download.DependencyDownloader;
+import org.apache.camel.main.download.DependencyDownloaderClassLoader;
+import org.apache.camel.main.download.MavenDependencyDownloader;
 import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.support.ObjectHelper;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.json.JsonObject;
 import org.apache.camel.util.json.Jsoner;
@@ -73,95 +76,51 @@ public final class PluginHelper {
                 String command = properties.getOrDefault("command", name).toString();
 
                 Optional<Plugin> plugin = FACTORY_FINDER.newInstance("camel-jbang-plugin-" + command, Plugin.class);
+                if (plugin.isEmpty()) {
+                    plugin = downloadPlugin(command, main);
+                }
                 if (plugin.isPresent()) {
                     plugin.get().customize(commandLine, main);
                 } else {
-                    String description = properties.getOrDefault("description", "").toString();
-                    String dependency = properties.getOrDefault("dependency",
-                            "org.apache.camel:camel-jbang-plugin-%s:${camel-version}".formatted(command)).toString();
-                    createSubCommand(commandLine, name, command, dependency, description, main);
+                    main.getOut().println("camel-jbang-plugin-" + command + " not found. Exit");
+                    main.quit(1);
                 }
             }
         }
     }
 
-    /**
-     * Create sub-command as a placeholder for calling a plugin. When the command gets executed the plugin is added to
-     * the classpath and a new JBang process is spawned with the same arguments. The factory finder mechanism will be
-     * able to resolve the actual plugin from the classpath so the real plugin command is run.
-     *
-     * @param commandLine to receive the new command
-     * @param name        the plugin name
-     * @param command     the plugin command
-     * @param dependency  the Maven dependency for the plugin
-     * @param description optional description of the plugin command
-     * @param main        current Camel JBang main
-     */
-    private static void createSubCommand(
-            CommandLine commandLine, String name, String command,
-            String dependency, String description, CamelJBangMain main) {
-        commandLine.addSubcommand(command, CommandLine.Model.CommandSpec.wrapWithoutInspection(
-                (Runnable) () -> {
-                    List<String> args = commandLine.getParseResult().originalArgs();
-                    if (args.contains("--help") || args.contains("--h")) {
-                        main.getOut().printf("Loading plugin %s for command %s%n", name, command);
-                    }
-
-                    String gav = dependency;
-                    if (gav.endsWith(":${camel-version}")) {
-                        gav = gav.substring(0, gav.length() - "${camel-version}".length()) + getCamelVersion(args);
-                    }
-
-                    // need to use jbang command to call plugin
-                    List<String> jbangArgs = new ArrayList<>();
-                    jbangArgs.add("jbang");
-                    // Add plugin dependency, so it is present on the classpath for the new JBang process
-                    jbangArgs.add("--deps=" + gav);
-
-                    jbangArgs.add("camel");
-                    jbangArgs.addAll(args);
-
-                    try {
-                        ProcessBuilder pb = new ProcessBuilder();
-                        pb.command(jbangArgs);
-
-                        pb.inheritIO(); // run in foreground (with IO so logs are visible)
-                        Process p = pb.start();
-
-                        // wait for that process to exit as we run in foreground
-                        int exitCode = p.waitFor();
-                        main.quit(exitCode);
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                        main.getOut().printf("Interrupted while spawning JBang process");
-                        main.quit(1);
-                    } catch (IOException e) {
-                        main.getOut().printf("Unable to spawn JBang process - %s%n", e.getMessage());
-                        main.quit(1);
-                    }
-                })
-                .usageMessage(new CommandLine.Model.UsageMessageSpec().description(description))
-                .addUnmatchedArgsBinding(CommandLine.Model.UnmatchedArgsBinding
-                        .forStringArrayConsumer(new CommandLine.Model.ISetter() {
-                            @Override
-                            public <T> T set(T value) throws Exception {
-                                return value;
-                            }
-                        })));
-    }
-
-    private static String getCamelVersion(List<String> args) {
-        Optional<String> version = args.stream()
-                .filter(arg -> arg.startsWith("--camel.version="))
-                .map(arg -> arg.substring("camel.version=".length()))
-                .findFirst();
-
-        if (version.isPresent()) {
-            return version.get();
+    private static Optional<Plugin> downloadPlugin(String command, CamelJBangMain main) {
+        DependencyDownloader downloader = new MavenDependencyDownloader();
+        DependencyDownloaderClassLoader ddlcl = new DependencyDownloaderClassLoader(PluginHelper.class.getClassLoader());
+        downloader.setClassLoader(ddlcl);
+        downloader.start();
+        String version = new VersionHelper().getVersion();
+        // downloads and adds to the classpath
+        downloader.downloadDependency("org.apache.camel", "camel-jbang-plugin-" + command, version);
+        Optional<Plugin> instance = Optional.empty();
+        InputStream in = null;
+        String path = FactoryFinder.DEFAULT_PATH + "camel-jbang-plugin/camel-jbang-plugin-" + command;
+        try {
+            // reads the class name from the plugin dependency
+            in = ddlcl.getResourceAsStream(path);
+            if (in != null) {
+                Properties prop = new Properties();
+                prop.load(in);
+                String pluginClassName = prop.getProperty("class");
+                DefaultClassResolver resolver = new DefaultClassResolver();
+                Class<?> pluginClass = resolver.resolveClass(pluginClassName, ddlcl);
+                instance = Optional.of(Plugin.class.cast(ObjectHelper.newInstance(pluginClass)));
+            } else {
+                String gav = String.join(":", "org.apache.camel", "camel-jbang-plugin-" + command, version);
+                main.getOut().printf(String.format("ERROR: Failed to read file %s in dependency %s.\n", path, gav));
+            }
+        } catch (IOException e) {
+            throw new RuntimeCamelException(String.format("Failed to read the file %s.", path), e);
+        } finally {
+            downloader.stop();
+            IOHelper.close(in);
         }
-
-        CamelCatalog catalog = new DefaultCamelCatalog();
-        return catalog.getCatalogVersion();
+        return instance;
     }
 
     public static JsonObject getOrCreatePluginConfig() {