diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java index ba5478d040..9362cb9be7 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java @@ -56,7 +56,7 @@ import java.nio.charset.Charset; */ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHandler { - private static final String TEMPORARY_FILE_SUFFIX =".writing"; + public static final String TEMPORARY_FILE_SUFFIX =".writing"; private final Log logger = LogFactory.getLog(this.getClass()); 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 5d402e3bc0..75debabc9e 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 @@ -19,9 +19,7 @@ package org.springframework.integration.file.remote.handler; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.nio.charset.Charset; import org.springframework.expression.Expression; @@ -29,6 +27,7 @@ import org.springframework.integration.Message; import org.springframework.integration.MessageDeliveryException; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.FileNameGenerator; +import org.springframework.integration.file.FileWritingMessageHandler; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.handler.AbstractMessageHandler; @@ -48,9 +47,6 @@ import org.springframework.util.StringUtils; */ public class FileTransferringMessageHandler extends AbstractMessageHandler { - private static final String TEMPORARY_FILE_SUFFIX = ".writing"; - - private final SessionFactory sessionFactory; private volatile ExpressionEvaluatingMessageProcessor directoryExpressionProcessor; @@ -60,6 +56,8 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { private volatile File temporaryDirectory = new File(System.getProperty("java.io.tmpdir")); private volatile String charset = Charset.defaultCharset().name(); + + private volatile boolean deleteOnExit; public FileTransferringMessageHandler(SessionFactory sessionFactory) { @@ -94,10 +92,10 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { File file = this.redeemForStorableFile(message); if (file != null && file.exists()) { Session session = this.sessionFactory.getSession(); - boolean sentSuccesfully = false; try { String targetDirectory = this.directoryExpressionProcessor.processMessage(message); - sentSuccesfully = this.sendFileToRemoteDirectory(file, targetDirectory, session); + String fileName = this.fileNameGenerator.generateFileName(message); + this.sendFileToRemoteDirectory(file, targetDirectory, fileName, session); } catch (FileNotFoundException e) { throw new MessageDeliveryException(message, @@ -112,59 +110,51 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { "Error handling message for file [" + file + "]", e); } finally { - if (file.exists()) { - try { - file.delete(); - } - catch (Throwable th) { - // ignore + if (deleteOnExit){ + if (file.exists()) { + try { + file.delete(); + } + catch (Throwable th) { + // ignore + } } } if (session != null) { session.close(); } } - if (!sentSuccesfully) { - throw new MessageDeliveryException(message, "Failed to transfer file '" + file + "'"); - } } } - private File handleFileMessage(File sourceFile, File tempFile, File resultFile) throws IOException { - FileCopyUtils.copy(sourceFile, tempFile); - tempFile.renameTo(resultFile); - return resultFile; - } - - private File handleByteArrayMessage(byte[] bytes, File tempFile, File resultFile) throws IOException { - FileCopyUtils.copy(bytes, tempFile); - tempFile.renameTo(resultFile); - return resultFile; - } - - private File handleStringMessage(String content, File tempFile, File resultFile, String charset) throws IOException { - OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tempFile), charset); - FileCopyUtils.copy(content, writer); - tempFile.renameTo(resultFile); - return resultFile; - } - private File redeemForStorableFile(Message message) throws MessageDeliveryException { try { Object payload = message.getPayload(); - String generateFileName = this.fileNameGenerator.generateFileName(message); - File tempFile = new File(this.temporaryDirectory, generateFileName + TEMPORARY_FILE_SUFFIX); - File resultFile = new File(this.temporaryDirectory, generateFileName); + File sendableFile = null; - if (payload instanceof String) { - sendableFile = this.handleStringMessage((String) payload, tempFile, resultFile, this.charset); + + if (payload instanceof File){ + sendableFile = (File) payload; + deleteOnExit = false; } - else if (payload instanceof File) { - sendableFile = this.handleFileMessage((File) payload, tempFile, resultFile); + else if (payload instanceof byte[] || payload instanceof String) { + String tempFileName = this.fileNameGenerator.generateFileName(message) + ".tmp"; + sendableFile = new File(this.temporaryDirectory, tempFileName); // will only create temp file for String/byte[] + deleteOnExit = true; + byte[] bytes = null; + if (payload instanceof String){ + bytes = ((String)payload).getBytes(charset); + } + else { + bytes = (byte[]) payload; + } + FileCopyUtils.copy(bytes, sendableFile); } - else if (payload instanceof byte[]) { - sendableFile = this.handleByteArrayMessage((byte[]) payload, tempFile, resultFile); + else { + throw new IllegalArgumentException("Unsupported payload type. The only supported payloads are " + + "java.io.File, java.lang.String and byte[]"); } + return sendableFile; } catch (Exception e) { @@ -172,15 +162,19 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { } } - private boolean sendFileToRemoteDirectory(File file, String remoteDirectory, Session session) throws FileNotFoundException, IOException { + private void sendFileToRemoteDirectory(File file, String remoteDirectory, String pathTo, Session session) + throws FileNotFoundException, IOException { + FileInputStream fileInputStream = new FileInputStream(file); if (!StringUtils.endsWithIgnoreCase(remoteDirectory, File.separator)) { - remoteDirectory += File.separatorChar; + remoteDirectory += File.separatorChar; } - String remoteFilePath = remoteDirectory + file.getName(); + String remoteFilePath = remoteDirectory + file.getName() + FileWritingMessageHandler.TEMPORARY_FILE_SUFFIX; + // write remote file first with .writing extension session.write(fileInputStream, remoteFilePath); fileInputStream.close(); - return true; + // then rename it to its final name + session.rename(remoteFilePath, pathTo); } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/CachingSessionFactory.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/CachingSessionFactory.java index 52621df315..6728c4328f 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/CachingSessionFactory.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/CachingSessionFactory.java @@ -136,6 +136,10 @@ public class CachingSessionFactory implements SessionFactory, DisposableBean { public boolean isOpen() { return this.targetSession.isOpen(); } + + public void rename(String pathFrom, String pathTo) throws IOException { + this.targetSession.rename(pathFrom, pathTo); + } } } 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 c3117d5ee8..5a8d45af4b 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 @@ -38,8 +38,11 @@ public interface Session { void read(String source, OutputStream outputStream) throws IOException; void write(InputStream inputStream, String destination) throws IOException; + + void rename(String pathFrom, String pathTo) throws IOException; void close(); boolean isOpen(); + } 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 0b1180ebc3..8406fc9dbd 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 @@ -25,6 +25,7 @@ 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.FileWritingMessageHandler; import org.springframework.integration.file.remote.session.Session; import org.springframework.util.Assert; @@ -78,7 +79,8 @@ class FtpSession implements Session { Assert.hasText(path, "path must not be null"); boolean completed = client.storeFile(path, inputStream); if (!completed){ - throw new IOException("Failed to copy '" + path + "'. Server replied with: " + client.getReplyString()); + throw new IOException("Failed to write to '" + (path+FileWritingMessageHandler.TEMPORARY_FILE_SUFFIX) + + "'. Server replied with: " + client.getReplyString()); } logger.info("File have been successfully transfered to: " + path); } @@ -102,4 +104,13 @@ class FtpSession implements Session { } return true; } + + public void rename(String pathFrom, String pathTo) throws IOException{ + boolean completed = client.rename(pathFrom, pathTo); + if (!completed){ + throw new IOException("Failed to rename '" + pathFrom + + "' to " + pathTo + "'. Server replied with: " + client.getReplyString()); + } + logger.info("File have been successfully renamed from: " + pathFrom + " to " + pathTo); + } } diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml deleted file mode 100644 index ad97969e73..0000000000 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java deleted file mode 100644 index 2f08a982d2..0000000000 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed 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.springframework.integration.ftp; - -import static junit.framework.Assert.assertNotNull; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.Test; -import org.mockito.Mockito; - -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.integration.Message; -import org.springframework.integration.endpoint.EventDrivenConsumer; -import org.springframework.integration.file.FileNameGenerator; -import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler; -import org.springframework.integration.message.GenericMessage; -import org.springframework.integration.test.util.TestUtils; - -/** - * @author Oleg Zhurakousky - */ -public class FtpParserOutboundTests { - - @Test - public void testFtpOutboundWithFileGenerator() throws Exception{ - ClassPathXmlApplicationContext context = - new ClassPathXmlApplicationContext("FtpParserOutboundTests-context.xml", this.getClass()); - FileNameGenerator fileNameGenerator = context.getBean("fileNameGenerator", FileNameGenerator.class); - assertNotNull(fileNameGenerator); - when(fileNameGenerator.generateFileName(Mockito.any(Message.class))).thenReturn("oleg-ftp-test.txt"); - EventDrivenConsumer fileOutboundEndpoint = context.getBean("ftpOutboundAdapter", EventDrivenConsumer.class); - FileTransferringMessageHandler handler = (FileTransferringMessageHandler) TestUtils.getPropertyValue(fileOutboundEndpoint, "handler"); - Message message = new GenericMessage("ftp file generator test"); - try { - handler.handleMessage(message); - } - catch (Exception e) { - // ignore - } - verify(fileNameGenerator, times(1)).generateFileName(message); - } - -} diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpInboundChannelAdapterSample-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpInboundChannelAdapterSample-context.xml index 7019a41b99..1272c3a4f4 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpInboundChannelAdapterSample-context.xml +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpInboundChannelAdapterSample-context.xml @@ -8,9 +8,10 @@ http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd"> - + - + + - + 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 6d9394c920..a8392e4f51 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,15 +8,16 @@ http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd"> - + - + + diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpSendingMessageHandlerTest.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpSendingMessageHandlerTest.java index fab0aef42a..0691b0d0ae 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpSendingMessageHandlerTest.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpSendingMessageHandlerTest.java @@ -133,6 +133,14 @@ public class FtpSendingMessageHandlerTest { return true; } }); + when(ftpClient.rename(Mockito.anyString(), Mockito.anyString())).thenAnswer(new Answer() { + public Boolean answer(InvocationOnMock invocation) + throws Throwable { + File file = new File((String) invocation.getArguments()[0]); + file.renameTo(new File(file.getParent(), (String) invocation.getArguments()[1])); + return true; + } + }); return ftpClient; } catch (Exception e) { throw new RuntimeException("Failed to create mock client", e); 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 0f8fa07e9c..6a658a2ca2 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 @@ -92,7 +92,7 @@ class SftpSession implements Session { FileCopyUtils.copy(is, os); } catch (SftpException e) { - throw new IOException("failed to copy file", e); + throw new IOException("failed to read file", e); } } @@ -102,7 +102,7 @@ class SftpSession implements Session { this.channel.put(inputStream, destination); } catch (SftpException e) { - throw new IOException("failed to copy file", e); + throw new IOException("failed to write file", e); } } @@ -131,4 +131,12 @@ class SftpSession implements Session { return this.jschSession.isConnected(); } + public void rename(String pathFrom, String pathTo) throws IOException { + try { + this.channel.rename(pathFrom, pathTo); + } catch (SftpException e) { + throw new IOException("failed to rename from " + pathFrom + " to " + pathTo, e); + } + } + } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundReceiveSample-ignored.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundReceiveSample-ignored.xml index 21d00db84b..51eb593d88 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundReceiveSample-ignored.xml +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpInboundReceiveSample-ignored.xml @@ -11,7 +11,7 @@ - + @@ -21,12 +21,12 @@ - + filename-regex=".*\.gz$"> + 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 de9d663707..8e82f164b6 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 @@ -9,7 +9,7 @@ - + @@ -23,6 +23,6 @@ channel="ftpChannel" charset="UTF-8" remote-filename-generator-expression="payload.getName() + '-foo'" - remote-directory="/Users/ozhurakousky/workspace-sts-2.3.3.M2/si/spring-integration/spring-integration-sftp/remote-target-dir"/> + remote-directory="/home/ozhurakousky"/> diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpSendingMessageHandlerTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpSendingMessageHandlerTests.java index b0aa881317..d2f8586d05 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpSendingMessageHandlerTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpSendingMessageHandlerTests.java @@ -16,67 +16,127 @@ package org.springframework.integration.sftp.outbound; -import static org.mockito.Mockito.atLeast; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; -import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.file.DefaultFileNameGenerator; +import org.springframework.integration.file.FileWritingMessageHandler; import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.sftp.session.DefaultSftpSessionFactory; +import org.springframework.integration.sftp.session.SftpTestSessionFactory; +import org.springframework.util.FileCopyUtils; + +import com.jcraft.jsch.ChannelSftp; /** * @author Oleg Zhurakousky */ -// there are few validations in this tests, but it is mainly to increase code coverage during CI public class SftpSendingMessageHandlerTests { + + private static com.jcraft.jsch.Session jschSession = mock(com.jcraft.jsch.Session.class); - @SuppressWarnings({ "unchecked", "rawtypes" }) @Test - public void testHandleFileNameMessage() throws Exception { - SessionFactory sessionFactory = mock(SessionFactory.class); - Session session = mock(Session.class); - when(sessionFactory.getSession()).thenReturn(session); + public void testHandleFileMessage() throws Exception { + File file = new File("remote-target-dir", "template.mf.test"); + if (file.exists()){ + file.delete(); + } + SessionFactory sessionFactory = new TestSftpSessionFactory(); FileTransferringMessageHandler handler = new FileTransferringMessageHandler(sessionFactory); - handler.setRemoteDirectoryExpression(new SpelExpressionParser().parseExpression("'foo.txt'")); - handler.handleMessage(new GenericMessage("hello")); - verify(sessionFactory, times(1)).getSession(); + DefaultFileNameGenerator fGenerator = new DefaultFileNameGenerator(); + fGenerator.setExpression("payload + '.test'"); + handler.setFileNameGenerator(fGenerator); + handler.setRemoteDirectoryExpression(new LiteralExpression("remote-target-dir")); + + handler.handleMessage(new GenericMessage(new File("template.mf"))); + assertTrue(new File("remote-target-dir", "template.mf.test").exists()); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test - public void testHandleFileAsByte() throws Exception { - SessionFactory sessionFactory = mock(SessionFactory.class); - Session session = mock(Session.class); - when(sessionFactory.getSession()).thenReturn(session); + public void testHandleStringMessage() throws Exception { + File file = new File("remote-target-dir", "foo.txt"); + if (file.exists()){ + file.delete(); + } + SessionFactory sessionFactory = new TestSftpSessionFactory(); FileTransferringMessageHandler handler = new FileTransferringMessageHandler(sessionFactory); - handler.setRemoteDirectoryExpression(new SpelExpressionParser().parseExpression("'foo.txt'")); + DefaultFileNameGenerator fGenerator = new DefaultFileNameGenerator(); + fGenerator.setExpression("'foo.txt'"); + handler.setFileNameGenerator(fGenerator); + handler.setRemoteDirectoryExpression(new LiteralExpression("remote-target-dir")); - handler.handleMessage(new GenericMessage("hello".getBytes())); - verify(sessionFactory, times(1)).getSession(); + handler.handleMessage(new GenericMessage("hello")); + assertTrue(new File("remote-target-dir", "foo.txt").exists()); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test - public void testHandleFileMessage() throws Exception { - SessionFactory sessionFactory = mock(SessionFactory.class); - Session session = mock(Session.class); - when(sessionFactory.getSession()).thenReturn(session); + public void testHandleBytesMessage() throws Exception { + File file = new File("remote-target-dir", "foo.txt"); + if (file.exists()){ + file.delete(); + } + SessionFactory sessionFactory = new TestSftpSessionFactory(); FileTransferringMessageHandler handler = new FileTransferringMessageHandler(sessionFactory); - handler.setRemoteDirectoryExpression(new SpelExpressionParser().parseExpression("'foo.txt'")); + DefaultFileNameGenerator fGenerator = new DefaultFileNameGenerator(); + fGenerator.setExpression("'foo.txt'"); + handler.setFileNameGenerator(fGenerator); + handler.setRemoteDirectoryExpression(new LiteralExpression("remote-target-dir")); handler.handleMessage(new GenericMessage("hello".getBytes())); + assertTrue(new File("remote-target-dir", "foo.txt").exists()); + } + + public static class TestSftpSessionFactory extends DefaultSftpSessionFactory { - File file = File.createTempFile("foo", ".txt"); - handler.handleMessage(new GenericMessage(file)); - verify(sessionFactory, atLeast(1)).getSession(); + @SuppressWarnings("rawtypes") + public Session getSession() { + try { + ChannelSftp channel = mock(ChannelSftp.class); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) + throws Throwable { + File file = new File((String)invocation.getArguments()[1]); + assertTrue(file.getName().endsWith(FileWritingMessageHandler.TEMPORARY_FILE_SUFFIX)); + FileCopyUtils.copy((InputStream)invocation.getArguments()[0], new FileOutputStream(file)); + return null; + } + + }).when(channel).put(Mockito.any(InputStream.class), Mockito.anyString()); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) + throws Throwable { + File file = new File((String) invocation.getArguments()[0]); + assertTrue(file.getName().endsWith(FileWritingMessageHandler.TEMPORARY_FILE_SUFFIX)); + file.renameTo(new File(file.getParent(), (String) invocation.getArguments()[1])); + return null; + } + + }).when(channel).rename(Mockito.anyString(), Mockito.anyString()); + when(jschSession.openChannel("sftp")).thenReturn(channel); + return SftpTestSessionFactory.createSftpSession(jschSession); + } catch (Exception e) { + throw new RuntimeException("Failed to create mock sftp session", e); + } + } } } diff --git a/spring-integration-sftp/src/test/resources/log4j.properties b/spring-integration-sftp/src/test/resources/log4j.properties index b1f9721f47..e46776bc79 100644 --- a/spring-integration-sftp/src/test/resources/log4j.properties +++ b/spring-integration-sftp/src/test/resources/log4j.properties @@ -5,5 +5,5 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.category.com.jcraft.jsch=DEBUG -log4j.category.org.springframework.integration=WARN +log4j.category.org.springframework.integration=DEBUG log4j.category.org.springframework.integration.sftp=DEBUG