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/11/11 12:31:25 UTC

[camel] 01/02: CAMEL-18712: camel-dsl-modeline - Make it possible to know if modeline can be parsed by a trait or not.

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 9be7a45d2cff4e38203f5309062a648359e9f40d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Nov 11 12:27:08 2022 +0100

    CAMEL-18712: camel-dsl-modeline - Make it possible to know if modeline can be parsed by a trait or not.
---
 .../camel/dsl/modeline/DefaultModelineFactory.java |  21 +++-
 ...elineParser.java => DefaultModelineParser.java} |  18 ++-
 .../apache/camel/dsl/modeline/ModelineParser.java  | 139 ++++++---------------
 .../apache/camel/dsl/jbang/core/commands/Run.java  |  10 ++
 .../java/org/apache/camel/main/KameletMain.java    |   6 +-
 .../camel/main/download/DependencyDownloader.java  |   8 ++
 .../main/download/DependencyDownloaderKamelet.java |   8 +-
 .../camel/main/download/DownloadListener.java      |   7 ++
 ...adListener.java => DownloadModelineParser.java} |  42 +++----
 .../main/download/MavenDependencyDownloader.java   |   8 ++
 10 files changed, 131 insertions(+), 136 deletions(-)

diff --git a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineFactory.java b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineFactory.java
index 2d7d8f75323..21c00fc06ce 100644
--- a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineFactory.java
+++ b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineFactory.java
@@ -28,6 +28,7 @@ import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.PropertiesSource;
 import org.apache.camel.spi.Resource;
 import org.apache.camel.spi.annotations.JdkService;
+import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.service.ServiceSupport;
 
 @JdkService(ModelineFactory.FACTORY)
@@ -50,12 +51,24 @@ public class DefaultModelineFactory extends ServiceSupport
     @Override
     public void parseModeline(Resource resource) throws Exception {
         List<CamelContextCustomizer> customizers = parser.parse(resource);
-        customizers.forEach(c -> c.configure(camelContext));
+        customizers.forEach(this::onConfigureModeline);
+    }
+
+    /**
+     * Configures the modeline via the {@link CamelContextCustomizer}
+     *
+     * @param customizer the customer for configuring a detected modeline
+     */
+    protected void onConfigureModeline(CamelContextCustomizer customizer) {
+        customizer.configure(camelContext);
     }
 
     @Override
     protected void doInit() throws Exception {
-        parser = new ModelineParser(camelContext);
+        parser = CamelContextHelper.findSingleByType(camelContext, ModelineParser.class);
+        if (parser == null) {
+            parser = createModelineParser();
+        }
 
         // the property is both a trait and a source but we must use the same instance
         // so we need to get the existing instance from the properties component to
@@ -67,6 +80,10 @@ public class DefaultModelineFactory extends ServiceSupport
         }
     }
 
