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 46f4a505525e CAMEL-25374: camel-jbang - quote characters in a file 
include/exclude value are reported with the line to write (#27427)
46f4a505525e is described below

commit 46f4a505525e0c5812b6aef336583794d83778ee
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Oct 6 11:23:36 2026 +0200

    CAMEL-25374: camel-jbang - quote characters in a file include/exclude value 
are reported with the line to write (#27427)
    
    Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../dsl/jbang/core/commands/ai/EndpointChecks.java | 40 ++++++++++++++++++++++
 .../commands/ai/SourceValidatorEndpointTest.java   | 24 +++++++++++++
 2 files changed, 64 insertions(+)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
index c63fcc273709..c6ef07caacc7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
@@ -367,6 +367,17 @@ final class EndpointChecks {
             if (!name.equals("include") && !name.equals("exclude") || 
value.startsWith("{{")) {
                 continue;
             }
+            String unquoted = withoutQuoteCharacters(value);
+            if (!unquoted.equals(value)) {
+                // \".*\\.json\" written as a plain YAML value: a backslash 
before a quote is not YAML escaping, so the
+                // quotes and backslashes are part of the regex and no file 
matches (CAMEL-25374)
+                errors.add(linePrefix(optionLineMap.getOrDefault(name, 
uriLineIdx)) + fullUri.substring(0, colon) + ": "
+                           + name + " has quote characters in its value (" + 
value + "): in YAML a backslash before a"
+                           + " quote is text, not escaping, and the quotes 
become part of the regex. Write the line as "
+                           + name + ": '" + unquoted.replace("\\\\", "\\") + 
"' (single quotes, one backslash before"
+                           + " the dot)");
+                continue;
+            }
             if (DOUBLED_BACKSLASH_ESCAPE.matcher(value).find()) {
                 // '.*\\.json$' in single quotes: YAML keeps both backslashes, 
and in a regex \\ is one literal
                 // backslash, so the pattern matches a file name with a 
backslash in it: no file matches and the route
@@ -388,6 +399,35 @@ final class EndpointChecks {
         }
     }
 
+    /**
+     * The value without the quote characters (" or ', with or without a 
backslash before them) at its ends, which a
+     * regex of a file name never has there; the value itself when it has none.
+     */
+    static String withoutQuoteCharacters(String value) {
+        // a backslash-quote first, so \" is taken as one piece
+        String[] quotes = { "\\\"", "\\'", "\"", "'" };
+        String v = value;
+        boolean changed = true;
+        while (changed && !v.isEmpty()) {
+            changed = false;
+            for (String q : quotes) {
+                if (v.startsWith(q)) {
+                    v = v.substring(q.length());
+                    changed = true;
+                    break;
+                }
+            }
+            for (String q : quotes) {
+                if (v.endsWith(q)) {
+                    v = v.substring(0, v.length() - q.length());
+                    changed = true;
+                    break;
+                }
+            }
+        }
+        return v;
+    }
+
     /**
      * file:archived/${header.monthDir} on a to: fails at startup: the 
directory of a file endpoint cannot be dynamic
      * (the runtime says "Dynamic expressions with ${ } placeholders is not 
allowed. Use the fileName option"). Says to
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorEndpointTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorEndpointTest.java
index 88e23e0c18f6..d0c9c9346bf4 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorEndpointTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorEndpointTest.java
@@ -593,6 +593,30 @@ class SourceValidatorEndpointTest {
                 .anyMatch(e -> e.startsWith("Line 3: file: the directory 
archived/${header.monthDir} cannot be dynamic"));
     }
 
+    /**
+     * CAMEL-25374: quotes escaped with a backslash in a plain YAML value are 
text, so they are part of the regex. The
+     * hint gives the line to write, without echoing the stray quotes back.
+     */
+    @Test
+    void quoteCharactersInAnIncludeRegexAreReported() {
+        String yaml = """
+                - route:
+                    from:
+                      uri: file:inbox
+                      parameters:
+                        include: \\".*\\\\.json\\"
+                      steps:
+                        - to:
+                            uri: log:done
+                """;
+        List<String> errors = SourceValidator.validateYamlEndpoints(yaml, 
catalog);
+        assertThat(errors).anyMatch(e -> e.startsWith("Line 5: file: include 
has quote characters in its value")
+                && e.contains("Write the line as include: '.*\\.json'"));
+        assertThat(errors).noneMatch(e -> e.contains("matches a literal 
backslash"));
+        
assertThat(EndpointChecks.withoutQuoteCharacters("'.*\\.json'")).isEqualTo(".*\\.json");
+        
assertThat(EndpointChecks.withoutQuoteCharacters(".*\\.json")).isEqualTo(".*\\.json");
+    }
+
     /** CAMEL-24854: a doubled backslash in an include regex (kept as is 
inside single quotes) matches no file. */
     @Test
     void aDoubledBackslashInAnIncludeRegexIsReported() {

Reply via email to