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 <clau...@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() {