You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/01/25 09:23:36 UTC
[camel] 01/02: CAMEL-17280: camel-jbang - Run from github using wildcards
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
commit b89f2238f936116e18d1c7a2514117a67830879b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jan 25 10:12:34 2022 +0100
CAMEL-17280: camel-jbang - Run from github using wildcards
---
.../apache/camel/dsl/jbang/core/commands/Run.java | 135 ++++++++++++++++++++-
1 file changed, 131 insertions(+), 4 deletions(-)
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 2283fe1..e0bf1f6 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
@@ -18,17 +18,26 @@ package org.apache.camel.dsl.jbang.core.commands;
import java.io.File;
import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
import java.nio.file.FileSystems;
+import java.time.Duration;
import java.util.StringJoiner;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.camel.CamelContext;
import org.apache.camel.dsl.jbang.core.common.RuntimeUtil;
import org.apache.camel.main.KameletMain;
import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.AntPathMatcher;
+import org.apache.camel.util.FileUtil;
import org.apache.camel.util.ObjectHelper;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
@@ -44,7 +53,7 @@ class Run implements Callable<Integer> {
private String[] files;
//CHECKSTYLE:OFF
- @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display the help and sub-commands")
+ @Option(names = {"-h", "--help"}, usageHelp = true, description = "Display the help and sub-commands")
private boolean helpRequested;
//CHECKSTYLE:ON
@@ -220,7 +229,33 @@ class Run implements Callable<Integer> {
// automatic map github https urls to github resolver
if (file.startsWith("https://github.com/")) {
- file = mapGithubUrl(file);
+ String ext = FileUtil.onlyExt(file);
+ boolean wildcard = FileUtil.onlyName(file, false).contains("*");
+ if (ext != null && !wildcard) {
+ // it is a single file so map to
+ file = asGithubSingleUrl(file);
+ } else {
+ StringJoiner files = new StringJoiner(",");
+ StringJoiner kamelets = new StringJoiner(",");
+ StringJoiner properties = new StringJoiner(",");
+ fetchGithubUrls(file, files, kamelets, properties);
+
+ if (files.length() > 0) {
+ file = files.toString();
+ }
+ if (properties.length() > 0) {
+ main.addInitialProperty("camel.component.properties.location", properties.toString());
+ }
+ if (kamelets.length() > 0) {
+ String loc = main.getInitialProperties().getProperty("camel.component.kamelet.location");
+ if (loc != null) {
+ loc = loc + "," + kamelets;
+ } else {
+ loc = kamelets.toString();
+ }
+ main.addInitialProperty("camel.component.kamelet.location", loc);
+ }
+ }
}
js.add(file);
@@ -253,7 +288,14 @@ class Run implements Callable<Integer> {
}
locations.append(file).append(",");
}
- main.addInitialProperty("camel.component.properties.location", locations.toString());
+ // there may be existing properties
+ String loc = main.getInitialProperties().getProperty("camel.component.properties.location");
+ if (loc != null) {
+ loc = loc + "," + locations;
+ } else {
+ loc = locations.toString();
+ }
+ main.addInitialProperty("camel.component.properties.location", loc);
}
System.out.println("Starting CamelJBang");
@@ -277,7 +319,7 @@ class Run implements Callable<Integer> {
return lockFile;
}
- private static String mapGithubUrl(String url) {
+ private static String asGithubSingleUrl(String url) throws Exception {
// strip https://github.com/
url = url.substring(19);
// https://github.com/apache/camel-k/blob/main/examples/languages/routes.kts
@@ -288,4 +330,89 @@ class Run implements Callable<Integer> {
url = url.replaceFirst("/", ":");
return "github:" + url;
}
+
+ private static void fetchGithubUrls(String url, StringJoiner files, StringJoiner kamelets, StringJoiner properties)
+ throws Exception {
+ // this is a directory, so we need to query github which files are there and filter them
+
+ // URL: https://api.github.com/repos/apache/camel-k/contents/examples/kamelets/kameletbindings
+ // URL: https://api.github.com/repos/apache/camel-k/contents/examples/kamelets/kameletbindings?ref=v1.7.0
+ // https://github.com/apache/camel-k/tree/main/examples/kamelets/kameletbindings
+ // https://github.com/apache/camel-k/tree/v1.7.0/examples/kamelets/kameletbindings
+
+ // strip https://github.com/
+ url = url.substring(19);
+
+ String[] parts = url.split("/");
+ if (parts.length < 5) {
+ return;
+ }
+
+ String org = parts[0];
+ String repo = parts[1];
+ String action = parts[2];
+ String branch = parts[3];
+ String path;
+ String wildcard = null;
+ StringJoiner sj = new StringJoiner("/");
+ for (int i = 4; i < parts.length; i++) {
+ if (i == parts.length - 1) {
+ // last element uses wildcard to filter which files to include
+ if (parts[i].contains("*")) {
+ wildcard = parts[i];
+ break;
+ }
+ }
+ sj.add(parts[i]);
+ }
+ path = sj.toString();
+
+ if ("tree".equals(action)) {
+ // https://api.github.com/repos/apache/camel-k/contents/examples/kamelets/kameletbindings?ref=v1.7.0
+ url = "https://api.github.com/repos/" + org + "/" + repo + "/contents/" + path;
+ if (!"main".equals(branch) && !"master".equals(branch)) {
+ url = url + "?ref=" + branch;
+ }
+ }
+
+ downloadGithubFiles(url, wildcard, files, kamelets, properties);
+ }
+
+ private static void downloadGithubFiles(
+ String url, String wildcard, StringJoiner files, StringJoiner kamelets, StringJoiner properties)
+ throws Exception {
+
+ // use JDK http client to call github api
+ HttpClient hc = HttpClient.newHttpClient();
+ HttpResponse<String> res = hc.send(HttpRequest.newBuilder(new URI(url)).timeout(Duration.ofSeconds(20)).build(),
+ HttpResponse.BodyHandlers.ofString());
+
+ if (res.statusCode() == 200) {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode root = mapper.readTree(res.body());
+ for (JsonNode c : root) {
+ String name = c.get("name").asText();
+ String ext = FileUtil.onlyExt(name, false);
+ boolean match = wildcard == null || AntPathMatcher.INSTANCE.match(wildcard, name, false);
+ if (match) {
+ if ("kamelet.yaml".equalsIgnoreCase(ext)) {
+ String htmlUrl = c.get("html_url").asText();
+ String u = asGithubSingleUrl(htmlUrl);
+ kamelets.add(u);
+ } else if ("properties".equalsIgnoreCase(ext)) {
+ String htmlUrl = c.get("html_url").asText();
+ String u = asGithubSingleUrl(htmlUrl);
+ properties.add(u);
+ } else if ("java".equalsIgnoreCase(ext) || "xml".equalsIgnoreCase(ext) || "yaml".equalsIgnoreCase(ext)
+ || "groovy".equalsIgnoreCase(ext) || "js".equalsIgnoreCase(ext) || "jsh".equalsIgnoreCase(ext)
+ || "kts".equalsIgnoreCase(ext)) {
+ String htmlUrl = c.get("html_url").asText();
+ String u = asGithubSingleUrl(htmlUrl);
+ files.add(u);
+ }
+ }
+ }
+ }
+ }
+
}