INT-3412 (S)FTP Append, rmdir, Client Access
JIRA: https://jira.spring.io/browse/INT-3412 Initial commit - review only. TODO: - SFTP Tests - Namespace/Adapter support for file append - Docs INT-3412 Polishing - Addressed PR comments - Completed SFTP implementation - Added namespace/parser support for `FileExistsMode` (append, etc) - Added SFTP Tests - Created Embedded SFTP server for tests (similar to FTP) - Converted tests that needed a real server to use the embedded server INT-3412 Docs and Polish (PR Comments)
This commit is contained in:
committed by
Artem Bilan
parent
bc3db5d4a9
commit
403c91801d
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
import org.springframework.integration.file.config.RemoteFileOutboundChannelAdapterParser;
|
||||
|
||||
/**
|
||||
* Provides namespace support for using FTP
|
||||
@@ -26,13 +25,15 @@ import org.springframework.integration.file.config.RemoteFileOutboundChannelAdap
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FtpNamespaceHandler extends AbstractIntegrationNamespaceHandler {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new FtpInboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new RemoteFileOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new FtpOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-gateway", new FtpOutboundGatewayParser());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2014 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.config;
|
||||
|
||||
import org.springframework.integration.file.config.RemoteFileOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
|
||||
|
||||
/**
|
||||
* Parser for FTP Outbound Channel Adapters.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class FtpOutboundChannelAdapterParser extends RemoteFileOutboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected Class<? extends RemoteFileOperations<?>> getTemplateClass() {
|
||||
return FtpRemoteFileTemplate.class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -16,9 +16,11 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.file.config.AbstractRemoteFileOutboundGatewayParser;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter;
|
||||
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
|
||||
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -28,6 +30,7 @@ import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
|
||||
*/
|
||||
public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayParser {
|
||||
|
||||
@Override
|
||||
public String getGatewayClassName() {
|
||||
return FtpOutboundGateway.class.getName();
|
||||
}
|
||||
@@ -42,4 +45,9 @@ public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayP
|
||||
return FtpRegexPatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends RemoteFileOperations<?>> getTemplateClass() {
|
||||
return FtpRemoteFileTemplate.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.apache.commons.net.ftp.FTPClientConfig;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.apache.commons.net.ftp.FTPReply;
|
||||
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -164,7 +163,7 @@ public abstract class AbstractFtpSessionFactory<T extends FTPClient> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session<FTPFile> getSession() {
|
||||
public FtpSession getSession() {
|
||||
try {
|
||||
return new FtpSession(this.createClient());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014 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.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.integration.file.remote.ClientCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.SessionCallback;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
/**
|
||||
* FTP version of {@code RemoteFileTemplate} providing type-safe access to
|
||||
* the underlying FTPClient object.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class FtpRemoteFileTemplate extends RemoteFileTemplate<FTPFile> {
|
||||
|
||||
public FtpRemoteFileTemplate(SessionFactory<FTPFile> sessionFactory) {
|
||||
super(sessionFactory);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T, C> T executeWithClient(final ClientCallback<C, T> callback) {
|
||||
return doExecuteWithClient((ClientCallback<FTPClient, T>) callback);
|
||||
}
|
||||
|
||||
protected <T> T doExecuteWithClient(final ClientCallback<FTPClient, T> callback) {
|
||||
return execute(new SessionCallback<FTPFile, T>() {
|
||||
|
||||
@Override
|
||||
public T doInSession(Session<FTPFile> session) throws IOException {
|
||||
return callback.doWithClient((FTPClient) session.getClientInstance());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(final String path) {
|
||||
return executeWithClient(new ClientCallback<FTPClient, Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean doWithClient(FTPClient client) {
|
||||
try {
|
||||
return client.getStatus(path) != null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to stat " + path, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class FtpSession implements Session<FTPFile> {
|
||||
@Override
|
||||
public void write(InputStream inputStream, String path) throws IOException {
|
||||
Assert.notNull(inputStream, "inputStream must not be null");
|
||||
Assert.hasText(path, "path must not be null");
|
||||
Assert.hasText(path, "path must not be null or empty");
|
||||
boolean completed = this.client.storeFile(path, inputStream);
|
||||
if (!completed) {
|
||||
throw new IOException("Failed to write to '" + path
|
||||
@@ -127,6 +127,20 @@ public class FtpSession implements Session<FTPFile> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(InputStream inputStream, String path) throws IOException {
|
||||
Assert.notNull(inputStream, "inputStream must not be null");
|
||||
Assert.hasText(path, "path must not be null or empty");
|
||||
boolean completed = this.client.appendFile(path, inputStream);
|
||||
if (!completed) {
|
||||
throw new IOException("Failed to append to '" + path
|
||||
+ "'. Server replied with: " + this.client.getReplyString());
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("File has been successfully appended to: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
@@ -168,6 +182,12 @@ public class FtpSession implements Session<FTPFile> {
|
||||
return this.client.makeDirectory(remoteDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rmdir(String directory) throws IOException {
|
||||
return this.client.removeDirectory(directory);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean exists(String path) throws IOException{
|
||||
Assert.hasText(path, "'path' must not be empty");
|
||||
@@ -187,4 +207,10 @@ public class FtpSession implements Session<FTPFile> {
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FTPClient getClientInstance() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ import org.springframework.integration.test.util.SocketUtils;
|
||||
* @since 3.0
|
||||
*/
|
||||
@Configuration
|
||||
public class TesFtpServer {
|
||||
public class TestFtpServer {
|
||||
|
||||
private final int ftpPort = SocketUtils.findAvailableServerSocket();
|
||||
|
||||
@@ -72,7 +72,7 @@ public class TesFtpServer {
|
||||
|
||||
private volatile FtpServer server;
|
||||
|
||||
public TesFtpServer(final String root) {
|
||||
public TestFtpServer(final String root) {
|
||||
this.ftpFolder = new TemporaryFolder() {
|
||||
|
||||
@Override
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -27,26 +27,30 @@ import static org.mockito.Mockito.when;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.session.CachingSessionFactory;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer;
|
||||
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizer;
|
||||
import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizingMessageSource;
|
||||
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
|
||||
import org.springframework.integration.ftp.session.FtpSession;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
|
||||
@@ -56,23 +60,39 @@ import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class FtpInboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
private SourcePollingChannelAdapter ftpInbound;
|
||||
|
||||
@Autowired
|
||||
private SourcePollingChannelAdapter simpleAdapterWithCachedSessions;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel autoChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("autoChannel.adapter")
|
||||
private SourcePollingChannelAdapter autoChannelAdapter;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void testFtpInboundChannelAdapterComplete() throws Exception{
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
SourcePollingChannelAdapter adapter = ac.getBean("ftpInbound", SourcePollingChannelAdapter.class);
|
||||
assertFalse(TestUtils.getPropertyValue(adapter, "autoStartup", Boolean.class));
|
||||
PriorityBlockingQueue<?> blockingQueue = TestUtils.getPropertyValue(adapter, "source.fileSource.toBeReceived", PriorityBlockingQueue.class);
|
||||
assertFalse(TestUtils.getPropertyValue(ftpInbound, "autoStartup", Boolean.class));
|
||||
PriorityBlockingQueue<?> blockingQueue = TestUtils.getPropertyValue(ftpInbound, "source.fileSource.toBeReceived", PriorityBlockingQueue.class);
|
||||
Comparator<?> comparator = blockingQueue.comparator();
|
||||
assertNotNull(comparator);
|
||||
assertEquals("ftpInbound", adapter.getComponentName());
|
||||
assertEquals("ftp:inbound-channel-adapter", adapter.getComponentType());
|
||||
assertNotNull(TestUtils.getPropertyValue(adapter, "poller"));
|
||||
assertEquals(ac.getBean("ftpChannel"), TestUtils.getPropertyValue(adapter, "outputChannel"));
|
||||
assertEquals("ftpInbound", ftpInbound.getComponentName());
|
||||
assertEquals("ftp:inbound-channel-adapter", ftpInbound.getComponentType());
|
||||
assertNotNull(TestUtils.getPropertyValue(ftpInbound, "poller"));
|
||||
assertEquals(context.getBean("ftpChannel"), TestUtils.getPropertyValue(ftpInbound, "outputChannel"));
|
||||
FtpInboundFileSynchronizingMessageSource inbound =
|
||||
(FtpInboundFileSynchronizingMessageSource) TestUtils.getPropertyValue(adapter, "source");
|
||||
(FtpInboundFileSynchronizingMessageSource) TestUtils.getPropertyValue(ftpInbound, "source");
|
||||
|
||||
FtpInboundFileSynchronizer fisync =
|
||||
(FtpInboundFileSynchronizer) TestUtils.getPropertyValue(inbound, "synchronizer");
|
||||
@@ -86,7 +106,7 @@ public class FtpInboundChannelAdapterParserTests {
|
||||
assertNotNull(filter);
|
||||
Object sessionFactory = TestUtils.getPropertyValue(fisync, "remoteFileTemplate.sessionFactory");
|
||||
assertTrue(DefaultFtpSessionFactory.class.isAssignableFrom(sessionFactory.getClass()));
|
||||
FileListFilter<?> acceptAllFilter = ac.getBean("acceptAllFilter", FileListFilter.class);
|
||||
FileListFilter<?> acceptAllFilter = context.getBean("acceptAllFilter", FileListFilter.class);
|
||||
assertTrue(TestUtils.getPropertyValue(inbound, "fileSource.scanner.filter.fileFilters", Collection.class).contains(acceptAllFilter));
|
||||
final AtomicReference<Method> genMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(AbstractInboundFileSynchronizer.class, new MethodCallback() {
|
||||
@@ -104,49 +124,26 @@ public class FtpInboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void cachingSessionFactory() throws Exception{
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext(
|
||||
"FtpInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
SourcePollingChannelAdapter adapter = ac.getBean("simpleAdapterWithCachedSessions", SourcePollingChannelAdapter.class);
|
||||
Object sessionFactory = TestUtils.getPropertyValue(adapter, "source.synchronizer.remoteFileTemplate.sessionFactory");
|
||||
Object sessionFactory = TestUtils.getPropertyValue(simpleAdapterWithCachedSessions, "source.synchronizer.remoteFileTemplate.sessionFactory");
|
||||
assertEquals(CachingSessionFactory.class, sessionFactory.getClass());
|
||||
FtpInboundFileSynchronizer fisync =
|
||||
TestUtils.getPropertyValue(adapter, "source.synchronizer", FtpInboundFileSynchronizer.class);
|
||||
TestUtils.getPropertyValue(simpleAdapterWithCachedSessions, "source.synchronizer", FtpInboundFileSynchronizer.class);
|
||||
String remoteFileSeparator = (String) TestUtils.getPropertyValue(fisync, "remoteFileSeparator");
|
||||
assertNotNull(remoteFileSeparator);
|
||||
assertEquals("/", remoteFileSeparator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFtpInboundChannelAdapterCompleteNoId() throws Exception{
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Map<String, SourcePollingChannelAdapter> spcas = ac.getBeansOfType(SourcePollingChannelAdapter.class);
|
||||
SourcePollingChannelAdapter adapter = null;
|
||||
for (String key : spcas.keySet()) {
|
||||
if (!key.equals("ftpInbound") && !key.equals("simpleAdapter")){
|
||||
adapter = spcas.get(key);
|
||||
}
|
||||
}
|
||||
assertNotNull(adapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoChannel() {
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("FtpInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
// Auto-created channel
|
||||
MessageChannel autoChannel = context.getBean("autoChannel", MessageChannel.class);
|
||||
SourcePollingChannelAdapter autoChannelAdapter = context.getBean("autoChannel.adapter", SourcePollingChannelAdapter.class);
|
||||
assertSame(autoChannel, TestUtils.getPropertyValue(autoChannelAdapter, "outputChannel"));
|
||||
}
|
||||
|
||||
public static class TestSessionFactoryBean implements FactoryBean<DefaultFtpSessionFactory> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public DefaultFtpSessionFactory getObject() throws Exception {
|
||||
DefaultFtpSessionFactory factory = mock(DefaultFtpSessionFactory.class);
|
||||
Session session = mock(Session.class);
|
||||
FtpSession session = mock(FtpSession.class);
|
||||
when(factory.getSession()).thenReturn(session);
|
||||
return factory;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
auto-create-directory="false"
|
||||
remote-file-separator=""
|
||||
temporary-file-suffix=".foo"
|
||||
mode="APPEND"
|
||||
remote-filename-generator="fileNameGenerator"
|
||||
order="23"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -20,29 +20,34 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.integration.channel.PublishSubscribeChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
|
||||
import org.springframework.integration.file.remote.session.CachingSessionFactory;
|
||||
import org.springframework.integration.file.support.FileExistsMode;
|
||||
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -50,25 +55,47 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class FtpOutboundChannelAdapterParserTests {
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer simpleAdapter;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer advisedAdapter;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer withBeanExpressions;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer ftpOutbound;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer ftpOutbound2;
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer ftpOutbound3;
|
||||
|
||||
@Autowired
|
||||
private PublishSubscribeChannel ftpChannel;
|
||||
|
||||
@Autowired
|
||||
private FileNameGenerator fileNameGenerator;
|
||||
|
||||
@Test
|
||||
public void testFtpOutboundChannelAdapterComplete() throws Exception{
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = ac.getBean("ftpOutbound");
|
||||
assertTrue(consumer instanceof EventDrivenConsumer);
|
||||
PublishSubscribeChannel channel = ac.getBean("ftpChannel", PublishSubscribeChannel.class);
|
||||
assertEquals(channel, TestUtils.getPropertyValue(consumer, "inputChannel"));
|
||||
assertEquals("ftpOutbound", ((EventDrivenConsumer)consumer).getComponentName());
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(consumer, "handler", FileTransferringMessageHandler.class);
|
||||
assertEquals(ftpChannel, TestUtils.getPropertyValue(ftpOutbound, "inputChannel"));
|
||||
assertEquals("ftpOutbound", ftpOutbound.getComponentName());
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(ftpOutbound, "handler", FileTransferringMessageHandler.class);
|
||||
String remoteFileSeparator = (String) TestUtils.getPropertyValue(handler, "remoteFileTemplate.remoteFileSeparator");
|
||||
assertNotNull(remoteFileSeparator);
|
||||
assertEquals(".foo", TestUtils.getPropertyValue(handler, "remoteFileTemplate.temporaryFileSuffix", String.class));
|
||||
assertEquals("", remoteFileSeparator);
|
||||
assertEquals(ac.getBean("fileNameGenerator"), TestUtils.getPropertyValue(handler, "remoteFileTemplate.fileNameGenerator"));
|
||||
assertEquals(this.fileNameGenerator, TestUtils.getPropertyValue(handler, "remoteFileTemplate.fileNameGenerator"));
|
||||
assertEquals("UTF-8", TestUtils.getPropertyValue(handler, "remoteFileTemplate.charset"));
|
||||
assertNotNull(TestUtils.getPropertyValue(handler, "remoteFileTemplate.directoryExpressionProcessor"));
|
||||
assertNotNull(TestUtils.getPropertyValue(handler, "remoteFileTemplate.temporaryDirectoryExpressionProcessor"));
|
||||
@@ -82,13 +109,15 @@ public class FtpOutboundChannelAdapterParserTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<MessageHandler> handlers = (Set<MessageHandler>) TestUtils
|
||||
.getPropertyValue(
|
||||
TestUtils.getPropertyValue(channel, "dispatcher"),
|
||||
TestUtils.getPropertyValue(ftpChannel, "dispatcher"),
|
||||
"handlers");
|
||||
Iterator<MessageHandler> iterator = handlers.iterator();
|
||||
assertSame(TestUtils.getPropertyValue(ac.getBean("ftpOutbound2"), "handler"), iterator.next());
|
||||
assertSame(TestUtils.getPropertyValue(this.ftpOutbound2, "handler"), iterator.next());
|
||||
assertSame(handler, iterator.next());
|
||||
assertEquals(FileExistsMode.APPEND, TestUtils.getPropertyValue(ftpOutbound, "handler.mode"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Test(expected=BeanCreationException.class)
|
||||
public void testFailWithEmptyRfsAndAcdTrue() throws Exception{
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-fail.xml", this.getClass());
|
||||
@@ -96,40 +125,30 @@ public class FtpOutboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void cachingByDefault() {
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext(
|
||||
"FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object adapter = ac.getBean("simpleAdapter");
|
||||
Object sfProperty = TestUtils.getPropertyValue(adapter, "handler.remoteFileTemplate.sessionFactory");
|
||||
Object sfProperty = TestUtils.getPropertyValue(simpleAdapter, "handler.remoteFileTemplate.sessionFactory");
|
||||
assertEquals(CachingSessionFactory.class, sfProperty.getClass());
|
||||
Object innerSfProperty = TestUtils.getPropertyValue(sfProperty, "sessionFactory");
|
||||
assertEquals(DefaultFtpSessionFactory.class, innerSfProperty.getClass());
|
||||
assertEquals(FileExistsMode.REPLACE, TestUtils.getPropertyValue(simpleAdapter, "handler.mode"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adviceChain() {
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext(
|
||||
"FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object adapter = ac.getBean("advisedAdapter");
|
||||
MessageHandler handler = TestUtils.getPropertyValue(adapter, "handler", MessageHandler.class);
|
||||
MessageHandler handler = TestUtils.getPropertyValue(advisedAdapter, "handler", MessageHandler.class);
|
||||
handler.handleMessage(new GenericMessage<String>("foo"));
|
||||
assertEquals(1, adviceCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemporaryFileSuffix() {
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
FileTransferringMessageHandler<?> handler =
|
||||
(FileTransferringMessageHandler<?>)TestUtils.getPropertyValue(ac.getBean("ftpOutbound3"), "handler");
|
||||
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"remoteFileTemplate.useTemporaryFileName"));
|
||||
FileTransferringMessageHandler<?> handler =
|
||||
(FileTransferringMessageHandler<?>)TestUtils.getPropertyValue(ftpOutbound3, "handler");
|
||||
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"remoteFileTemplate.useTemporaryFileName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanExpressions() throws Exception{
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = ac.getBean("withBeanExpressions");
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(consumer, "handler", FileTransferringMessageHandler.class);
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(withBeanExpressions, "handler", FileTransferringMessageHandler.class);
|
||||
ExpressionEvaluatingMessageProcessor<?> dirExpProc = TestUtils.getPropertyValue(handler,
|
||||
"remoteFileTemplate.directoryExpressionProcessor", ExpressionEvaluatingMessageProcessor.class);
|
||||
assertNotNull(dirExpProc);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -46,6 +46,7 @@ import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -60,6 +61,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class FtpOutboundGatewayParserTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -19,35 +19,43 @@ package org.springframework.integration.ftp.config;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizer;
|
||||
import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizingMessageSource;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class FtpsInboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
private SourcePollingChannelAdapter ftpInbound;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel ftpChannel;
|
||||
|
||||
@Test
|
||||
public void testFtpsInboundChannelAdapterComplete() throws Exception{
|
||||
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpsInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
SourcePollingChannelAdapter adapter = ac.getBean("ftpInbound", SourcePollingChannelAdapter.class);
|
||||
assertEquals("ftpInbound", adapter.getComponentName());
|
||||
assertEquals("ftp:inbound-channel-adapter", adapter.getComponentType());
|
||||
assertNotNull(TestUtils.getPropertyValue(adapter, "poller"));
|
||||
assertEquals(ac.getBean("ftpChannel"), TestUtils.getPropertyValue(adapter, "outputChannel"));
|
||||
assertEquals("ftpInbound", ftpInbound.getComponentName());
|
||||
assertEquals("ftp:inbound-channel-adapter", ftpInbound.getComponentType());
|
||||
assertNotNull(TestUtils.getPropertyValue(ftpInbound, "poller"));
|
||||
assertEquals(this.ftpChannel, TestUtils.getPropertyValue(ftpInbound, "outputChannel"));
|
||||
FtpInboundFileSynchronizingMessageSource inbound =
|
||||
(FtpInboundFileSynchronizingMessageSource) TestUtils.getPropertyValue(adapter, "source");
|
||||
(FtpInboundFileSynchronizingMessageSource) TestUtils.getPropertyValue(ftpInbound, "source");
|
||||
|
||||
FtpInboundFileSynchronizer fisync =
|
||||
(FtpInboundFileSynchronizer) TestUtils.getPropertyValue(inbound, "synchronizer");
|
||||
@@ -55,19 +63,4 @@ public class FtpsInboundChannelAdapterParserTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFtpsInboundChannelAdapterCompleteNoId() throws Exception{
|
||||
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpsInboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Map<String, SourcePollingChannelAdapter> spcas = ac.getBeansOfType(SourcePollingChannelAdapter.class);
|
||||
SourcePollingChannelAdapter adapter = null;
|
||||
for (String key : spcas.keySet()) {
|
||||
if (!key.equals("ftpInbound")){
|
||||
adapter = spcas.get(key);
|
||||
}
|
||||
}
|
||||
assertNotNull(adapter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -20,13 +20,18 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
|
||||
import org.springframework.integration.ftp.session.DefaultFtpsSessionFactory;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -34,17 +39,27 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class FtpsOutboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer ftpOutbound;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel ftpChannel;
|
||||
|
||||
@Autowired
|
||||
private FileNameGenerator fileNameGenerator;
|
||||
|
||||
@Test
|
||||
public void testFtpsOutboundChannelAdapterComplete() throws Exception{
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("FtpsOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = ac.getBean("ftpOutbound");
|
||||
assertTrue(consumer instanceof EventDrivenConsumer);
|
||||
assertEquals(ac.getBean("ftpChannel"), TestUtils.getPropertyValue(consumer, "inputChannel"));
|
||||
assertEquals("ftpOutbound", ((EventDrivenConsumer)consumer).getComponentName());
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(consumer, "handler", FileTransferringMessageHandler.class);
|
||||
assertEquals(ac.getBean("fileNameGenerator"), TestUtils.getPropertyValue(handler, "remoteFileTemplate.fileNameGenerator"));
|
||||
assertTrue(ftpOutbound instanceof EventDrivenConsumer);
|
||||
assertEquals(this.ftpChannel, TestUtils.getPropertyValue(ftpOutbound, "inputChannel"));
|
||||
assertEquals("ftpOutbound", ftpOutbound.getComponentName());
|
||||
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(ftpOutbound, "handler", FileTransferringMessageHandler.class);
|
||||
assertEquals(this.fileNameGenerator, TestUtils.getPropertyValue(handler, "remoteFileTemplate.fileNameGenerator"));
|
||||
assertEquals("UTF-8", TestUtils.getPropertyValue(handler, "remoteFileTemplate.charset"));
|
||||
DefaultFtpsSessionFactory sf = TestUtils.getPropertyValue(handler, "remoteFileTemplate.sessionFactory", DefaultFtpsSessionFactory.class);
|
||||
assertEquals("localhost", TestUtils.getPropertyValue(sf, "host"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -48,20 +48,20 @@ import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.file.remote.FileInfo;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
|
||||
import org.springframework.integration.ftp.session.AbstractFtpSessionFactory;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
@@ -207,17 +207,20 @@ public class FtpOutboundTests {
|
||||
File destFile = new File(targetDir, srcFile.getName());
|
||||
destFile.deleteOnExit();
|
||||
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("FtpOutboundInsideChainTests-context.xml", getClass());
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"FtpOutboundInsideChainTests-context.xml", getClass());
|
||||
|
||||
MessageChannel channel = context.getBean("outboundChainChannel", MessageChannel.class);
|
||||
|
||||
channel.send(new GenericMessage<File>(srcFile));
|
||||
assertTrue("destination file was not created", destFile.exists());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test //INT-2275
|
||||
public void testFtpOutboundGatewayInsideChain() throws Exception {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("FtpOutboundInsideChainTests-context.xml", getClass());
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"FtpOutboundInsideChainTests-context.xml", getClass());
|
||||
|
||||
MessageChannel channel = context.getBean("ftpOutboundGatewayInsideChain", MessageChannel.class);
|
||||
|
||||
@@ -235,6 +238,7 @@ public class FtpOutboundTests {
|
||||
for (FileInfo<?> remoteFile : remoteFiles) {
|
||||
assertTrue(files.contains(remoteFile.getFilename()));
|
||||
}
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="ftpServer" class="org.springframework.integration.ftp.TesFtpServer">
|
||||
<bean id="ftpServer" class="org.springframework.integration.ftp.TestFtpServer">
|
||||
<constructor-arg value="FtpServerOutboundTests"/>
|
||||
</bean>
|
||||
|
||||
@@ -104,4 +104,35 @@
|
||||
remote-directory="ftpTarget"
|
||||
reply-channel="output"/>
|
||||
|
||||
<int:channel id="appending" />
|
||||
|
||||
<int-ftp:outbound-channel-adapter id="appender"
|
||||
session-factory="ftpSessionFactory"
|
||||
channel="appending"
|
||||
mode="APPEND"
|
||||
use-temporary-file-name="false"
|
||||
remote-directory="ftpTarget"
|
||||
auto-create-directory="true"
|
||||
remote-file-separator="/" />
|
||||
|
||||
<int:channel id="ignoring" />
|
||||
|
||||
<int-ftp:outbound-channel-adapter id="ignore"
|
||||
session-factory="ftpSessionFactory"
|
||||
channel="ignoring"
|
||||
mode="IGNORE"
|
||||
remote-directory="ftpTarget"
|
||||
auto-create-directory="true"
|
||||
remote-file-separator="/" />
|
||||
|
||||
<int:channel id="failing" />
|
||||
|
||||
<int-ftp:outbound-channel-adapter id="fail"
|
||||
session-factory="ftpSessionFactory"
|
||||
channel="failing"
|
||||
mode="FAIL"
|
||||
remote-directory="ftpTarget"
|
||||
auto-create-directory="true"
|
||||
remote-file-separator="/" />
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.ftp.outbound;
|
||||
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -42,12 +43,17 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.file.FileHeaders;
|
||||
import org.springframework.integration.file.remote.InputStreamCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.SessionCallback;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.ftp.TesFtpServer;
|
||||
import org.springframework.integration.ftp.TestFtpServer;
|
||||
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
|
||||
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -65,10 +71,10 @@ import org.springframework.util.FileCopyUtils;
|
||||
public class FtpServerOutboundTests {
|
||||
|
||||
@Autowired
|
||||
private TesFtpServer ftpServer;
|
||||
private TestFtpServer ftpServer;
|
||||
|
||||
@Autowired
|
||||
private SessionFactory<FTPFile> ftpSessionFactory;
|
||||
private DefaultFtpSessionFactory ftpSessionFactory;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
@@ -97,6 +103,15 @@ public class FtpServerOutboundTests {
|
||||
@Autowired
|
||||
private DirectChannel inboundMPutRecursiveFiltered;
|
||||
|
||||
@Autowired
|
||||
private DirectChannel appending;
|
||||
|
||||
@Autowired
|
||||
private DirectChannel ignoring;
|
||||
|
||||
@Autowired
|
||||
private DirectChannel failing;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.ftpServer.recursiveDelete(ftpServer.getTargetLocalDirectory());
|
||||
@@ -304,4 +319,39 @@ public class FtpServerOutboundTests {
|
||||
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3412FileMode() {
|
||||
Message<String> m = MessageBuilder.withPayload("foo")
|
||||
.setHeader(FileHeaders.FILENAME, "appending.txt")
|
||||
.build();
|
||||
appending.send(m);
|
||||
appending.send(m);
|
||||
|
||||
FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(ftpSessionFactory);
|
||||
assertLength6(template);
|
||||
|
||||
ignoring.send(m);
|
||||
assertLength6(template);
|
||||
try {
|
||||
failing.send(m);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (MessagingException e) {
|
||||
assertThat(e.getCause().getCause().getMessage(), containsString("The destination file already exists"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void assertLength6(FtpRemoteFileTemplate template) {
|
||||
FTPFile[] files = template.execute(new SessionCallback<FTPFile, FTPFile[]>() {
|
||||
|
||||
@Override
|
||||
public FTPFile[] doInSession(Session<FTPFile> session) throws IOException {
|
||||
return session.list("ftpTarget/appending.txt");
|
||||
}
|
||||
});
|
||||
assertEquals(1, files.length);
|
||||
assertEquals(6, files[0].getSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?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-ftp="http://www.springframework.org/schema/integration/ftp"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/ftp
|
||||
http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="ftpServer" class="org.springframework.integration.ftp.TestFtpServer">
|
||||
<constructor-arg value="FtpRemoteFileTemplateTests"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2014 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.session;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.remote.ClientCallbackWithoutResult;
|
||||
import org.springframework.integration.file.remote.SessionCallback;
|
||||
import org.springframework.integration.file.remote.SessionCallbackWithoutResult;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.ftp.TestFtpServer;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class FtpRemoteFileTemplateTests {
|
||||
|
||||
@Autowired
|
||||
private TestFtpServer ftpServer;
|
||||
|
||||
@Autowired
|
||||
private DefaultFtpSessionFactory sessionFactory;
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void setup() {
|
||||
this.ftpServer.recursiveDelete(ftpServer.getTargetLocalDirectory());
|
||||
this.ftpServer.recursiveDelete(ftpServer.getTargetFtpDirectory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testINT3412AppendStatRmdir() {
|
||||
FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(sessionFactory);
|
||||
DefaultFileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
|
||||
fileNameGenerator.setExpression("'foobar.txt'");
|
||||
template.setFileNameGenerator(fileNameGenerator);
|
||||
template.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
|
||||
template.setUseTemporaryFileName(false);
|
||||
template.execute(new SessionCallback<FTPFile, Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean doInSession(Session<FTPFile> session) throws IOException {
|
||||
session.mkdir("foo/");
|
||||
return session.mkdir("foo/bar/");
|
||||
}
|
||||
|
||||
});
|
||||
template.append(new GenericMessage<String>("foo"));
|
||||
template.append(new GenericMessage<String>("bar"));
|
||||
assertTrue(template.exists("foo/foobar.txt"));
|
||||
template.executeWithClient(new ClientCallbackWithoutResult<FTPClient>() {
|
||||
|
||||
@Override
|
||||
public void doWithClientWithoutResult(FTPClient client) {
|
||||
try {
|
||||
FTPFile[] files = client.listFiles("foo/foobar.txt");
|
||||
assertEquals(6, files[0].getSize());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
template.execute(new SessionCallbackWithoutResult<FTPFile>() {
|
||||
|
||||
@Override
|
||||
public void doInSessionWithoutResult(Session<FTPFile> session) throws IOException {
|
||||
assertTrue(session.remove("foo/foobar.txt"));
|
||||
assertTrue(session.rmdir("foo/bar/"));
|
||||
FTPFile[] files = session.list("foo/");
|
||||
assertEquals(0, files.length);
|
||||
assertTrue(session.rmdir("foo/"));
|
||||
}
|
||||
});
|
||||
assertFalse(template.exists("foo"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user