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);
|
||||
|
||||
Reference in New Issue
Block a user