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 2010/11/25 17:32:35 UTC

svn commit: r1039088 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/component/file/ camel-core/src/main/java/org/apache/camel/util/ camel-core/src/test/java/org/apache/camel/util/ components/camel-ftp/src/main/java/org/apache/camel/compon...

Author: davsclaus
Date: Thu Nov 25 16:32:34 2010
New Revision: 1039088

URL: http://svn.apache.org/viewvc?rev=1039088&view=rev
Log:
CAMEL-3359: Added separator option to ftp producer to dictate what path separator to use when uploading files.

Added:
    camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest.java
      - copied, changed from r1039026, camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathNoStepwiseTest.java
    camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest.java
    camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/FileUtil.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/util/FileUtilTest.java
    camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java
    camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
    camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
    camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/UriConfigurationTest.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/file/GenericFileProducer.java Thu Nov 25 16:32:34 2010
@@ -199,8 +199,11 @@ public class GenericFileProducer<T> exte
     public void writeFile(Exchange exchange, String fileName) throws GenericFileOperationFailedException {
         // build directory if auto create is enabled
         if (endpoint.isAutoCreate()) {
+            // we must normalize it (to avoid having both \ and / in the name which confuses java.io.File)
+            String name = FileUtil.normalizePath(fileName);
+
             // use java.io.File to compute the file path
-            File file = new File(fileName);
+            File file = new File(name);
             String directory = file.getParent();
             boolean absolute = FileUtil.isAbsolute(file);
             if (directory != null) {
@@ -277,8 +280,10 @@ public class GenericFileProducer<T> exte
             answer = baseDir + endpoint.getGeneratedFileName(exchange.getIn());
         }
 
-        // must normalize path to cater for Windows and other OS
-        answer = normalizePath(answer);
+        if (endpoint.getConfiguration().needToNormalize()) {
+            // must normalize path to cater for Windows and other OS
+            answer = normalizePath(answer);
+        }
 
         return answer;
     }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/FileUtil.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/FileUtil.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/FileUtil.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/FileUtil.java Thu Nov 25 16:32:34 2010
@@ -42,9 +42,12 @@ public final class FileUtil {
      * Normalizes the path to cater for Windows and other platforms
      */
     public static String normalizePath(String path) {
-        // special handling for Windows where we need to convert / to \\
         if (path != null && isWindows() && path.indexOf('/') >= 0) {
+            // special handling for Windows where we need to convert / to \\
             return path.replace('/', '\\');
+        } else if (path != null && path.indexOf('\\') >= 0) {
+            // for other systems make sure we use / as separators
+            return path.replace('\\', '/');
         }
         return path;
     }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/FileUtilTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/FileUtilTest.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/util/FileUtilTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/FileUtilTest.java Thu Nov 25 16:32:34 2010
@@ -28,8 +28,10 @@ public class FileUtilTest extends TestCa
     public void testNormalizePath() {
         if (FileUtil.isWindows()) {
             assertEquals("foo\\bar", FileUtil.normalizePath("foo/bar"));
+            assertEquals("foo\\bar\\baz", FileUtil.normalizePath("foo/bar\\baz"));
         } else {
             assertEquals("foo/bar", FileUtil.normalizePath("foo/bar"));
+            assertEquals("foo/bar/baz", FileUtil.normalizePath("foo/bar\\baz"));
         }
     }
 

Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpOperations.java Thu Nov 25 16:32:34 2010
@@ -433,6 +433,9 @@ public class FtpOperations implements Re
     }
 
     public boolean storeFile(String name, Exchange exchange) throws GenericFileOperationFailedException {
+        // must normalize name first
+        name = endpoint.getConfiguration().normalizePath(name);
+
         if (log.isTraceEnabled()) {
             log.trace("storeFile(" + name + ")");
         }

Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java Thu Nov 25 16:32:34 2010
@@ -25,6 +25,16 @@ import org.apache.camel.util.ObjectHelpe
  * Configuration of the FTP server
  */
 public abstract class RemoteFileConfiguration extends GenericFileConfiguration {
+
+    /**
+     * Path separator as either unix or windows style.
+     * <p/>
+     * UNIX = Path separator / is used
+     * Windows = Path separator \ is used
+     * Auto = Use existing path separator in file name
+     */
+    public enum PathSeparator { UNIX, Windows, Auto };
+
     private String protocol;
     private String username;
     private String host;
@@ -38,6 +48,7 @@ public abstract class RemoteFileConfigur
     private boolean throwExceptionOnConnectFailed;
     private String siteCommand;
     private boolean stepwise = true;
+    private PathSeparator separator = PathSeparator.Auto;
 
     public RemoteFileConfiguration() {
     }
@@ -234,4 +245,39 @@ public abstract class RemoteFileConfigur
     public void setStepwise(boolean stepwise) {
         this.stepwise = stepwise;
     }
+
+    public PathSeparator getSeparator() {
+        return separator;
+    }
+
+    /**
+     * Sets the path separator to be used.
+     * <p/>
+     * UNIX = Path separator / is used
+     * Windows = Path separator \ is used
+     * Auto = (is default) Use existing path separator in file name
+     */
+    public void setSeparator(PathSeparator separator) {
+        this.separator = separator;
+    }
+
+    /**
+     * Normalizes the given path according to the configured path separator.
+     *
+     * @param path  the given path
+     * @return the normalized path
+     */
+    public String normalizePath(String path) {
+        if (ObjectHelper.isEmpty(path) || separator == PathSeparator.Auto) {
+            return path;
+        }
+
+        if (separator == PathSeparator.UNIX) {
+            // unix style
+            return path.replace('\\', '/');
+        } else {
+            // windows style
+            return path.replace('/', '\\');
+        }
+    }
 }

Modified: camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java (original)
+++ camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpOperations.java Thu Nov 25 16:32:34 2010
@@ -606,6 +606,9 @@ public class SftpOperations implements R
     }
 
     public boolean storeFile(String name, Exchange exchange) throws GenericFileOperationFailedException {
+        // must normalize name first
+        name = endpoint.getConfiguration().normalizePath(name);
+
         if (LOG.isTraceEnabled()) {
             LOG.trace("storeFile(" + name + ")");
         }

Copied: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest.java (from r1039026, camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathNoStepwiseTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest.java?p2=camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest.java&p1=camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathNoStepwiseTest.java&r1=1039026&r2=1039088&rev=1039088&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathNoStepwiseTest.java (original)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest.java Thu Nov 25 16:32:34 2010
@@ -18,22 +18,33 @@ package org.apache.camel.component.file.
 
 import java.io.File;
 
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
 import org.apache.camel.converter.IOConverter;
 import org.junit.Test;
 
-public class FtpProducerFileWithPathNoStepwiseTest extends FtpServerTestSupport {
+public class FtpProducerFileWithPathPathSeparatorAutoNoStepwiseTest extends FtpServerTestSupport {
 
     private String getFtpUrl() {
-        return "ftp://admin@localhost:" + getPort() + "/upload?password=admin&stepwise=false";
+        return "ftp://admin@localhost:" + getPort() + "/upload?password=admin&stepwise=false&separator=Auto";
     }
 
     @Test
     public void testProducerFileWithPathNoStepwise() throws Exception {
-        sendFile(getFtpUrl(), "Hello World", "hello/claus.txt");
+        Exchange out = template.send(getFtpUrl(), new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Hello World");
+                exchange.getIn().setHeader(Exchange.FILE_NAME, "hello/claus.txt");
+            }
+        });
+        assertNotNull(out);
 
         File file = new File(FTP_ROOT_DIR + "upload/hello/claus.txt");
         file = file.getAbsoluteFile();
         assertTrue("The uploaded file should exists", file.exists());
         assertEquals("Hello World", IOConverter.toString(file, null));
+
+        assertEquals("upload/hello/claus.txt", out.getIn().getHeader(Exchange.FILE_NAME_PRODUCED));
     }
+
 }
\ No newline at end of file

Added: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest.java?rev=1039088&view=auto
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest.java (added)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest.java Thu Nov 25 16:32:34 2010
@@ -0,0 +1,50 @@
+/**
+ * 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.remote;
+
+import java.io.File;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.converter.IOConverter;
+import org.junit.Test;
+
+public class FtpProducerFileWithPathPathSeparatorUnixNoStepwiseTest extends FtpServerTestSupport {
+
+    private String getFtpUrl() {
+        return "ftp://admin@localhost:" + getPort() + "/upload?password=admin&stepwise=false&separator=UNIX";
+    }
+
+    @Test
+    public void testProducerFileWithPathNoStepwise() throws Exception {
+        Exchange out = template.send(getFtpUrl(), new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Hello World");
+                exchange.getIn().setHeader(Exchange.FILE_NAME, "hello\\claus.txt");
+            }
+        });
+        assertNotNull(out);
+
+        File file = new File(FTP_ROOT_DIR + "upload/hello/claus.txt");
+        file = file.getAbsoluteFile();
+        assertTrue("The uploaded file should exists", file.exists());
+        assertEquals("Hello World", IOConverter.toString(file, null));
+
+        assertEquals("upload/hello\\claus.txt", out.getIn().getHeader(Exchange.FILE_NAME_PRODUCED));
+    }
+
+}
\ No newline at end of file

Added: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest.java?rev=1039088&view=auto
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest.java (added)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest.java Thu Nov 25 16:32:34 2010
@@ -0,0 +1,50 @@
+/**
+ * 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.remote;
+
+import java.io.File;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.converter.IOConverter;
+import org.junit.Test;
+
+public class FtpProducerFileWithPathPathSeparatorWindowsNoStepwiseTest extends FtpServerTestSupport {
+
+    private String getFtpUrl() {
+        return "ftp://admin@localhost:" + getPort() + "/upload?password=admin&stepwise=false&separator=Windows";
+    }
+
+    @Test
+    public void testProducerFileWithPathNoStepwise() throws Exception {
+        Exchange out = template.send(getFtpUrl(), new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Hello World");
+                exchange.getIn().setHeader(Exchange.FILE_NAME, "hello/claus.txt");
+            }
+        });
+        assertNotNull(out);
+
+        File file = new File(FTP_ROOT_DIR + "upload/hello/claus.txt");
+        file = file.getAbsoluteFile();
+        assertTrue("The uploaded file should exists", file.exists());
+        assertEquals("Hello World", IOConverter.toString(file, null));
+
+        assertEquals("upload/hello/claus.txt", out.getIn().getHeader(Exchange.FILE_NAME_PRODUCED));
+    }
+
+}
\ No newline at end of file

Modified: camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/UriConfigurationTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/UriConfigurationTest.java?rev=1039088&r1=1039087&r2=1039088&view=diff
==============================================================================
--- camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/UriConfigurationTest.java (original)
+++ camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/UriConfigurationTest.java Thu Nov 25 16:32:34 2010
@@ -32,7 +32,7 @@ public class UriConfigurationTest extend
         Endpoint endpoint = context.getEndpoint("ftp://hostname");
         assertIsInstanceOf(FtpEndpoint.class, endpoint);
         FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
-        RemoteFileConfiguration config = (RemoteFileConfiguration) ftpEndpoint.getConfiguration();
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
 
         assertEquals("ftp", config.getProtocol());
         assertEquals("hostname", config.getHost());
@@ -40,6 +40,7 @@ public class UriConfigurationTest extend
         assertNull(config.getUsername());
         assertNull(config.getPassword());
         assertEquals(false, config.isBinary());
+        assertEquals(RemoteFileConfiguration.PathSeparator.Auto, config.getSeparator());
     }
 
     @Test
@@ -47,7 +48,7 @@ public class UriConfigurationTest extend
         Endpoint endpoint = context.getEndpoint("sftp://hostname");
         assertIsInstanceOf(SftpEndpoint.class, endpoint);
         SftpEndpoint sftpEndpoint = (SftpEndpoint) endpoint;
-        RemoteFileConfiguration config = (RemoteFileConfiguration) sftpEndpoint.getConfiguration();
+        RemoteFileConfiguration config = sftpEndpoint.getConfiguration();
 
         assertEquals("sftp", config.getProtocol());
         assertEquals("hostname", config.getHost());
@@ -55,6 +56,7 @@ public class UriConfigurationTest extend
         assertNull(config.getUsername());
         assertNull(config.getPassword());
         assertEquals(false, config.isBinary());
+        assertEquals(RemoteFileConfiguration.PathSeparator.Auto, config.getSeparator());
     }
     
     @Test
@@ -72,6 +74,7 @@ public class UriConfigurationTest extend
         assertEquals(false, config.isBinary());
         assertEquals(false, config.isImplicit());
         assertEquals("TLS", config.getSecurityProtocol());
+        assertEquals(RemoteFileConfiguration.PathSeparator.Auto, config.getSeparator());
     }
 
     @Test
@@ -96,7 +99,7 @@ public class UriConfigurationTest extend
         Endpoint endpoint = context.getEndpoint("ftp://user@hostname:1021/some/file?password=secret&binary=true");
         assertIsInstanceOf(FtpEndpoint.class, endpoint);
         FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
-        RemoteFileConfiguration config = (RemoteFileConfiguration) ftpEndpoint.getConfiguration();
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
 
         assertEquals("ftp", config.getProtocol());
         assertEquals("hostname", config.getHost());
@@ -111,7 +114,7 @@ public class UriConfigurationTest extend
         Endpoint endpoint = context.getEndpoint("sftp://user@hostname:1021/some/file?password=secret&binary=true");
         assertIsInstanceOf(SftpEndpoint.class, endpoint);
         SftpEndpoint sftpEndpoint = (SftpEndpoint) endpoint;
-        RemoteFileConfiguration config = (RemoteFileConfiguration) sftpEndpoint.getConfiguration();
+        RemoteFileConfiguration config = sftpEndpoint.getConfiguration();
 
         assertEquals("sftp", config.getProtocol());
         assertEquals("hostname", config.getHost());
@@ -202,7 +205,7 @@ public class UriConfigurationTest extend
         Endpoint endpoint = context.getEndpoint("ftp://user:secret@hostname:1021/some/file");
         assertIsInstanceOf(FtpEndpoint.class, endpoint);
         FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
-        RemoteFileConfiguration config = (RemoteFileConfiguration) ftpEndpoint.getConfiguration();
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
         
         assertEquals("ftp", config.getProtocol());
         assertEquals("hostname", config.getHost());
@@ -215,7 +218,7 @@ public class UriConfigurationTest extend
     public void testStartingDirectoryWithDot() throws Exception {
         Endpoint endpoint = context.getEndpoint("ftp://user@hostname?password=secret");
         FtpEndpoint ftpEndpoint = assertIsInstanceOf(FtpEndpoint.class, endpoint);
-        FtpConfiguration config = (FtpConfiguration) ftpEndpoint.getConfiguration();
+        FtpConfiguration config = ftpEndpoint.getConfiguration();
         config.setHost("somewhere");
         config.setDirectory("temp.dir");
         ftpEndpoint.createConsumer(new Processor() {
@@ -224,4 +227,53 @@ public class UriConfigurationTest extend
             }
         });
     }
+
+    @Test
+    public void testPathSeparatorAuto() {
+        Endpoint endpoint = context.getEndpoint("ftp://hostname/foo/bar?separator=Auto");
+        assertIsInstanceOf(FtpEndpoint.class, endpoint);
+        FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
+
+        assertEquals("ftp", config.getProtocol());
+        assertEquals("hostname", config.getHost());
+        assertEquals("foo/bar", config.getDirectory());
+        assertEquals(RemoteFileConfiguration.PathSeparator.Auto, config.getSeparator());
+
+        assertEquals("foo/bar/hello.txt", config.normalizePath("foo/bar/hello.txt"));
+        assertEquals("foo\\bar\\hello.txt", config.normalizePath("foo\\bar\\hello.txt"));
+    }
+
+    @Test
+    public void testPathSeparatorUnix() {
+        Endpoint endpoint = context.getEndpoint("ftp://hostname/foo/bar?separator=UNIX");
+        assertIsInstanceOf(FtpEndpoint.class, endpoint);
+        FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
+
+        assertEquals("ftp", config.getProtocol());
+        assertEquals("hostname", config.getHost());
+        assertEquals("foo/bar", config.getDirectory());
+        assertEquals(RemoteFileConfiguration.PathSeparator.UNIX, config.getSeparator());
+
+        assertEquals("foo/bar/hello.txt", config.normalizePath("foo/bar/hello.txt"));
+        assertEquals("foo/bar/hello.txt", config.normalizePath("foo\\bar\\hello.txt"));
+    }
+
+    @Test
+    public void testPathSeparatorWindows() {
+        Endpoint endpoint = context.getEndpoint("ftp://hostname/foo/bar?separator=Windows");
+        assertIsInstanceOf(FtpEndpoint.class, endpoint);
+        FtpEndpoint ftpEndpoint = (FtpEndpoint) endpoint;
+        RemoteFileConfiguration config = ftpEndpoint.getConfiguration();
+
+        assertEquals("ftp", config.getProtocol());
+        assertEquals("hostname", config.getHost());
+        assertEquals("foo/bar", config.getDirectory());
+        assertEquals(RemoteFileConfiguration.PathSeparator.Windows, config.getSeparator());
+
+        assertEquals("foo\\bar\\hello.txt", config.normalizePath("foo/bar/hello.txt"));
+        assertEquals("foo\\bar\\hello.txt", config.normalizePath("foo\\bar\\hello.txt"));
+    }
+
 }
\ No newline at end of file