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 05887701aa5 Jb agent (#11953)
05887701aa5 is described below

commit 05887701aa56f0442d6b5797f1ccba735bd64477
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Nov 9 12:43:24 2023 +0100

    Jb agent (#11953)
    
    * CAMEL-20082: camel-jbang - Export to support javaagents
    
    * CAMEL-20033: camel-jbang - Write to settings properties file using JDK 
Properties code that escapes key and value so it works on Windows.
    
    * CAMEL-20082: camel-jbang - Export to support javaagents
---
 .../modules/ROOT/pages/camel-jbang.adoc            | 32 ++++++++++++++
 .../dsl/jbang/core/commands/ExportBaseCommand.java | 51 ++++++++++++++++++++++
 .../dsl/jbang/core/commands/ExportCamelMain.java   |  3 ++
 .../camel/dsl/jbang/core/common/RuntimeUtil.java   | 22 ++++++----
 .../org/apache/camel/tooling/maven/MavenGav.java   |  4 ++
 .../apache/camel/tooling/maven/MavenGavTest.java   | 10 +++++
 6 files changed, 114 insertions(+), 8 deletions(-)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 33d49016bcb..a76df70f438 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -2510,6 +2510,38 @@ Will let Camel JBang export this into as 
`src/main/jkube/configmap.yaml`.
 
 You can find more information about resource fragments at the 
https://eclipse.dev/jkube/docs/kubernetes-maven-plugin/#_resource_fragments[Eclipse
 JKube] website.
 
+==== Exporting with Java Agent included
+
+The Camel Main runtime allows to export with Java Agents that makes it easier 
to run your Camel integration
+with Java Agents such as OpenTelemetry Agent.
+
+NOTE: Only `camel-main` as runtime supports exporting with Java Agents 
included.
+
+This requires to specify the agent as a dependency with `agent:` as prefix as 
shown below in `application.properties`:
+
+[source,properties]
+----
+camel.jbang.dependencies=camel:opentelemetry,agent:io.opentelemetry.javaagent:opentelemetry-javaagent:1.31.0
+camel.opentelemetry.enabled=true
+----
+
+Then you can export to `--runtime=camel-main` as follows:
+
+[source,bash]
+----
+camel export --runtime=camel-main --gav=com.foo:acme:1.0-SNAPSHOT 
--directory=../myproject
+----
+
+Then Camel JBang will detect the `agent:` dependency and download this from 
Maven and save to a `../myproject/agent` folder.
+You can then start the Camel integration from Java via:
+
+[source,bash]
+----
+cd ../myproject
+mvn clean package
+java -javaagent:agent/opentelemetry-javaagent-1.31.0.jar -jar 
target/acme-1.0-SNAPSHOT.jar
+----
+
 === Exporting with selected files
 
 By default, Camel will export what was last run, or all files from the current 
directory.
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index dbf055cc107..fcadf188cb0 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -48,7 +49,11 @@ import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.dsl.jbang.core.common.RuntimeCompletionCandidates;
 import org.apache.camel.dsl.jbang.core.common.RuntimeUtil;
 import org.apache.camel.dsl.jbang.core.common.VersionHelper;
+import org.apache.camel.tooling.maven.MavenArtifact;
+import org.apache.camel.tooling.maven.MavenDownloader;
+import org.apache.camel.tooling.maven.MavenDownloaderImpl;
 import org.apache.camel.tooling.maven.MavenGav;
+import org.apache.camel.tooling.maven.MavenResolutionException;
 import org.apache.camel.util.CamelCaseOrderedProperties;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
@@ -71,6 +76,10 @@ abstract class ExportBaseCommand extends CamelCommand {
     private static final Pattern PACKAGE_PATTERN = Pattern.compile(
             "^\\s*package\\s+([a-zA-Z][.\\w]*)\\s*;.*$", Pattern.MULTILINE);
 
+    private static final Set<String> EXCLUDED_GROUP_IDS = 
Set.of("org.fusesource.jansi", "org.apache.logging.log4j");
+
+    private MavenDownloader downloader;
+
     @CommandLine.Parameters(description = "The Camel file(s) to export. If no 
files is specified then what was last run will be exported.",
                             arity = "0..9", paramLabel = "<files>", 
parameterConsumer = FilesConsumer.class)
     protected Path[] filePaths; // Defined only for file path completion; the 
field never used
@@ -810,6 +819,48 @@ abstract class ExportBaseCommand extends CamelCommand {
         }
     }
 
+    protected void copyAgentDependencies(Set<String> deps) throws Exception {
+        for (String d : deps) {
+            if (d.startsWith("agent:")) {
+                File libDir = new File(BUILD_DIR, "agent");
+                libDir.mkdirs();
+                String n = d.substring(6);
+                MavenGav gav = MavenGav.parseGav(n);
+                copyAgentLibDependencies(gav);
+            }
+        }
+    }
+
+    private void copyAgentLibDependencies(MavenGav gav) {
+        try {
+            List<MavenArtifact> artifacts = getDownloader().resolveArtifacts(
+                    List.of(gav.toString()), Set.of(), true, 
gav.getVersion().contains("SNAPSHOT"));
+            for (MavenArtifact artifact : artifacts) {
+                Path target = Paths.get(BUILD_DIR, "agent", 
artifact.getFile().getName());
+                if (Files.exists(target) || 
EXCLUDED_GROUP_IDS.contains(artifact.getGav().getGroupId())) {
+                    continue;
+                }
+                Files.copy(artifact.getFile().toPath(), target);
+            }
+        } catch (MavenResolutionException e) {
+            System.err.println("Error resolving the artifact: " + gav + " due 
to: " + e.getMessage());
+        } catch (IOException e) {
+            System.err.println("Error copying the artifact: " + gav + " due 
to: " + e.getMessage());
+        }
+    }
+
+    private MavenDownloader getDownloader() {
+        if (downloader == null) {
+            init();
+        }
+        return downloader;
+    }
+
+    private void init() {
+        this.downloader = new MavenDownloaderImpl();
+        ((MavenDownloaderImpl) downloader).build();
+    }
+
     static class FilesConsumer extends ParameterConsumer<Export> {
         @Override
         protected void doConsumeParameters(Stack<String> args, Export cmd) {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
index bb9110b3ff0..e39290f0f9a 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
@@ -130,6 +130,9 @@ class ExportCamelMain extends Export {
         Set<String> deps = resolveDependencies(settings, profile);
         // copy local lib JARs
         copyLocalLibDependencies(deps);
+        // copy agent JARs and remove as dependency
+        copyAgentDependencies(deps);
+        deps.removeIf(d -> d.startsWith("agent:"));
         if ("maven".equals(buildTool)) {
             createMavenPom(settings, profile, new File(BUILD_DIR, "pom.xml"), 
deps, srcPackageName);
             if (mavenWrapper) {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
index 97d985590b6..834acfb682e 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
@@ -19,6 +19,8 @@ package org.apache.camel.dsl.jbang.core.common;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -99,17 +101,21 @@ public final class RuntimeUtil {
     }
 
     public static List<String> loadPropertiesLines(File file) throws 
IOException {
-        List<String> lines = new ArrayList<>();
         if (!file.exists()) {
-            return lines;
+            return new ArrayList<>();
         }
 
-        Properties prop = new OrderedProperties();
-        loadProperties(prop, file);
-        for (String k : prop.stringPropertyNames()) {
-            String v = prop.getProperty(k);
-            if (v != null) {
-                lines.add(k + "=" + v);
+        List<String> lines = new ArrayList<>();
+        for (String line : Files.readAllLines(file.toPath())) {
+            // need to use java.util.Properties to read raw value and un-escape
+            Properties prop = new OrderedProperties();
+            prop.load(new StringReader(line));
+
+            for (String key : prop.stringPropertyNames()) {
+                String value = prop.getProperty(key);
+                if (value != null) {
+                    lines.add(key + "=" + value);
+                }
             }
         }
         return lines;
diff --git 
a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenGav.java
 
b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenGav.java
index 3e0127b0c9d..1fe0be511be 100644
--- 
a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenGav.java
+++ 
b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenGav.java
@@ -97,6 +97,10 @@ public final class MavenGav {
             } else if (defaultVersion != null) {
                 answer.setVersion(defaultVersion);
             }
+        } else if (gav.startsWith("agent:")) {
+            // special for java agent JARs
+            answer = parseGav(gav.substring(6));
+            answer.setPackaging("agent");
         } else {
             // for those used to OSGi's pax-url-aether syntax
             String[] parts = gav.startsWith("mvn:") ? 
gav.substring(4).split(":") : gav.split(":");
diff --git 
a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenGavTest.java
 
b/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenGavTest.java
index 7ead04cc8c6..aaa02a45151 100644
--- 
a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenGavTest.java
+++ 
b/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenGavTest.java
@@ -49,4 +49,14 @@ class MavenGavTest {
         assertEquals("junit-api", gav.getArtifactId());
         assertEquals("99.99", gav.getVersion());
     }
+
+    @Test
+    void parseAgentGav() {
+        MavenGav gav = 
MavenGav.parseGav("agent:io.opentelemetry.javaagent:opentelemetry-javaagent:1.31.0");
+
+        assertEquals("io.opentelemetry.javaagent", gav.getGroupId());
+        assertEquals("opentelemetry-javaagent", gav.getArtifactId());
+        assertEquals("1.31.0", gav.getVersion());
+        assertEquals("agent", gav.getPackaging());
+    }
 }

Reply via email to