INT-833: Added basic support for extending the scanning mechanism

This commit is contained in:
Iwein Fuld
2009-12-12 19:53:45 +00:00
parent 4cf8defc68
commit 55a9b13927
9 changed files with 426 additions and 210 deletions

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2009 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;
import java.io.File;
/**
* Strategy for scanning directories. Implementations may select all children and grandchildren of the scanned directory
* in any order. This interface is intended to enable the selection and ordering of files in a directory like
* RecursiveDirectoryScanner. If the only requirement is to ignore certain files a FileListFilter implementation should
* suffice.
*
* @author Iwein Fuld
*/
public interface DirectoryScanner {
/**
* Scans the directory according to the strategy particular to this implementation and returns the selected files
* as a File array.
*
* @param directory the directory to scan for files
* @return a list of files representing the content of the directory
*/
File[] listFiles(File directory) throws IllegalArgumentException;
}

View File

@@ -67,6 +67,8 @@ public class FileReadingMessageSource implements MessageSource<File>,
private volatile File directory;
private volatile DirectoryScanner scanner = new ToplevelDirectoryScanner();
private volatile boolean autoCreateDirectory = true;
/**
@@ -109,6 +111,14 @@ public class FileReadingMessageSource implements MessageSource<File>,
this.directory = directory;
}
/**
* Optionally specify a custom scanner, for example the
* {@link org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner}
*/
public void setScanner(DirectoryScanner scanner) {
this.scanner = scanner;
}
/**
* Specify whether to create the source directory automatically if it does
* not yet exist upon initialization. By default, this value is
@@ -202,7 +212,7 @@ public class FileReadingMessageSource implements MessageSource<File>,
}
private void scanInputDirectory() {
File[] fileArray = directory.listFiles();
File[] fileArray = scanner.listFiles(directory);
if (fileArray == null) {
throw new MessagingException("The path [" + this.directory
+ "] does not denote a properly accessible directory.");
@@ -241,7 +251,7 @@ public class FileReadingMessageSource implements MessageSource<File>,
* Implementation of FileLocker that doesn't provide any protection against
* duplicate listing.
*/
class NoopFileLocker implements FileLocker {
private static class NoopFileLocker implements FileLocker {
public boolean lock(File fileToLock) {
return true;
@@ -251,4 +261,10 @@ public class FileReadingMessageSource implements MessageSource<File>,
// noop
}
}
private static class ToplevelDirectoryScanner implements DirectoryScanner {
public File[] listFiles(File directory) throws IllegalArgumentException {
return directory.listFiles();
}
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.integration.file;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* DirectoryScanner that lists all files inside a directory and subdirectories, without limit. This scanner should not
* be used with directories that contain a vast number of files, as all the file names will be read into memory and the
* scanning will be done recursively.
*
* @author Iwein Fuld
*/
public class RecursiveLeafOnlyDirectoryScanner implements DirectoryScanner {
public File[] listFiles(File directory) throws IllegalArgumentException {
File[] rootFiles = directory.listFiles();
List<File> files = new ArrayList<File>(rootFiles.length);
for (File rootFile : rootFiles) {
if (rootFile.isDirectory()){
files.addAll(Arrays.asList(listFiles(rootFile)));
} else {
files.add(rootFile);
}
}
return files.toArray(new File[files.size()]);
}
}

View File

@@ -42,6 +42,7 @@ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChann
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
PACKAGE_NAME + ".config.FileReadingMessageSourceFactoryBean");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "comparator");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "scanner");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "directory");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-directory");
String filterBeanName = this.registerFileListFilter(element, parserContext);

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.file.config;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.integration.file.DirectoryScanner;
import org.springframework.integration.file.FileListFilter;
import org.springframework.integration.file.FileReadingMessageSource;
@@ -40,7 +41,9 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean, Resourc
private volatile FileListFilter filter;
private volatile Comparator<File> comparator;
private volatile Comparator<File> comparator;
private volatile DirectoryScanner scanner;
private volatile Boolean scanEachPoll;
@@ -61,7 +64,11 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean, Resourc
this.comparator = comparator;
}
public void setFilter(FileListFilter filter) {
public void setScanner(DirectoryScanner scanner) {
this.scanner = scanner;
}
public void setFilter(FileListFilter filter) {
this.filter = filter;
}
@@ -105,6 +112,9 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean, Resourc
if (this.autoCreateDirectory != null) {
this.source.setAutoCreateDirectory(this.autoCreateDirectory);
}
if (this.scanner != null) {
this.source.setScanner(this.scanner);
}
this.source.afterPropertiesSet();
}
}

View File

