initial commit of my work to make building filesystem based adapters more consistent, cleaner.
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience implementation patterned off {@link org.springframework.integration.file.FileListFilter}
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public abstract class AbstractFtpFileListFilter implements FtpFileListFilter {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
abstract public boolean accept(FTPFile ftpFile);
|
||||
|
||||
public List<FTPFile> filterFiles(FTPFile[] files) {
|
||||
List<FTPFile> accepted = new ArrayList<FTPFile>();
|
||||
|
||||
if (files != null) {
|
||||
for (FTPFile f : files) {
|
||||
if (this.accept(f)) {
|
||||
accepted.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return accepted;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Patterned very much on the {@link org.springframework.integration.file.CompositeFileListFilter}
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class CompositeFtpFileListFilter implements FtpFileListFilter {
|
||||
private Set<FtpFileListFilter> filters;
|
||||
|
||||
public CompositeFtpFileListFilter(FtpFileListFilter... ftpFileListFilter) {
|
||||
this.filters = new LinkedHashSet<FtpFileListFilter>(Arrays.asList(ftpFileListFilter));
|
||||
}
|
||||
|
||||
public CompositeFtpFileListFilter(Collection<FtpFileListFilter> ftpFileListFilter) {
|
||||
this.filters = new LinkedHashSet<FtpFileListFilter>(ftpFileListFilter);
|
||||
}
|
||||
public void addFilter( FtpFileListFilter ftpFileListFilter ) {
|
||||
this.filters.add(ftpFileListFilter);
|
||||
}
|
||||
public List<FTPFile> filterFiles(FTPFile[] files) {
|
||||
Assert.notNull(files, "files[] can't be null!");
|
||||
|
||||
List<FTPFile> leftOver = Arrays.asList(files);
|
||||
|
||||
for (FtpFileListFilter ff : this.filters)
|
||||
leftOver = ff.filterFiles(leftOver.toArray(new FTPFile[leftOver.size()]));
|
||||
|
||||
return leftOver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.integration.file.entries.EntryNamer;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.file.entries.EntryNamer} for {@link org.apache.commons.net.ftp.FTPFile} objects
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpFileEntryNamer implements EntryNamer<FTPFile> {
|
||||
public String nameOf(FTPFile entry) {
|
||||
return entry.getName();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Filters out all the FTPFiles taken in a scan of the remote mount o
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public interface FtpFileListFilter {
|
||||
List<FTPFile> filterFiles (FTPFile [] files);
|
||||
}
|
||||
@@ -20,10 +20,8 @@ import org.springframework.context.Lifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.file.AcceptOnceFileListFilter;
|
||||
import org.springframework.integration.file.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.PatternMatchingFileListFilter;
|
||||
import org.springframework.integration.file.entries.*;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
|
||||
@@ -37,10 +35,11 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
@Deprecated
|
||||
public class FtpFileSource implements MessageSource<File>, InitializingBean, Lifecycle {
|
||||
private FileReadingMessageSource fileSource;
|
||||
private FtpInboundSynchronizer synchronizer;
|
||||
|
||||
private EntryNamer fileEntryName = new FileEntryNamer();
|
||||
public FtpFileSource() {
|
||||
this(new FileReadingMessageSource(), new FtpInboundSynchronizer());
|
||||
}
|
||||
@@ -48,9 +47,12 @@ public class FtpFileSource implements MessageSource<File>, InitializingBean, Lif
|
||||
public FtpFileSource(FileReadingMessageSource fileSource, FtpInboundSynchronizer synchronizer) {
|
||||
this.fileSource = fileSource;
|
||||
this.synchronizer = synchronizer;
|
||||
|
||||
Pattern completePattern = Pattern.compile("^.*(?<!" + FtpInboundSynchronizer.INCOMPLETE_EXTENSION + ")$");
|
||||
fileSource.setFilter(new CompositeFileListFilter(new AcceptOnceFileListFilter(), new PatternMatchingFileListFilter(completePattern)));
|
||||
|
||||
EntryListFilter<File> f =new CompositeEntryListFilter<File>(new AcceptOnceEntryFileListFilter<File>(),
|
||||
new PatternMatchingEntryListFilter(fileEntryName,completePattern));
|
||||
|
||||
fileSource.setFilter(f);
|
||||
}
|
||||
|
||||
public void setFileSource(FileReadingMessageSource fileSource) {
|
||||
@@ -63,10 +65,10 @@ public class FtpFileSource implements MessageSource<File>, InitializingBean, Lif
|
||||
|
||||
public void setLocalWorkingDirectory(Resource localWorkingDirectory) {
|
||||
this.synchronizer.setLocalDirectory(localWorkingDirectory);
|
||||
|
||||
try {
|
||||
this.fileSource.setDirectory(localWorkingDirectory.getFile());
|
||||
} catch (IOException e) {
|
||||
// oops
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -11,6 +12,9 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.entries.CompositeEntryListFilter;
|
||||
import org.springframework.integration.file.entries.EntryListFilter;
|
||||
import org.springframework.integration.file.entries.PatternMatchingEntryListFilter;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -19,15 +23,15 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* Makes it easier to assemble the moving pieces involved in standing up an {@link FtpMessageSourceFactoryBean}
|
||||
* Makes it easier to assemble the moving pieces involved in standing up an {@link org.springframework.integration.ftp.FtpFileSource}
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpMessageSourceFactoryBean extends AbstractFactoryBean<FtpFileSource> implements ResourceLoaderAware, ApplicationContextAware {
|
||||
@Deprecated
|
||||
public class FtpFileSourceFactoryBean extends AbstractFactoryBean<FtpFileSource> implements ResourceLoaderAware, ApplicationContextAware {
|
||||
private int port;
|
||||
private boolean autoCreateDirectories;
|
||||
private String filenamePattern;
|
||||
@@ -47,7 +51,7 @@ public class FtpMessageSourceFactoryBean extends AbstractFactoryBean<FtpFileSour
|
||||
/**
|
||||
* Used to teach the FTP adapter what files you are interested in receiving
|
||||
*/
|
||||
private FtpFileListFilter filter;
|
||||
private EntryListFilter<FTPFile> filter;
|
||||
|
||||
public void setFilenamePattern(String filenamePattern) {
|
||||
this.filenamePattern = filenamePattern;
|
||||
@@ -98,10 +102,11 @@ public class FtpMessageSourceFactoryBean extends AbstractFactoryBean<FtpFileSour
|
||||
this.clientMode = clientMode;
|
||||
}
|
||||
|
||||
public void setFilter(FtpFileListFilter filter) {
|
||||
public void setFilter(EntryListFilter<FTPFile> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
private FtpFileEntryNamer ftpFileEntryNamer =new FtpFileEntryNamer();
|
||||
@Override
|
||||
protected FtpFileSource createInstance() throws Exception {
|
||||
// setup local dir
|
||||
@@ -120,17 +125,15 @@ public class FtpMessageSourceFactoryBean extends AbstractFactoryBean<FtpFileSour
|
||||
|
||||
this.ftpInboundSynchronizer = new FtpInboundSynchronizer();
|
||||
|
||||
CompositeFtpFileListFilter compositeFtpFileListFilter = new CompositeFtpFileListFilter();
|
||||
CompositeEntryListFilter<FTPFile> compositeFtpFileListFilter = new CompositeEntryListFilter<FTPFile>() ;
|
||||
if( StringUtils.hasText( this.filenamePattern)){
|
||||
PatternMatchingEntryListFilter<FTPFile> ftpFilePatternMatchingEntryListFilter = new PatternMatchingEntryListFilter<FTPFile>(ftpFileEntryNamer,filenamePattern) ;
|
||||
compositeFtpFileListFilter.addFilter( ftpFilePatternMatchingEntryListFilter);
|
||||
|
||||
if (StringUtils.hasText(this.filenamePattern)) {
|
||||
PatternMatchingFtpFileListFilter patternMatchingFTPFileListFilter = new PatternMatchingFtpFileListFilter();
|
||||
patternMatchingFTPFileListFilter.setPattern(Pattern.compile(this.filenamePattern));
|
||||
compositeFtpFileListFilter.addFilter(patternMatchingFTPFileListFilter);
|
||||
}
|
||||
if(this.filter != null)
|
||||
compositeFtpFileListFilter.addFilter( this.filter);
|
||||
|
||||
if (this.filter != null) {
|
||||
compositeFtpFileListFilter.addFilter(this.filter);
|
||||
}
|
||||
|
||||
this.ftpInboundSynchronizer.setFilter(compositeFtpFileListFilter);
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.file.entries.AcceptAllEntryListFilter;
|
||||
import org.springframework.integration.file.entries.EntryListFilter;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
@@ -44,6 +46,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
@Deprecated
|
||||
public class FtpInboundSynchronizer implements InitializingBean, Lifecycle {
|
||||
private static final Log logger = LogFactory.getLog(FtpInboundSynchronizer.class);
|
||||
static final String INCOMPLETE_EXTENSION = ".INCOMPLETE";
|
||||
@@ -54,14 +57,10 @@ public class FtpInboundSynchronizer implements InitializingBean, Lifecycle {
|
||||
private volatile Resource localDirectory;
|
||||
private boolean running = false;
|
||||
private ScheduledFuture<?> scheduledFuture;
|
||||
private FtpFileListFilter filter;
|
||||
private FtpFileListFilter acceptAllFtpFileListFilter = new FtpFileListFilter() {
|
||||
public List<FTPFile> filterFiles(FTPFile[] files) {
|
||||
return Arrays.asList(files);
|
||||
}
|
||||
};
|
||||
private EntryListFilter<FTPFile> filter;
|
||||
private EntryListFilter<FTPFile> acceptAllFtpFileListFilter = new AcceptAllEntryListFilter<FTPFile>();
|
||||
|
||||
public void setFilter(FtpFileListFilter filter) {
|
||||
public void setFilter(EntryListFilter<FTPFile> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@@ -94,7 +93,7 @@ public class FtpInboundSynchronizer implements InitializingBean, Lifecycle {
|
||||
FTPClient client = this.clientPool.getClient();
|
||||
Assert.state(client != null, FtpClientPool.class.getSimpleName() + " returned 'null' client this most likely a bug in the pool implementation.");
|
||||
|
||||
Collection<FTPFile> fileList = this.filter.filterFiles(client.listFiles());
|
||||
Collection<FTPFile> fileList = this.filter.filterEntries(client.listFiles());
|
||||
|
||||
try {
|
||||
for (FTPFile ftpFile : fileList) {
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* Validates {@link org.apache.commons.net.ftp.FTPFile}s against a {@link java.util.regex.Pattern}.
|
||||
* Patterned very much like {@link org.springframework.integration.file.PatternMatchingFileListFilter}.
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class PatternMatchingFtpFileListFilter extends AbstractFtpFileListFilter implements InitializingBean {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Pattern pattern;
|
||||
private String patternExpression;
|
||||
|
||||
public void setPattern(Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public void setPatternExpression(String patternExpression) {
|
||||
this.patternExpression = patternExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(FTPFile ftpFile) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("testing: " + ToStringBuilder.reflectionToString(ftpFile));
|
||||
}
|
||||
|
||||
return (ftpFile != null) && this.pattern.matcher(ftpFile.getName()).matches();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (StringUtils.hasText(this.patternExpression) && (this.pattern == null)) {
|
||||
this.pattern = Pattern.compile(this.patternExpression);
|
||||
}
|
||||
|
||||
Assert.notNull(this.pattern, "the pattern must not be null");
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ftp.FtpSendingMessageHandlerFactoryBean;
|
||||
import org.springframework.integration.ftp.impl.FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -57,7 +59,7 @@ public class FtpNamespaceHandler extends NamespaceHandlerSupport {
|
||||
private static class FTPMessageSendingConsumerBeanDefinitionParser extends AbstractOutboundChannelAdapterParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PACKAGE_NAME + ".FtpSendingMessageHandlerFactoryBean");
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpSendingMessageHandlerFactoryBean.class.getName());
|
||||
|
||||
for (String p : "auto-create-directories,username,port,password,host,key-file,key-file-password,remote-directory".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
@@ -79,17 +81,20 @@ public class FtpNamespaceHandler extends NamespaceHandlerSupport {
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PACKAGE_NAME + ".FtpMessageSourceFactoryBean");
|
||||
|
||||
// reference
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class.getName());
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,"filter");
|
||||
|
||||
for (String p : ("filename-pattern,auto-create-directories,username,password,host,port," + "remote-directory,local-working-directory").split(",")) {
|
||||
for (String p : ("auto-delete-remote-files-on-sync,filename-pattern,auto-create-directories,username,password,host,port," +
|
||||
"remote-directory,local-working-directory").split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
|
||||
int clientMode = CLIENT_MODES.get(element.getAttribute("client-mode"));
|
||||
builder.addPropertyValue("clientMode", clientMode);
|
||||
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer;
|
||||
import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource;
|
||||
import org.springframework.integration.ftp.FtpClientPool;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* An FTP-adapter implementation of {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer}
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpInboundRemoteFileSystemSynchronizer extends AbstractInboundRemoteFileSystemSychronizer<FTPFile> {
|
||||
protected FtpClientPool clientPool;
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
Assert.notNull(this.clientPool, "clientPool can't be null");
|
||||
|
||||
if (this.shouldDeleteSourceFile) {
|
||||
this.entryAcknowledgmentStrategy = new DeletionEntryAcknowledgmentStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link org.springframework.integration.ftp.FtpClientPool} that holds references to {@link org.apache.commons.net.ftp.FTPClient} instances
|
||||
*
|
||||
* @param clientPool the {@link org.springframework.integration.ftp.FtpClientPool}
|
||||
*/
|
||||
public void setClientPool(FtpClientPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
|
||||
protected boolean copyFileToLocalDirectory(FTPClient client, FTPFile ftpFile, Resource localDirectory)
|
||||
throws IOException, FileNotFoundException {
|
||||
String remoteFileName = ftpFile.getName();
|
||||
String localFileName = localDirectory.getFile().getPath() + "/" + remoteFileName;
|
||||
File localFile = new File(localFileName);
|
||||
|
||||
if (!localFile.exists()) {
|
||||
String tempFileName = localFileName + AbstractInboundRemoteFileSystemSynchronizingMessageSource.INCOMPLETE_EXTENSION;
|
||||
File file = new File(tempFileName);
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
|
||||
try {
|
||||
client.retrieveFile(remoteFileName, fos);
|
||||
|
||||
// Perhaps we have some dispatch of hte source file to do?
|
||||
acknowledge(client, ftpFile);
|
||||
} catch (Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
|
||||
file.renameTo(localFile);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void syncRemoteToLocalFileSystem() {
|
||||
try {
|
||||
FTPClient client = this.clientPool.getClient();
|
||||
Assert.state(client != null, FtpClientPool.class.getSimpleName() + " returned a 'null' client. " + "This most likely a bug in the pool implementation.");
|
||||
|
||||
Collection<FTPFile> fileList = this.filter.filterEntries(client.listFiles());
|
||||
|
||||
try {
|
||||
for (FTPFile ftpFile : fileList) {
|
||||
if ((ftpFile != null) && ftpFile.isFile()) {
|
||||
copyFileToLocalDirectory(client, ftpFile, this.localDirectory);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.clientPool.releaseClient(client);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new MessagingException("Problem occurred while synchronizing remote to local directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Trigger getTrigger() {
|
||||
return new PeriodicTrigger(10 * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* An ackowledgment strategy that deletes
|
||||
*/
|
||||
class DeletionEntryAcknowledgmentStrategy implements AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy<FTPFile> {
|
||||
public void acknowledge(Object useful, FTPFile msg)
|
||||
throws Exception {
|
||||
FTPClient ftpClient = (FTPClient) useful;
|
||||
if ((msg != null) && ftpClient.deleteFile(msg.getName())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("deleted " + msg.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource;
|
||||
import org.springframework.integration.ftp.FtpClientPool;
|
||||
|
||||
|
||||
/**
|
||||
* a {@link org.springframework.integration.core.MessageSource} implementation for FTP
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpInboundRemoteFileSystemSynchronizingMessageSource extends AbstractInboundRemoteFileSystemSynchronizingMessageSource<FTPFile, FtpInboundRemoteFileSystemSynchronizer> {
|
||||
private volatile FtpClientPool clientPool;
|
||||
|
||||
public void setClientPool(FtpClientPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.synchronizer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
this.synchronizer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
this.synchronizer.setClientPool(this.clientPool);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
import org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer;
|
||||
import org.springframework.integration.file.entries.CompositeEntryListFilter;
|
||||
import org.springframework.integration.file.entries.EntryListFilter;
|
||||
import org.springframework.integration.file.entries.PatternMatchingEntryListFilter;
|
||||
import org.springframework.integration.ftp.DefaultFtpClientFactory;
|
||||
import org.springframework.integration.ftp.FtpFileEntryNamer;
|
||||
import org.springframework.integration.ftp.QueuedFtpClientPool;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* Factory to make building the namespace easier
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean extends AbstractFactoryBean<FtpInboundRemoteFileSystemSynchronizingMessageSource> implements ResourceLoaderAware {
|
||||
private volatile String port;
|
||||
private volatile String autoCreateDirectories;
|
||||
private volatile String filenamePattern;
|
||||
private volatile String username;
|
||||
private volatile String password;
|
||||
private volatile String host;
|
||||
private volatile String remoteDirectory;
|
||||
private volatile String localWorkingDirectory;
|
||||
private volatile ResourceLoader resourceLoader;
|
||||
private volatile Resource localDirectoryResource;
|
||||
private volatile EntryListFilter<FTPFile> filter;
|
||||
private volatile int clientMode = FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE;
|
||||
private volatile String autoDeleteRemoteFilesOnSync;
|
||||
|
||||
public void setAutoDeleteRemoteFilesOnSync(String autoDeleteRemoteFilesOnSync) {
|
||||
this.autoDeleteRemoteFilesOnSync = autoDeleteRemoteFilesOnSync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return FtpInboundRemoteFileSystemSynchronizingMessageSource.class;
|
||||
}
|
||||
|
||||
private Resource fromText(String path) {
|
||||
ResourceEditor resourceEditor = new ResourceEditor(this.resourceLoader);
|
||||
resourceEditor.setAsText(path);
|
||||
return (Resource) resourceEditor.getValue();
|
||||
}
|
||||
|
||||
private DefaultFtpClientFactory defaultFtpClientFactory() {
|
||||
DefaultFtpClientFactory defaultFtpClientFactory = new DefaultFtpClientFactory();
|
||||
defaultFtpClientFactory.setHost(this.host);
|
||||
defaultFtpClientFactory.setPassword(this.password);
|
||||
defaultFtpClientFactory.setPort(Integer.parseInt(this.port));
|
||||
defaultFtpClientFactory.setRemoteWorkingDirectory(this.remoteDirectory);
|
||||
defaultFtpClientFactory.setUsername(this.username);
|
||||
defaultFtpClientFactory.setClientMode(this.clientMode);
|
||||
|
||||
return defaultFtpClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FtpInboundRemoteFileSystemSynchronizingMessageSource createInstance()
|
||||
throws Exception {
|
||||
boolean autoCreatDirs = Boolean.parseBoolean(this.autoCreateDirectories);
|
||||
boolean ackRemoteDir = Boolean.parseBoolean(this.autoDeleteRemoteFilesOnSync);
|
||||
|
||||
FtpInboundRemoteFileSystemSynchronizingMessageSource ftpRemoteFileSystemSynchronizingMessageSource = new FtpInboundRemoteFileSystemSynchronizingMessageSource();
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setAutoCreateDirectories(autoCreatDirs);
|
||||
|
||||
if (!StringUtils.hasText(this.localWorkingDirectory)) {
|
||||
File tmp = new File(SystemUtils.getJavaIoTmpDir(), "ftpInbound");
|
||||
this.localWorkingDirectory = "file://" + tmp.getAbsolutePath();
|
||||
}
|
||||
|
||||
this.localDirectoryResource = this.fromText(this.localWorkingDirectory);
|
||||
|
||||
FtpFileEntryNamer ftpFileEntryNamer = new FtpFileEntryNamer();
|
||||
CompositeEntryListFilter<FTPFile> compositeFtpFileListFilter = new CompositeEntryListFilter<FTPFile>();
|
||||
|
||||
if (StringUtils.hasText(this.filenamePattern)) {
|
||||
PatternMatchingEntryListFilter<FTPFile> ftpFilePatternMatchingEntryListFilter = new PatternMatchingEntryListFilter<FTPFile>(ftpFileEntryNamer, filenamePattern);
|
||||
compositeFtpFileListFilter.addFilter(ftpFilePatternMatchingEntryListFilter);
|
||||
}
|
||||
|
||||
if (this.filter != null) {
|
||||
compositeFtpFileListFilter.addFilter(this.filter);
|
||||
}
|
||||
|
||||
QueuedFtpClientPool queuedFtpClientPool = new QueuedFtpClientPool(15, defaultFtpClientFactory());
|
||||
|
||||
FtpInboundRemoteFileSystemSynchronizer ftpRemoteFileSystemSynchronizer = new FtpInboundRemoteFileSystemSynchronizer();
|
||||
ftpRemoteFileSystemSynchronizer.setClientPool(queuedFtpClientPool);
|
||||
ftpRemoteFileSystemSynchronizer.setLocalDirectory(this.localDirectoryResource);
|
||||
ftpRemoteFileSystemSynchronizer.setShouldDeleteSourceFile(ackRemoteDir);
|
||||
|
||||
if (compositeFtpFileListFilter != null) {
|
||||
ftpRemoteFileSystemSynchronizer.setFilter(compositeFtpFileListFilter);
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setRemotePredicate(compositeFtpFileListFilter);
|
||||
}
|
||||
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setSynchronizer(ftpRemoteFileSystemSynchronizer);
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setClientPool(queuedFtpClientPool);
|
||||
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setLocalDirectory(this.localDirectoryResource);
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setBeanFactory(this.getBeanFactory());
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.setAutoStartup(true);
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.afterPropertiesSet();
|
||||
ftpRemoteFileSystemSynchronizingMessageSource.start();
|
||||
|
||||
return ftpRemoteFileSystemSynchronizingMessageSource;
|
||||
}
|
||||
|
||||
public void setPort(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setAutoCreateDirectories(String autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
|
||||
public void setFilenamePattern(String filenamePattern) {
|
||||
this.filenamePattern = filenamePattern;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setRemoteDirectory(String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
|
||||
public void setLocalWorkingDirectory(String localWorkingDirectory) {
|
||||
this.localWorkingDirectory = localWorkingDirectory;
|
||||
}
|
||||
|
||||
public void setFilter(EntryListFilter<FTPFile> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public void setClientMode(int clientMode) {
|
||||
this.clientMode = clientMode;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ftp.FtpFileListFilter"/>
|
||||
<tool:expected-type type="org.springframework.integration.file.entries.EntryListFilter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -29,5 +29,6 @@ public class InboundFtpFileServiceActivator {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext =
|
||||
new ClassPathXmlApplicationContext("inbound-ftp-context.xml");
|
||||
classPathXmlApplicationContext.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
filename-pattern=".*?jpg"
|
||||
>
|
||||
<int:poller>
|
||||
<int:interval-trigger interval="10000" time-unit="MILLISECONDS"/>
|
||||
<int:interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</int:poller>
|
||||
</ftp:inbound-channel-adapter>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user