This is an automated email from the ASF dual-hosted git repository.

Croway 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 8e285fd0fa9f CAMEL-26644: Normalize file component path separators for 
getFile/directory consistency (#29250)
8e285fd0fa9f is described below

commit 8e285fd0fa9f96ef876e9a6ab042831786768665
Author: Salvatore Mongiardo <[email protected]>
AuthorDate: Thu Nov 5 19:22:13 2026 +0100

    CAMEL-26644: Normalize file component path separators for getFile/directory 
consistency (#29250)
    
    On Linux/macOS, a backslash in the file: URI path (e.g. file:target\subdir)
    was preserved by getFile() but normalized to / by 
getConfiguration().getDirectory(),
    causing the producer to create a spurious backslash-named directory and the 
consumer
    to miss files. Apply FileUtil.normalizePath(remaining) in 
FileComponent.buildFileEndpoint()
    so getFile().getPath() and getDirectory() return consistent values on all 
platforms.
---
 .../apache/camel/component/file/FileComponent.java |  2 +
 .../file/FileComponentPathSeparatorTest.java       | 86 ++++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  9 +++
 3 files changed, 97 insertions(+)

diff --git 
a/components/camel-file/src/main/java/org/apache/camel/component/file/FileComponent.java
 
b/components/camel-file/src/main/java/org/apache/camel/component/file/FileComponent.java
index 67df9131f7c0..c002a75729f3 100644
--- 
a/components/camel-file/src/main/java/org/apache/camel/component/file/FileComponent.java
+++ 
b/components/camel-file/src/main/java/org/apache/camel/component/file/FileComponent.java
@@ -57,6 +57,8 @@ public class FileComponent extends GenericFileComponent<File> 
{
                                                + " Use the fileName option to 
set the dynamic expression.");
         }
 
+        remaining = FileUtil.normalizePath(remaining);
+
         File file = new File(remaining);
 
         FileEndpoint result = new FileEndpoint(uri, this);
diff --git 
a/components/camel-file/src/test/java/org/apache/camel/component/file/FileComponentPathSeparatorTest.java
 
b/components/camel-file/src/test/java/org/apache/camel/component/file/FileComponentPathSeparatorTest.java
new file mode 100644
index 000000000000..1a9c0bb0fe18
--- /dev/null
+++ 
b/components/camel-file/src/test/java/org/apache/camel/component/file/FileComponentPathSeparatorTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.file;
+
+import java.util.HashMap;
+
+import org.apache.camel.util.FileUtil;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class FileComponentPathSeparatorTest {
+
+    @Test
+    public void shouldNormalizeBackslashesInAbsolutePath() throws Exception {
+        FileComponent component = new FileComponent();
+        FileEndpoint endpoint = (FileEndpoint) component.buildFileEndpoint(
+                "file:C:\\Users\\test\\target", "C:\\Users\\test\\target", new 
HashMap<>());
+
+        String directory = endpoint.getConfiguration().getDirectory();
+        String filePath = endpoint.getFile().getPath();
+
+        String expected = FileUtil.normalizePath("C:/Users/test/target");
+        assertEquals(expected, directory);
+        assertEquals(expected, filePath);
+    }
+
+    @Test
+    public void shouldNormalizeBackslashesInRelativePath() throws Exception {
+        FileComponent component = new FileComponent();
+        FileEndpoint endpoint = (FileEndpoint) component.buildFileEndpoint(
+                "file:target\\subdir", "target\\subdir", new HashMap<>());
+
+        String directory = endpoint.getConfiguration().getDirectory();
+        String filePath = endpoint.getFile().getPath();
+
+        String expected = FileUtil.normalizePath("target/subdir");
+        assertEquals(expected, directory);
+        assertEquals(expected, filePath);
+    }
+
+    @Test
+    @DisabledOnOs(OS.WINDOWS)
+    public void shouldPreserveForwardSlashPaths() throws Exception {
+        FileComponent component = new FileComponent();
+        FileEndpoint endpoint = (FileEndpoint) component.buildFileEndpoint(
+                "file:/home/user/target", "/home/user/target", new 
HashMap<>());
+
+        String directory = endpoint.getConfiguration().getDirectory();
+        String filePath = endpoint.getFile().getPath();
+
+        String expected = FileUtil.normalizePath("/home/user/target");
+        assertEquals(expected, directory);
+        assertEquals(expected, filePath);
+    }
+
+    @Test
+    @DisabledOnOs(OS.WINDOWS)
+    public void shouldNormalizePosixBackslashOnNonWindows() throws Exception {
+        FileComponent component = new FileComponent();
+        FileEndpoint endpoint = (FileEndpoint) component.buildFileEndpoint(
+                "file:/tmp/a\\b", "/tmp/a\\b", new HashMap<>());
+
+        String directory = endpoint.getConfiguration().getDirectory();
+        String filePath = endpoint.getFile().getPath();
+
+        assertEquals("/tmp/a/b", directory);
+        assertEquals("/tmp/a/b", filePath);
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 9a115537a237..8d76abb015b2 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -1618,6 +1618,15 @@ as soon as the encoding changed a byte, a body read with 
another charset (such a
 characters. The checksum is now calculated from the bytes written to the file, 
and the body is decoded as it is
 without `checksumFileAlgorithm`. Checksums of such files differ from the ones 
written before.
 
+=== camel-file - path separator normalization for getFile/directory consistency
+
+On Linux and macOS, a backslash in the `file:` URI path (e.g. 
`file:target\subdir`) is now normalized
+to a forward slash, so that `getFile().getPath()` and 
`getConfiguration().getDirectory()` return the
+same value. Previously, `getFile()` preserved the backslash while 
`getDirectory()` replaced it with `/`,
+which could cause the producer to create a spurious directory with a backslash 
in its name and the
+consumer to miss files in a backslash-named directory. On Windows, where 
`java.io.File` already
+normalizes both separators to `\`, this change has no effect.
+
 === camel-flatpack - with splitRows each message has its own row, and a 
failing row fails the producer
 
 With `splitRows=true` (the default), every row message shared the one parsed 
`DataSet`, so the next row moved the row

Reply via email to