+    protected ModelineParser createModelineParser() {
+        return new DefaultModelineParser(camelContext);
+    }
+
     @Override
     public String toString() {
         return "camel-dsl-modeline";
diff --git a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineParser.java
similarity index 89%
copy from dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java
copy to dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineParser.java
index 24a8b9065c0..d626c1da6f8 100644
--- a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java
+++ b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/DefaultModelineParser.java
@@ -29,14 +29,14 @@ import org.apache.camel.spi.Resource;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.StringQuoteHelper;
 
-public class ModelineParser {
+public class DefaultModelineParser implements ModelineParser {
 
     public static final String MODELINE_START = "camel-k:";
 
     private final CamelContext camelContext;
     private final Map<String, Trait> traits = new HashMap<>();
 
-    public ModelineParser(CamelContext camelContext) {
+    public DefaultModelineParser(CamelContext camelContext) {
         this.camelContext = camelContext;
 
         // add known traits
@@ -49,10 +49,12 @@ public class ModelineParser {
         this.traits.put(trait.getName(), trait);
     }
 
+    @Override
     public void addTrait(Trait trait) {
         this.traits.put(trait.getName(), trait);
     }
 
+    @Override
     public List<CamelContextCustomizer> parse(Resource resource) throws Exception {
         List<CamelContextCustomizer> answer = new ArrayList<>();
 
@@ -84,9 +86,9 @@ public class ModelineParser {
             String[] parts = StringQuoteHelper.splitSafeQuote(line, ' ', false);
             for (String part : parts) {
                 part = part.trim();
-                String name = StringHelper.before(part, "=");
+                String key = StringHelper.before(part, "=");
                 String value = StringHelper.after(part, "=");
-                Trait trait = traits.get(name);
+                Trait trait = parseModeline(resource, key, value);
                 if (trait != null) {
                     CamelContextCustomizer customizer = trait.parseTrait(resource, value);
                     if (customizer != null) {
@@ -99,7 +101,13 @@ public class ModelineParser {
         return answer;
     }
 
-    private static boolean isModeline(String line) {
+    @Override
+    public Trait parseModeline(Resource resource, String key, String value) {
+        return traits.get(key);
+    }
+
+    @Override
+    public boolean isModeline(String line) {
         // the line must be a comment and start with camel-k
         if (line == null) {
             return false;
diff --git a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java
index 24a8b9065c0..fb3e082d6bf 100644
--- a/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java
+++ b/dsl/camel-dsl-modeline/src/main/java/org/apache/camel/dsl/modeline/ModelineParser.java
@@ -16,110 +16,47 @@
  */
 package org.apache.camel.dsl.modeline;
 
-import java.io.LineNumberReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.Resource;
-import org.apache.camel.util.StringHelper;
-import org.apache.camel.util.StringQuoteHelper;
-
-public class ModelineParser {
-
-    public static final String MODELINE_START = "camel-k:";
-
-    private final CamelContext camelContext;
-    private final Map<String, Trait> traits = new HashMap<>();
-
-    public ModelineParser(CamelContext camelContext) {
-        this.camelContext = camelContext;
-
-        // add known traits
-        Trait trait = new DependencyTrait();
-        this.traits.put(trait.getName(), trait);
-        // property trait is added from the default mode line factory
-        trait = new NameTrait();
-        this.traits.put(trait.getName(), trait);
-        trait = new EnvTrait();
-        this.traits.put(trait.getName(), trait);
-    }
-
-    public void addTrait(Trait trait) {
-        this.traits.put(trait.getName(), trait);
-    }
-
-    public List<CamelContextCustomizer> parse(Resource resource) throws Exception {
-        List<CamelContextCustomizer> answer = new ArrayList<>();
-
-        if (resource.exists()) {
-            try (LineNumberReader reader = new LineNumberReader(resource.getReader())) {
-                String line = reader.readLine();
-                while (line != null) {
-                    List<CamelContextCustomizer> list = parse(resource, line);
-                    answer.addAll(list);
-                    line = reader.readLine();
-                }
-            }
-        }
-
-        return answer;
-    }
-
-    protected List<CamelContextCustomizer> parse(Resource resource, String line) {
-        if (!isModeline(line)) {
-            return Collections.emptyList();
-        }
-        line = removeLeadingComments(line);
-
-        List<CamelContextCustomizer> answer = new ArrayList<>();
-
-        if (line.startsWith(MODELINE_START)) {
-            line = line.substring(MODELINE_START.length()).trim();
-            // split into key value pairs
-            String[] parts = StringQuoteHelper.splitSafeQuote(line, ' ', false);
-            for (String part : parts) {
-                part = part.trim();
-                String name = StringHelper.before(part, "=");
-                String value = StringHelper.after(part, "=");
-                Trait trait = traits.get(name);
-                if (trait != null) {
-                    CamelContextCustomizer customizer = trait.parseTrait(resource, value);
-                    if (customizer != null) {
-                        answer.add(customizer);
-                    }
-                }
-            }
-        }
-
-        return answer;
-    }
-
-    private static boolean isModeline(String line) {
-        // the line must be a comment and start with camel-k
-        if (line == null) {
-            return false;
-        }
-        line = removeLeadingComments(line);
-        return line.startsWith(MODELINE_START);
-    }
-
-    private static String removeLeadingComments(String line) {
-        if (line == null) {
-            return null;
-        }
-
-        line = line.trim();
-        while (line.startsWith("/") || line.startsWith("#")) {
-            line = line.substring(1);
-        }
-
-        line = line.trim();
-        return line;
-    }
 
+/**
+ * Modeline parser
+ */
+public interface ModelineParser {
+
+    /**
+     * Adds the {@link Trait} to the parser
+     *
+     * @param trait the trait
+     */
+    void addTrait(Trait trait);
+
+    /**
+     * Is the given source code line a modeline?
+     *
+     * @param  line the source code line
+     * @return      <tt>true</tt> if modeline, <tt>false</tt> if not
+     */
+    boolean isModeline(String line);
+
+    /**
+     * Parses the resource to detect modelines and process them via {@link Trait}s
+     *
+     * @param  resource  the source code resource
+     * @return           list of {@link CamelContextCustomizer} customizers that processes the modelines
+     * @throws Exception is thrown if error during parsing
+     */
+    List<CamelContextCustomizer> parse(Resource resource) throws Exception;
+
+    /**
+     * A modeline was detected while parsing
+     *
+     * @param  resource the resource
+     * @param  key      the mode line key
+     * @param  value    the mode line value
+     * @return          the trait that handles the detected modeline
+     */
+    Trait parseModeline(Resource resource, String key, String value);
 }
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 63578d16e6a..59fec3a3f41 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
@@ -810,6 +810,7 @@ class Run extends CamelCommand {
     private class RunDownloadListener implements DownloadListener {
         final Set<String> downloaded = new HashSet<>();
         final Set<String> kamelets = new HashSet<>();
+        final Set<String> modelines = new HashSet<>();
 
         @Override
         public void onDownloadDependency(String groupId, String artifactId, String version) {
@@ -836,6 +837,15 @@ class Run extends CamelCommand {
                 kamelets.add(name);
             }
         }
+
+        @Override
+        public void onLoadingModeline(String key, String value) {
+            String line = key + "=" + value;
+            if (!modelines.contains(line)) {
+                writeSettings("modeline", line);
+                modelines.add(line);
+            }
+        }
     }
 
 }
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 29425efe780..9c31b64fba1 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -42,6 +42,7 @@ import org.apache.camel.main.download.DependencyDownloaderRoutesLoader;
 import org.apache.camel.main.download.DependencyDownloaderStrategy;
 import org.apache.camel.main.download.DependencyDownloaderUriFactoryResolver;
 import org.apache.camel.main.download.DownloadListener;
+import org.apache.camel.main.download.DownloadModelineParser;
 import org.apache.camel.main.download.KameletMainInjector;
 import org.apache.camel.main.download.KnownDependenciesResolver;
 import org.apache.camel.main.download.MavenDependencyDownloader;
@@ -426,8 +427,8 @@ public class KameletMain extends MainCommandLineSupport {
             known.loadKnownDependencies();
             DependencyDownloaderPropertyBindingListener listener
                     = new DependencyDownloaderPropertyBindingListener(answer, known);
-            answer.getRegistry().bind(DependencyDownloaderPropertyBindingListener.class.getName(), listener);
-            answer.getRegistry().bind(DependencyDownloaderStrategy.class.getName(),
+            answer.getRegistry().bind(DependencyDownloaderPropertyBindingListener.class.getSimpleName(), listener);
+            answer.getRegistry().bind(DependencyDownloaderStrategy.class.getSimpleName(),
                     new DependencyDownloaderStrategy(answer));
             answer.setClassResolver(new DependencyDownloaderClassResolver(answer, known));
             answer.setComponentResolver(new DependencyDownloaderComponentResolver(answer, stub));
@@ -437,6 +438,7 @@ public class KameletMain extends MainCommandLineSupport {
             answer.setResourceLoader(new DependencyDownloaderResourceLoader(answer));
             answer.setInjector(new KameletMainInjector(answer.getInjector(), stub));
             answer.addService(new DependencyDownloaderKamelet(answer));
+            answer.getRegistry().bind(DownloadModelineParser.class.getSimpleName(), new DownloadModelineParser(answer));
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeException(e);
         }
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 3c3bb7ef622..cce2e991f6e 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
@@ -127,4 +127,12 @@ public interface DependencyDownloader extends CamelContextAware, StaticService {
      */
     void onLoadingKamelet(String name);
 
+    /**
+     * When a modeline is being loaded
+     *
+     * @param key   modeline key
+     * @param value modeline value
+     */
+    void onLoadingModeline(String key, String value);
+
 }
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderKamelet.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderKamelet.java
index 2a51675e01f..6dadc4e80b7 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderKamelet.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderKamelet.java
@@ -154,7 +154,9 @@ public final class DependencyDownloaderKamelet extends ServiceSupport
         protected RouteBuilder builder(YamlDeserializationContext ctx, Node node) {
             Node name = nodeAt(node, "/metadata/name");
             String text = YamlDeserializerSupport.asText(name);
-            downloader.onLoadingKamelet(text);
+            if (downloader != null) {
+                downloader.onLoadingKamelet(text);
+            }
 
             final List<String> dependencies = new ArrayList<>();
             // always include kamelets-utils
@@ -175,7 +177,9 @@ public final class DependencyDownloaderKamelet extends ServiceSupport
                 }
             }
 
-            downloadDependencies(dependencies);
+            if (downloader != null) {
+                downloadDependencies(dependencies);
+            }
 
             // need to fool and return an empty route builder
             return new RouteBuilder() {
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java
index 482bd1b889f..d9707c31197 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java
@@ -45,4 +45,11 @@ public interface DownloadListener {
         // noop
     }
 
+    /**
+     * When a modeline is detected
+     */
+    default void onLoadingModeline(String key, String value) {
+        // noop
+    }
+
 }
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadModelineParser.java
similarity index 50%
copy from dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java
copy to dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadModelineParser.java
index 482bd1b889f..97555054790 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadListener.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DownloadModelineParser.java
@@ -16,33 +16,27 @@
  */
 package org.apache.camel.main.download;
 
-/**
- * Listener for downloading a dependency (can be downloaded from a local cache)
- */
-public interface DownloadListener {
-
-    /**
-     * Downloads a new dependency
-     */
-    void onDownloadDependency(String groupId, String artifactId, String version);
+import org.apache.camel.CamelContext;
+import org.apache.camel.dsl.modeline.DefaultModelineParser;
+import org.apache.camel.dsl.modeline.Trait;
+import org.apache.camel.spi.Resource;
 
-    /**
-     * After the dependency has been downloaded
-     */
-    default void onDownloadedDependency(String groupId, String artifactId, String version) {
-        // noop
-    }
+public class DownloadModelineParser extends DefaultModelineParser {
 
-    /**
-     * Uses an existing already downloaded dependency
-     */
-    void onAlreadyDownloadedDependency(String groupId, String artifactId, String version);
+    private final DependencyDownloader downloader;
 
-    /**
-     * When a kamelet is being downloaded (typically loaded directly from camel-kamelets JAR)
-     */
-    default void onLoadingKamelet(String name) {
-        // noop
+    public DownloadModelineParser(CamelContext camelContext) {
+        super(camelContext);
+        this.downloader = camelContext.hasService(DependencyDownloader.class);
     }
 
+    @Override
+    public Trait parseModeline(Resource resource, String key, String value) {
+        Trait answer = super.parseModeline(resource, key, value);
+        if (downloader != null && answer != null) {
+            // only trigger for modelines for traits that can parse
+            downloader.onLoadingModeline(key, value);
+        }
+        return answer;
+    }
 }
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 3a3d4699104..33d9841a97e 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
@@ -479,6 +479,14 @@ public class MavenDependencyDownloader extends ServiceSupport implements Depende
         }
     }
 
+    @Override
+    public void onLoadingModeline(String key, String value) {
+        // trigger listener
+        for (DownloadListener listener : downloadListeners) {
+            listener.onLoadingModeline(key, value);
+        }
+    }
+
     @Override
     protected void doBuild() throws Exception {
         if (classLoader == null && camelContext != null) {