INT-4204: Introduce ExpressionFileListFilter
JIRA: https://jira.spring.io/browse/INT-4204 Fix error message in the `AbstractRemoteFileOutboundGatewayParser`
This commit is contained in:
committed by
Gary Russell
parent
33b60c9601
commit
9836828f54
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -23,6 +23,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
|
||||
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
@@ -92,21 +93,34 @@ public abstract class AbstractRemoteFileOutboundGatewayParser extends AbstractCo
|
||||
protected void configureFilter(BeanDefinitionBuilder builder, Element element, ParserContext parserContext,
|
||||
String filterAttribute, String patternPrefix, String propertyName) {
|
||||
String filter = element.getAttribute(filterAttribute);
|
||||
String filterExpression = element.getAttribute(filterAttribute + "-expression");
|
||||
String fileNamePattern = element.getAttribute(patternPrefix + "-pattern");
|
||||
String fileNameRegex = element.getAttribute(patternPrefix + "-regex");
|
||||
boolean hasFilter = StringUtils.hasText(filter);
|
||||
boolean hasFilterExpression = StringUtils.hasText(filterExpression);
|
||||
boolean hasFileNamePattern = StringUtils.hasText(fileNamePattern);
|
||||
boolean hasFileNameRegex = StringUtils.hasText(fileNameRegex);
|
||||
int count = hasFilter ? 1 : 0;
|
||||
count += hasFilterExpression ? 1 : 0;
|
||||
count += hasFileNamePattern ? 1 : 0;
|
||||
count += hasFileNameRegex ? 1 : 0;
|
||||
if (count > 1) {
|
||||
parserContext.getReaderContext().error("at most one of '" + patternPrefix + "-pattern', " +
|
||||
"'" + patternPrefix + "-regex', or '" + filterAttribute + "' is allowed on a remote file outbound gateway", element);
|
||||
parserContext.getReaderContext()
|
||||
.error("at most one of '" + patternPrefix + "-pattern', " +
|
||||
"'" + patternPrefix + "-regex', '" + filterAttribute +
|
||||
"' or '" + filterAttribute + "-expression' is allowed on a remote file outbound gateway",
|
||||
element);
|
||||
}
|
||||
else if (hasFilter) {
|
||||
builder.addPropertyReference(propertyName, filter);
|
||||
}
|
||||
else if (hasFilterExpression) {
|
||||
BeanDefinition expressionFilterBeanDefinition =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFileListFilter.class)
|
||||
.addConstructorArgValue(filterExpression)
|
||||
.getBeanDefinition();
|
||||
builder.addPropertyValue(propertyName, expressionFilterBeanDefinition);
|
||||
}
|
||||
else if (hasFileNamePattern) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"filter".equals(filterAttribute) ?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.locking.NioFileLocker;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -87,8 +88,13 @@ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChann
|
||||
String preventDuplicates = element.getAttribute("prevent-duplicates");
|
||||
String ignoreHidden = element.getAttribute("ignore-hidden");
|
||||
String filter = element.getAttribute("filter");
|
||||
if (!StringUtils.hasText(filter) && !StringUtils.hasText(filenamePattern) && !StringUtils.hasText(filenameRegex)
|
||||
&& !StringUtils.hasText(preventDuplicates) && !StringUtils.hasText(ignoreHidden)) {
|
||||
String filterExpression = element.getAttribute("filter-expression");
|
||||
if (!StringUtils.hasText(filter)
|
||||
&& !StringUtils.hasText(filenamePattern)
|
||||
&& !StringUtils.hasText(filenameRegex)
|
||||
&& !StringUtils.hasText(preventDuplicates)
|
||||
&& !StringUtils.hasText(ignoreHidden)
|
||||
&& !StringUtils.hasText(filterExpression)) {
|
||||
return null;
|
||||
}
|
||||
BeanDefinitionBuilder factoryBeanBuilder =
|
||||
@@ -97,6 +103,17 @@ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChann
|
||||
if (StringUtils.hasText(filter)) {
|
||||
factoryBeanBuilder.addPropertyReference("filter", filter);
|
||||
}
|
||||
if (StringUtils.hasText(filterExpression)) {
|
||||
if (StringUtils.hasText(filter)) {
|
||||
parserContext.getReaderContext()
|
||||
.error("At most one of 'filter' or 'filter-expression' can be provided.", element);
|
||||
}
|
||||
BeanDefinition expressionFilterBeanDefinition =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFileListFilter.class)
|
||||
.addConstructorArgValue(filterExpression)
|
||||
.getBeanDefinition();
|
||||
factoryBeanBuilder.addPropertyValue("filter", expressionFilterBeanDefinition);
|
||||
}
|
||||
if (StringUtils.hasText(filenamePattern)) {
|
||||
if (StringUtils.hasText(filter)) {
|
||||
parserContext.getReaderContext().error(
|
||||
@@ -113,8 +130,8 @@ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChann
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(factoryBeanBuilder, element, "prevent-duplicates");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(factoryBeanBuilder, element, "ignore-hidden");
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(
|
||||
factoryBeanBuilder.getBeanDefinition(), parserContext.getRegistry());
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(factoryBeanBuilder.getBeanDefinition(),
|
||||
parserContext.getRegistry());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -23,6 +23,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -32,6 +33,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @author David Turanski
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*
|
||||
*/
|
||||
@@ -93,12 +95,14 @@ public final class FileParserUtils {
|
||||
static void configureFilter(BeanDefinitionBuilder synchronizerBuilder, Element element, ParserContext parserContext,
|
||||
Class<? extends FileListFilter<?>> patternClass, Class<? extends FileListFilter<?>> regexClass) {
|
||||
String filter = element.getAttribute("filter");
|
||||
String filterExpression = element.getAttribute("filter-expression");
|
||||
String fileNamePattern = element.getAttribute("filename-pattern");
|
||||
String fileNameRegex = element.getAttribute("filename-regex");
|
||||
boolean hasFilter = StringUtils.hasText(filter);
|
||||
boolean hasFilterExpression = StringUtils.hasText(filterExpression);
|
||||
boolean hasFileNamePattern = StringUtils.hasText(fileNamePattern);
|
||||
boolean hasFileNameRegex = StringUtils.hasText(fileNameRegex);
|
||||
if (hasFilter || hasFileNamePattern || hasFileNameRegex) {
|
||||
if (hasFilter || hasFilterExpression || hasFileNamePattern || hasFileNameRegex) {
|
||||
int count = 0;
|
||||
if (hasFilter) {
|
||||
count++;
|
||||
@@ -109,13 +113,24 @@ public final class FileParserUtils {
|
||||
if (hasFileNameRegex) {
|
||||
count++;
|
||||
}
|
||||
if (hasFilterExpression) {
|
||||
count++;
|
||||
}
|
||||
if (count != 1) {
|
||||
parserContext.getReaderContext().error("at most one of 'filename-pattern', " +
|
||||
"'filename-regex', or 'filter' is allowed on remote file inbound adapter", element);
|
||||
"'filename-regex', 'filter' or 'filter-expression' is allowed on remote file inbound adapter",
|
||||
element);
|
||||
}
|
||||
if (hasFilter) {
|
||||
synchronizerBuilder.addPropertyReference("filter", filter);
|
||||
}
|
||||
else if (hasFilterExpression) {
|
||||
BeanDefinition expressionFilterBeanDefinition =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFileListFilter.class)
|
||||
.addConstructorArgValue(filterExpression)
|
||||
.getBeanDefinition();
|
||||
synchronizerBuilder.addPropertyValue("filter", expressionFilterBeanDefinition);
|
||||
}
|
||||
else if (hasFileNamePattern) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(patternClass);
|
||||
filterBuilder.addConstructorArgValue(fileNamePattern);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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,16 +17,22 @@
|
||||
package org.springframework.integration.file.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.integration.dsl.ComponentsRegistration;
|
||||
import org.springframework.integration.dsl.MessageSourceSpec;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.integration.file.DirectoryScanner;
|
||||
import org.springframework.integration.file.FileLocker;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.config.FileListFilterFactoryBean;
|
||||
import org.springframework.integration.file.filters.AcceptAllFileListFilter;
|
||||
import org.springframework.integration.file.filters.AcceptOnceFileListFilter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.filters.IgnoreHiddenFileListFilter;
|
||||
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
|
||||
@@ -42,12 +48,15 @@ import org.springframework.util.Assert;
|
||||
* @since 5.0
|
||||
*/
|
||||
public class FileInboundChannelAdapterSpec
|
||||
extends MessageSourceSpec<FileInboundChannelAdapterSpec, FileReadingMessageSource> {
|
||||
extends MessageSourceSpec<FileInboundChannelAdapterSpec, FileReadingMessageSource>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
private final FileListFilterFactoryBean fileListFilterFactoryBean = new FileListFilterFactoryBean();
|
||||
|
||||
private FileLocker locker;
|
||||
|
||||
private ExpressionFileListFilter<File> expressionFileListFilter;
|
||||
|
||||
FileInboundChannelAdapterSpec() {
|
||||
this.target = new FileReadingMessageSource();
|
||||
}
|
||||
@@ -117,6 +126,30 @@ public class FileInboundChannelAdapterSpec
|
||||
return _this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param expression the SpEL expression for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public FileInboundChannelAdapterSpec filterExpression(String expression) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(expression);
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param filterFunction the {@link Function} for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public FileInboundChannelAdapterSpec filterFunction(Function<File, Boolean> filterFunction) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure an {@link AcceptOnceFileListFilter} if {@code preventDuplicates == true},
|
||||
* otherwise - {@link AcceptAllFileListFilter}.
|
||||
@@ -226,4 +259,14 @@ public class FileInboundChannelAdapterSpec
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> getComponentsToRegister() {
|
||||
if (this.expressionFileListFilter != null) {
|
||||
return Collections.singleton(this.expressionFileListFilter);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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,15 +17,18 @@
|
||||
package org.springframework.integration.file.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.dsl.ComponentsRegistration;
|
||||
import org.springframework.integration.dsl.MessageSourceSpec;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer;
|
||||
import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource;
|
||||
@@ -43,12 +46,15 @@ import org.springframework.integration.file.remote.synchronizer.AbstractInboundF
|
||||
*/
|
||||
public abstract class RemoteFileInboundChannelAdapterSpec<F, S extends RemoteFileInboundChannelAdapterSpec<F, S, MS>,
|
||||
MS extends AbstractInboundFileSynchronizingMessageSource<F>>
|
||||
extends MessageSourceSpec<S, MS> implements ComponentsRegistration {
|
||||
extends MessageSourceSpec<S, MS>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
protected final AbstractInboundFileSynchronizer<F> synchronizer;
|
||||
|
||||
private CompositeFileListFilter<F> filter;
|
||||
|
||||
private ExpressionFileListFilter<F> expressionFileListFilter;
|
||||
|
||||
protected RemoteFileInboundChannelAdapterSpec(AbstractInboundFileSynchronizer<F> synchronizer) {
|
||||
this.synchronizer = synchronizer;
|
||||
}
|
||||
@@ -171,7 +177,7 @@ public abstract class RemoteFileInboundChannelAdapterSpec<F, S extends RemoteFil
|
||||
this.filter = (CompositeFileListFilter<F>) filter;
|
||||
}
|
||||
else {
|
||||
this.filter = new CompositeFileListFilter<F>();
|
||||
this.filter = new CompositeFileListFilter<>();
|
||||
this.filter.addFilter(filter);
|
||||
}
|
||||
this.synchronizer.setFilter(this.filter);
|
||||
@@ -182,6 +188,30 @@ public abstract class RemoteFileInboundChannelAdapterSpec<F, S extends RemoteFil
|
||||
return _this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param expression the SpEL expression for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterExpression(String expression) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(expression);
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param filterFunction the {@link Function} for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterFunction(Function<F, Boolean> filterFunction) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a simple pattern filter (e.g. '*.txt').
|
||||
* @param pattern the pattern.
|
||||
@@ -220,7 +250,14 @@ public abstract class RemoteFileInboundChannelAdapterSpec<F, S extends RemoteFil
|
||||
|
||||
@Override
|
||||
public Collection<Object> getComponentsToRegister() {
|
||||
return Collections.singletonList(this.synchronizer);
|
||||
List<Object> componentsToRegister = new ArrayList<>();
|
||||
componentsToRegister.add(this.synchronizer);
|
||||
|
||||
if (this.expressionFileListFilter != null) {
|
||||
componentsToRegister.add(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
return componentsToRegister;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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,12 +17,18 @@
|
||||
package org.springframework.integration.file.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.dsl.ComponentsRegistration;
|
||||
import org.springframework.integration.dsl.MessageHandlerSpec;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
|
||||
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
|
||||
@@ -40,10 +46,15 @@ import org.springframework.messaging.Message;
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutboundGatewaySpec<F, S>>
|
||||
extends MessageHandlerSpec<S, AbstractRemoteFileOutboundGateway<F>> {
|
||||
extends MessageHandlerSpec<S, AbstractRemoteFileOutboundGateway<F>>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
private CompositeFileListFilter<F> filter;
|
||||
|
||||
private ExpressionFileListFilter<F> expressionFileListFilter;
|
||||
|
||||
private ExpressionFileListFilter<File> mputExpressionFileListFilter;
|
||||
|
||||
private CompositeFileListFilter<File> mputFilter;
|
||||
|
||||
protected RemoteFileOutboundGatewaySpec(AbstractRemoteFileOutboundGateway<F> outboundGateway) {
|
||||
@@ -166,6 +177,30 @@ public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutbo
|
||||
return _this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param expression the SpEL expression for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterExpression(String expression) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(expression);
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param filterFunction the {@link Function} for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterFunction(Function<F, Boolean> filterFunction) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link FileListFilter} that runs against the <em>local</em> file system view when
|
||||
* using {@code MPUT} command.
|
||||
@@ -205,10 +240,34 @@ public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutbo
|
||||
* @param regex the {@link SimplePatternFileListFilter} for {@code MPUT} command.
|
||||
* @return the Spec.
|
||||
*/
|
||||
public S regexMpuFilter(String regex) {
|
||||
public S regexMputFilter(String regex) {
|
||||
return mputFilter(new RegexPatternFileListFilter(regex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param expression the SpEL expression for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S mputFilterExpression(String expression) {
|
||||
this.mputExpressionFileListFilter = new ExpressionFileListFilter<>(expression);
|
||||
return mputFilter(this.mputExpressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param filterFunction the {@link Function} for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S mputFilterFunction(Function<File, Boolean> filterFunction) {
|
||||
this.mputExpressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
|
||||
return mputFilter(this.mputExpressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a SpEL expression for files renaming during transfer.
|
||||
* @param expression the String in SpEL syntax.
|
||||
@@ -280,6 +339,20 @@ public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutbo
|
||||
return _this();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> getComponentsToRegister() {
|
||||
List<Object> componentsToRegister = new ArrayList<>();
|
||||
if (this.expressionFileListFilter != null) {
|
||||
componentsToRegister.add(this.expressionFileListFilter);
|
||||
}
|
||||
if (this.mputExpressionFileListFilter != null) {
|
||||
componentsToRegister.add(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
return componentsToRegister;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify a simple pattern to match remote files (e.g. '*.txt').
|
||||
* @param pattern the pattern.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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,12 +16,17 @@
|
||||
|
||||
package org.springframework.integration.file.dsl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.dsl.ComponentsRegistration;
|
||||
import org.springframework.integration.dsl.MessageSourceSpec;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.AbstractRemoteFileStreamingMessageSource;
|
||||
import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource;
|
||||
@@ -38,13 +43,16 @@ import org.springframework.messaging.Message;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class
|
||||
RemoteFileStreamingInboundChannelAdapterSpec<F, S extends RemoteFileStreamingInboundChannelAdapterSpec<F, S, MS>,
|
||||
public abstract class RemoteFileStreamingInboundChannelAdapterSpec<F,
|
||||
S extends RemoteFileStreamingInboundChannelAdapterSpec<F, S, MS>,
|
||||
MS extends AbstractRemoteFileStreamingMessageSource<F>>
|
||||
extends MessageSourceSpec<S, MS> {
|
||||
extends MessageSourceSpec<S, MS>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
private CompositeFileListFilter<F> filter;
|
||||
|
||||
private ExpressionFileListFilter<F> expressionFileListFilter;
|
||||
|
||||
/**
|
||||
* Configure the file name path separator used by the remote system. Defaults to '/'.
|
||||
* @param remoteFileSeparator the remoteFileSeparator.
|
||||
@@ -109,6 +117,40 @@ public abstract class
|
||||
return _this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param expression the SpEL expression for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterExpression(String expression) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(expression);
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link ExpressionFileListFilter}.
|
||||
* @param filterFunction the {@link Function} for files filtering.
|
||||
* @return the spec.
|
||||
* @see FileReadingMessageSource#setFilter(FileListFilter)
|
||||
* @see ExpressionFileListFilter
|
||||
*/
|
||||
public S filterFunction(Function<F, Boolean> filterFunction) {
|
||||
this.expressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
|
||||
return filter(this.expressionFileListFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> getComponentsToRegister() {
|
||||
if (this.expressionFileListFilter != null) {
|
||||
return Collections.singleton(this.expressionFileListFilter);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a simple pattern filter (e.g. '*.txt').
|
||||
* @param pattern the pattern.
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2017 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.file.filters;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A SpEL expression based {@link AbstractFileListFilter} implementation.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ExpressionFileListFilter<F> extends AbstractFileListFilter<F>
|
||||
implements BeanFactoryAware {
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
private final Expression expression;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private EvaluationContext evaluationContext;
|
||||
|
||||
public ExpressionFileListFilter(String expression) {
|
||||
this(EXPRESSION_PARSER.parseExpression(expression));
|
||||
Assert.hasText(expression, "'expression' must not be empty");
|
||||
}
|
||||
|
||||
public ExpressionFileListFilter(Expression expression) {
|
||||
Assert.notNull(expression, "'expression' must not be null");
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean accept(F file) {
|
||||
return this.expression.getValue(getEvaluationContext(), file, Boolean.class);
|
||||
}
|
||||
|
||||
private EvaluationContext getEvaluationContext() {
|
||||
if (this.evaluationContext == null) {
|
||||
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.beanFactory);
|
||||
}
|
||||
return this.evaluationContext;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -76,6 +76,14 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/file"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
xmlns="http://www.springframework.org/schema/integration/file"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<inbound-channel-adapter id="inputDirPoller"
|
||||
directory="${inputdir}"
|
||||
auto-startup="false">
|
||||
directory="${inputdir}"
|
||||
filter-expression="true"
|
||||
auto-startup="false">
|
||||
<integration:poller fixed-rate="5000"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<context:property-placeholder location="classpath:org/springframework/integration/file/config/test.properties" />
|
||||
|
||||
<context:property-placeholder location="classpath:org/springframework/integration/file/config/test.properties"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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,30 +16,45 @@
|
||||
|
||||
package org.springframework.integration.file.config;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Iwein Fuld
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
public class FileInboundChannelAdapterWithClasspathInPropertiesTests {
|
||||
|
||||
@Autowired(required = true)
|
||||
@Autowired
|
||||
private FileReadingMessageSource source;
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private DirectFieldAccessor accessor;
|
||||
|
||||
@Before
|
||||
@@ -48,10 +63,25 @@ public class FileInboundChannelAdapterWithClasspathInPropertiesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void inputDirectory() throws Exception {
|
||||
File expected = new ClassPathResource("").getFile();
|
||||
File actual = (File) accessor.getPropertyValue("directory");
|
||||
assertEquals("'directory' should be set", expected, actual);
|
||||
|
||||
FileListFilter<File> fileListFilter =
|
||||
TestUtils.getPropertyValue(this.source, "scanner.filter", FileListFilter.class);
|
||||
assertThat(fileListFilter, instanceOf(CompositeFileListFilter.class));
|
||||
Set<FileListFilter<File>> fileFilters =
|
||||
TestUtils.getPropertyValue(fileListFilter, "fileFilters", Set.class);
|
||||
assertEquals(2, fileFilters.size());
|
||||
Iterator<FileListFilter<File>> iterator = fileFilters.iterator();
|
||||
iterator.next();
|
||||
FileListFilter<File> expressionFilter = iterator.next();
|
||||
assertThat(expressionFilter, instanceOf(ExpressionFileListFilter.class));
|
||||
assertEquals("true",
|
||||
TestUtils.getPropertyValue(expressionFilter, "expression.expression", String.class));
|
||||
assertSame(this.beanFactory, TestUtils.getPropertyValue(expressionFilter, "beanFactory"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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.
|
||||
@@ -391,7 +391,7 @@ public class FileTests {
|
||||
public IntegrationFlow fileSplitterFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Files.inboundAdapter(tmpDir.getRoot())
|
||||
.patternFilter("foo.tmp"),
|
||||
.filterFunction(f -> "foo.tmp".equals(f.getName())),
|
||||
e -> e.poller(p -> p.fixedDelay(100)))
|
||||
.split(Files.splitter()
|
||||
.markers()
|
||||
|
||||
@@ -337,6 +337,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -376,6 +384,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mput-filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'mput-filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mput-pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -546,6 +562,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:maxFetchGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
expression="payload"
|
||||
order="1"
|
||||
mode="APPEND"
|
||||
mput-regex=".*">
|
||||
mput-filter-expression="name matches '.*'">
|
||||
<int:poller fixed-delay="1000"/>
|
||||
</int-ftp:outbound-gateway>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
|
||||
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
|
||||
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Command;
|
||||
@@ -108,7 +109,7 @@ public class FtpOutboundGatewayParserTests {
|
||||
assertEquals(Long.valueOf(777), sendTimeout);
|
||||
assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
|
||||
assertThat(TestUtils.getPropertyValue(gateway, "mputFilter"),
|
||||
Matchers.instanceOf(RegexPatternFileListFilter.class));
|
||||
Matchers.instanceOf(ExpressionFileListFilter.class));
|
||||
assertEquals(FileExistsMode.APPEND, TestUtils.getPropertyValue(gateway, "fileExistsMode"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -153,7 +153,7 @@ public class FtpTests extends FtpTestSupport {
|
||||
.handle(Ftp.outboundGateway(sessionFactory(),
|
||||
AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
|
||||
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
|
||||
.regexFileNameFilter("(subFtpSource|.*1.txt)")
|
||||
.filterExpression("name matches 'subFtpSource|.*1.txt'")
|
||||
.localDirectoryExpression("'" + getTargetLocalDirectoryName() + "' + #remoteDirectory")
|
||||
.localFilenameExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')"))
|
||||
.channel(out);
|
||||
|
||||
@@ -339,6 +339,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -378,6 +386,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mput-filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'mput-filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mput-pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -547,6 +563,14 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SpEL expression to evaluate against file to accept it for processing or not.
|
||||
Mutually exclusive with 'filter' attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:maxFetchGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
session-factory="csf"
|
||||
auto-startup="false"
|
||||
phase="23"
|
||||
filename-pattern="*.txt"
|
||||
filter-expression="new org.springframework.util.AntPathMatcher().match('*.txt', filename)"
|
||||
remote-file-separator="X"
|
||||
remote-directory-expression="'foo/bar'">
|
||||
<int:poller fixed-rate="1000" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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.
|
||||
@@ -32,6 +32,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.file.filters.ExpressionFileListFilter;
|
||||
import org.springframework.integration.file.remote.session.CachingSessionFactory;
|
||||
import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.sftp.inbound.SftpStreamingMessageSource;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -54,6 +56,9 @@ public class SftpStreamingInboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private SourcePollingChannelAdapter sftpInbound;
|
||||
|
||||
@Autowired
|
||||
private SourcePollingChannelAdapter contextLoadsWithNoComparator;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel sftpChannel;
|
||||
|
||||
@@ -74,6 +79,10 @@ public class SftpStreamingInboundChannelAdapterParserTests {
|
||||
assertThat(TestUtils.getPropertyValue(source, "filter"), instanceOf(SftpSimplePatternFileListFilter.class));
|
||||
assertSame(this.csf, TestUtils.getPropertyValue(source, "remoteFileTemplate.sessionFactory"));
|
||||
assertEquals(31, TestUtils.getPropertyValue(source, "maxFetchSize"));
|
||||
|
||||
source = TestUtils.getPropertyValue(this.contextLoadsWithNoComparator, "source",
|
||||
SftpStreamingMessageSource.class);
|
||||
assertThat(TestUtils.getPropertyValue(source, "filter"), instanceOf(ExpressionFileListFilter.class));
|
||||
}
|
||||
|
||||
public static class TestSessionFactoryBean implements FactoryBean<DefaultSftpSessionFactory> {
|
||||
|
||||
@@ -69,7 +69,7 @@ metadata store on every update (if the store implements `Flushable`).
|
||||
A common problem with reading files is that a file may be detected before it is ready.
|
||||
The default `AcceptOnceFileListFilter` does not prevent this.
|
||||
In most cases, this can be prevented if the file-writing process renames each file as soon as it is ready for reading.
|
||||
A filename-pattern or filename-regex filter that accepts only files that are ready (e.g.
|
||||
A `filename-pattern` or `filename-regex` filter that accepts only files that are ready (e.g.
|
||||
based on a known suffix), composed with the default `AcceptOnceFileListFilter` allows for this.
|
||||
The `CompositeFileListFilter` enables the composition.
|
||||
[source,xml]
|
||||
@@ -106,6 +106,16 @@ to, say, network glitches.
|
||||
</bean>
|
||||
----
|
||||
|
||||
Starting with _version 5.0_ an `ExpressionFileListFilter` has been introduced to allow to execute SpEL expression against file as a context evaluation root object.
|
||||
For this purpose all the XML components for file handling (local and remote), alongside with an existing `filter` attribute, have been supplied with the `filter-expression` option:
|
||||
[source, xml]
|
||||
----
|
||||
<int-file:inbound-channel-adapter
|
||||
directory="${inputdir}"
|
||||
filter-expression="name matches '.text'"
|
||||
auto-startup="false"/>
|
||||
----
|
||||
|
||||
*Message Headers*
|
||||
|
||||
Starting with _version 5.0_ the `FileReadingMessageSource`, in addition to the `payload` as a polled `File`, populates these headers to the outbound `Message`:
|
||||
|
||||
@@ -516,6 +516,7 @@ See <<file-splitter>> and <<stream-transformer>> for more information about thes
|
||||
filename-pattern="*.txt"
|
||||
filename-regex=".*\.txt"
|
||||
filter="filter"
|
||||
filter-expression="@myFilterBean.check(#root)"
|
||||
remote-file-separator="/"
|
||||
comparator="comparator"
|
||||
max-fetch-size="1"
|
||||
@@ -524,7 +525,7 @@ See <<file-splitter>> and <<stream-transformer>> for more information about thes
|
||||
</int-ftp:inbound-streaming-channel-adapter>
|
||||
----
|
||||
|
||||
Only one of `filename-pattern`, `filename-regex` or `filter` is allowed.
|
||||
Only one of `filename-pattern`, `filename-regex`, `filter` or `filter-expression` is allowed.
|
||||
|
||||
IMPORTANT: Unlike the non-streaming inbound channel adapter, this adapter does not prevent duplicates by default.
|
||||
If you do not delete the remote file (e.g. using an outbound gateway with an rm command) and you wish to prevent the
|
||||
@@ -911,7 +912,7 @@ _mput_ sends multiple files to the server and supports the following option:
|
||||
The message payload must be a `java.io.File` representing a local directory.
|
||||
|
||||
The same attributes as the `put` command are supported.
|
||||
In addition, files in the local directory can be filtered with one of `mput-pattern`, `mput-regex` or `mput-filter`.
|
||||
In addition, files in the local directory can be filtered with one of `mput-pattern`, `mput-regex`, `mput-filter` or `mput-filter-expression`.
|
||||
The filter works with recursion, as long as the subdirectories themselves pass the filter.
|
||||
Subdirectories that do not pass the filter are not recursed.
|
||||
|
||||
|
||||
@@ -555,6 +555,7 @@ See <<file-splitter>> and <<stream-transformer>> for more information about thes
|
||||
filename-pattern="*.txt"
|
||||
filename-regex=".*\.txt"
|
||||
filter="filter"
|
||||
filter-expression="@myFilterBean.check(#root)"
|
||||
remote-file-separator="/"
|
||||
comparator="comparator"
|
||||
max-fetch-size="1"
|
||||
@@ -563,7 +564,7 @@ See <<file-splitter>> and <<stream-transformer>> for more information about thes
|
||||
</int-sftp:inbound-streaming-channel-adapter>
|
||||
----
|
||||
|
||||
Only one of `filename-pattern`, `filename-regex` or `filter` is allowed.
|
||||
Only one of `filename-pattern`, `filename-regex`, `filter` or `filter-expression` is allowed.
|
||||
|
||||
IMPORTANT: Unlike the non-streaming inbound channel adapter, this adapter does not prevent duplicates by default.
|
||||
If you do not delete the remote file (e.g. using an outbound gateway with an rm command) and you wish to prevent the
|
||||
@@ -935,7 +936,7 @@ _mput_ sends multiple files to the server and supports the following option:
|
||||
The message payload must be a `java.io.File` representing a local directory.
|
||||
|
||||
The same attributes as the `put` command are supported.
|
||||
In addition, files in the local directory can be filtered with one of `mput-pattern`, `mput-regex` or `mput-filter`.
|
||||
In addition, files in the local directory can be filtered with one of `mput-pattern`, `mput-regex`, `mput-filter` or `mput-filter-expression`.
|
||||
The filter works with recursion, as long as the subdirectories themselves pass the filter.
|
||||
Subdirectories that do not pass the filter are not recursed.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user