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 e9a09c926cc CAMEL-22098: camel-jbang - camel dependency runtime
e9a09c926cc is described below
commit e9a09c926cce01035df7562260270f5665adb8ed
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed May 21 19:44:17 2025 +0200
CAMEL-22098: camel-jbang - camel dependency runtime
---
.../dsl/jbang/core/commands/CamelJBangMain.java | 3 +-
.../dsl/jbang/core/commands/DependencyRuntime.java | 188 +++++++++++++++++++++
.../camel/dsl/jbang/core/commands/RunHelper.java | 9 +-
.../camel/dsl/jbang/core/common/CatalogLoader.java | 56 ++++--
.../jbang/core/commands/DependencyListTest.java | 5 +-
.../camel/main/download/DependencyDownloader.java | 11 ++
.../main/download/MavenDependencyDownloader.java | 17 +-
7 files changed, 264 insertions(+), 25 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index 52834122c6f..b18d6cd299d 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -143,7 +143,8 @@ public class CamelJBangMain implements Callable<Integer> {
.addSubcommand("dependency", new CommandLine(new
DependencyCommand(main))
.addSubcommand("list", new CommandLine(new
DependencyList(main)))
.addSubcommand("copy", new CommandLine(new
DependencyCopy(main)))
- .addSubcommand("update", new CommandLine(new
DependencyUpdate(main))))
+ .addSubcommand("update", new CommandLine(new
DependencyUpdate(main)))
+ .addSubcommand("runtime", new CommandLine(new
DependencyRuntime(main))))
.addSubcommand("catalog", new CommandLine(new
CatalogCommand(main))
.addSubcommand("component", new CommandLine(new
CatalogComponent(main)))
.addSubcommand("dataformat", new CommandLine(new
CatalogDataFormat(main)))
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
new file mode 100644
index 00000000000..20f6941e472
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyRuntime.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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.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.CommandLineHelper;
+import org.apache.camel.dsl.jbang.core.common.XmlHelper;
+import org.apache.camel.util.json.Jsoner;
+import picocli.CommandLine;
+
[email protected](name = "runtime",
+ description = "Display Camel runtime and version for
given Maven project", sortOptions = false,
+ showDefaultValues = true)
+public class DependencyRuntime extends CamelCommand {
+
+ protected static final String EXPORT_DIR =
CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/export";
+
+ @CommandLine.Option(names = { "--json" },
+ description = "Output in JSON Format")
+ boolean jsonOutput;
+
+ public DependencyRuntime(CamelJBangMain main) {
+ super(main);
+ }
+
+ @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;
+ }
+
+ 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();
+ }
+
+ // 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 repos = 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();
+ }
+
+ // 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);
+ }
+ }
+
+ String runtime = "camel-main";
+ if (springBootVersion != null) {
+ runtime = "camel-spring-boot";
+ } else if (quarkusVersion != null) {
+ runtime = "camel-quarkus";
+ }
+
+ 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);
+ }
+ }
+ }
+
+ return 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 ca0b2631793..57f2c986327 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
@@ -61,6 +61,8 @@ public final class RunHelper {
Path pomPath = Paths.get("pom.xml");
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)) {
@@ -89,7 +91,7 @@ public final class RunHelper {
// camel dependencies
String a = d.getArtifactId();
- if (!isInCamelCatalog(a)) {
+ if (!isInCamelCatalog(catalog, a)) {
// not a known camel artifact
continue;
}
@@ -170,7 +172,10 @@ public final class RunHelper {
}
public static boolean isInCamelCatalog(String artifactId) {
- CamelCatalog catalog = new DefaultCamelCatalog();
+ return isInCamelCatalog(new DefaultCamelCatalog(), artifactId);
+ }
+
+ public static boolean isInCamelCatalog(CamelCatalog catalog, String
artifactId) {
for (String n : catalog.findComponentNames()) {
String a = catalog.componentModel(n).getArtifactId();
if (artifactId.equals(a)) {
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 8aac715a2cd..bca0712fcb9 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
@@ -19,6 +19,7 @@ package org.apache.camel.dsl.jbang.core.common;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -193,20 +194,25 @@ public final class CatalogLoader {
if (camelQuarkusVersion != null) {
// download camel-quarkus-catalog we use to know if we have an
extension or not
- downloader.downloadDependency("org.apache.camel.quarkus",
"camel-quarkus-catalog", camelQuarkusVersion);
-
- Class<RuntimeProvider> clazz = (Class<RuntimeProvider>)
cl.loadClass(QUARKUS_CATALOG_PROVIDER);
- if (clazz != null) {
- Class<CamelCatalog> clazz2 = (Class<CamelCatalog>)
cl.loadClass(DEFAULT_CAMEL_CATALOG);
- if (clazz2 != null) {
- answer = ObjectHelper.newInstance(clazz2);
- }
- RuntimeProvider provider = ObjectHelper.newInstance(clazz);
- if (provider != null) {
- answer.setRuntimeProvider(provider);
+ List<MavenArtifact> artifacts =
downloader.downloadArtifacts("org.apache.camel.quarkus",
+ "camel-quarkus-catalog", camelQuarkusVersion, true);
+ if (artifacts != null) {
+ // this will add to classpath
+ downloader.downloadDependency("org.apache.camel.quarkus",
"camel-quarkus-catalog", camelQuarkusVersion);
+
+ Class<RuntimeProvider> clazz = (Class<RuntimeProvider>)
cl.loadClass(QUARKUS_CATALOG_PROVIDER);
+ if (clazz != null) {
+ Class<CamelCatalog> clazz2 = (Class<CamelCatalog>)
cl.loadClass(DEFAULT_CAMEL_CATALOG);
+ if (clazz2 != null) {
+ answer = ObjectHelper.newInstance(clazz2);
+ }
+ RuntimeProvider provider =
ObjectHelper.newInstance(clazz);
+ if (provider != null) {
+ answer.setRuntimeProvider(provider);
+ }
+ // use classloader that loaded quarkus provider to
ensure we can load its resources
+ answer.getVersionManager().setClassLoader(cl);
}
- // use classloader that loaded quarkus provider to ensure
we can load its resources
- answer.getVersionManager().setClassLoader(cl);
}
}
answer.enableCache();
@@ -217,6 +223,30 @@ public final class CatalogLoader {
return answer;
}
+ public static String resolveCamelVersionFromQuarkus(String repos, String
camelQuarkusVersion) 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.quarkus",
"camel-quarkus-catalog",
+ camelQuarkusVersion, 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;
+ }
+
private static final class DownloadCatalogVersionManager implements
VersionManager {
private ClassLoader classLoader;
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
index 385a6952eed..47fa955555c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
@@ -55,7 +55,7 @@ class DependencyListTest extends CamelCommandBaseTest {
@ParameterizedTest
@MethodSource("runtimeProvider")
public void shouldDependencyList(RuntimeType rt) throws Exception {
- Export command = createCommand(rt, new String[] {
"classpath:route.yaml" },
+ DependencyList command = createCommand(rt, new String[] {
"classpath:route.yaml" },
"--gav=examples:route:1.0.0", "--dir=" + workingDir,
"--quiet", "--camel-version=4.11.0",
"--quarkus-version=3.22.2", "--spring-boot-version=3.4.5");
int exit = command.doCall();
@@ -75,9 +75,8 @@ class DependencyListTest extends CamelCommandBaseTest {
}
}
- private Export createCommand(RuntimeType rt, String[] files, String...
args) {
+ private DependencyList createCommand(RuntimeType rt, String[] files,
String... args) {
DependencyList command = new DependencyList(new
CamelJBangMain().withPrinter(printer));
- ;
CommandLine.populateCommand(command, "--gav=examples:route:1.0.0",
"--dir=" + workingDir, "--quiet",
"--runtime=%s".formatted(rt.runtime()));
if (args != null) {
diff --git
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
index 840ca8b136b..fec871a2ae4 100644
---
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
+++
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
@@ -155,6 +155,17 @@ public interface DependencyDownloader extends
CamelContextAware, StaticService {
*/
MavenArtifact downloadArtifact(String groupId, String artifactId, String
version);
+ /**
+ * Downloads maven artifact (can also include transitive dependencies).
+ *
+ * @param groupId maven group id
+ * @param artifactId maven artifact id
+ * @param version maven version
+ * @param transitively whether to include transitive dependencies
+ * @return the artifacts, or null if none found
+ */
+ List<MavenArtifact> downloadArtifacts(String groupId, String artifactId,
String version, boolean transitively);
+
/**
* Resolves the available versions for the given maven artifact
*
diff --git
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
index 7b1954c33fd..47bda5971e1 100644
---
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
+++
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
@@ -330,24 +330,29 @@ public class MavenDependencyDownloader extends
ServiceSupport implements Depende
@Override
public MavenArtifact downloadArtifact(String groupId, String artifactId,
String version) {
+ List<MavenArtifact> artifacts = downloadArtifacts(groupId, artifactId,
version, false);
+ if (artifacts != null && artifacts.size() == 1) {
+ return artifacts.get(0);
+ }
+ return null;
+ }
+
+ @Override
+ public List<MavenArtifact> downloadArtifacts(String groupId, String
artifactId, String version, boolean transitively) {
String gav = groupId + ":" + artifactId + ":" + version;
List<String> deps = List.of(gav);
// include Apache snapshot to make it easy to use upcoming releases
boolean useApacheSnapshots = "org.apache.camel".equals(groupId) &&
version.contains("SNAPSHOT");
- List<MavenArtifact> artifacts = resolveDependenciesViaAether(deps,
null, false, useApacheSnapshots);
+ List<MavenArtifact> artifacts = resolveDependenciesViaAether(deps,
null, transitively, useApacheSnapshots);
if (verbose) {
LOG.info("Dependencies: {} -> [{}]", gav, artifacts);
} else {
LOG.debug("Dependencies: {} -> [{}]", gav, artifacts);
}
- if (artifacts.size() == 1) {
- return artifacts.get(0);
- }
-
- return null;
+ return artifacts;
}
@Override