Merge remote-tracking branch 'upstream/master' into 4.0.0-WIP

Conflicts:
	spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java
	spring-integration-core/src/main/java/org/springframework/integration/support/channel/BeanFactoryChannelResolver.java
	spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java
	spring-integration-core/src/test/java/org/springframework/integration/config/AggregatorParserTests.java
	spring-integration-core/src/test/java/org/springframework/integration/config/annotation/AggregatorAnnotationTests.java
	spring-integration-core/src/test/java/org/springframework/integration/config/xml/ControlBusTests.java
	spring-integration-file/src/main/java/org/springframework/integration/file/DefaultFileNameGenerator.java
	spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java
	spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java
	spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
	spring-integration-ftp/src/test/java/org/springframework/integration/ftp/inbound/FtpInboundRemoteFileSystemSynchronizerTests.java
	spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java
	spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java
	spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java
	spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/HelloWorldInterceptor.java
	spring-integration-jpa/src/test/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayIntegrationTests.java
	spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageGroupStoreTests.java
	spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoDbMessageStoreTests.java
	spring-integration-redis/src/test/java/org/springframework/integration/redis/config/RedisOutboundChannelAdapterParserTests.java
	spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
	spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpInboundRemoteFileSystemSynchronizerTests.java
	spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpServerOutboundTests.java

