This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch dr in repository https://gitbox.apache.org/repos/asf/camel.git
commit 5c721a412f6e4054611e6eec869607f2473712f7 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Jun 12 22:04:42 2025 +0200 CAMEL-22165: camel-jbang dependency runtime (deep analysis to resolve from parent poms) --- .../dsl/jbang/core/commands/DependencyRuntime.java | 222 ++++++++++----------- .../apache/camel/dsl/jbang/core/commands/Run.java | 2 +- .../camel/dsl/jbang/core/commands/RunHelper.java | 173 +++++++++++----- .../camel/dsl/jbang/core/common/CatalogLoader.java | 25 +++ 4 files changed, 245 insertions(+), 177 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyRuntime.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyRuntime.java index 8e2ff4bcb61..aba3720e406 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyRuntime.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyRuntime.java @@ -16,24 +16,19 @@ */ package org.apache.camel.dsl.jbang.core.commands; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.StringJoiner; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.dsl.jbang.core.common.CatalogLoader; -import org.apache.camel.dsl.jbang.core.common.XmlHelper; +import org.apache.camel.tooling.maven.MavenGav; import org.apache.camel.util.json.Jsoner; +import org.apache.maven.model.Model; +import org.apache.maven.model.Repository; import picocli.CommandLine; @CommandLine.Command(name = "runtime", @@ -52,130 +47,113 @@ public class DependencyRuntime extends CamelCommand { @Override public Integer doCall() throws Exception { // read pom.xml - Path pom = Paths.get(".").resolve("pom.xml"); - if (Files.exists(pom)) { - DocumentBuilderFactory dbf = XmlHelper.createDocumentBuilderFactory(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document dom = db.parse(Files.newInputStream(pom)); - NodeList nl = dom.getElementsByTagName("dependency"); - String camelVersion = null; - String camelQuarkusVersion = null; - String springBootVersion = null; - String quarkusVersion = null; - String quarkusGroupId = "io.quarkus.platform"; - for (int i = 0; i < nl.getLength(); i++) { - Element node = (Element) nl.item(i); - - // must be child at <project/dependencyManagement> or <project/dependencies> - String p = node.getParentNode().getNodeName(); - String p2 = node.getParentNode().getParentNode().getNodeName(); - boolean accept = ("dependencyManagement".equals(p2) || "project".equals(p2)) && (p.equals("dependencies")); - if (!accept) { - continue; - } + Path pomPath = Paths.get("pom.xml"); + Model model = RunHelper.loadMavenModel(pomPath); + if (model == null) { + return 0; + } - String g = node.getElementsByTagName("groupId").item(0).getTextContent(); - String a = node.getElementsByTagName("artifactId").item(0).getTextContent(); - String v = null; - NodeList vl = node.getElementsByTagName("version"); - if (vl.getLength() > 0) { - v = vl.item(0).getTextContent(); - } + List<String> deps = RunHelper.scanMavenDependenciesFromModel(pomPath, model); + if (deps.isEmpty()) { + return 0; + } - // BOMs - if ("org.apache.camel".equals(g) && "camel-bom".equals(a)) { - camelVersion = v; - continue; - } - if ("org.apache.camel.springboot".equals(g) && "camel-spring-boot-bom".equals(a)) { - camelVersion = v; - continue; - } - if ("org.springframework.boot".equals(g) && "spring-boot-dependencies".equals(a)) { - springBootVersion = v; - continue; - } - if (("${quarkus.platform.group-id}".equals(g) || "io.quarkus.platform".equals(g)) && - ("${quarkus.platform.artifact-id}".equals(a) || "quarkus-bom".equals(a))) { - if ("${quarkus.platform.version}".equals(v)) { - quarkusVersion = dom.getElementsByTagName("quarkus.platform.version").item(0).getTextContent(); - } else { - quarkusVersion = v; - } - continue; - } - if (("${quarkus.platform.group-id}".equals(g))) { - quarkusGroupId = dom.getElementsByTagName("quarkus.platform.group-id").item(0).getTextContent(); - } + String camelVersion = null; + String camelSpringBootVersion = null; + String camelQuarkusVersion = null; + String springBootVersion = null; + String quarkusVersion = null; + String quarkusGroupId = null; + + for (String dep : deps) { + MavenGav gav = MavenGav.parseGav(dep); + if (camelVersion == null && "org.apache.camel".equals(gav.getGroupId())) { + camelVersion = gav.getVersion(); + } + if (camelSpringBootVersion == null && "org.apache.camel.springboot".equals(gav.getGroupId())) { + camelSpringBootVersion = gav.getVersion(); + } + if (camelQuarkusVersion == null && "org.apache.camel.quarkus".equals(gav.getGroupId())) { + camelQuarkusVersion = gav.getVersion(); + } + if (springBootVersion == null && "org.springframework.boot".equals(gav.getGroupId())) { + springBootVersion = gav.getVersion(); } + if (quarkusVersion == null && "io.quarkus".equals(gav.getGroupId())) { + quarkusVersion = gav.getVersion(); + } + if (quarkusGroupId == null && "quarkus-bom".equals(gav.getArtifactId())) { + quarkusGroupId = gav.getGroupId(); + quarkusVersion = gav.getVersion(); + } + } - String repos = null; + if (springBootVersion != null && camelVersion == null) { StringJoiner sj = new StringJoiner(","); - nl = dom.getElementsByTagName("repository"); - for (int i = 0; i < nl.getLength(); i++) { - Element node = (Element) nl.item(i); - - // must be child at <repositories/repository> - String p = node.getParentNode().getNodeName(); - boolean accept = "repositories".equals(p); - if (!accept) { - continue; - } - String url = node.getElementsByTagName("url").item(0).getTextContent(); - sj.add(url); - } - if (sj.length() > 0) { - repos = sj.toString(); + for (Repository r : model.getRepositories()) { + sj.add(r.getUrl()); } + String repos = sj.length() > 0 ? sj.toString() : null; + camelVersion = CatalogLoader.resolveCamelVersionFromSpringBoot(repos, camelSpringBootVersion); + } - // its a bit harder to know the camel version from Quarkus because of the universal BOM - if (quarkusVersion != null && camelVersion == null) { - CamelCatalog catalog = CatalogLoader.loadQuarkusCatalog(repos, quarkusVersion, quarkusGroupId); - if (catalog != null) { - // find out the camel quarkus version via the constant language that are built-in camel-core - camelQuarkusVersion = catalog.languageModel("constant").getVersion(); - // okay so the camel version is also hard to resolve from quarkus - camelVersion = CatalogLoader.resolveCamelVersionFromQuarkus(repos, camelQuarkusVersion); - } + // its a bit harder to know the camel version from Quarkus because of the universal BOM + if (quarkusVersion != null && camelVersion == null) { + StringJoiner sj = new StringJoiner(","); + for (Repository r : model.getRepositories()) { + sj.add(r.getUrl()); + } + String repos = sj.length() > 0 ? sj.toString() : null; + CamelCatalog catalog = CatalogLoader.loadQuarkusCatalog(repos, quarkusVersion, quarkusGroupId); + if (catalog != null) { + // find out the camel quarkus version via the constant language that are built-in camel-core + camelQuarkusVersion = catalog.languageModel("constant").getVersion(); + // okay so the camel version is also hard to resolve from quarkus + camelVersion = CatalogLoader.resolveCamelVersionFromQuarkus(repos, camelQuarkusVersion); } + } + + String runtime = "camel-main"; + if (springBootVersion != null) { + runtime = "camel-spring-boot"; + } else if (quarkusVersion != null) { + runtime = "camel-quarkus"; + } - String runtime = "camel-main"; + if (jsonOutput) { + Map<String, String> map = new LinkedHashMap<>(); + map.put("runtime", runtime); + if (camelVersion != null) { + map.put("camelVersion", camelVersion); + } + if (camelSpringBootVersion != null) { + map.put("camelSpringBootVersion", camelSpringBootVersion); + } + if (camelQuarkusVersion != null) { + map.put("camelQuarkusVersion", camelQuarkusVersion); + } if (springBootVersion != null) { - runtime = "camel-spring-boot"; - } else if (quarkusVersion != null) { - runtime = "camel-quarkus"; + map.put("springBootVersion", springBootVersion); } - - if (jsonOutput) { - Map<String, String> map = new LinkedHashMap<>(); - map.put("runtime", runtime); - if (camelVersion != null) { - map.put("camelVersion", camelVersion); - } - if (camelQuarkusVersion != null) { - map.put("camelQuarkusVersion", camelQuarkusVersion); - } - if (springBootVersion != null) { - map.put("springBootVersion", springBootVersion); - } - if (quarkusVersion != null) { - map.put("quarkusVersion", quarkusVersion); - } - printer().println( - Jsoner.serialize(map)); - } else { - printer().println("Runtime: " + runtime); - if (camelVersion != null) { - printer().println("Camel Version: " + camelVersion); - } - if (camelQuarkusVersion != null) { - printer().println("Camel Quarkus Version: " + camelQuarkusVersion); - } - if (springBootVersion != null) { - printer().println("Spring Boot Version: " + springBootVersion); - } else if (quarkusVersion != null) { - printer().println("Quarkus Version: " + quarkusVersion); - } + if (quarkusVersion != null) { + map.put("quarkusVersion", quarkusVersion); + } + printer().println(Jsoner.serialize(map)); + } else { + printer().println("Runtime: " + runtime); + if (camelVersion != null) { + printer().println("Camel Version: " + camelVersion); + } + if (camelSpringBootVersion != null) { + printer().println("Camel Spring Boot Version: " + camelSpringBootVersion); + } + if (camelQuarkusVersion != null) { + printer().println("Camel Quarkus Version: " + camelQuarkusVersion); + } + if (springBootVersion != null) { + printer().println("Spring Boot Version: " + springBootVersion); + } else if (quarkusVersion != null) { + printer().println("Quarkus Version: " + quarkusVersion); } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java index a973234597e..1787954d53b 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java @@ -733,7 +733,7 @@ public class Run extends CamelCommand { // find source files files = RunHelper.scanMavenOrGradleProject(); // include extra dependencies from pom.xml - var pomDependencies = RunHelper.scanMavenDependenciesFromPom(); + var pomDependencies = RunHelper.scanMavenDependenciesFromPom(Paths.get("pom.xml")); addDependencies(pomDependencies.toArray(new String[0])); } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java index 57f2c986327..8f5e2607ff6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java @@ -23,15 +23,20 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.StringJoiner; import java.util.stream.Stream; import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.main.download.MavenDependencyDownloader; +import org.apache.camel.tooling.maven.MavenArtifact; +import org.apache.camel.util.FileUtil; import org.apache.camel.util.ReflectionHelper; -import org.apache.camel.util.StringHelper; import org.apache.maven.model.Dependency; import org.apache.maven.model.Model; +import org.apache.maven.model.Repository; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; public final class RunHelper { @@ -56,68 +61,108 @@ public final class RunHelper { return null; } - public static List<String> scanMavenDependenciesFromPom() { - List<String> answer = new ArrayList<>(); - - Path pomPath = Paths.get("pom.xml"); + public static Model loadMavenModel(Path pomPath) throws Exception { + Model answer = null; if (Files.exists(pomPath) && Files.isRegularFile(pomPath)) { - CamelCatalog catalog = new DefaultCamelCatalog(); - // find additional dependencies form pom.xml MavenXpp3Reader mavenReader = new MavenXpp3Reader(); try (Reader reader = Files.newBufferedReader(pomPath)) { - Model model = mavenReader.read(reader); - model.setPomFile(pomPath.toFile()); // Still need File for Maven Model + answer = mavenReader.read(reader); + answer.setPomFile(pomPath.toFile()); // Still need File for Maven Model + } + } + return answer; + } - for (Dependency d : model.getDependencies()) { - String g = d.getGroupId(); - String scope = d.getScope(); - boolean accept = scope == null || "compile".equals(scope); - // 3rd party dependencies - if (accept && !g.startsWith("org.apache.camel")) { - String v = d.getVersion(); - if (v != null && v.startsWith("${") && v.endsWith("}")) { - // version uses placeholder, so try to find them - v = v.substring(2, v.length() - 1); - v = findMavenProperty((Path) pomPath, v); - } - if (v != null) { - String gav = "mvn:" + g + ":" + d.getArtifactId() + ":" + v; - if (!answer.contains(gav)) { - answer.add(gav); - } - } - } else if (accept && g.startsWith("org.apache.camel")) { - // camel dependencies - String a = d.getArtifactId(); + public static List<String> scanMavenDependenciesFromPom(Path pomPath) throws Exception { + Model model = loadMavenModel(pomPath); + if (model != null) { + return scanMavenDependenciesFromModel(pomPath, model); + } + return Collections.EMPTY_LIST; + } - if (!isInCamelCatalog(catalog, a)) { - // not a known camel artifact - continue; - } + public static List<String> scanMavenDependenciesFromModel(Path pomPath, Model model) throws Exception { + String camelVersion = null; + String camelSpringBootVersion = null; + String springBootVersion = null; + String quarkusVersion = null; - if (a.endsWith("-starter")) { - a = StringHelper.before(a, "-starter"); - } - if (a.startsWith("camel-quarkus-")) { - a = StringHelper.after(a, "camel-quarkus"); - } - if (a.startsWith("camel-")) { - a = StringHelper.after(a, "camel-"); - } - String gav = "camel:" + a; - if (!answer.contains(gav)) { - answer.add(gav); - } + StringJoiner sj = new StringJoiner(","); + for (Repository r : model.getRepositories()) { + sj.add(r.getUrl()); + } + + MavenDependencyDownloader downloader = new MavenDependencyDownloader(); + if (sj.length() > 0) { + downloader.setRepositories(sj.toString()); + } + downloader.build(); + + List<String> answer = new ArrayList<>(); + if (model.getDependencyManagement() != null) { + for (Dependency d : model.getDependencyManagement().getDependencies()) { + String g = resolveDependencyPlaceholder(d.getGroupId(), pomPath, downloader); + String a = resolveDependencyPlaceholder(d.getArtifactId(), pomPath, downloader); + String v = resolveDependencyPlaceholder(d.getVersion(), pomPath, downloader); + if (v != null) { + if ("org.apache.camel".equals(g) && "camel-bom".equals(a)) { + camelVersion = v; + } else if ("org.apache.camel.springboot".equals(g) + && "camel-spring-boot-bom".equals(a)) { + camelSpringBootVersion = v; + } else if ("org.springframework.boot".equals(g) + && "spring-boot-dependencies".equals(a)) { + springBootVersion = v; + } else if ("io.quarkus.platform".equals(g) + && "quarkus-bom".equals(a)) { + quarkusVersion = v; + } + String gav = "mvn:" + g + ":" + a + ":" + v; + if (!answer.contains(gav)) { + answer.add(gav); } } - } catch (Exception ex) { - // do something better here + } + } + + for (Dependency d : model.getDependencies()) { + String scope = d.getScope(); + boolean accept = scope == null || "compile".equals(scope); + if (accept) { + String g = resolveDependencyPlaceholder(d.getGroupId(), pomPath, downloader); + String a = resolveDependencyPlaceholder(d.getArtifactId(), pomPath, downloader); + String v = resolveDependencyPlaceholder(d.getVersion(), pomPath, downloader); + if (v == null && ("org.apache.camel".equals(g))) { + v = camelVersion; + } else if (v == null && ("org.apache.camel.springboot".equals(g))) { + v = camelSpringBootVersion; + } else if (v == null && "org.springframework.boot".equals(g)) { + v = springBootVersion; + } else if (v == null && "io.quarkus.platform".equals(g)) { + v = quarkusVersion; + } + String gav = "mvn:" + g + ":" + a; + if (v != null) { + gav += ":" + v; + } + if (!answer.contains(gav)) { + answer.add(gav); + } } } return answer; } + private static String resolveDependencyPlaceholder(String value, Path pomPath, MavenDependencyDownloader downloader) { + if (value != null && value.startsWith("${") && value.endsWith("}")) { + // version uses placeholder, so try to find them + value = value.substring(2, value.length() - 1); + value = findMavenProperty(pomPath, value, downloader); + } + return value; + } + public static List<String> scanMavenOrGradleProject() { List<String> answer = new ArrayList<>(); @@ -129,7 +174,7 @@ public final class RunHelper { return answer; } - public static String findMavenProperty(Path pomPath, String placeholder) { + public static String findMavenProperty(Path pomPath, String placeholder, MavenDependencyDownloader downloader) { if (Files.exists(pomPath) && Files.isRegularFile(pomPath)) { // find additional dependencies form pom.xml MavenXpp3Reader mavenReader = new MavenXpp3Reader(); @@ -137,13 +182,33 @@ public final class RunHelper { Model model = mavenReader.read(reader); model.setPomFile(pomPath.toFile()); // Still need File for Maven Model String p = model.getProperties().getProperty(placeholder); + if (p != null && p.startsWith("${") && p.endsWith("}")) { + p = p.substring(2, p.length() - 1); + if ("project.version".equals(p)) { + p = model.getVersion(); + } else { + p = model.getProperties().getProperty(p); + } + } if (p != null) { return p; } else if (model.getParent() != null) { p = model.getParent().getRelativePath(); if (p != null) { - Path parentPath = pomPath.getParent().resolve(p); - return findMavenProperty(parentPath, placeholder); + String dir = FileUtil.onlyPath(pomPath.toAbsolutePath().toString()); + p = FileUtil.compactPath(dir + "/" + p); + pomPath = Paths.get(p); + boolean exists = Files.exists(pomPath) && Files.isRegularFile(pomPath); + if (exists) { + return findMavenProperty(pomPath, placeholder, downloader); + } else if (downloader != null) { + // download dependency as it's not in local path + MavenArtifact ma = downloader.downloadArtifact(model.getParent().getGroupId(), + model.getParent().getArtifactId() + ":pom", model.getParent().getVersion()); + if (ma != null) { + return findMavenProperty(ma.getFile(), placeholder, downloader); + } + } } } } catch (Exception ex) { @@ -155,8 +220,8 @@ public final class RunHelper { // Keep for backward compatibility @Deprecated - public static String findMavenProperty(java.io.File f, String placeholder) { - return findMavenProperty(f.toPath(), placeholder); + public static String findMavenProperty(java.io.File f, String placeholder, MavenDependencyDownloader downloader) { + return findMavenProperty(f.toPath(), placeholder, downloader); } public static Stream<Path> walk(Path dir) { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java index bca0712fcb9..19b1337db5a 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java @@ -223,6 +223,31 @@ public final class CatalogLoader { return answer; } + public static String resolveCamelVersionFromSpringBoot(String repos, String camelSpringBootVersion) throws Exception { + DependencyDownloaderClassLoader cl = new DependencyDownloaderClassLoader(CatalogLoader.class.getClassLoader()); + MavenDependencyDownloader downloader = new MavenDependencyDownloader(); + downloader.setRepositories(repos); + downloader.setClassLoader(cl); + try { + downloader.start(); + + List<MavenArtifact> artifacts + = downloader.downloadArtifacts("org.apache.camel.springboot", "camel-catalog-provider-springboot", + camelSpringBootVersion, true); + for (MavenArtifact ma : artifacts) { + String g = ma.getGav().getGroupId(); + String a = ma.getGav().getArtifactId(); + if ("org.apache.camel".equals(g) && "camel-catalog".equals(a)) { + return ma.getGav().getVersion(); + } + } + } finally { + downloader.stop(); + } + + return null; + } + public static String resolveCamelVersionFromQuarkus(String repos, String camelQuarkusVersion) throws Exception { DependencyDownloaderClassLoader cl = new DependencyDownloaderClassLoader(CatalogLoader.class.getClassLoader()); MavenDependencyDownloader downloader = new MavenDependencyDownloader();