INT-1591 removing the FileNameExtractor strategy in favor of concrete implementations of AbstractPatternMatchingFileListFilter

This commit is contained in:
Mark Fisher
2010-11-08 18:32:57 -05:00
parent 2a8994d7b6
commit 23c8c28d0c
13 changed files with 128 additions and 161 deletions

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2002-2010 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.entries;
/**
* Responsible for coercing a String identification out of the T entry.
*
* @author Josh Long
* @param <T> the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files)
*/
public interface EntryNameExtractor<T> {
/**
* This is the one place I couldn't spackle over the interface differences between an FTPFile (FTP adapter), File (File adapter), and LsEntry (SFTP adapter)
* with generics alone. So we have a typed strategy implementation for accessing a property....
*
* @param entry the entry in a file system listing
* @return the String name that might be used to reference that entry or to do regular expression checks against
*/
String getName(T entry);
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2002-2010 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.entries;
import java.io.File;
/**
* {@link java.io.File}-based implementation of the {@link EntryNameExtractor} strategy.
*
* @author Josh Long
* @since 2.0
*/
public class FileEntryNameExtractor implements EntryNameExtractor<File> {
public String getName(File entry) {
return (entry != null) ? entry.getName() : null;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2002-2010 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.util.regex.Pattern;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Filters a listing of files by qualifying their 'name' (as determined by {@link org.springframework.integration.file.entries.EntryNameExtractor})
* against a regular expression (an instance of {@link java.util.regex.Pattern})
*
* @author Iwein Fuld
* @author Josh Long
* @param <F> the type of file entry
* @since 2.0
*/
public abstract class AbstractPatternMatchingFileListFilter<F> extends AbstractFileListFilter<F> implements InitializingBean {
private volatile Pattern pattern;
public AbstractPatternMatchingFileListFilter(String pattern) {
this.pattern = Pattern.compile(pattern);
}
public AbstractPatternMatchingFileListFilter(Pattern pattern) {
this.pattern = pattern;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
public void setPattern(String pattern) {
this.pattern = Pattern.compile(pattern);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.pattern, "'pattern' must not be null!");
}
@Override
public boolean accept(F file) {
return (file != null) && this.pattern.matcher(this.getFilename(file)).matches();
}
/**
* Subclasses must implement this method to extract the file's name.
*/
protected abstract String getFilename(F file);
}

View File

@@ -16,65 +16,27 @@
package org.springframework.integration.file.filters;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.file.entries.EntryNameExtractor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.regex.Pattern;
/**
* Filters a listing of files by qualifying their 'name' (as determined by {@link org.springframework.integration.file.entries.EntryNameExtractor})
* against a regular expression (an instance of {@link java.util.regex.Pattern})
*
* @author Iwein Fuld
* @author Josh Long
* @param <F> the type of file entry
* @since 2.0
* Implementation of AbstractPatternMatchingFileListFilter for java.io.File entries.
*
* @author Mark Fisher
*/
public class PatternMatchingFileListFilter<F> extends AbstractFileListFilter<F> implements InitializingBean {
public class PatternMatchingFileListFilter extends AbstractPatternMatchingFileListFilter<File> {
private volatile EntryNameExtractor<F> entryNameExtractor;
private volatile Pattern pattern;
private volatile String patternExpression;
public PatternMatchingFileListFilter(EntryNameExtractor<F> entryNameExtractor, String pattern) {
this.entryNameExtractor = entryNameExtractor;
this.patternExpression = pattern;
public PatternMatchingFileListFilter(String pattern) {
super(pattern);
}
public PatternMatchingFileListFilter(EntryNameExtractor<F> entryNameExtractor, Pattern pattern) {
this.entryNameExtractor = entryNameExtractor;
this.pattern = pattern;
}
public void setEntryNameExtractor(EntryNameExtractor<F> entryNameExtractor) {
this.entryNameExtractor = entryNameExtractor;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
public void setPatternExpression(String patternExpression) {
this.patternExpression = patternExpression;
}
public void afterPropertiesSet() throws Exception {
if (StringUtils.hasText(this.patternExpression) && (pattern == null)) {
this.pattern = Pattern.compile(this.patternExpression);
}
Assert.notNull(this.entryNameExtractor, "'entryNameExtractor' must not be null!");
Assert.notNull(this.pattern, "'pattern' must not be null!");
public PatternMatchingFileListFilter(Pattern pattern) {
super(pattern);
}
@Override
public boolean accept(F entry) {
return (entry != null) && this.pattern.matcher(this.entryNameExtractor.getName(entry)).matches();
protected String getFilename(File file) {
return (file != null) ? file.getName() : null;
}
}

View File

@@ -26,7 +26,7 @@ import org.springframework.util.AntPathMatcher;
*
* @author Iwein Fuld
* @see org.springframework.util.AntPathMatcher
* @see org.springframework.integration.file.filters.PatternMatchingFileListFilter
* @see org.springframework.integration.file.filters.AbstractPatternMatchingFileListFilter
* @since 2.0.0
*/
public class SimplePatternFileListFilter extends AbstractFileListFilter<File> {

View File

@@ -27,7 +27,6 @@ import org.springframework.integration.MessagingException;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.entries.FileEntryNameExtractor;
import org.springframework.integration.file.filters.AcceptOnceFileListFilter;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
@@ -155,11 +154,10 @@ public abstract class AbstractInboundRemoteFileSystemSynchronizingMessageSource<
@SuppressWarnings("unchecked")
private FileListFilter<File> buildFilter() {
FileEntryNameExtractor fileEntryNameExtractor = new FileEntryNameExtractor();
Pattern completePattern = Pattern.compile("^.*(?<!" + INCOMPLETE_EXTENSION + ")$");
return new CompositeFileListFilter<File>(Arrays.asList(
new AcceptOnceFileListFilter<File>(),
new PatternMatchingFileListFilter<File>(fileEntryNameExtractor, completePattern)));
new PatternMatchingFileListFilter(completePattern)));
}
}

View File

@@ -10,8 +10,6 @@
p:directory="file:${java.io.tmpdir}/FileReadingMessageSourceIntegrationTests"
p:filter-ref="compositeFilter"/>
<bean id="entryNameExtractor" class="org.springframework.integration.file.entries.FileEntryNameExtractor"/>
<!-- customized filter -->
<bean id="legacyCompositeFilter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg>
@@ -19,7 +17,6 @@
<bean class="org.springframework.integration.file.filters.AcceptOnceFileListFilter"/>
<bean class="org.springframework.integration.file.TestFileListFilter"/>
<bean class="org.springframework.integration.file.filters.PatternMatchingFileListFilter">
<constructor-arg ref="entryNameExtractor"/>
<constructor-arg value="test*"/>
</bean>
</list>

View File

@@ -27,7 +27,6 @@ import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.file.entries.FileEntryNameExtractor;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.filters.PatternMatchingFileListFilter;
@@ -36,13 +35,11 @@ import org.springframework.integration.file.filters.PatternMatchingFileListFilte
*/
public class PatternMatchingFileListFilterTests {
private FileEntryNameExtractor fileEntryNameExtractor = new FileEntryNameExtractor();
@Test
public void matchSingleFile() {
File[] files = new File[]{new File("/some/path/test.txt")};
Pattern pattern = Pattern.compile("[a-z]+\\.txt");
PatternMatchingFileListFilter<File> filter = new PatternMatchingFileListFilter<File>(fileEntryNameExtractor, pattern);
PatternMatchingFileListFilter filter = new PatternMatchingFileListFilter(pattern);
List<File> accepted = filter.filterFiles(files);
assertEquals(1, accepted.size());
}
@@ -51,7 +48,7 @@ public class PatternMatchingFileListFilterTests {
public void noMatchWithSingleFile() {
File[] files = new File[]{new File("/some/path/Test.txt")};
Pattern pattern = Pattern.compile("[a-z]+\\.txt");
PatternMatchingFileListFilter<File> filter = new PatternMatchingFileListFilter<File>(fileEntryNameExtractor, pattern);
PatternMatchingFileListFilter filter = new PatternMatchingFileListFilter(pattern);
List<File> accepted = filter.filterFiles(files);
assertEquals(0, accepted.size());
}
@@ -65,7 +62,7 @@ public class PatternMatchingFileListFilterTests {
new File("/some/path/bar.not")
};
Pattern pattern = Pattern.compile("[a-z]+\\.txt");
PatternMatchingFileListFilter<File> filter = new PatternMatchingFileListFilter<File>(this.fileEntryNameExtractor, pattern);
PatternMatchingFileListFilter filter = new PatternMatchingFileListFilter(pattern);
List<File> accepted = filter.filterFiles(files);
assertEquals(2, accepted.size());
assertTrue(accepted.contains(new File("/some/path/foo.txt")));

View File

@@ -4,14 +4,7 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--<bean class="org.springframework.integration.file.filters.PatternMatchingFileListFilter">
<constructor-arg value="fo+\.[tx]{3}"/>
</bean>
-->
<bean id="filter" class="org.springframework.integration.file.filters.PatternMatchingFileListFilter">
<constructor-arg>
<bean class="org.springframework.integration.file.entries.FileEntryNameExtractor"/>
</constructor-arg>
<constructor-arg value="fo+\.[tx]{3}"/>
</bean>

View File

@@ -16,18 +16,30 @@
package org.springframework.integration.ftp;
import java.util.regex.Pattern;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.integration.file.entries.EntryNameExtractor;
import org.springframework.integration.file.filters.AbstractPatternMatchingFileListFilter;
/**
* A {@link org.springframework.integration.file.entries.EntryNameExtractor} for {@link org.apache.commons.net.ftp.FTPFile} objects
*
* @author Josh Long
* @author Mark Fisher
* @since 2.0
*/
public class FtpFileEntryNameExtractor implements EntryNameExtractor<FTPFile> {
public class FtpPatternMatchingFileListFilter extends AbstractPatternMatchingFileListFilter<FTPFile> {
public String getName(FTPFile entry) {
return entry.getName();
public FtpPatternMatchingFileListFilter(String pattern) {
super(pattern);
}
public FtpPatternMatchingFileListFilter(Pattern pattern) {
super(pattern);
}
@Override
protected String getFilename(FTPFile file) {
return file.getName();
}
}

View File

@@ -30,7 +30,6 @@ import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.filters.PatternMatchingFileListFilter;
import org.springframework.util.StringUtils;
/**
@@ -154,11 +153,10 @@ public class FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean
this.localWorkingDirectory = "file://" + tmp.getAbsolutePath();
}
this.localDirectoryResource = this.fromText(this.localWorkingDirectory);
FtpFileEntryNameExtractor fileEntryNameExtractor = new FtpFileEntryNameExtractor();
CompositeFileListFilter<FTPFile> compositeFtpFileListFilter = new CompositeFileListFilter<FTPFile>();
if (StringUtils.hasText(this.filenamePattern)) {
PatternMatchingFileListFilter<FTPFile> ftpFilePatternMatchingFileListFilter =
new PatternMatchingFileListFilter<FTPFile>(fileEntryNameExtractor, filenamePattern);
FtpPatternMatchingFileListFilter ftpFilePatternMatchingFileListFilter =
new FtpPatternMatchingFileListFilter(filenamePattern);
compositeFtpFileListFilter.addFilter(ftpFilePatternMatchingFileListFilter);
}
if (this.filter != null) {

View File

@@ -16,18 +16,30 @@
package org.springframework.integration.sftp;
import org.springframework.integration.file.entries.EntryNameExtractor;
import java.util.regex.Pattern;
import org.springframework.integration.file.filters.AbstractPatternMatchingFileListFilter;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
/**
* Stratgy for naming a {@link com.jcraft.jsch.ChannelSftp.LsEntry} instance.
*
* @author Josh Long
* @author Mark Fisher
* @since 2.0
*/
public class SftpEntryNameExtractor implements EntryNameExtractor<ChannelSftp.LsEntry> {
public class SftpPatternMatchingFileListFilter extends AbstractPatternMatchingFileListFilter<ChannelSftp.LsEntry> {
public String getName(ChannelSftp.LsEntry entry) {
public SftpPatternMatchingFileListFilter(String pattern) {
super(pattern);
}
public SftpPatternMatchingFileListFilter(Pattern pattern) {
super(pattern);
}
@Override
protected String getFilename(LsEntry entry) {
return entry.getFilename();
}

View File

@@ -27,9 +27,8 @@ import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.filters.PatternMatchingFileListFilter;
import org.springframework.integration.sftp.QueuedSftpSessionPool;
import org.springframework.integration.sftp.SftpEntryNameExtractor;
import org.springframework.integration.sftp.SftpPatternMatchingFileListFilter;
import org.springframework.integration.sftp.SftpSessionFactory;
import org.springframework.integration.sftp.impl.SftpInboundRemoteFileSystemSynchronizer;
import org.springframework.integration.sftp.impl.SftpInboundRemoteFileSystemSynchronizingMessageSource;
@@ -171,12 +170,11 @@ public class SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean
this.localDirectoryResource = this.resourceFromString(localDirectoryPath);
// remote predicates
SftpEntryNameExtractor sftpEntryNameExtractor = new SftpEntryNameExtractor();
CompositeFileListFilter<ChannelSftp.LsEntry> compositeFtpFileListFilter = new CompositeFileListFilter<ChannelSftp.LsEntry>();
if (StringUtils.hasText(this.filenamePattern)) {
PatternMatchingFileListFilter<ChannelSftp.LsEntry> ftpFilePatternMatchingEntryListFilter =
new PatternMatchingFileListFilter<ChannelSftp.LsEntry>(sftpEntryNameExtractor, filenamePattern);
compositeFtpFileListFilter.addFilter(ftpFilePatternMatchingEntryListFilter);
SftpPatternMatchingFileListFilter sftpFilePatternMatchingEntryListFilter =
new SftpPatternMatchingFileListFilter(filenamePattern);
compositeFtpFileListFilter.addFilter(sftpFilePatternMatchingEntryListFilter);
}
if (this.filter != null) {
compositeFtpFileListFilter.addFilter(this.filter);