Resolved.
This commit is contained in:
Gary Russell
2013-11-25 17:59:51 -05:00
191 changed files with 8774 additions and 2707 deletions

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2013 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.filters;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.integration.file.filters.AbstractPersistentAcceptOnceFileListFilter;
import org.springframework.integration.metadata.MetadataStore;
/**
* Since the super class deems files as 'not seen' if the timestamp is different, remote file
* users should use the adapter's preserve-timestamp option. Otherwise if a file is re-fetched
* it will have a new timestamp.
*
* @author Gary Russell
* @since 3.0
*
*/
public class FtpPersistentAcceptOnceFileListFilter extends AbstractPersistentAcceptOnceFileListFilter<FTPFile> {
public FtpPersistentAcceptOnceFileListFilter(MetadataStore store, String prefix) {
super(store, prefix);
}
@Override
protected long modified(FTPFile file) {
return file.getTimestamp().getTimeInMillis();
}
@Override
protected String fileName(FTPFile file) {
return file.getName();
}
}

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.integration.file.remote.AbstractFileInfo;
import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.session.FtpFileInfo;
@@ -40,6 +41,11 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway<FTPFil
super(sessionFactory, command, expression);
}
private FtpOutboundGateway(RemoteFileTemplate<FTPFile> remoteFileTemplate, String command, String expression) {
super(remoteFileTemplate, command, expression);
}
@Override
protected boolean isDirectory(FTPFile file) {
return file.isDirectory();

View File

@@ -26,73 +26,6 @@
<xsd:all>
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
</xsd:all>
<xsd:attribute name="remote-directory-expression"
type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to provide a SpEL expression which
will compute the directory
path where the files will be transferred to
(e.g., "headers.['remote_dir'] +
'/myTransfers'");
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="temporary-remote-directory-expression"
type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to provide a SpEL expression which
will compute the temporary directory
path where files will be transferred to before they are moved to the remote-directory
(e.g., "headers.['remote_dir'] +
'/temp/myTransfers'");
</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-filename-generator" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to specify a reference to
[org.springframework.integration.file.FileNameGenerator] bean.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.file.FileNameGenerator" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="remote-filename-generator-expression"
type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to provide SpEL expression which
will compute file name of
the remote file (e.g., assuming payload
is java.io.File
"payload.getName() + '.transfered'");
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="use-temporary-file-name" type="xsd:string" default="true">
<xsd:annotation>
<xsd:documentation>
Allows you to suppress using a temporary file name while writing the file.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -113,6 +46,7 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="int-file:remoteOutboundAttributeGroup" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -268,7 +202,7 @@
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="base-adapter-type">
<xsd:extension base="base-ftp-adapter-type">
<xsd:all>
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
</xsd:all>
@@ -379,7 +313,9 @@
<xsd:documentation>
Allows you to specify a reference to
[org.springframework.integration.file.filters.FileListFilter]
bean.
bean. This filter acts against the remote server view when using the 'ls'
or 'mget' commands.
Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -387,10 +323,11 @@
<xsd:annotation>
<xsd:documentation>
Allows you to provide file name pattern to
determine the file names retrieved by the ls command
determine the file names retrieved by the 'ls' and 'mget' commands
and is based
on simple pattern matching algorithm (e.g., "*.txt, fo*.txt"
etc.)
Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -398,9 +335,49 @@
<xsd:annotation>
<xsd:documentation>
Allows you to provide Regular Expression to
determine the file names retrieved by the ls command.
determine the file names retrieved by the 'ls' and 'mget' commands.
(e.g.,
"f[o]+\.txt" etc.)
Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mput-filter" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.file.filters.FileListFilter" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Allows you to specify a reference to
[org.springframework.integration.file.filters.FileListFilter]
bean. This filter acts on the local file system when using the 'mput' command.
Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mput-pattern" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to provide file name pattern to
determine the file names sent by the 'mput' command
and is based
on simple pattern matching algorithm (e.g., "*.txt, fo*.txt"
etc.)
Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mput-regex" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to provide Regular Expression to
determine the file names sent by the 'mput' command
(e.g.,
"f[o]+\.txt" etc.)
Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -486,6 +463,7 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="int-file:remoteOutboundAttributeGroup" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@@ -101,7 +101,7 @@ public class TesFtpServer {
fos.close();
targetFtpDirectory = new File(ftpRootFolder, "ftpTarget");
targetFtpDirectory.mkdirs();
targetFtpDirectory.mkdir();
}
};
this.localFolder = new TemporaryFolder() {
@@ -123,7 +123,7 @@ public class TesFtpServer {
file.createNewFile();
targetLocalDirectory = new File(rootFolder, "localTarget");
targetLocalDirectory.mkdirs();
targetLocalDirectory.mkdir();
}
};
}
@@ -183,14 +183,16 @@ public class TesFtpServer {
}
public static void recursiveDelete(File file) {
public void recursiveDelete(File file) {
File[] files = file.listFiles();
if (files != null) {
for (File each : files) {
recursiveDelete(each);
}
}
file.delete();
if (!(file.equals(this.targetFtpDirectory) || file.equals(this.targetLocalDirectory))) {
file.delete();
}
}

View File

@@ -84,7 +84,7 @@ public class FtpInboundChannelAdapterParserTests {
assertEquals("", remoteFileSeparator);
FtpSimplePatternFileListFilter filter = (FtpSimplePatternFileListFilter) TestUtils.getPropertyValue(fisync, "filter");
assertNotNull(filter);
Object sessionFactory = TestUtils.getPropertyValue(fisync, "sessionFactory");
Object sessionFactory = TestUtils.getPropertyValue(fisync, "remoteFileTemplate.sessionFactory");
assertTrue(DefaultFtpSessionFactory.class.isAssignableFrom(sessionFactory.getClass()));
FileListFilter<?> acceptAllFilter = ac.getBean("acceptAllFilter", FileListFilter.class);
assertTrue(TestUtils.getPropertyValue(inbound, "fileSource.scanner.filter.fileFilters", Collection.class).contains(acceptAllFilter));
@@ -107,7 +107,7 @@ public class FtpInboundChannelAdapterParserTests {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"FtpInboundChannelAdapterParserTests-context.xml", this.getClass());
SourcePollingChannelAdapter adapter = ac.getBean("simpleAdapterWithCachedSessions", SourcePollingChannelAdapter.class);
Object sessionFactory = TestUtils.getPropertyValue(adapter, "source.synchronizer.sessionFactory");
Object sessionFactory = TestUtils.getPropertyValue(adapter, "source.synchronizer.remoteFileTemplate.sessionFactory");
assertEquals(CachingSessionFactory.class, sessionFactory.getClass());
FtpInboundFileSynchronizer fisync =
TestUtils.getPropertyValue(adapter, "source.synchronizer", FtpInboundFileSynchronizer.class);
@@ -142,6 +142,7 @@ public class FtpInboundChannelAdapterParserTests {
public static class TestSessionFactoryBean implements FactoryBean<DefaultFtpSessionFactory> {
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public DefaultFtpSessionFactory getObject() throws Exception {
DefaultFtpSessionFactory factory = mock(DefaultFtpSessionFactory.class);
@@ -150,10 +151,12 @@ public class FtpInboundChannelAdapterParserTests {
return factory;
}
@Override
public Class<?> getObjectType() {
return DefaultFtpSessionFactory.class;
}
@Override
public boolean isSingleton() {
return true;
}

View File

@@ -64,15 +64,15 @@ public class FtpOutboundChannelAdapterParserTests {
assertEquals(channel, TestUtils.getPropertyValue(consumer, "inputChannel"));
assertEquals("ftpOutbound", ((EventDrivenConsumer)consumer).getComponentName());
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(consumer, "handler", FileTransferringMessageHandler.class);
String remoteFileSeparator = (String) TestUtils.getPropertyValue(handler, "remoteFileSeparator");
String remoteFileSeparator = (String) TestUtils.getPropertyValue(handler, "remoteFileTemplate.remoteFileSeparator");
assertNotNull(remoteFileSeparator);
assertEquals(".foo", TestUtils.getPropertyValue(handler, "temporaryFileSuffix", String.class));
assertEquals(".foo", TestUtils.getPropertyValue(handler, "remoteFileTemplate.temporaryFileSuffix", String.class));
assertEquals("", remoteFileSeparator);
assertEquals(ac.getBean("fileNameGenerator"), TestUtils.getPropertyValue(handler, "fileNameGenerator"));
assertEquals("UTF-8", TestUtils.getPropertyValue(handler, "charset"));
assertNotNull(TestUtils.getPropertyValue(handler, "directoryExpressionProcessor"));
assertNotNull(TestUtils.getPropertyValue(handler, "temporaryDirectoryExpressionProcessor"));
Object sfProperty = TestUtils.getPropertyValue(handler, "sessionFactory");
assertEquals(ac.getBean("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"));
Object sfProperty = TestUtils.getPropertyValue(handler, "remoteFileTemplate.sessionFactory");
assertEquals(DefaultFtpSessionFactory.class, sfProperty.getClass());
DefaultFtpSessionFactory sessionFactory = (DefaultFtpSessionFactory) sfProperty;
assertEquals("localhost", TestUtils.getPropertyValue(sessionFactory, "host"));
@@ -99,7 +99,7 @@ public class FtpOutboundChannelAdapterParserTests {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
Object adapter = ac.getBean("simpleAdapter");
Object sfProperty = TestUtils.getPropertyValue(adapter, "handler.sessionFactory");
Object sfProperty = TestUtils.getPropertyValue(adapter, "handler.remoteFileTemplate.sessionFactory");
assertEquals(CachingSessionFactory.class, sfProperty.getClass());
Object innerSfProperty = TestUtils.getPropertyValue(sfProperty, "sessionFactory");
assertEquals(DefaultFtpSessionFactory.class, innerSfProperty.getClass());
@@ -121,7 +121,7 @@ public class FtpOutboundChannelAdapterParserTests {
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
FileTransferringMessageHandler<?> handler =
(FileTransferringMessageHandler<?>)TestUtils.getPropertyValue(ac.getBean("ftpOutbound3"), "handler");
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"useTemporaryFileName"));
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"remoteFileTemplate.useTemporaryFileName"));
}
@Test
@@ -131,16 +131,16 @@ public class FtpOutboundChannelAdapterParserTests {
Object consumer = ac.getBean("withBeanExpressions");
FileTransferringMessageHandler<?> handler = TestUtils.getPropertyValue(consumer, "handler", FileTransferringMessageHandler.class);
ExpressionEvaluatingMessageProcessor<?> dirExpProc = TestUtils.getPropertyValue(handler,
"directoryExpressionProcessor", ExpressionEvaluatingMessageProcessor.class);
"remoteFileTemplate.directoryExpressionProcessor", ExpressionEvaluatingMessageProcessor.class);
assertNotNull(dirExpProc);
Message<String> message = MessageBuilder.withPayload("qux").build();
assertEquals("foo", dirExpProc.processMessage(message));
ExpressionEvaluatingMessageProcessor<?> tempDirExpProc = TestUtils.getPropertyValue(handler,
"temporaryDirectoryExpressionProcessor", ExpressionEvaluatingMessageProcessor.class);
"remoteFileTemplate.temporaryDirectoryExpressionProcessor", ExpressionEvaluatingMessageProcessor.class);
assertNotNull(tempDirExpProc);
assertEquals("bar", tempDirExpProc.processMessage(message));
DefaultFileNameGenerator generator = TestUtils.getPropertyValue(handler,
"fileNameGenerator", DefaultFileNameGenerator.class);
"remoteFileTemplate.fileNameGenerator", DefaultFileNameGenerator.class);
assertNotNull(generator);
assertEquals("baz", generator.generateFileName(message));
}

View File

@@ -29,6 +29,7 @@
command-options="-1 -f"
expression="payload"
order="1"
mput-regex=".*"
/>
<bean id="fooString" class="java.lang.String">
@@ -49,6 +50,7 @@
order="2"
requires-reply="false"
local-filename-generator-expression="#remoteFileName.toUpperCase() + '.a' + @fooString"
mput-pattern="*"
>
<int-ftp:request-handler-advice-chain>
<bean class="org.springframework.integration.ftp.config.FtpOutboundGatewayParserTests$FooAdvice" />
@@ -66,6 +68,26 @@
order="1"
/>
<int-ftp:outbound-gateway id="gateway4"
session-factory="csf"
request-channel="inbound1"
reply-channel="outbound"
command="mput"
expression="payload"
remote-directory="/foo"
remote-file-separator="X"
auto-create-directory="true"
remote-filename-generator="fileNameGenerator"
temporary-remote-directory="/bar"
rename-expression="'foo'"
order="1"
mput-regex=".*"
/>
<bean id="fileNameGenerator" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.integration.file.FileNameGenerator"/>
</bean>
<int-ftp:outbound-gateway id="withBeanExpression"
local-directory="local-test-dir"
session-factory="sf"

View File

@@ -18,28 +18,34 @@ package org.springframework.integration.ftp.config;
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.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.expression.Expression;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Command;
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Option;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
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.support.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ReflectionUtils;
@@ -65,17 +71,23 @@ public class FtpOutboundGatewayParserTests {
@Autowired
AbstractEndpoint gateway3;
@Autowired
AbstractEndpoint gateway4;
@Autowired
AbstractEndpoint withBeanExpression;
@Autowired
FileNameGenerator generator;
private static volatile int adviceCalled;
@Test
public void testGateway1() {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway1,
"handler", FtpOutboundGateway.class);
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileSeparator"));
assertNotNull(TestUtils.getPropertyValue(gateway, "sessionFactory"));
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileTemplate.remoteFileSeparator"));
assertNotNull(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory"));
assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals("local-test-dir", TestUtils.getPropertyValue(gateway, "localDirectoryExpression.literalValue"));
assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
@@ -90,15 +102,16 @@ public class FtpOutboundGatewayParserTests {
Long sendTimeout = TestUtils.getPropertyValue(gateway, "messagingTemplate.sendTimeout", Long.class);
assertEquals(Long.valueOf(777), sendTimeout);
assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertThat(TestUtils.getPropertyValue(gateway, "mputFilter"), Matchers.instanceOf(RegexPatternFileListFilter.class));
}
@Test
public void testGateway2() throws Exception {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway2,
"handler", FtpOutboundGateway.class);
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileSeparator"));
assertNotNull(TestUtils.getPropertyValue(gateway, "sessionFactory"));
assertTrue(TestUtils.getPropertyValue(gateway, "sessionFactory") instanceof CachingSessionFactory);
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileTemplate.remoteFileSeparator"));
assertNotNull(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory"));
assertTrue(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory") instanceof CachingSessionFactory);
assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals("local-test-dir", TestUtils.getPropertyValue(gateway, "localDirectoryExpression.literalValue"));
assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
@@ -124,18 +137,37 @@ public class FtpOutboundGatewayParserTests {
}
});
assertEquals("FOO.afoo", genMethod.get().invoke(gateway, new GenericMessage<String>(""), "foo"));
assertThat(TestUtils.getPropertyValue(gateway, "mputFilter"), Matchers.instanceOf(SimplePatternFileListFilter.class));
}
@Test
public void testGatewayMv() {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway3,
"handler", FtpOutboundGateway.class);
assertNotNull(TestUtils.getPropertyValue(gateway, "sessionFactory"));
assertNotNull(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory"));
assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals(Command.MV, TestUtils.getPropertyValue(gateway, "command"));
assertEquals("'foo'", TestUtils.getPropertyValue(gateway, "renameProcessor.expression.expression"));
}
@Test
public void testGatewayMPut() {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway4,
"handler", FtpOutboundGateway.class);
assertNotNull(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory"));
assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals(Command.MPUT, TestUtils.getPropertyValue(gateway, "command"));
assertEquals("'foo'", TestUtils.getPropertyValue(gateway, "renameProcessor.expression.expression"));
assertThat(TestUtils.getPropertyValue(gateway, "mputFilter"), Matchers.instanceOf(RegexPatternFileListFilter.class));
assertSame(generator, TestUtils.getPropertyValue(gateway, "remoteFileTemplate.fileNameGenerator"));
assertEquals("/foo",
TestUtils.getPropertyValue(gateway, "remoteFileTemplate.directoryExpressionProcessor.expression", Expression.class)
.getExpressionString());
assertEquals("/bar",
TestUtils.getPropertyValue(gateway, "remoteFileTemplate.temporaryDirectoryExpressionProcessor.expression", Expression.class)
.getExpressionString());
}
@Test
public void testWithBeanExpression() {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(withBeanExpression,

View File

@@ -44,9 +44,9 @@ public class FtpsOutboundChannelAdapterParserTests {
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, "fileNameGenerator"));
assertEquals("UTF-8", TestUtils.getPropertyValue(handler, "charset"));
DefaultFtpsSessionFactory sf = TestUtils.getPropertyValue(handler, "sessionFactory", DefaultFtpsSessionFactory.class);
assertEquals(ac.getBean("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"));
assertEquals(22, TestUtils.getPropertyValue(sf, "port"));
}

View File

@@ -33,11 +33,14 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
@@ -46,8 +49,13 @@ import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.ftp.filters.FtpPersistentAcceptOnceFileListFilter;
import org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter;
import org.springframework.integration.ftp.session.AbstractFtpSessionFactory;
import org.springframework.integration.metadata.PropertiesPersistingMetadataStore;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
/**
@@ -61,6 +69,7 @@ public class FtpInboundRemoteFileSystemSynchronizerTests {
private static FTPClient ftpClient = mock(FTPClient.class);
@Before
@After
public void cleanup(){
File file = new File("test");
@@ -86,7 +95,16 @@ public class FtpInboundRemoteFileSystemSynchronizerTests {
synchronizer.setDeleteRemoteFiles(true);
synchronizer.setPreserveTimestamp(true);
synchronizer.setRemoteDirectory("remote-test-dir");
synchronizer.setFilter(new FtpRegexPatternFileListFilter(".*\\.test$"));
FtpRegexPatternFileListFilter patternFilter = new FtpRegexPatternFileListFilter(".*\\.test$");
PropertiesPersistingMetadataStore store = new PropertiesPersistingMetadataStore();
store.setBaseDirectory("test");
FtpPersistentAcceptOnceFileListFilter persistFilter =
new FtpPersistentAcceptOnceFileListFilter(store, "foo");
List<FileListFilter<FTPFile>> filters = new ArrayList<FileListFilter<FTPFile>>();
filters.add(persistFilter);
filters.add(patternFilter);
CompositeFileListFilter<FTPFile> filter = new CompositeFileListFilter<FTPFile>(filters);
synchronizer.setFilter(filter);
synchronizer.setIntegrationEvaluationContext(ExpressionUtils.createStandardEvaluationContext());
ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
@@ -120,28 +138,49 @@ public class FtpInboundRemoteFileSystemSynchronizerTests {
assertTrue(new File("test/A.TEST.a").exists());
assertTrue(new File("test/B.TEST.a").exists());
TestUtils.getPropertyValue(ms, "localFileListFilter.seen", Queue.class).clear();
new File("test/A.TEST.a").delete();
new File("test/B.TEST.a").delete();
// the remote filter should prevent a re-fetch
nothing = ms.receive();
assertNull(nothing);
}
public static class TestFtpSessionFactory extends AbstractFtpSessionFactory<FTPClient> {
private final Collection<Object> ftpFiles = new ArrayList<Object>();
private void init() {
String[] files = new File("remote-test-dir").list();
for (String fileName : files) {
FTPFile file = new FTPFile();
file.setName(fileName);
file.setType(FTPFile.FILE_TYPE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 1);
file.setTimestamp(calendar);
ftpFiles.add(file);
}
}
@Override
protected FTPClient createClientInstance() {
if (this.ftpFiles.size() == 0) {
this.init();
}
try {
when(ftpClient.getReplyCode()).thenReturn(250);
when(ftpClient.login("kermit", "frog")).thenReturn(true);
when(ftpClient.changeWorkingDirectory(Mockito.anyString())).thenReturn(true);
String[] files = new File("remote-test-dir").list();
Collection<Object> ftpFiles = new ArrayList<Object>();
for (String fileName : files) {
FTPFile file = new FTPFile();
file.setName(fileName);
file.setType(FTPFile.FILE_TYPE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 1);
file.setTimestamp(calendar);
ftpFiles.add(file);
when(ftpClient.retrieveFile(Mockito.eq("remote-test-dir/" + fileName) , Mockito.any(OutputStream.class))).thenReturn(true);
}
when(ftpClient.listFiles("remote-test-dir")).thenReturn(ftpFiles.toArray(new FTPFile[]{}));

View File

@@ -56,6 +56,7 @@ 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;
@@ -94,6 +95,7 @@ public class FtpOutboundTests {
FileTransferringMessageHandler<FTPFile> handler = new FileTransferringMessageHandler<FTPFile>(sessionFactory);
handler.setRemoteDirectoryExpression(new LiteralExpression("remote-target-dir"));
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return "handlerContent.test";
}
@@ -117,6 +119,7 @@ public class FtpOutboundTests {
FileTransferringMessageHandler<FTPFile> handler = new FileTransferringMessageHandler<FTPFile>(sessionFactory);
handler.setRemoteDirectoryExpression(new LiteralExpression("remote-target-dir"));
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return "handlerContent.test";
}
@@ -138,6 +141,7 @@ public class FtpOutboundTests {
FileTransferringMessageHandler<FTPFile> handler = new FileTransferringMessageHandler<FTPFile>(sessionFactory);
handler.setRemoteDirectoryExpression(new LiteralExpression(targetDir.getName()));
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return ((File)message.getPayload()).getName() + ".test";
}
@@ -163,6 +167,7 @@ public class FtpOutboundTests {
FileTransferringMessageHandler<FTPFile> handler = new FileTransferringMessageHandler<FTPFile>(sessionFactory);
handler.setRemoteDirectoryExpression(new LiteralExpression(targetDir.getName()));
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return ((File)message.getPayload()).getName() + ".test";
}
@@ -172,7 +177,7 @@ public class FtpOutboundTests {
File srcFile = new File(UUID.randomUUID() + ".txt");
Log logger = spy(TestUtils.getPropertyValue(handler, "logger", Log.class));
Log logger = spy(TestUtils.getPropertyValue(handler, "remoteFileTemplate.logger", Log.class));
when(logger.isWarnEnabled()).thenReturn(true);
final AtomicReference<String> logged = new AtomicReference<String>();
doAnswer(new Answer<Object>(){
@@ -184,7 +189,8 @@ public class FtpOutboundTests {
return null;
}
}).when(logger).warn(Mockito.anyString());
new DirectFieldAccessor(handler).setPropertyValue("logger", logger);
RemoteFileTemplate<?> template = TestUtils.getPropertyValue(handler, "remoteFileTemplate", RemoteFileTemplate.class);
new DirectFieldAccessor(template).setPropertyValue("logger", logger);
handler.handleMessage(new GenericMessage<File>(srcFile));
assertNotNull(logged.get());
assertEquals("File " + srcFile.toString() + " does not exist", logged.get());
@@ -242,6 +248,7 @@ public class FtpOutboundTests {
when(ftpClient.changeWorkingDirectory(Mockito.anyString())).thenReturn(true);
when(ftpClient.printWorkingDirectory()).thenReturn("remote-target-dir");
when(ftpClient.storeFile(Mockito.anyString(), Mockito.any(InputStream.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
String fileName = (String) invocation.getArguments()[0];
InputStream fis = (InputStream) invocation.getArguments()[1];
@@ -250,6 +257,7 @@ public class FtpOutboundTests {
}
});
when(ftpClient.rename(Mockito.anyString(), Mockito.anyString())).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation)
throws Throwable {
File file = new File((String) invocation.getArguments()[0]);

View File

@@ -68,4 +68,40 @@
local-filename-generator-expression="#remoteFileName.replaceFirst('ftpSource', 'localTarget')"
reply-channel="output"/>
<int:channel id="inboundMPut"/>
<int-ftp:outbound-gateway session-factory="ftpSessionFactory"
request-channel="inboundMPut"
command="mput"
auto-create-directory="true"
filename-pattern="*.txt"
expression="payload"
remote-directory="ftpTarget"
reply-channel="output"/>
<int:channel id="inboundMPutRecursive"/>
<int-ftp:outbound-gateway session-factory="ftpSessionFactory"
request-channel="inboundMPutRecursive"
command="mput"
command-options="-R"
auto-create-directory="true"
filename-pattern="*.txt"
expression="payload"
remote-directory="ftpTarget"
reply-channel="output"/>
<int:channel id="inboundMPutRecursiveFiltered"/>
<int-ftp:outbound-gateway session-factory="ftpSessionFactory"
request-channel="inboundMPutRecursiveFiltered"
command="mput"
command-options="-R"
mput-regex="(.*1.txt|sub.*)"
auto-create-directory="true"
filename-pattern="*.txt"
expression="payload"
remote-directory="ftpTarget"
reply-channel="output"/>
</beans>

View File

@@ -16,24 +16,36 @@
package org.springframework.integration.ftp.outbound;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.net.ftp.FTPFile;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.remote.InputStreamCallback;
import org.springframework.integration.file.remote.RemoteFileTemplate;
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.messaging.Message;
import org.springframework.messaging.PollableChannel;
@@ -44,6 +56,8 @@ import org.springframework.util.FileCopyUtils;
/**
* @author Artem Bilan
* @author Gary Russell
*
* @since 3.0
*/
@ContextConfiguration
@@ -51,7 +65,10 @@ import org.springframework.util.FileCopyUtils;
public class FtpServerOutboundTests {
@Autowired
public TesFtpServer ftpServer;
private TesFtpServer ftpServer;
@Autowired
private SessionFactory<FTPFile> ftpSessionFactory;
@Autowired
private PollableChannel output;
@@ -71,10 +88,19 @@ public class FtpServerOutboundTests {
@Autowired
private DirectChannel inboundMGetRecursiveFiltered;
@Autowired
private DirectChannel inboundMPut;
@Autowired
private DirectChannel inboundMPutRecursive;
@Autowired
private DirectChannel inboundMPutRecursiveFiltered;
@Before
public void setup() {
TesFtpServer.recursiveDelete(ftpServer.getTargetLocalDirectory());
TesFtpServer.recursiveDelete(ftpServer.getTargetFtpDirectory());
this.ftpServer.recursiveDelete(ftpServer.getTargetLocalDirectory());
this.ftpServer.recursiveDelete(ftpServer.getTargetFtpDirectory());
}
@Test
@@ -176,7 +202,7 @@ public class FtpServerOutboundTests {
@Test
public void testInt3100RawGET() throws Exception {
Session<?> session = this.ftpServer.ftpSessionFactory().getSession();
Session<?> session = this.ftpSessionFactory.getSession();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileCopyUtils.copy(session.readRaw("ftpSource/ftpSource1.txt"), baos);
assertTrue(session.finalizeRaw());
@@ -190,5 +216,90 @@ public class FtpServerOutboundTests {
session.close();
}
@Test
public void testRawGETWithTemplate() throws Exception {
RemoteFileTemplate<FTPFile> template = new RemoteFileTemplate<FTPFile>(this.ftpSessionFactory);
template.setFileNameExpression(new SpelExpressionParser().parseExpression("payload"));
template.setBeanFactory(mock(BeanFactory.class));
template.afterPropertiesSet();
final ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
assertTrue(template.get(new GenericMessage<String>("ftpSource/ftpSource1.txt"), new InputStreamCallback() {
@Override
public void doWithInputStream(InputStream stream) throws IOException {
FileCopyUtils.copy(stream, baos1);
}
}));
assertEquals("source1", new String(baos1.toByteArray()));
final ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
assertTrue(template.get(new GenericMessage<String>("ftpSource/ftpSource2.txt"), new InputStreamCallback() {
@Override
public void doWithInputStream(InputStream stream) throws IOException {
FileCopyUtils.copy(stream, baos2);
}
}));
assertEquals("source2", new String(baos2.toByteArray()));
}
@Test
public void testInt3088MPutNotRecursive() {
this.inboundMPut.send(new GenericMessage<File>(this.ftpServer.getSourceLocalDirectory()));
@SuppressWarnings("unchecked")
Message<List<String>> out = (Message<List<String>>) this.output.receive(1000);
assertNotNull(out);
assertEquals(2, out.getPayload().size());
assertThat(out.getPayload().get(0),
not(equalTo(out.getPayload().get(1))));
assertThat(
out.getPayload().get(0),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt")));
assertThat(
out.getPayload().get(1),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt")));
}
@Test
public void testInt3088MPutRecursive() {
this.inboundMPutRecursive.send(new GenericMessage<File>(this.ftpServer.getSourceLocalDirectory()));
@SuppressWarnings("unchecked")
Message<List<String>> out = (Message<List<String>>) this.output.receive(1000);
assertNotNull(out);
assertEquals(3, out.getPayload().size());
assertThat(out.getPayload().get(0),
not(equalTo(out.getPayload().get(1))));
assertThat(
out.getPayload().get(0),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt"),
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
assertThat(
out.getPayload().get(1),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt"),
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
assertThat(
out.getPayload().get(2),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt"),
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
}
@Test
public void testInt3088MPutRecursiveFiltered() {
this.inboundMPutRecursiveFiltered.send(new GenericMessage<File>(this.ftpServer.getSourceLocalDirectory()));
@SuppressWarnings("unchecked")
Message<List<String>> out = (Message<List<String>>) this.output.receive(1000);
assertNotNull(out);
assertEquals(2, out.getPayload().size());
assertThat(out.getPayload().get(0),
not(equalTo(out.getPayload().get(1))));
assertThat(
out.getPayload().get(0),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt"),
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
assertThat(
out.getPayload().get(1),
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt"),
equalTo("ftpTarget/subLocalSource/subLocalSource1.txt")));
}
}