From c1107a229e9ab8715974219f59852778a48343e0 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 18 Oct 2011 12:17:14 -0400 Subject: [PATCH] Improved check for existing directories modified for Remote File adapters (e.g., FTP/SFTP) added 'auto-create-directory' attribute to FTP outbound adapter refactored code structure of FileTransferringMessageHandler --- .../FileTransferringMessageHandler.java | 37 +------------- .../file/remote/session/Session.java | 1 - .../RemoteFileOutboundGatewayTests.java | 9 ++-- .../integration/ftp/session/FtpSession.java | 1 - .../ftp/config/spring-integration-ftp-2.1.xsd | 7 +++ ...tpOutboundChannelAdapterSample-context.xml | 7 +-- .../ftp/session/SessionFactoryTests.java | 7 ++- .../integration/sftp/session/SftpSession.java | 48 +++++++++++++++++-- .../SftpInboundOutboundSanitySample.java | 8 ++-- .../SftpOutboundTransferSample-ignored.xml | 2 +- .../sftp/session/SftpTestSessionFactory.java | 4 +- 11 files changed, 72 insertions(+), 59 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java index d1a5d110e2..8a4f3abad1 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java @@ -61,8 +61,7 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { private volatile String charset = "UTF-8"; private volatile String remoteFileSeparator = "/"; - - + public FileTransferringMessageHandler(SessionFactory sessionFactory) { Assert.notNull(sessionFactory, "sessionFactory must not be null"); this.sessionFactory = sessionFactory; @@ -193,7 +192,7 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { String tempFilePath = remoteFilePath + this.temporaryFileSuffix; if (this.autoCreateDirectory){ - this.ensureDirectoryExists(session, remoteDirectory, remoteDirectory); + session.mkdir(remoteDirectory); } try { @@ -208,36 +207,4 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { fileInputStream.close(); } } - - private void ensureDirectoryExists(Session session, String remoteDirectory, String originalRemoteDirectory){ - try { - session.list(remoteDirectory); - } catch (IOException e) { - if (logger.isDebugEnabled()){ - logger.debug("Directory '" + remoteDirectory + "' does not exist. Will attempt to auto-create it"); - } - int nextSeparatorIndex = remoteDirectory.lastIndexOf(this.remoteFileSeparator); - if (nextSeparatorIndex <= 0){ - throw new MessagingException("Failed to auto-create directory '" + originalRemoteDirectory + "'"); - } - else { - remoteDirectory = remoteDirectory.substring(0, nextSeparatorIndex); - this.ensureDirectoryExists(session, remoteDirectory, originalRemoteDirectory); - } - } - String missingDirectoryPath = originalRemoteDirectory.substring(remoteDirectory.length()); - String[] directories = StringUtils.tokenizeToStringArray(missingDirectoryPath, this.remoteFileSeparator); - String directory = remoteDirectory + this.remoteFileSeparator; - for (String directorySegment : directories) { - directory += directorySegment+this.remoteFileSeparator; - if (logger.isDebugEnabled()){ - logger.debug("Creating '" + directory + "'"); - } - try { - session.mkdir(directory); - } catch (Exception e) { - throw new MessagingException("Failed to auto-create directory '" + directory + "'"); - } - } - } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/Session.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/Session.java index 09408ddc01..be3413b4ab 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/Session.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/Session.java @@ -46,5 +46,4 @@ public interface Session { void close(); boolean isOpen(); - } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java index f38bec6393..2481f7973b 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java @@ -270,7 +270,8 @@ public class RemoteFileOutboundGatewayTests { } public boolean isOpen() { return open; - } }); + } + }); @SuppressWarnings("unchecked") Message out = (Message) gw.handleRequestMessage(new GenericMessage("f1")); File outFile = new File(this.tmpDir + "/f1"); @@ -323,7 +324,8 @@ public class RemoteFileOutboundGatewayTests { } public boolean isOpen() { return open; - } }); + } + }); @SuppressWarnings("unchecked") Message out = (Message) gw.handleRequestMessage(new GenericMessage("x/f1")); File outFile = new File(this.tmpDir + "/f1"); @@ -374,7 +376,8 @@ public class RemoteFileOutboundGatewayTests { } public boolean isOpen() { return open; - } }); + } + }); gw.handleRequestMessage(new GenericMessage("f1")); File out = new File(this.tmpDir + "/x/f1"); assertTrue(out.exists()); diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java index 5ddd3f2c4a..8fb2c5931a 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java @@ -24,7 +24,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; - import org.springframework.integration.file.remote.session.Session; import org.springframework.util.Assert; diff --git a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd index e6672bf35f..3ce1800dfe 100644 --- a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd +++ b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd @@ -37,6 +37,13 @@ + + + + Specify whether to automatically create the remote target directory if it doesn't exist. + + + diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterSample-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterSample-context.xml index c1bfab5da7..42d402a9dc 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterSample-context.xml +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterSample-context.xml @@ -8,8 +8,8 @@ http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd"> - - + + @@ -17,7 +17,8 @@ diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/SessionFactoryTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/SessionFactoryTests.java index a940fcacae..2de9f0ede5 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/SessionFactoryTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/SessionFactoryTests.java @@ -15,13 +15,13 @@ */ package org.springframework.integration.ftp.session; -import static junit.framework.Assert.fail; - import java.lang.reflect.Field; import org.apache.commons.net.ftp.FTPClient; import org.junit.Test; +import static junit.framework.Assert.fail; + /** * @author Oleg Zhurakousky * @@ -47,7 +47,6 @@ public class SessionFactoryTests { fail(); } } - } - + } } } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index fce80a3af9..a8a112bc63 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -25,9 +25,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.NestedIOException; +import org.springframework.integration.MessagingException; import org.springframework.integration.file.remote.session.Session; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; +import org.springframework.util.StringUtils; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp.LsEntry; @@ -167,12 +169,50 @@ class SftpSession implements Session { } } - public void mkdir(String directory) throws IOException { - try { - this.channel.mkdir(directory); + public void mkdir(String remoteDirectory) throws IOException { + try { + this.mkdirRecursively(remoteDirectory, remoteDirectory); } catch (SftpException e) { - throw new NestedIOException("failed to create remote directory '" + directory + "'.", e); + throw new NestedIOException("failed to create remote directory '" + remoteDirectory + "'.", e); } } + private void mkdirRecursively(String remoteDirectory, String originalRemoteDirectory) throws SftpException{ + String remoteFileSeparator = "/"; + if (this.exists(remoteDirectory)){ + String missingDirectoryPath = originalRemoteDirectory.substring(remoteDirectory.length()); + String[] directories = StringUtils.tokenizeToStringArray(missingDirectoryPath, remoteFileSeparator); + String directory = remoteDirectory + remoteFileSeparator; + for (String directorySegment : directories) { + directory += directorySegment + remoteFileSeparator; + if (logger.isDebugEnabled()){ + logger.debug("Creating '" + directory + "'"); + } + this.channel.mkdir(directory); + } + } + else { + if (logger.isDebugEnabled()){ + logger.debug("Directory '" + remoteDirectory + "' does not exist. Will attempt to auto-create it"); + } + int nextSeparatorIndex = remoteDirectory.lastIndexOf(remoteFileSeparator); + if (nextSeparatorIndex <= 0){ + throw new MessagingException("Failed to auto-create directory '" + originalRemoteDirectory + "'"); + } + else { + remoteDirectory = remoteDirectory.substring(0, nextSeparatorIndex); + this.mkdirRecursively(remoteDirectory, originalRemoteDirectory); + } + } + } + private boolean exists(String path){ + try { + this.channel.lstat(path); + return true; + } + catch (SftpException e) { + // ignore + } + return false; + } } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundOutboundSanitySample.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundOutboundSanitySample.java index c01be69628..95b84dc188 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundOutboundSanitySample.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundOutboundSanitySample.java @@ -15,18 +15,17 @@ */ package org.springframework.integration.sftp.config; -import static junit.framework.Assert.assertTrue; - import java.io.File; import org.junit.Ignore; import org.junit.Test; - import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.MessageChannel; import org.springframework.integration.message.GenericMessage; +import static junit.framework.Assert.assertTrue; + /** * @author Oleg Zhurakousy * @@ -72,11 +71,10 @@ public class SftpInboundOutboundSanitySample { MessageChannel ftpChannel = ac.getBean("ftpChannel", MessageChannel.class); ftpChannel.send(new GenericMessage(fileA)); ftpChannel.send(new GenericMessage(fileB)); - Thread.sleep(3000); + Thread.sleep(6000); fileA = new File("remote-target-dir/a.test-foo"); fileB = new File("remote-target-dir/b.test-foo"); assertTrue(fileA.exists()); assertTrue(fileB.exists()); } - } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundTransferSample-ignored.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundTransferSample-ignored.xml index aa070179d1..de5d04234e 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundTransferSample-ignored.xml +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundTransferSample-ignored.xml @@ -24,6 +24,6 @@ temporary-file-suffix=".foo" remote-filename-generator-expression="payload.getName() + '-foo'" auto-create-directory="true" - remote-directory="/Users/ozhurakousky/workspace-sts-2.3.3.M2/si/spring-integration/spring-integration-sftp/remote-target-dir/foo/bar/baz"/> + remote-directory="spring-integration-sftp/remote-target-dir/bar/baz"/> diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpTestSessionFactory.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpTestSessionFactory.java index 09170e4106..4debabd518 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpTestSessionFactory.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpTestSessionFactory.java @@ -19,11 +19,11 @@ import org.springframework.integration.file.remote.session.Session; /** * @author Oleg Zhurakousky - * + * */ public class SftpTestSessionFactory { - public static Session createSftpSession(com.jcraft.jsch.Session jschSession){ + public static Session createSftpSession(com.jcraft.jsch.Session jschSession) { SftpSession sftpSession = new SftpSession(jschSession); sftpSession.connect(); return sftpSession;