Author: davsclaus
Date: Sat Jul 26 04:13:57 2008
New Revision: 679979

URL: http://svn.apache.org/viewvc?rev=679979&view=rev
Log:
CAMEL-758: SFTP and FTPProdcer - creating remote folders should handle existing 
folders

Added:
    
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
   (with props)
Modified:
    
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
    
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
    
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java

Modified: 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
--- 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
 (original)
+++ 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
 Sat Jul 26 04:13:57 2008
@@ -47,12 +47,12 @@
         } catch (FTPConnectionClosedException e) {
             // If the server disconnected us, then we must manually disconnect
             // the client before attempting to reconnect
-            LOG.warn("Disconnecting due to exception: " + e.toString());
+            LOG.warn("Disconnecting due to exception: " + e.getMessage());
             disconnect();
             // Rethrow to signify that we didn't deliver
             throw e;
         } catch (RuntimeCamelException e) {
-            LOG.warn("Caught RuntimeCamelException: " + e.toString());
+            LOG.warn("Caught RuntimeCamelException: " + e.getMessage(), e);
             LOG.warn("Hoping an explicit disconnect/reconnect will solve the 
problem");
             disconnect();
             // Rethrow to signify that we didn't deliver
@@ -61,40 +61,40 @@
     }
 
     protected void connectIfNecessary() throws IOException {
-        // TODO: is there a way to avoid copy-pasting the reconnect logic?
         if (!client.isConnected()) {
-            LOG.warn("FtpProducer's client isn't connected, trying to 
reconnect...");
+            LOG.debug("Not connected, trying to reconnect.");
             endpoint.connect(client);
-            LOG.info("Connected to " + endpoint.getConfiguration());
+            LOG.info("Connected to " + 
endpoint.getConfiguration().remoteServerInformation());
         }
     }
 
     public void disconnect() throws IOException {
-        LOG.info("FtpProducer's client is being explicitly disconnected");
+        LOG.debug("Disconnecting from " + 
endpoint.getConfiguration().remoteServerInformation());
         endpoint.disconnect(client);
     }
 
     public void process(RemoteFileExchange exchange) throws Exception {
         InputStream payload = exchange.getIn().getBody(InputStream.class);
         try {
+            String remoteServer = 
endpoint.getConfiguration().remoteServerInformation();
             String fileName = createFileName(exchange.getIn(), 
endpoint.getConfiguration());
 
             int lastPathIndex = fileName.lastIndexOf('/');
             if (lastPathIndex != -1) {
                 String directory = fileName.substring(0, lastPathIndex);
                 if (!buildDirectory(client, directory)) {
-                    LOG.warn("Couldn't build directory: " + directory + " 
(either permissions deny it, or it already exists)");
+                    LOG.warn("Couldn't build directory: " + directory + " 
(could be because of denied permissions)");
                 }
             }
 
-            final boolean success = client.storeFile(fileName, payload);
+            boolean success = client.storeFile(fileName, payload);
             if (!success) {
-                // TODO: Should we not have better exception for this?
-                throw new RuntimeCamelException("Error sending file: " + 
fileName);
+                throw new RuntimeCamelException("Error sending file: " + 
fileName + " to: " + remoteServer);
             }
 
-            RemoteFileConfiguration config = endpoint.getConfiguration();
-            LOG.info("Sent: " + fileName + " to " + 
config.toString().substring(0, config.toString().indexOf(config.getFile())));
+            if (LOG.isInfoEnabled()) {
+                LOG.info("Sent: " + fileName + " to: " + remoteServer);
+            }
         } finally {
             if (payload != null) {
                 payload.close();
@@ -108,7 +108,7 @@
         try {
             connectIfNecessary();
         } catch (IOException e) {
-            LOG.warn("Couldn't connect to " + endpoint.getConfiguration());
+            LOG.warn("Couldn't connect to: " + 
endpoint.getConfiguration().remoteServerInformation());
         }
         super.doStart();
     }
@@ -121,24 +121,24 @@
     }
 
     protected static boolean buildDirectory(FTPClient ftpClient, String 
dirName) throws IOException {
-        boolean atLeastOneSuccess = false;
-        final StringBuilder sb = new StringBuilder(dirName.length());
-        final String[] dirs = dirName.split("\\/");
-
-        for (String dir : dirs) {
-            sb.append(dir).append('/');
-            String directory = sb.toString();
-
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Trying to build directory: " + directory);
-            }
-            final boolean success = ftpClient.makeDirectory(directory);
+        String originalDirectory = ftpClient.printWorkingDirectory();
 
-            if (!atLeastOneSuccess && success) {
-                atLeastOneSuccess = true;
+        boolean success = false;
+        try {
+            // maybe the full directory already exsits
+            success = ftpClient.changeWorkingDirectory(dirName);
+            if (!success) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Trying to build remote directory: " + dirName);
+                }
+                success = ftpClient.makeDirectory(dirName);
             }
+        } finally {
+            // change back to original directory
+            ftpClient.changeWorkingDirectory(originalDirectory);
         }
 
-        return atLeastOneSuccess;
+        return success;
     }
+
 }

Modified: 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
--- 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
 (original)
+++ 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
 Sat Jul 26 04:13:57 2008
@@ -46,7 +46,14 @@
     }
 
     public String toString() {
-        return protocol + "://" + username + "@" + host + ":" + port + "/" + 
file;
+        return remoteServerInformation() + "/" + file;
+    }
+
+    /**
+     * Returns human readable server information for logging purpose
+     */
+    public String remoteServerInformation() {
+        return protocol + "://" + username + "@" + host + ":" + port;
     }
 
     public void configure(URI uri) {

Modified: 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
--- 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
 (original)
+++ 
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
 Sat Jul 26 04:13:57 2008
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.file.remote;
 
-
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -29,7 +28,6 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-
 public class SftpProducer extends RemoteFileProducer<RemoteFileExchange> {
     private static final transient Log LOG = 
LogFactory.getLog(SftpProducer.class);
 
@@ -46,30 +44,29 @@
     protected void connectIfNecessary() throws JSchException {
         if (channel == null || !channel.isConnected()) {
             if (session == null || !session.isConnected()) {
-                LOG.info("Session isn't connected, trying to recreate and 
connect...");
+                LOG.debug("Session isn't connected, trying to recreate and 
connect.");
                 session = endpoint.createSession();
                 session.connect();
             }
-            LOG.info("Channel isn't connected, trying to recreate and 
connect...");
+            LOG.debug("Channel isn't connected, trying to recreate and 
connect.");
             channel = endpoint.createChannelSftp(session);
             channel.connect();
-            LOG.info("Connected to " + endpoint.getConfiguration().toString());
+            LOG.info("Connected to " + 
endpoint.getConfiguration().remoteServerInformation());
         }
     }
 
     protected void disconnect() throws JSchException {
         if (session != null) {
-            LOG.info("Session is being explicitly disconnected");
+            LOG.debug("Session is being explicitly disconnected");
             session.disconnect();
         }
         if (channel != null) {
-            LOG.info("Channel is being explicitly disconnected");
+            LOG.debug("Channel is being explicitly disconnected");
             channel.disconnect();
         }
     }
 
     public void process(Exchange exchange) throws Exception {
-        // TODO: is there a way to avoid copy-pasting the reconnect logic?
         connectIfNecessary();
         // If the attempt to connect isn't successful, then the thrown
         // exception will signify that we couldn't deliver
@@ -78,15 +75,16 @@
         } catch (JSchException e) {
             // If the connection has gone stale, then we must manually 
disconnect
             // the client before attempting to reconnect
-            LOG.warn("Disconnecting due to exception: " + e.toString());
+            LOG.warn("Disconnecting due to exception: " + e.getMessage());
             disconnect();
             // Rethrow to signify that we didn't deliver
             throw e;
         } catch (SftpException e) {
             // Still not sure if/when these come up and what we should do 
about them
             // client.disconnect();
-            LOG.warn("Caught SftpException:" + e.toString());
-            LOG.warn("Doing nothing for now, need to determine an appropriate 
action");
+            LOG.warn("Caught SftpException:" + e.getMessage(), e);
+            LOG.warn("Hoping an explicit disconnect/reconnect will solve the 
problem");
+            disconnect();
             // Rethrow to signify that we didn't deliver
             throw e;
         }
@@ -95,6 +93,7 @@
     public void process(RemoteFileExchange exchange) throws Exception {
         InputStream payload = exchange.getIn().getBody(InputStream.class);
         try {
+            String remoteServer = 
endpoint.getConfiguration().remoteServerInformation();
             String fileName = createFileName(exchange.getIn(), 
endpoint.getConfiguration());
 
             int lastPathIndex = fileName.lastIndexOf('/');
@@ -102,12 +101,15 @@
                 String directory = fileName.substring(0, lastPathIndex);
                 boolean success = buildDirectory(channel, directory);
                 if (!success) {
-                    LOG.warn("Couldn't build directory: " + directory + " 
(either permissions deny it, or it already exists)");
+                    LOG.warn("Couldn't build directory: " + directory + " 
(could be because of denied permissions)");
                 }
             }
 
             channel.put(payload, fileName);
-            LOG.info("Sent: " + fileName + " to " + 
endpoint.getConfiguration());
+
+            if (LOG.isInfoEnabled()) {
+                LOG.info("Sent: " + fileName + " to: " + remoteServer);
+            }
         } finally {
             if (payload != null) {
                 payload.close();
@@ -121,7 +123,7 @@
         try {
             connectIfNecessary();
         } catch (JSchException e) {
-            LOG.warn("Couldn't connect to " + endpoint.getConfiguration());
+            LOG.warn("Couldn't connect to: " + 
endpoint.getConfiguration().remoteServerInformation());
         }
         super.doStart();
     }
@@ -135,24 +137,31 @@
 
     protected static boolean buildDirectory(ChannelSftp sftpClient, String 
dirName)
         throws IOException, SftpException {
+        String originalDirectory = sftpClient.pwd();
 
-        boolean atLeastOneSuccess = false;
-        final StringBuilder sb = new StringBuilder(dirName.length());
-        final String[] dirs = dirName.split("\\/");
-        for (String dir : dirs) {
-            sb.append(dir).append('/');
-            String directory = sb.toString();
-
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Trying to build directory: " + directory);
+        boolean success = false;
+        try {
+            // maybe the full directory already exsits
+            try {
+                sftpClient.cd(dirName);
+                success = true;
+            } catch (SftpException e) {
+                // ignore, we could not change directory so try to create it 
instead
             }
-            sftpClient.mkdir(directory);
-            if (!atLeastOneSuccess) {
-                atLeastOneSuccess = true;
+
+            if (!success) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Trying to build remote directory: " + dirName);
+                }
+                sftpClient.mkdir(dirName);
+                success = true;
             }
+        } finally {
+            // change back to original directory
+            sftpClient.cd(originalDirectory);
         }
 
-        return atLeastOneSuccess;
+        return success;
     }
 
 }
\ No newline at end of file

Added: 
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java?rev=679979&view=auto
==============================================================================
--- 
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
 (added)
+++ 
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
 Sat Jul 26 04:13:57 2008
@@ -0,0 +1,65 @@
+/**
+ * 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.ContextTestSupport;
+import org.apache.camel.converter.IOConverter;
+import org.apache.camel.component.file.FileComponent;
+
+/**
+ * Unit test to verify that Camel can build remote directory on FTP server if 
missing (full or part of). 
+ */
+public class FtpProducerBuildDirectoryTest extends FtpServerTestSupport {
+
+    private String port = "20018";
+    private String ftpUrl = "ftp://[EMAIL PROTECTED]:" + port + 
"/upload/user/claus?binary=false&password=admin";
+
+    public String getPort() {
+        return port;
+    }
+
+    public void testProduceAndBuildFullRemotFolderTest() throws Exception {
+        deleteDirectory("./res/home/");
+
+        template.sendBodyAndHeader(ftpUrl, "Hello World", 
FileComponent.HEADER_FILE_NAME, "claus.txt");
+
+        File file = new File("./res/home/upload/user/claus/claus.txt");
+        file = file.getAbsoluteFile();
+        assertTrue("The uploaded file should exists", file.exists());
+        assertEquals("Hello World", IOConverter.toString(file));
+    }
+
+    public void testProduceAndBuildPartOfRemotFolderTest() throws Exception {
+        deleteDirectory("./res/home/");
+        createDirectory("./res/home/upload/user/superman");
+
+        template.sendBodyAndHeader(ftpUrl, "Bye World", 
FileComponent.HEADER_FILE_NAME, "claus.txt");
+
+        File file = new File("./res/home/upload/user/claus/claus.txt");
+        file = file.getAbsoluteFile();
+        assertTrue("The uploaded file should exists", file.exists());
+        assertEquals("Bye World", IOConverter.toString(file));
+    }
+
+    private static void createDirectory(String s) {
+        File file = new File(s);
+        file.mkdirs();
+    }
+
+}

Propchange: 
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date


Reply via email to