@@ -1,66 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/file"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/file"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/file"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for Spring Integration File Adapters.
]]></xsd:documentation>
</xsd:annotation>
</xsd:annotation>
<xsd:element name="inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures an inbound Channel Adapter that polls a directory and sends
Messages whose payloads are instances of java.io.File.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="comparator" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures an inbound Channel Adapter that polls a directory and sends
Messages whose payloads are instances of java.io.File.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="comparator" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specify a Comparator to be used when ordering Files. If none is provided, the
order will be determined by the java.io.File implementation of Comparable.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="filter" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileListFilter"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="filename-pattern" type="xsd:string"/>
<xsd:attribute name="prevent-duplicates" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="filter" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileListFilter"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="filename-pattern" type="xsd:string"/>
<xsd:attribute name="scanner" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.file.DirectoryScanner"/>
</tool:annotation>
<xsd:documentation>
Reference to a custom DirectoryScanner implementation.
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="prevent-duplicates" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A boolean flag indicating whether duplicates should be prevented. If a 'filter' reference is
provided, duplicate prevention will not be enabled by default (the assumption is that the
provided filter is sufficient), but setting this to true will enable it. If a 'filename-pattern'
@@ -69,171 +82,171 @@
duplicate prevention is enabled by default, but setting this to false will disable it. For more
detail on the actual duplicate prevention, see the javadoc for AcceptOnceFileListFilter.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:string" default="true"/>
<xsd:attribute name="auto-create-directory" type="xsd:string" default="true">
<xsd:annotation>
<xsd:documentation>
Specify whether to automatically create the source directory if it does not yet exist when this
adapter is being initialized. The default value is 'true'. If set to 'false' and the directory
does not exist upon initialization, an Exception will be thrown.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:string" default="true"/>
<xsd:attribute name="auto-create-directory" type="xsd:string" default="true">
<xsd:annotation>
<xsd:documentation>
Specify whether to automatically create the source directory if it does not yet exist when this
adapter is being initialized. The default value is 'true'. If set to 'false' and the directory
does not exist upon initialization, an Exception will be thrown.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures an outbound Channel Adapter that writes Message payloads to a File.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="outboundFileBaseType">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures an outbound Channel Adapter that writes Message payloads to a File.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="outboundFileBaseType">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-gateway">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures an outbound Gateway that writes request Message payloads to a File and
then generates a reply Message containing the newly written File as its payload.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="outboundFileBaseType">
<xsd:attribute name="request-channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-gateway">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures an outbound Gateway that writes request Message payloads to a File and
then generates a reply Message containing the newly written File as its payload.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="outboundFileBaseType">
<xsd:attribute name="request-channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="outboundFileBaseType">
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="filename-generator" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileNameGenerator"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="delete-source-files" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:complexType name="outboundFileBaseType">
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="filename-generator" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileNameGenerator"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="delete-source-files" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specify whether to delete source files after writing to the destination directory.
This will take effect if the Message payload is the actual source File instance
or if the original File instance (or its path) is available in the header value
associated with the FileHeaders.ORIGINAL_FILE constant. The default value is false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-create-directory" type="xsd:string" default="true">
<xsd:annotation>
<xsd:documentation>
Specify whether to automatically create the destination directory if it does not yet exist
when this adapter is being initialized. The default value is 'true'. If set to 'false' and
the directory does not exist upon initialization, an Exception will be thrown.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:string"/>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-create-directory" type="xsd:string" default="true">
<xsd:annotation>
<xsd:documentation>
Specify whether to automatically create the destination directory if it does not yet exist
when this adapter is being initialized. The default value is 'true'. If set to 'false' and
the directory does not exist upon initialization, an Exception will be thrown.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:string"/>
</xsd:complexType>
<xsd:element name="file-to-string-transformer">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Creates a Transformer that converts a File payload to a String.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="transformerType">
<xsd:attribute name="charset" type="xsd:string"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="file-to-string-transformer">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Creates a Transformer that converts a File payload to a String.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="transformerType">
<xsd:attribute name="charset" type="xsd:string"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="file-to-bytes-transformer">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Creates a Transformer that converts a File payload to an array of bytes.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="transformerType"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="file-to-bytes-transformer">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Creates a Transformer that converts a File payload to an array of bytes.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="transformerType"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="transformerType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="input-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="output-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="delete-files" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="transformerType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="input-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="output-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="delete-files" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,32 @@
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
<beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<inbound-channel-adapter id="fileSource"
directory="#{directory.root}"
auto-startup="true"
scanner="recursiveScanner"
channel="files">
<integration:poller>
<integration:interval-trigger interval="100"/>
</integration:poller>
</inbound-channel-adapter>
<integration:channel id="files">
<integration:queue capacity="10"/>
</integration:channel>
<beans:bean id="recursiveScanner" class="org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner"/>
<beans:bean id="directory" class="org.junit.rules.TemporaryFolder" init-method="create" destroy-method="delete"/>
</beans:beans>

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2009 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.recursive;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.core.Message;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItem;
import static org.junit.matchers.JUnitMatchers.hasItems;
import static org.springframework.integration.test.matcher.PayloadMatcher.hasPayload;
/**
* @author Iwein Fuld
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class FileInboundChannelAdapterWithRecursiveDirectoryTests {
@Autowired
private TemporaryFolder directory;
@Autowired
private PollableChannel files;
@Test(timeout = 2000)
public void shouldScanDirectoriesRecursively() throws IOException {
//when
File folder = directory.newFolder("foo");
File file = new File(folder, "bar");
file.createNewFile();
//verify
assertThat(files.receive(), hasPayload(file));
}
@Test(timeout = 2000)
public void shouldReturnFilesMultipleLevels() throws IOException {
//when
File folder = directory.newFolder("foo");
File siblingFile = directory.newFile("bar");
File childFile = new File(folder, "baz");
childFile.createNewFile();
List<Message<?>> received = Arrays.asList(files.receive(), files.receive());
//verify
assertThat(received, hasItems(hasPayload(siblingFile), hasPayload(childFile)));
}
}