diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/filters/LastModifiedFileListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/LastModifiedFileListFilter.java new file mode 100644 index 0000000000..40d33bd329 --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/LastModifiedFileListFilter.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 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 java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * The {@link FileListFilter} implementation to filter those files which + * {@link File#lastModified()} is less than the {@link #age} in comparison + * with the current time. + *

+ * The resolution is done in seconds. + * + * @author Gary Russell + * @since 4.2 + * + */ +public class LastModifiedFileListFilter implements FileListFilter { + + private static final long DEFAULT_AGE = 60; + + private volatile long age = DEFAULT_AGE; + + public long getAge() { + return age; + } + + /** + * Set the age that files have to be before being passed by this filter. + * If {@link File#lastModified()} plus age is greater than the current time, the file + * is filtered. The resolution is seconds. + * Defaults to 60 seconds. + * @param age the age + */ + public void setAge(long age) { + setAge(age, TimeUnit.SECONDS); + } + + /** + * Set the age that files have to be before being passed by this filter. + * If {@link File#lastModified()} plus age is greater than the current time, the file + * is filtered. The resolution is seconds. + * Defaults to 60 seconds. + * @param age the age + * @param unit the timeUnit. + */ + public void setAge(long age, TimeUnit unit) { + this.age = unit.toSeconds(age); + } + + @Override + public List filterFiles(File[] files) { + List list = new ArrayList(); + long now = System.currentTimeMillis() / 1000; + for (File file : files) { + if (file.lastModified() / 1000 + this.age <= now) { + list.add(file); + } + } + return list; + } + +} diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/filters/LastModifiedFileListFilterTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/filters/LastModifiedFileListFilterTests.java new file mode 100644 index 0000000000..742bea91fe --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/filters/LastModifiedFileListFilterTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 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 static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.concurrent.TimeUnit; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * @author Gary Russell + * @since 4.2 + * + */ +public class LastModifiedFileListFilterTests { + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + @Test + public void testAge() throws Exception { + LastModifiedFileListFilter filter = new LastModifiedFileListFilter(); + filter.setAge(1, TimeUnit.SECONDS); + File foo = this.folder.newFile(); + FileOutputStream fileOutputStream = new FileOutputStream(foo); + fileOutputStream.write("x".getBytes()); + fileOutputStream.close(); + assertEquals(0, filter.filterFiles(new File[] { foo }).size()); + Thread.sleep(2000); + assertEquals(1, filter.filterFiles(new File[] { foo }).size()); + } + +} diff --git a/src/reference/asciidoc/file.adoc b/src/reference/asciidoc/file.adoc index 1eb57555de..e9e02aa7d8 100644 --- a/src/reference/asciidoc/file.adoc +++ b/src/reference/asciidoc/file.adoc @@ -90,7 +90,24 @@ The `CompositeFileListFilter` enables the composition. ---- -The configuration can be simplified using the file specific namespace. +If it is not possible to create the file with a temporary name and rename to the final name, another alternative is +provided. +The `LastModifiedFileListFilter` was added in _version 4.2_. +This filter can be configured with an `age` property and only files older than this will be passed by the filter. +The age defaults to 60 seconds, but you should choose an age that is large enough to avoid picking up a file early, due +to, say, network glitches. + +[source, xml] +---- + + + +---- + +[[file-namespace-support]] +==== Namespace Support + +The configuration for file reading can be simplified using the file specific namespace. To do this use the following template. [source,xml] ---- diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index f5bd133860..90b93e6ca3 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -58,19 +58,31 @@ As an alternative to the existing `selector` attribute, the `` now su [[x4.2-file-changes]] ==== File Changes +See <> for more information about these changes. + +===== Appending NewLines + The `` and `` now support an `append-new-line` attribute. If set to `true`, a new line is appended to the file after a message is written. The default attribute value is `false`. +===== Ignoring Hidden Files + The `ignore-hidden` attribute has been introduced for the `` to pick up or not the _hidden_ files from the source directory. It is `true` by default. +===== Writing InputStream Payloads + The `FileWritingMessageHandler` now also accepts `InputStream` as a valid message payload type. +===== HeadDirectoryScanner + The `HeadDirectoryScanner` can now be used with other `FileListFilter` s. -See <> for more information. +===== Last Modified Filter + +The `LastModifiedFileListFilter` has been added. [[x4.2-class-package-change]] ==== Class Package Change