From 280da19191f8cf9f8a6ea7ff0f9c249be3595eac Mon Sep 17 00:00:00 2001 From: Iwein Fuld Date: Thu, 11 Sep 2008 16:25:05 +0000 Subject: [PATCH] Replaced FileFilter usage with FileListFilter --- .../file/AcceptOnceFileFilter.java | 17 ++++- .../integration/file/CompositeFileFilter.java | 34 ++++----- .../integration/file/FileListFilter.java | 10 +++ .../file/ModificationTimeFileFilter.java | 15 ---- .../integration/file/PollableFileSource.java | 69 +++++++------------ .../file/CompositeFileFilterTest.java | 45 +++++++----- ...ableFileSourceIntegrationTests-context.xml | 2 + .../file/PollableFileSourceTests.java | 29 +++----- .../integration/file/TestFileFilter.java | 9 +-- 9 files changed, 109 insertions(+), 121 deletions(-) create mode 100644 org.springframework.integration.file/src/main/java/org/springframework/integration/file/FileListFilter.java delete mode 100644 org.springframework.integration.file/src/main/java/org/springframework/integration/file/ModificationTimeFileFilter.java diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/AcceptOnceFileFilter.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/AcceptOnceFileFilter.java index a160a03297..0c26477534 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/AcceptOnceFileFilter.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/AcceptOnceFileFilter.java @@ -1,11 +1,12 @@ package org.springframework.integration.file; import java.io.File; -import java.io.FileFilter; +import java.util.ArrayList; +import java.util.List; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; -class AcceptOnceFileFilter implements FileFilter { +public class AcceptOnceFileFilter implements FileListFilter { private final Queue seen; @@ -19,7 +20,17 @@ class AcceptOnceFileFilter implements FileFilter { seen = new LinkedBlockingQueue(); } - public boolean accept(File pathname) { + public List filterFiles(File[] files) { + List accepted = new ArrayList(); + for (File file : files) { + if (accept(file)) { + accepted.add(file); + } + } + return accepted; + } + + private boolean accept(File pathname) { synchronized (monitor) { if (!seen.contains(pathname)) { if (!seen.offer(pathname)) { diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/CompositeFileFilter.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/CompositeFileFilter.java index 51e0503571..56333134e1 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/CompositeFileFilter.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/CompositeFileFilter.java @@ -20,37 +20,37 @@ import java.io.FileFilter; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; /** * Composition that delegates to multiple {@link FileFilter}s. The compostition - * is AND based, meaning that all filters must {@link #accept(File)} in order - * for a file to be accepted by the composite. + * is AND based, meaning that all filters must {@link #filterFiles(File)} in + * order for a file to be accepted by the composite. * * @author Iwein Fuld */ -class CompositeFileFilter implements FileFilter { +public class CompositeFileFilter implements FileListFilter { - private final Set fileFilters; + private final Set fileFilters; - public CompositeFileFilter(FileFilter... fileFilters) { - this.fileFilters = new HashSet(Arrays.asList(fileFilters)); + public CompositeFileFilter(FileListFilter... fileFilters) { + this.fileFilters = new HashSet(Arrays.asList(fileFilters)); } - public CompositeFileFilter(HashSet fileFilters) { - this.fileFilters = new HashSet(fileFilters); + public CompositeFileFilter(Collection fileFilters) { + this.fileFilters = new HashSet(fileFilters); } /** * {@inheritDoc} */ - public boolean accept(File pathname) { - for (FileFilter fileFilter : fileFilters) { - if (!fileFilter.accept(pathname)) { - return false; - } + public List filterFiles(File[] files) { + List leftOver = Arrays.asList(files); + for (FileListFilter fileFilter : fileFilters) { + leftOver = fileFilter.filterFiles(leftOver.toArray(new File[] {})); } - return true; + return leftOver; } /** @@ -58,7 +58,7 @@ class CompositeFileFilter implements FileFilter { * @param filters one or more new filters to be used * @return a new CompositeFileFilter with the additional filters */ - public CompositeFileFilter addFilter(FileFilter... filters) { + public CompositeFileFilter addFilter(FileListFilter... filters) { return addFilters(Arrays.asList(filters)); } @@ -69,8 +69,8 @@ class CompositeFileFilter implements FileFilter { * @param filtersToAdd * @return a new CompositeFileFilter with the added filters */ - public CompositeFileFilter addFilters(Collection filtersToAdd) { - HashSet newFilterSet = new HashSet(filtersToAdd); + public CompositeFileFilter addFilters(Collection filtersToAdd) { + HashSet newFilterSet = new HashSet(filtersToAdd); newFilterSet.addAll(fileFilters); return new CompositeFileFilter(newFilterSet); } diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/FileListFilter.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/FileListFilter.java new file mode 100644 index 0000000000..2a780d0fdb --- /dev/null +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/FileListFilter.java @@ -0,0 +1,10 @@ +package org.springframework.integration.file; + +import java.io.File; +import java.util.List; + +public interface FileListFilter { + + List filterFiles(File[] files); + +} diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/ModificationTimeFileFilter.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/ModificationTimeFileFilter.java deleted file mode 100644 index 4540aec6d8..0000000000 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/ModificationTimeFileFilter.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.springframework.integration.file; - -import java.io.File; -import java.io.FileFilter; - -class ModificationTimeFileFilter implements FileFilter { - - private final long modificationTime; - public ModificationTimeFileFilter(long modificationTime) { - this.modificationTime = modificationTime; - } - public boolean accept(File file) { - return modificationTime <= file.lastModified(); - } -} diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/PollableFileSource.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/PollableFileSource.java index 64cd2bb785..7b89a318d8 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/PollableFileSource.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/PollableFileSource.java @@ -17,10 +17,10 @@ package org.springframework.integration.file; import java.io.File; import java.io.FileFilter; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Queue; +import java.util.Set; import java.util.concurrent.PriorityBlockingQueue; import org.apache.commons.logging.Log; @@ -50,21 +50,13 @@ import org.springframework.util.Assert; */ public class PollableFileSource implements PollableSource, MessageDeliveryAware, InitializingBean { - private static final Log log = LogFactory.getLog(PollableFileSource.class); + private static final Log logger = LogFactory.getLog(PollableFileSource.class); private volatile File inputDirectory; - private volatile Queue fileQueue = new PriorityBlockingQueue(); + private final Queue toBeReceived = new PriorityBlockingQueue(); - private volatile FileFilter filter = new AcceptOnceFileFilter(); - - /** - * Sets a queue to be used to hold files that are not processed yet. By - * default a {@link PriorityBlockingQueue} with natural ordering is used. - */ - public void setQueue(Queue queue) { - this.fileQueue = queue; - } + private volatile FileListFilter filter = new AcceptOnceFileFilter(); public void setInputDirectory(File inputDirectory) { this.inputDirectory = inputDirectory; @@ -78,8 +70,8 @@ public class PollableFileSource implements PollableSource, MessageDelivery * {@link CompositeFileFilter} can be used to group them together

* Note that the supplied filter must be thread safe. */ - public void setFilter(FileFilter filter) { - Assert.notNull(filter); + public void setFilter(FileListFilter filter) { + Assert.notNull(filter, "'filter' should not be null"); this.filter = filter; } @@ -89,23 +81,16 @@ public class PollableFileSource implements PollableSource, MessageDelivery Assert.isTrue(this.inputDirectory.canRead(), "No read permissions on " + inputDirectory); } - /** - * {@inheritDoc} - * - * @return the Message created by the {@link #messageCreator} based on the - * next file from the {@link #fileQueue}. Existence of the file is not - * guaranteed, so the consumer of the message needs to check this. - */ public Message receive() throws MessagingException { traceState(); refreshQueue(); Message message = null; - File file = fileQueue.poll(); + File file = toBeReceived.poll(); // we can't rely on isEmpty for concurrency reasons if (file != null) { message = new GenericMessage(file); - if (log.isInfoEnabled()) { - log.info("Created message: [" + message + "]"); + if (logger.isInfoEnabled()) { + logger.info("Created message: [" + message + "]"); } } traceState(); @@ -113,41 +98,33 @@ public class PollableFileSource implements PollableSource, MessageDelivery } private void refreshQueue() { - List freshFiles = new ArrayList(processFileList(Arrays.asList(inputDirectory.listFiles(filter)))); + List filteredFiles = filter.filterFiles((inputDirectory.listFiles())); + Set freshFiles = new HashSet(filteredFiles); if (!freshFiles.isEmpty()) { // don't duplicate what's on the queue already - freshFiles.removeAll(fileQueue); - fileQueue.addAll(freshFiles); - if (log.isDebugEnabled()) { - log.debug("Added to queue: " + freshFiles); + freshFiles.removeAll(toBeReceived); + toBeReceived.addAll(freshFiles); + if (logger.isDebugEnabled()) { + logger.debug("Added to queue: " + freshFiles); } } } - /** - * TODO point to FileFilter options - * @param files - * @return - */ - protected List processFileList(List files) { - return files; - } - /** * In concurrent scenarios onFailure() might cause failing files to be * ignored. If this is not acceptable access to this method should be * synchronized on this instance externally. */ public void onFailure(Message failedMessage, Throwable t) { - if (log.isWarnEnabled()) { - log.warn("Failed to send: " + failedMessage); + if (logger.isWarnEnabled()) { + logger.warn("Failed to send: " + failedMessage); } - fileQueue.add(failedMessage.getPayload()); + toBeReceived.add(failedMessage.getPayload()); } public void onSend(Message sentMessage) { - if (log.isDebugEnabled()) { - log.debug("Sent: " + sentMessage); + if (logger.isDebugEnabled()) { + logger.debug("Sent: " + sentMessage); } } @@ -155,8 +132,8 @@ public class PollableFileSource implements PollableSource, MessageDelivery * utility method to trace the stateful collections of this instance. */ private void traceState() { - if (log.isTraceEnabled()) { - log.trace("Files to be received: [" + fileQueue + "]"); + if (logger.isTraceEnabled()) { + logger.trace("Files to be received: [" + toBeReceived + "]"); } } } diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/CompositeFileFilterTest.java b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/CompositeFileFilterTest.java index c822eeef83..4b690944b3 100644 --- a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/CompositeFileFilterTest.java +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/CompositeFileFilterTest.java @@ -15,12 +15,20 @@ */ package org.springframework.integration.file; -import java.io.File; -import java.io.FileFilter; -import static org.easymock.classextension.EasyMock.*; -import static org.junit.Assert.*; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.createNiceMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -import org.junit.Before; import org.junit.Test; /** @@ -28,40 +36,41 @@ import org.junit.Test; */ public class CompositeFileFilterTest { - private FileFilter fileFilterMock1 = createMock(FileFilter.class); - private FileFilter fileFilterMock2 = createMock(FileFilter.class); + private FileListFilter fileFilterMock1 = createMock(FileListFilter.class); + + private FileListFilter fileFilterMock2 = createMock(FileListFilter.class); private File fileMock = createNiceMock(File.class); - - @Test public void forwardedToFilters() throws Exception { CompositeFileFilter compositeFileFilter = new CompositeFileFilter(fileFilterMock1, fileFilterMock2); - expect(fileFilterMock1.accept(fileMock)).andReturn(true).times(1); - expect(fileFilterMock2.accept(fileMock)).andReturn(true).times(1); + List returnedFiles = Arrays.asList(new File[] { fileMock }); + expect(fileFilterMock1.filterFiles(isA(File[].class))).andReturn(returnedFiles).times(1); + expect(fileFilterMock2.filterFiles(isA(File[].class))).andReturn(returnedFiles).times(1); replay(fileFilterMock1, fileFilterMock2); - assertTrue(compositeFileFilter.accept(fileMock)); + assertEquals(returnedFiles, compositeFileFilter.filterFiles(new File[]{fileMock})); verify(fileFilterMock1, fileFilterMock2); } @Test public void forwardedToAddedFilters() throws Exception { CompositeFileFilter compositeFileFilter = new CompositeFileFilter().addFilter(fileFilterMock1, fileFilterMock2); - expect(fileFilterMock1.accept(fileMock)).andReturn(true).times(1); - expect(fileFilterMock2.accept(fileMock)).andReturn(true).times(1); + List returnedFiles = Arrays.asList(new File[] { fileMock }); + expect(fileFilterMock1.filterFiles(isA(File[].class))).andReturn(returnedFiles).times(1); + expect(fileFilterMock2.filterFiles(isA(File[].class))).andReturn(returnedFiles).times(1); replay(fileFilterMock1, fileFilterMock2); - assertTrue(compositeFileFilter.accept(fileMock)); + assertEquals(returnedFiles, compositeFileFilter.filterFiles(new File[]{fileMock})); verify(fileFilterMock1, fileFilterMock2); } @Test public void negative() throws Exception { CompositeFileFilter compositeFileFilter = new CompositeFileFilter(fileFilterMock1, fileFilterMock2); - expect(fileFilterMock1.accept(fileMock)).andReturn(false).times(1); - expect(fileFilterMock2.accept(fileMock)).andReturn(true).anyTimes(); + expect(fileFilterMock2.filterFiles(isA(File[].class))).andReturn(new ArrayList()).times(1); + expect(fileFilterMock1.filterFiles(isA(File[].class))).andReturn(new ArrayList()).times(1); replay(fileFilterMock1, fileFilterMock2); - assertFalse(compositeFileFilter.accept(fileMock)); + assertTrue(compositeFileFilter.filterFiles(new File[]{fileMock}).isEmpty()); verify(fileFilterMock1, fileFilterMock2); } } diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceIntegrationTests-context.xml b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceIntegrationTests-context.xml index af95659f47..3a92943f39 100644 --- a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceIntegrationTests-context.xml +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceIntegrationTests-context.xml @@ -2,9 +2,11 @@ + + diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceTests.java b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceTests.java index 2fcc0b424f..f6fee398b8 100644 --- a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceTests.java +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/PollableFileSourceTests.java @@ -16,16 +16,14 @@ package org.springframework.integration.file; import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.isA; import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.replay; -import static org.easymock.classextension.EasyMock.reset; import static org.easymock.classextension.EasyMock.verify; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.File; -import java.io.FileFilter; import org.junit.Before; import org.junit.Test; @@ -43,11 +41,9 @@ public class PollableFileSourceTests { private File inputDirectory; - private FileFilter filterMock = createMock(FileFilter.class); - private File fileMock = createMock(File.class); - private Object[] allMocks = new Object[] { inputDirectoryMock, filterMock, fileMock }; + private Object[] allMocks = new Object[] { inputDirectoryMock, fileMock }; @Before public void initialize() throws Exception { @@ -56,15 +52,9 @@ public class PollableFileSourceTests { pollableFileSource.setInputDirectory(inputDirectoryMock); } - @Before - public void setDefaultExpectations() { - expect(fileMock.exists()).andReturn(true).anyTimes(); - } - @Test public void straightProcess() throws Exception { - reset(fileMock); - expect(inputDirectoryMock.listFiles(isA(FileFilter.class))).andReturn(new File[] { fileMock }); + expect(inputDirectoryMock.listFiles()).andReturn(new File[] { fileMock }); replay(allMocks); pollableFileSource.onSend(pollableFileSource.receive()); verify(allMocks); @@ -72,10 +62,11 @@ public class PollableFileSourceTests { @Test public void requeueOnFailure() throws Exception { - expect(inputDirectoryMock.listFiles(isA(FileFilter.class))).andReturn(new File[] { fileMock }); - expect(inputDirectoryMock.listFiles(isA(FileFilter.class))).andReturn(new File[] {}); + expect(inputDirectoryMock.listFiles()).andReturn(new File[] { fileMock }); + expect(inputDirectoryMock.listFiles()).andReturn(new File[] {}); replay(allMocks); Message received = pollableFileSource.receive(); + assertNotNull(received); pollableFileSource.onFailure(received, new RuntimeException("failed")); assertEquals(received.getPayload(), pollableFileSource.receive().getPayload()); verify(allMocks); @@ -83,10 +74,12 @@ public class PollableFileSourceTests { @Test public void noDuplication() throws Exception { - expect(inputDirectoryMock.listFiles(isA(FileFilter.class))).andReturn(new File[] { fileMock }); - expect(inputDirectoryMock.listFiles(isA(FileFilter.class))).andReturn(new File[] {}); + expect(inputDirectoryMock.listFiles()).andReturn(new File[] { fileMock }); + expect(inputDirectoryMock.listFiles()).andReturn(new File[] {}); replay(allMocks); - assertEquals(fileMock, pollableFileSource.receive().getPayload()); + Message received = pollableFileSource.receive(); + assertNotNull(received); + assertEquals(fileMock, received.getPayload()); assertNull(pollableFileSource.receive()); verify(allMocks); } diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/TestFileFilter.java b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/TestFileFilter.java index 8e5e096e6e..196a1bb49c 100644 --- a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/TestFileFilter.java +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/TestFileFilter.java @@ -1,12 +1,13 @@ package org.springframework.integration.file; import java.io.File; -import java.io.FileFilter; +import java.util.Arrays; +import java.util.List; -public class TestFileFilter implements FileFilter{ +public class TestFileFilter implements FileListFilter { - public boolean accept(File pathname) { - return true; + public List filterFiles(File[] files) { + return Arrays.asList(files); } }