INT-1668 added logic to FTP/SFTP to ensure that the files are being uploaded with .writing extension and then renamed. Added rename(..) method to Session strategy. Ensured that file to be uploaded is not copied locally. Tested upload/download with both SFTP and FTP of a very large files. Added more mock tests
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-ftp="http://www.springframework.org/schema/integration/ftp"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
|
||||
http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd">
|
||||
|
||||
<int:channel id="ftpOutbound"/>
|
||||
|
||||
<bean id="ftpSessionFactory" class="org.springframework.integration.ftp.session.DefaultFtpsSessionFactory">
|
||||
<property name="host" value="localhost"/>
|
||||
<property name="port" value="22"/>
|
||||
<property name="username" value="oleg"/>
|
||||
<property name="password" value="password"/>
|
||||
<property name="clientMode" value="0"/>
|
||||
<property name="fileType" value="2"/>
|
||||
</bean>
|
||||
|
||||
<int-ftp:outbound-channel-adapter id="ftpOutboundAdapter"
|
||||
session-factory="ftpSessionFactory"
|
||||
remote-directory="foo/bar"
|
||||
channel="ftpOutbound"
|
||||
remote-filename-generator="fileNameGenerator"/>
|
||||
|
||||
<bean id="fileNameGenerator" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.integration.file.FileNameGenerator"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -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<String> message = new GenericMessage<String>("ftp file generator test");
|
||||
try {
|
||||
handler.handleMessage(message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
verify(fileNameGenerator, times(1)).generateFileName(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,9 +8,10 @@
|
||||
http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd">
|
||||
|
||||
<bean id="ftpClientFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
|
||||
<property name="host" value="localhost"/>
|
||||
<property name="host" value="192.168.1.155"/>
|
||||
<property name="username" value="oleg"/>
|
||||
<property name="password" value="xxxx"/>
|
||||
<property name="password" value="password"/>
|
||||
<property name="bufferSize" value="1000000"/>
|
||||
</bean>
|
||||
|
||||
<int-ftp:inbound-channel-adapter id="ftpInbound"
|
||||
@@ -18,10 +19,10 @@
|
||||
session-factory="ftpClientFactory"
|
||||
auto-create-local-directory="true"
|
||||
delete-remote-files="false"
|
||||
filename-regex=".*\.test$"
|
||||
remote-directory="/Users/ozhurakousky/workspace-sts-2.3.3.M2/si/spring-integration/spring-integration-ftp/remote-test-dir"
|
||||
filename-regex=".*\.gz$"
|
||||
remote-directory="/home/ozhurakousky/Downloads"
|
||||
local-directory="file:local-test-dir">
|
||||
<int:poller fixed-rate="1000"/>
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-ftp:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="ftpChannel">
|
||||
|
||||
@@ -8,15 +8,16 @@
|
||||
http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd">
|
||||
|
||||
<bean id="ftpSessionFactory" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
|
||||
<property name="host" value="localhost"/>
|
||||
<property name="host" value="192.168.1.155"/>
|
||||
<property name="username" value="oleg"/>
|
||||
<property name="password" value="xxxx"/>
|
||||
<property name="password" value="password"/>
|
||||
<property name="bufferSize" value="1000000"/>
|
||||
</bean>
|
||||
|
||||
<int:channel id="ftpChannel"/>
|
||||
|
||||
<int-ftp:outbound-channel-adapter
|
||||
session-factory="ftpSessionFactory"
|
||||
remote-directory="/Users/ozhurakousky/workspace-sts-2.3.3.M2/si/spring-integration/spring-integration-ftp/remote-target-dir"
|
||||
remote-directory="/home/ozhurakousky"
|
||||
channel="ftpChannel"/>
|
||||
</beans>
|
||||
|
||||
@@ -133,6 +133,14 @@ public class FtpSendingMessageHandlerTest {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
when(ftpClient.rename(Mockito.anyString(), Mockito.anyString())).thenAnswer(new Answer<Boolean>() {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user