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() {