INT-3129: FTP local-filename-generator-expression
* Add `local-filename-generator-expression` attribute to FTP and SFTP Outbound Gateway * Refactoring for `(S)FtpOutboundGatewayParser` * Add `local-filename-generator-expression` tests * Add 'What's New' and attribute description JIRA: https://jira.springsource.org/browse/INT-3129 Polishing Doc Polishing Assert attribute is only set for get/mget Move tests to the get gateways
This commit is contained in:
committed by
Gary Russell
parent
bbf93e1385
commit
417c848c0b
@@ -19,6 +19,7 @@ import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -55,7 +56,16 @@ public abstract class AbstractRemoteFileOutboundGatewayParser extends AbstractCo
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "local-directory");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-local-directory");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "order");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "rename-expression"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply"); return builder;
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "rename-expression");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
|
||||
String localFileGeneratorExpression = element.getAttribute("local-filename-generator-expression");
|
||||
if (StringUtils.hasText(localFileGeneratorExpression)) {
|
||||
BeanDefinitionBuilder localFileGeneratorExpressionBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class);
|
||||
localFileGeneratorExpressionBuilder.addConstructorArgValue(localFileGeneratorExpression);
|
||||
builder.addPropertyValue("localFilenameGeneratorExpression", localFileGeneratorExpressionBuilder.getBeanDefinition());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected void configureFilter(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
|
||||
@@ -77,21 +87,21 @@ public abstract class AbstractRemoteFileOutboundGatewayParser extends AbstractCo
|
||||
}
|
||||
else if (hasFileNamePattern) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
this.getSimplePatternFileListFilterClassname());
|
||||
this.getSimplePatternFileListFilterClassName());
|
||||
filterBuilder.addConstructorArgValue(fileNamePattern);
|
||||
builder.addPropertyValue("filter", filterBuilder.getBeanDefinition());
|
||||
}
|
||||
else if (hasFileNameRegex) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
this.getRegexPatternFileListFilterClassname());
|
||||
this.getRegexPatternFileListFilterClassName());
|
||||
filterBuilder.addConstructorArgValue(fileNameRegex);
|
||||
builder.addPropertyValue("filter", filterBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getRegexPatternFileListFilterClassname();
|
||||
protected abstract String getRegexPatternFileListFilterClassName();
|
||||
|
||||
protected abstract String getSimplePatternFileListFilterClassname();
|
||||
protected abstract String getSimplePatternFileListFilterClassName();
|
||||
|
||||
protected abstract String getGatewayClassName();
|
||||
|
||||
|
||||
@@ -29,9 +29,12 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.integration.file.FileHeaders;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.AbstractFileInfo;
|
||||
@@ -49,6 +52,7 @@ import org.springframework.util.StringUtils;
|
||||
* Base class for Outbound Gateways that perform remote file operations.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.1
|
||||
*/
|
||||
public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReplyProducingMessageHandler {
|
||||
@@ -178,6 +182,8 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
private volatile FileListFilter<F> filter;
|
||||
|
||||
|
||||
private volatile Expression localFilenameGeneratorExpression;
|
||||
|
||||
public AbstractRemoteFileOutboundGateway(SessionFactory<F> sessionFactory, String command,
|
||||
String expression) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
@@ -249,6 +255,12 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
new SpelExpressionParser().parseExpression(expression));
|
||||
}
|
||||
|
||||
public void setLocalFilenameGeneratorExpression(Expression localFilenameGeneratorExpression) {
|
||||
Assert.notNull(localFilenameGeneratorExpression, "'localFilenameGeneratorExpression' must not be null");
|
||||
this.localFilenameGeneratorExpression = localFilenameGeneratorExpression;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
@@ -334,7 +346,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
if (remoteDir.length() == 0) {
|
||||
remoteDir = this.remoteFileSeparator;
|
||||
}
|
||||
File payload = get(session, remoteFilePath, remoteFilename, true);
|
||||
File payload = get(requestMessage, session, remoteFilePath, remoteFilename, true);
|
||||
return MessageBuilder.withPayload(payload)
|
||||
.setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir)
|
||||
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
|
||||
@@ -348,7 +360,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
if (remoteDir.length() == 0) {
|
||||
remoteDir = this.remoteFileSeparator;
|
||||
}
|
||||
List<File> payload = mGet(session, remoteDir, remoteFilename);
|
||||
List<File> payload = mGet(requestMessage, session, remoteDir, remoteFilename);
|
||||
return MessageBuilder.withPayload(payload)
|
||||
.setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir)
|
||||
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
|
||||
@@ -454,11 +466,13 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
|
||||
/**
|
||||
* Copy a remote file to the configured local directory.
|
||||
*
|
||||
* @param message
|
||||
* @param session
|
||||
* @param remoteFilePath
|
||||
* @throws IOException
|
||||
*/
|
||||
protected File get(Session<F> session, String remoteFilePath, String remoteFilename, boolean lsFirst)
|
||||
protected File get(Message<?> message, Session<F> session, String remoteFilePath, String remoteFilename, boolean lsFirst)
|
||||
throws IOException {
|
||||
F[] files = null;
|
||||
if (lsFirst) {
|
||||
@@ -467,7 +481,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
throw new MessagingException(remoteFilePath + " is not a file");
|
||||
}
|
||||
}
|
||||
File localFile = new File(this.localDirectory, remoteFilename);
|
||||
File localFile = new File(this.localDirectory, this.generateLocalFileName(message, remoteFilename));
|
||||
if (!localFile.exists()) {
|
||||
String tempFileName = localFile.getAbsolutePath() + this.temporaryFileSuffix;
|
||||
File tempFile = new File(tempFileName);
|
||||
@@ -488,6 +502,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
fileOutputStream.close();
|
||||
}
|
||||
catch (Exception ignored2) {
|
||||
//Ignore it
|
||||
}
|
||||
}
|
||||
if (!tempFile.renameTo(localFile)) {
|
||||
@@ -503,8 +518,8 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
}
|
||||
}
|
||||
|
||||
protected List<File> mGet(Session<F> session, String remoteDirectory,
|
||||
String remoteFilename) throws IOException {
|
||||
protected List<File> mGet(Message<?> message, Session<F> session, String remoteDirectory,
|
||||
String remoteFilename) throws IOException {
|
||||
String path = generateFullPath(remoteDirectory, remoteFilename);
|
||||
String[] fileNames = session.listNames(path);
|
||||
if (fileNames == null) {
|
||||
@@ -519,11 +534,11 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
File file;
|
||||
if (fileName.contains(this.remoteFileSeparator) &&
|
||||
fileName.startsWith(remoteDirectory)) { // the server returned the full path
|
||||
file = this.get(session, fileName,
|
||||
file = this.get(message, session, fileName,
|
||||
fileName.substring(fileName.lastIndexOf(this.remoteFileSeparator)), false);
|
||||
}
|
||||
else {
|
||||
file = this.get(session, generateFullPath(remoteDirectory, fileName), fileName, false);
|
||||
file = this.get(message, session, generateFullPath(remoteDirectory, fileName), fileName, false);
|
||||
}
|
||||
files.add(file);
|
||||
}
|
||||
@@ -573,6 +588,15 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
|
||||
session.rename(remoteFilePath, remoteFileNewPath);
|
||||
}
|
||||
|
||||
private String generateLocalFileName(Message<?> message, String remoteFileName){
|
||||
if (this.localFilenameGeneratorExpression != null){
|
||||
EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
|
||||
evaluationContext.setVariable("remoteFileName", remoteFileName);
|
||||
return this.localFilenameGeneratorExpression.getValue(evaluationContext, message, String.class);
|
||||
}
|
||||
return remoteFileName;
|
||||
}
|
||||
|
||||
abstract protected boolean isDirectory(F file);
|
||||
|
||||
abstract protected boolean isLink(F file);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
@@ -16,28 +16,30 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.file.config.AbstractRemoteFileOutboundGatewayParser;
|
||||
import org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter;
|
||||
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayParser {
|
||||
|
||||
private static final String BASE_PACKAGE = "org.springframework.integration.ftp";
|
||||
|
||||
public String getGatewayClassName() {
|
||||
return BASE_PACKAGE + ".gateway.FtpOutboundGateway";
|
||||
return FtpOutboundGateway.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSimplePatternFileListFilterClassname() {
|
||||
return BASE_PACKAGE + ".filters.FtpSimplePatternFileListFilter";
|
||||
protected String getSimplePatternFileListFilterClassName() {
|
||||
return FtpSimplePatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRegexPatternFileListFilterClassname() {
|
||||
return BASE_PACKAGE + ".filters.FtpRegexPatternFileListFilter";
|
||||
protected String getRegexPatternFileListFilterClassName() {
|
||||
return FtpRegexPatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -394,6 +394,21 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="local-filename-generator-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Allows you to provide a SpEL expression to
|
||||
generate the file name of
|
||||
the local (transferred) file. The root
|
||||
object of the SpEL
|
||||
evaluation is the request Message, but the name of the original
|
||||
remote file is also provided as the 'remoteFileName' variable.
|
||||
For example, a valid expression would be:
|
||||
"#remoteFileName.toUpperCase() + headers.foo".
|
||||
Only used with 'get' and 'mget' commands.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="local-directory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
order="1"
|
||||
/>
|
||||
|
||||
<bean id="fooString" class="java.lang.String">
|
||||
<constructor-arg value="foo" />
|
||||
</bean>
|
||||
|
||||
<int-ftp:outbound-gateway id="gateway2"
|
||||
local-directory="local-test-dir"
|
||||
session-factory="csf"
|
||||
@@ -44,6 +48,7 @@
|
||||
expression="payload"
|
||||
order="2"
|
||||
requires-reply="false"
|
||||
local-filename-generator-expression="#remoteFileName.toUpperCase() + '.a' + @fooString"
|
||||
>
|
||||
<int-ftp:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.ftp.config.FtpOutboundGatewayParserTests$FooAdvice" />
|
||||
|
||||
@@ -21,10 +21,13 @@ import static org.junit.Assert.assertNotNull;
|
||||
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.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
@@ -39,6 +42,7 @@ import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -77,8 +81,9 @@ public class FtpOutboundGatewayParserTests {
|
||||
assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "filter"));
|
||||
assertEquals(Command.LS, TestUtils.getPropertyValue(gateway, "command"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
|
||||
Set<Option> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
|
||||
assertTrue(options.contains(Option.NAME_ONLY));
|
||||
assertTrue(options.contains(Option.NOSORT));
|
||||
|
||||
@@ -88,7 +93,7 @@ public class FtpOutboundGatewayParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGateway2() {
|
||||
public void testGateway2() throws Exception {
|
||||
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway2,
|
||||
"handler", FtpOutboundGateway.class);
|
||||
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileSeparator"));
|
||||
@@ -104,6 +109,21 @@ public class FtpOutboundGatewayParserTests {
|
||||
gateway.handleMessage(new GenericMessage<String>("foo"));
|
||||
assertFalse(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
|
||||
assertEquals(1, adviceCalled);
|
||||
|
||||
//INT-3129
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "localFilenameGeneratorExpression"));
|
||||
final AtomicReference<Method> genMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(FtpOutboundGateway.class, new ReflectionUtils.MethodCallback() {
|
||||
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if ("generateLocalFileName".equals(method.getName())) {
|
||||
method.setAccessible(true);
|
||||
genMethod.set(method);
|
||||
}
|
||||
}
|
||||
});
|
||||
assertEquals("FOO.afoo", genMethod.get().invoke(gateway, new GenericMessage<String>(""), "foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
@@ -16,28 +16,30 @@
|
||||
package org.springframework.integration.sftp.config;
|
||||
|
||||
import org.springframework.integration.file.config.AbstractRemoteFileOutboundGatewayParser;
|
||||
import org.springframework.integration.sftp.filters.SftpRegexPatternFileListFilter;
|
||||
import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.sftp.gateway.SftpOutboundGateway;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
public class SftpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayParser {
|
||||
|
||||
private static final String BASE_PACKAGE = "org.springframework.integration.sftp";
|
||||
|
||||
public String getGatewayClassName() {
|
||||
return BASE_PACKAGE + ".gateway.SftpOutboundGateway";
|
||||
return SftpOutboundGateway.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSimplePatternFileListFilterClassname() {
|
||||
return BASE_PACKAGE + ".filters.SftpSimplePatternFileListFilter";
|
||||
protected String getSimplePatternFileListFilterClassName() {
|
||||
return SftpSimplePatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRegexPatternFileListFilterClassname() {
|
||||
return BASE_PACKAGE + ".filters.SftpRegexPatternFileListFilter";
|
||||
protected String getRegexPatternFileListFilterClassName() {
|
||||
return SftpRegexPatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -393,6 +393,21 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="local-filename-generator-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Allows you to provide a SpEL expression to
|
||||
generate the file name of
|
||||
the local (transferred) file. The root
|
||||
object of the SpEL
|
||||
evaluation is the request Message, but the name of the original
|
||||
remote file is also provided as the 'remoteFileName' variable.
|
||||
For example, a valid expression would be:
|
||||
"#remoteFileName.toUpperCase() + headers.foo".
|
||||
Only used with 'get' and 'mget' commands.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="local-directory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
order="1"
|
||||
/>
|
||||
|
||||
<bean id="fooString" class="java.lang.String">
|
||||
<constructor-arg value="foo" />
|
||||
</bean>
|
||||
|
||||
<int-sftp:outbound-gateway id="gateway2"
|
||||
local-directory="local-test-dir"
|
||||
session-factory="csf"
|
||||
@@ -44,6 +48,7 @@
|
||||
expression="payload"
|
||||
order="2"
|
||||
requires-reply="false"
|
||||
local-filename-generator-expression="#remoteFileName.toUpperCase() + '.a' + @fooString"
|
||||
/>
|
||||
|
||||
<int-sftp:outbound-gateway id="gateway3"
|
||||
|
||||
@@ -21,10 +21,13 @@ import static org.junit.Assert.assertNotNull;
|
||||
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.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
@@ -37,6 +40,7 @@ import org.springframework.integration.sftp.gateway.SftpOutboundGateway;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -77,7 +81,7 @@ public class SftpOutboundGatewayParserTests {
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "filter"));
|
||||
assertEquals(Command.LS, TestUtils.getPropertyValue(gateway, "command"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
|
||||
Set<Option> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
|
||||
assertTrue(options.contains(Option.NAME_ONLY));
|
||||
assertTrue(options.contains(Option.NOSORT));
|
||||
|
||||
@@ -86,7 +90,7 @@ public class SftpOutboundGatewayParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGateway2() {
|
||||
public void testGateway2() throws Exception {
|
||||
SftpOutboundGateway gateway = TestUtils.getPropertyValue(gateway2,
|
||||
"handler", SftpOutboundGateway.class);
|
||||
assertEquals("X", TestUtils.getPropertyValue(gateway, "remoteFileSeparator"));
|
||||
@@ -100,6 +104,21 @@ public class SftpOutboundGatewayParserTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> options = TestUtils.getPropertyValue(gateway, "options", Set.class);
|
||||
assertTrue(options.contains(Option.PRESERVE_TIMESTAMP));
|
||||
|
||||
//INT-3129
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "localFilenameGeneratorExpression"));
|
||||
final AtomicReference<Method> genMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(SftpOutboundGateway.class, new ReflectionUtils.MethodCallback() {
|
||||
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if ("generateLocalFileName".equals(method.getName())) {
|
||||
method.setAccessible(true);
|
||||
genMethod.set(method);
|
||||
}
|
||||
}
|
||||
});
|
||||
assertEquals("FOO.afoo", genMethod.get().invoke(gateway, new GenericMessage<String>(""), "foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -341,7 +341,7 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
<listitem>mv (move/rename file)</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para><emphasis>ls</emphasis></para>
|
||||
<para><emphasis role="bold">ls</emphasis></para>
|
||||
<para>
|
||||
ls lists remote file(s) and supports the following options:
|
||||
<itemizedlist>
|
||||
@@ -366,7 +366,7 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
The remote directory that the <emphasis>ls</emphasis> command acted on is provided
|
||||
in the <classname>file_remoteDirectory</classname> header.
|
||||
</para>
|
||||
<para><emphasis>get</emphasis></para>
|
||||
<para><emphasis role="bold">get</emphasis></para>
|
||||
<para>
|
||||
<emphasis>get</emphasis> retrieves a remote file and supports the following option:
|
||||
<itemizedlist>
|
||||
@@ -381,7 +381,7 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
The remote directory is provided in the <classname>file_remoteDirectory</classname> header, and the filename is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>mget</emphasis></para>
|
||||
<para><emphasis role="bold">mget</emphasis></para>
|
||||
<para>
|
||||
<emphasis>mget</emphasis> retrieves multiple remote files based on a pattern and supports the following option:
|
||||
<itemizedlist>
|
||||
@@ -399,7 +399,7 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
for the filenames is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>rm</emphasis></para>
|
||||
<para><emphasis role="bold">rm</emphasis></para>
|
||||
<para>
|
||||
The <emphasis>rm</emphasis> command has no options.
|
||||
</para>
|
||||
@@ -409,7 +409,7 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
The remote directory is provided in the <classname>file_remoteDirectory</classname> header, and the filename is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>mv</emphasis></para>
|
||||
<para><emphasis role="bold">mv</emphasis></para>
|
||||
<para>
|
||||
The <emphasis>mv</emphasis> command has no options.
|
||||
</para>
|
||||
@@ -425,9 +425,20 @@ protected void postProcessClientBeforeConnect(T client) throws IOException {
|
||||
the <code>file_renameTo</code> header.
|
||||
</para>
|
||||
<para>
|
||||
For all commands, the PATH that the command acts on is provided by the 'expression'
|
||||
property of the gateway. For the mget command, the expression might evaluate to '*', meaning
|
||||
retrieve all files, or 'somedirectory/*' etc.
|
||||
<emphasis role="bold">Additional Information</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
The <emphasis>get</emphasis> and <emphasis>mget</emphasis> commands support
|
||||
the <emphasis>local-filename-generator-expression</emphasis> attribute. It
|
||||
defines a SpEL expression to generate the name of local file(s) during the transfer.
|
||||
The root object of the evaluation context is the request Message but, in addition, the <code>remoteFileName</code>
|
||||
variable is also available, which is particularly useful for <emphasis>mget</emphasis>, for
|
||||
example: <code>local-filename-generator-expression="#remoteFileName.toUpperCase() + headers.foo"</code>
|
||||
</para>
|
||||
<para>
|
||||
For all commands, the PATH that the command acts on is provided by the 'expression'
|
||||
property of the gateway. For the mget command, the expression might evaluate to '*', meaning
|
||||
retrieve all files, or 'somedirectory/*' etc.
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
|
||||
@@ -377,7 +377,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
<listitem>mv (move/rename file)</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para><emphasis>ls</emphasis></para>
|
||||
<para><emphasis role="bold">ls</emphasis></para>
|
||||
<para>
|
||||
ls lists remote file(s) and supports the following options:
|
||||
<itemizedlist>
|
||||
@@ -402,7 +402,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
The remote directory that the <emphasis>ls</emphasis> command acted on is provided
|
||||
in the <classname>file_remoteDirectory</classname> header.
|
||||
</para>
|
||||
<para><emphasis>get</emphasis></para>
|
||||
<para><emphasis role="bold">get</emphasis></para>
|
||||
<para>
|
||||
<emphasis>get</emphasis> retrieves a remote file and supports the following option:
|
||||
<itemizedlist>
|
||||
@@ -417,7 +417,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
The remote directory is provided in the <classname>file_remoteDirectory</classname> header, and the filename is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>mget</emphasis></para>
|
||||
<para><emphasis role="bold">mget</emphasis></para>
|
||||
<para>
|
||||
<emphasis>mget</emphasis> retrieves multiple remote files based on a pattern and supports the following option:
|
||||
<itemizedlist>
|
||||
@@ -435,7 +435,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
for the filenames is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>rm</emphasis></para>
|
||||
<para><emphasis role="bold">rm</emphasis></para>
|
||||
<para>
|
||||
The <emphasis>rm</emphasis> command has no options.
|
||||
</para>
|
||||
@@ -445,7 +445,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
The remote directory is provided in the <classname>file_remoteDirectory</classname> header, and the filename is
|
||||
provided in the <classname>file_remoteFile</classname> header.
|
||||
</para>
|
||||
<para><emphasis>mv</emphasis></para>
|
||||
<para><emphasis role="bold">mv</emphasis></para>
|
||||
<para>
|
||||
The <emphasis>mv</emphasis> command has no options.
|
||||
</para>
|
||||
@@ -461,9 +461,20 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/sftp
|
||||
the <code>file_renameTo</code> header.
|
||||
</para>
|
||||
<para>
|
||||
For all commands, the PATH that the command acts on is provided by the 'expression'
|
||||
property of the gateway. For the mget command, the expression might evaluate to '*', meaning
|
||||
retrieve all files, or 'somedirectory/*' etc.
|
||||
<emphasis role="bold">Additional Information</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
The <emphasis>get</emphasis> and <emphasis>mget</emphasis> commands support
|
||||
the <emphasis>local-filename-generator-expression</emphasis> attribute. It
|
||||
defines a SpEL expression to generate the name of local file(s) during the transfer.
|
||||
The root object of the evaluation context is the request Message but, in addition, the <code>remoteFileName</code>
|
||||
variable is also available, which is particularly useful for <emphasis>mget</emphasis>, for
|
||||
example: <code>local-filename-generator-expression="#remoteFileName.toUpperCase() + headers.foo"</code>
|
||||
</para>
|
||||
<para>
|
||||
For all commands, the PATH that the command acts on is provided by the 'expression'
|
||||
property of the gateway. For the mget command, the expression might evaluate to '*', meaning
|
||||
retrieve all files, or 'somedirectory/*' etc.
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
|
||||
@@ -175,6 +175,10 @@
|
||||
to be maintained across JVM executions, a custom filter that retains state, perhaps on
|
||||
the file system, can now be configured.
|
||||
</para>
|
||||
<para>
|
||||
For more information, see
|
||||
<xref linkend="ftp-inbound"/> and <xref linkend="sftp-inbound"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-xFTP-gw">
|
||||
<title>FTP, SFTP and FTPS Gateways</title>
|
||||
@@ -182,6 +186,12 @@
|
||||
The gateways now support the <code>mv</code> command, enabling the renaming of remote
|
||||
files.
|
||||
</para>
|
||||
<para>
|
||||
The <code>local-filename-generator-expression</code> attribute is now supported,
|
||||
enabling the naming of local files during transfer. By default, the same
|
||||
name as the remote file is used. For more information, see
|
||||
<xref linkend="ftp-outbound-gateway"/> and <xref linkend="sftp-outbound-gateway"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-jdbc-mysql-v5_6_4">
|
||||
<title>JDBC Message Store Improvements</title>
|
||||
|
||||
Reference in New Issue
Block a user