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
This commit is contained in:
Oleg Zhurakousky
2011-10-18 12:17:14 -04:00
committed by Mark Fisher
parent 22c43a199b
commit c1107a229e
11 changed files with 72 additions and 59 deletions

View File

@@ -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 + "'");
}
}
}
}

View File

@@ -46,5 +46,4 @@ public interface Session {
void close();
boolean isOpen();
}

View File

@@ -270,7 +270,8 @@ public class RemoteFileOutboundGatewayTests {
}
public boolean isOpen() {
return open;
} });
}
});
@SuppressWarnings("unchecked")
Message<File> out = (Message<File>) gw.handleRequestMessage(new GenericMessage<String>("f1"));
File outFile = new File(this.tmpDir + "/f1");
@@ -323,7 +324,8 @@ public class RemoteFileOutboundGatewayTests {
}
public boolean isOpen() {
return open;
} });
}
});
@SuppressWarnings("unchecked")
Message<File> out = (Message<File>) gw.handleRequestMessage(new GenericMessage<String>("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<String>("f1"));
File out = new File(this.tmpDir + "/x/f1");
assertTrue(out.exists());

View File

@@ -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;

View File

@@ -37,6 +37,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-create-directory" type="xsd:string" default="false">
<xsd:annotation>
<xsd:documentation>
Specify whether to automatically create the remote target directory if it doesn't exist.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="remote-file-separator" type="xsd:string" default="/">
<xsd:annotation>
<xsd:documentation>

View File

@@ -8,8 +8,8 @@
http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd">
<bean id="ftpSessionFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="192.168.1.155"/>
<property name="username" value="oleg"/>
<property name="host" value="192.168.28.143"/>
<property name="username" value="user"/>
<property name="password" value="password"/>
<property name="bufferSize" value="1000000"/>
</bean>
@@ -17,7 +17,8 @@
<int:channel id="ftpChannel"/>
<int-ftp:outbound-channel-adapter
auto-create-directory="true"
session-factory="ftpSessionFactory"
remote-directory="/home/ozhurakousky"
remote-directory="./dsf/sdfsfs/sdffs"
channel="ftpChannel"/>
</beans>

View File

@@ -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();
}
}
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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<File>(fileA));
ftpChannel.send(new GenericMessage<File>(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());
}
}

View File

@@ -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"/>
</beans>

View File

@@ -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;