re-adding src from branch to include FTPS support.
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPClientConfig;
|
||||
import org.apache.commons.net.ftp.FTPReply;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
|
||||
|
||||
abstract public class AbstractFtpClientFactory<T extends FTPClient> implements FtpClientFactory<T> {
|
||||
private static final Log logger = LogFactory.getLog(FtpClientFactory.class);
|
||||
private static final String DEFAULT_REMOTE_WORKING_DIRECTORY = "/";
|
||||
protected FTPClientConfig config;
|
||||
protected String username;
|
||||
protected String host;
|
||||
protected String password;
|
||||
protected int port = FTP.DEFAULT_PORT;
|
||||
protected String remoteWorkingDirectory = DEFAULT_REMOTE_WORKING_DIRECTORY;
|
||||
protected int clientMode = FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE;
|
||||
protected int fileType = FTP.BINARY_FILE_TYPE;
|
||||
|
||||
public void setFileType(int fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
public void setConfig(FTPClientConfig config) {
|
||||
Assert.notNull(config);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
Assert.hasText(host);
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
Assert.isTrue(port > 0, "Port number should be > 0");
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setUsername(String user) {
|
||||
Assert.hasText(user, "'user' should be a nonempty string");
|
||||
this.username = user;
|
||||
}
|
||||
|
||||
public void setPassword(String pass) {
|
||||
Assert.notNull(pass, "password should not be null");
|
||||
this.password = pass;
|
||||
}
|
||||
|
||||
public void setRemoteWorkingDirectory(String remoteWorkingDirectory) {
|
||||
Assert.notNull(remoteWorkingDirectory, "remote directory should not be null");
|
||||
this.remoteWorkingDirectory = remoteWorkingDirectory.replaceAll("^$", "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set client mode for example
|
||||
* <code>FTPClient.ACTIVE_LOCAL_CONNECTION_MODE</code> (default) Only local
|
||||
* modes are supported.
|
||||
*/
|
||||
public void setClientMode(int clientMode) {
|
||||
this.clientMode = clientMode;
|
||||
}
|
||||
|
||||
protected abstract T createSingleInstanceOfClient();
|
||||
|
||||
/**
|
||||
* this is a hook to setup the state of the {@link org.apache.commons.net.ftp.FTPClient} impl *after* the
|
||||
* implementation's {@link org.apache.commons.net.ftp.FTPClient#connect(String)} method's been called but before any
|
||||
* action's been taken.
|
||||
*
|
||||
* @param t the ftp client instance on which to act
|
||||
* @throws IOException if anything should go wrong
|
||||
*/
|
||||
protected void onAfterConnect(T t) throws IOException {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
public T getClient() throws SocketException, IOException {
|
||||
T client = createSingleInstanceOfClient();
|
||||
client.configure(config);
|
||||
|
||||
if (!StringUtils.hasText(username)) {
|
||||
throw new MessagingException("username is required");
|
||||
}
|
||||
|
||||
client.connect(host);
|
||||
onAfterConnect(client);
|
||||
|
||||
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
|
||||
throw new MessagingException("Connecting to server [" + host + ":" + port + "] failed, please check the connection");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Connected to server [" + host + ":" + port + "]");
|
||||
}
|
||||
|
||||
if (!client.login(username, password)) {
|
||||
throw new MessagingException("Login failed. Please check the username and password.");
|
||||
}
|
||||
|
||||
setClientMode(client);
|
||||
|
||||
client.setFileType(this.fileType);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("login successful");
|
||||
}
|
||||
|
||||
if (!remoteWorkingDirectory.equals(client.printWorkingDirectory()) && !client.changeWorkingDirectory(remoteWorkingDirectory)) {
|
||||
throw new MessagingException("Could not change directory to '" + remoteWorkingDirectory + "'. Please check the path.");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("working directory is: " + client.printWorkingDirectory());
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mode of the connection. Only local modes are supported.
|
||||
*/
|
||||
protected void setClientMode(FTPClient client) {
|
||||
switch (clientMode) {
|
||||
case FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE:
|
||||
client.enterLocalActiveMode();
|
||||
|
||||
break;
|
||||
|
||||
case FTPClient.PASSIVE_LOCAL_DATA_CONNECTION_MODE:
|
||||
client.enterLocalPassiveMode();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
|
||||
/**
|
||||
* Factors out the client factory creaton
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class ClientFactorySupport {
|
||||
public static DefaultFtpsClientFactory ftpsClientFactory(String host, int port, String remoteDir, String user, String pw, int fileType, int clientMode, String prot, String protocol,
|
||||
String authValue, Boolean implicit, TrustManager trustManager, KeyManager keyManager, Boolean sessionCreation, Boolean useClientMode, Boolean wantsClientAuth, Boolean needClientAuth , String [] cipherSuites) {
|
||||
DefaultFtpsClientFactory defaultFtpClientFactory = new DefaultFtpsClientFactory();
|
||||
defaultFtpClientFactory.setHost(host);
|
||||
defaultFtpClientFactory.setPassword(pw);
|
||||
defaultFtpClientFactory.setPort((port));
|
||||
defaultFtpClientFactory.setRemoteWorkingDirectory(remoteDir);
|
||||
defaultFtpClientFactory.setUsername(user);
|
||||
defaultFtpClientFactory.setFileType(fileType);
|
||||
defaultFtpClientFactory.setClientMode(clientMode);
|
||||
|
||||
if(cipherSuites !=null)
|
||||
defaultFtpClientFactory.setCipherSuites( cipherSuites );
|
||||
|
||||
|
||||
|
||||
if (StringUtils.hasText(prot)) {
|
||||
defaultFtpClientFactory.setProt(prot);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(protocol)) {
|
||||
defaultFtpClientFactory.setProtocol(protocol);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(authValue)) {
|
||||
defaultFtpClientFactory.setAuthValue(authValue);
|
||||
}
|
||||
|
||||
if (null != implicit) {
|
||||
defaultFtpClientFactory.setImplicit(implicit);
|
||||
}
|
||||
|
||||
if (trustManager != null) {
|
||||
defaultFtpClientFactory.setTrustManager(trustManager);
|
||||
}
|
||||
|
||||
if (keyManager != null) {
|
||||
defaultFtpClientFactory.setKeyManager(keyManager);
|
||||
}
|
||||
|
||||
if (needClientAuth != null) {
|
||||
defaultFtpClientFactory.setNeedClientAuth(needClientAuth);
|
||||
}
|
||||
|
||||
if (wantsClientAuth != null) {
|
||||
defaultFtpClientFactory.setWantsClientAuth(wantsClientAuth);
|
||||
}
|
||||
|
||||
if (sessionCreation != null) {
|
||||
defaultFtpClientFactory.setSessionCreation(sessionCreation);
|
||||
}
|
||||
|
||||
if (useClientMode != null) {
|
||||
defaultFtpClientFactory.setUseClientMode(useClientMode);
|
||||
}
|
||||
|
||||
return defaultFtpClientFactory;
|
||||
}
|
||||
|
||||
public static DefaultFtpClientFactory ftpClientFactory(String host, int port, String remoteDir, String user, String pw, int clientMode) {
|
||||
DefaultFtpClientFactory defaultFtpClientFactory = new DefaultFtpClientFactory();
|
||||
defaultFtpClientFactory.setHost(host);
|
||||
defaultFtpClientFactory.setPassword(pw);
|
||||
defaultFtpClientFactory.setPort(port);
|
||||
defaultFtpClientFactory.setRemoteWorkingDirectory(remoteDir);
|
||||
defaultFtpClientFactory.setUsername(user);
|
||||
defaultFtpClientFactory.setClientMode(clientMode);
|
||||
|
||||
return defaultFtpClientFactory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of FtpClientFactory.
|
||||
*
|
||||
* @author iwein
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class DefaultFtpClientFactory extends AbstractFtpClientFactory<FTPClient> {
|
||||
@Override
|
||||
protected FTPClient createSingleInstanceOfClient() {
|
||||
return new FTPClient();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPSClient;
|
||||
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.net.SocketException;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
|
||||
/**
|
||||
* provides a working FTPS implementation
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class DefaultFtpsClientFactory extends AbstractFtpClientFactory<FTPSClient> {
|
||||
private Boolean useClientMode;
|
||||
private Boolean sessionCreation;
|
||||
private String authValue;
|
||||
private TrustManager trustManager;
|
||||
private String[] cipherSuites;
|
||||
private String[] protocols;
|
||||
private KeyManager keyManager;
|
||||
private Boolean needClientAuth;
|
||||
private Boolean wantsClientAuth;
|
||||
private boolean implicit = false;
|
||||
private String prot = "P";
|
||||
private String protocol;
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
File file = new File(SystemUtils.getUserHome(), "Desktop/ftp.properties");
|
||||
Resource r = new FileSystemResource(file);
|
||||
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
|
||||
propertiesFactoryBean.setLocation(r);
|
||||
propertiesFactoryBean.afterPropertiesSet();
|
||||
|
||||
Properties props = propertiesFactoryBean.getObject();
|
||||
|
||||
String user = props.getProperty("ftp.username");
|
||||
String pw = props.getProperty("ftp.password");
|
||||
String host = props.getProperty("ftp.host");
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("doesn't exist");
|
||||
}
|
||||
|
||||
DefaultFtpsClientFactory defaultFtpsClientFactory = new DefaultFtpsClientFactory();
|
||||
defaultFtpsClientFactory.setUsername(user);
|
||||
defaultFtpsClientFactory.setImplicit(false);
|
||||
defaultFtpsClientFactory.setPassword(pw);
|
||||
defaultFtpsClientFactory.setClientMode(FTPClient.PASSIVE_LOCAL_DATA_CONNECTION_MODE);
|
||||
defaultFtpsClientFactory.setHost(host);
|
||||
|
||||
FTPSClient ftpClient = defaultFtpsClientFactory.getClient();
|
||||
|
||||
InputStream fileStream = r.getInputStream();
|
||||
ftpClient.storeFile("pushed.java", fileStream);
|
||||
fileStream.close();
|
||||
ftpClient.disconnect();
|
||||
}
|
||||
|
||||
public void setUseClientMode(Boolean useClientMode) {
|
||||
this.useClientMode = useClientMode;
|
||||
}
|
||||
|
||||
public void setSessionCreation(Boolean sessionCreation) {
|
||||
this.sessionCreation = sessionCreation;
|
||||
}
|
||||
|
||||
public void setAuthValue(String authValue) {
|
||||
this.authValue = authValue;
|
||||
}
|
||||
|
||||
public void setTrustManager(TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
||||
public void setCipherSuites(String[] cipherSuites) {
|
||||
this.cipherSuites = cipherSuites;
|
||||
}
|
||||
|
||||
public void setProtocols(String[] protocols) {
|
||||
this.protocols = protocols;
|
||||
}
|
||||
|
||||
public void setKeyManager(KeyManager keyManager) {
|
||||
this.keyManager = keyManager;
|
||||
}
|
||||
|
||||
public void setNeedClientAuth(Boolean needClientAuth) {
|
||||
this.needClientAuth = needClientAuth;
|
||||
}
|
||||
|
||||
public void setWantsClientAuth(Boolean wantsClientAuth) {
|
||||
this.wantsClientAuth = wantsClientAuth;
|
||||
}
|
||||
|
||||
public void setProt(String prot) {
|
||||
this.prot = prot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterConnect(FTPSClient ftpsClient)
|
||||
throws IOException {
|
||||
ftpsClient.execPBSZ(0);
|
||||
ftpsClient.execPROT(this.prot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FTPSClient getClient() throws SocketException, IOException {
|
||||
FTPSClient ftpsClient = super.getClient();
|
||||
|
||||
if (StringUtils.hasText(this.authValue)) {
|
||||
ftpsClient.setAuthValue(authValue);
|
||||
}
|
||||
|
||||
if (this.trustManager != null) {
|
||||
ftpsClient.setTrustManager(this.trustManager);
|
||||
}
|
||||
|
||||
if (this.cipherSuites != null) {
|
||||
ftpsClient.setEnabledCipherSuites(this.cipherSuites);
|
||||
}
|
||||
|
||||
if (this.protocols != null) {
|
||||
ftpsClient.setEnabledProtocols(this.protocols);
|
||||
}
|
||||
|
||||
if (this.sessionCreation != null) {
|
||||
ftpsClient.setEnabledSessionCreation(this.sessionCreation);
|
||||
}
|
||||
|
||||
if (this.useClientMode != null) {
|
||||
ftpsClient.setUseClientMode(this.useClientMode);
|
||||
}
|
||||
|
||||
if (this.sessionCreation != null) {
|
||||
ftpsClient.setEnabledSessionCreation(this.sessionCreation);
|
||||
}
|
||||
|
||||
if (this.keyManager != null) {
|
||||
ftpsClient.setKeyManager(keyManager);
|
||||
}
|
||||
|
||||
if (this.needClientAuth != null) {
|
||||
ftpsClient.setNeedClientAuth(this.needClientAuth);
|
||||
}
|
||||
|
||||
if (this.wantsClientAuth != null) {
|
||||
ftpsClient.setWantClientAuth(this.wantsClientAuth);
|
||||
}
|
||||
|
||||
return ftpsClient;
|
||||
}
|
||||
|
||||
public void setImplicit(boolean implicit) {
|
||||
this.implicit = implicit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FTPSClient createSingleInstanceOfClient() {
|
||||
try {
|
||||
if (StringUtils.hasText(this.protocol)) {
|
||||
return new FTPSClient(this.protocol, this.implicit);
|
||||
}
|
||||
|
||||
return new FTPSClient(this.implicit);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Factory for {@link FTPClient}.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
public interface FtpClientFactory <T extends FTPClient>{
|
||||
/**
|
||||
* @return Fully configured and connected FTPClient. Never <code>null</code>.
|
||||
* @throws IOException thrown when a networking IO subsystem error occurs
|
||||
*/
|
||||
T getClient() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ftp;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
|
||||
|
||||
/**
|
||||
* A pool of {@link FTPClient} instances. The pool can be used to control the
|
||||
* number of open FTP connections and reuse these connections efficiently.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
public interface FtpClientPool extends FtpClientFactory {
|
||||
/**
|
||||
* Releases the client back to the pool. When calling this method the caller
|
||||
* is no longer responsible for the connection. The pool is free to do with
|
||||
* it as it sees fit, which means either recycling or disconnecting it most
|
||||
* probably.
|
||||
* <p/>
|
||||
* The caller should NOT disconnect the client before calling this method.
|
||||
* <p/>
|
||||
* The caller is NOT expected to use the client after calling this method.
|
||||
* Doing so can lead to unexpected behavior.
|
||||
*
|
||||
* @param client the {@link FTPClient} to release. Implementations of this
|
||||
* method are recommended to deal gracefully with a <code>null</code>
|
||||
* argument, although the endpoint implementations in
|
||||
* <code>org.springframework.integration.ftp</code> will never pass in
|
||||
* <code>null</code>.
|
||||
*/
|
||||
void releaseClient(FTPClient client);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ftp;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.SocketException;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.core.MessageHandler} implementation that sends files to an FTP server.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpSendingMessageHandler implements MessageHandler, InitializingBean {
|
||||
|
||||
private FtpClientPool ftpClientPool;
|
||||
|
||||
public FtpSendingMessageHandler() {
|
||||
}
|
||||
|
||||
public FtpSendingMessageHandler(FtpClientPool ftpClientPool) {
|
||||
this.ftpClientPool = ftpClientPool;
|
||||
}
|
||||
|
||||
public void setFtpClientPool(FtpClientPool ftpClientPool) {
|
||||
this.ftpClientPool = ftpClientPool;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(ftpClientPool, "'ftpClientPool' must not be null");
|
||||
Assert.notNull(temporaryBufferFolder, "'temporaryBufferFolder' must not be null");
|
||||
temporaryBufferFolderFile = this.temporaryBufferFolder.getFile();
|
||||
}
|
||||
|
||||
/* Ugh this needs to be put in a convenient place accessible for all the file:, sftp:, and ftp:* adapters */
|
||||
|
||||
private File handleFileMessage(File sourceFile, File tempFile, File resultFile)
|
||||
throws IOException {
|
||||
if (sourceFile.renameTo(resultFile)) {
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
FileCopyUtils.copy(sourceFile, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private File handleByteArrayMessage(byte[] bytes, File tempFile, File resultFile)
|
||||
throws IOException {
|
||||
FileCopyUtils.copy(bytes, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private File handleStringMessage(String content, File tempFile, File resultFile, String charset)
|
||||
throws IOException {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tempFile), charset);
|
||||
FileCopyUtils.copy(content, writer);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private static final String TEMPORARY_FILE_SUFFIX = ".writing";
|
||||
private FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
|
||||
private File temporaryBufferFolderFile;
|
||||
private Resource temporaryBufferFolder = new FileSystemResource(SystemUtils.getJavaIoTmpDir());
|
||||
|
||||
public void setTemporaryBufferFolder(Resource temporaryBufferFolder) {
|
||||
this.temporaryBufferFolder = temporaryBufferFolder;
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
|
||||
private File redeemForStorableFile(Message<?> msg) throws MessageDeliveryException {
|
||||
try {
|
||||
Object payload = msg.getPayload();
|
||||
String generateFileName = this.fileNameGenerator.generateFileName(msg);
|
||||
File tempFile = new File(temporaryBufferFolderFile, generateFileName + TEMPORARY_FILE_SUFFIX);
|
||||
File resultFile = new File(temporaryBufferFolderFile, generateFileName);
|
||||
File sendableFile;
|
||||
if (payload instanceof String)
|
||||
sendableFile = this.handleStringMessage((String) payload, tempFile, resultFile, this.charset);
|
||||
else if (payload instanceof File)
|
||||
sendableFile = this.handleFileMessage((File) payload, tempFile, resultFile);
|
||||
else if (payload instanceof byte[])
|
||||
sendableFile = this.handleByteArrayMessage((byte[]) payload, tempFile, resultFile);
|
||||
else sendableFile = null;
|
||||
return sendableFile;
|
||||
} catch (Throwable th) {
|
||||
throw new MessageDeliveryException(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String charset;
|
||||
|
||||
public void setCharset(String charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
/* Ugh this needs to be put in a convenient place accessible for all the file:, sftp:, and ftp:* adapters */
|
||||
|
||||
|
||||
public void handleMessage(Message<?> message) throws MessageRejectedException,
|
||||
MessageHandlingException, MessageDeliveryException {
|
||||
|
||||
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
|
||||
Object payload = message.getPayload();
|
||||
|
||||
Assert.notNull(payload, "Message payload must not be null");
|
||||
|
||||
File file = this.redeemForStorableFile(message);
|
||||
|
||||
if ((file != null) && file.exists()) {
|
||||
FTPClient client = null;
|
||||
boolean sentSuccesfully;
|
||||
|
||||
try {
|
||||
client = getFtpClient();
|
||||
sentSuccesfully = sendFile(file, client);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new MessageDeliveryException(message, "File [" + file + "] not found in local working directory; it was moved or deleted unexpectedly", e);
|
||||
} catch (IOException e) {
|
||||
throw new MessageDeliveryException(message, "Error transferring file [" + file + "] from local working directory to remote FTP directory", e);
|
||||
} catch (Exception e) {
|
||||
throw new MessageDeliveryException(message, "Error handling message for file [" + file + "]", e);
|
||||
} finally {
|
||||
if (file.exists())
|
||||
try {
|
||||
file.delete();
|
||||
} catch (Throwable th) {
|
||||
/// noop
|
||||
}
|
||||
if (client != null) {
|
||||
ftpClientPool.releaseClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sentSuccesfully) {
|
||||
throw new MessageDeliveryException(message, "Failed to store file '" + file + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean sendFile(File file, FTPClient client)
|
||||
throws FileNotFoundException, IOException {
|
||||
FileInputStream fileInputStream = new FileInputStream(file);
|
||||
boolean sent = client.storeFile(file.getName(), fileInputStream);
|
||||
fileInputStream.close();
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
private FTPClient getFtpClient() throws SocketException, IOException {
|
||||
FTPClient client;
|
||||
client = this.ftpClientPool.getClient();
|
||||
Assert.state(client != null, FtpClientPool.class.getSimpleName() + " returned 'null' client this most likely a bug in the pool implementation.");
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
|
||||
/**
|
||||
* A factory bean implementation that handles constructing an outbound FTP adapter.
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpSendingMessageHandlerFactoryBean extends AbstractFactoryBean<FtpSendingMessageHandler> implements ResourceLoaderAware, ApplicationContextAware {
|
||||
protected int port;
|
||||
protected String username;
|
||||
protected String password;
|
||||
protected String host;
|
||||
protected String remoteDirectory;
|
||||
protected int clientMode;
|
||||
|
||||
// private vars
|
||||
private ResourceLoader resourceLoader;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public void setClientMode(int clientMode) {
|
||||
this.clientMode = clientMode;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?extends FtpSendingMessageHandler> getObjectType() {
|
||||
return FtpSendingMessageHandler.class;
|
||||
}
|
||||
|
||||
protected AbstractFtpClientFactory clientFactory() {
|
||||
return ClientFactorySupport.ftpClientFactory( this.host, this.port , this.remoteDirectory , this.username , this.password , this.clientMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FtpSendingMessageHandler createInstance()
|
||||
throws Exception {
|
||||
// the dependencies for the outbound-adapter are much simpler
|
||||
// they only require an instance of the pool
|
||||
AbstractFtpClientFactory defaultFtpClientFactory = clientFactory();
|
||||
|
||||
QueuedFtpClientPool queuedFtpClientPool = new QueuedFtpClientPool(15, defaultFtpClientFactory);
|
||||
|
||||
FtpSendingMessageHandler ftpSendingMessageHandler = new FtpSendingMessageHandler(queuedFtpClientPool);
|
||||
ftpSendingMessageHandler.afterPropertiesSet();
|
||||
|
||||
return ftpSendingMessageHandler;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
public class FtpsSendingMessageHandlerFactoryBean extends FtpSendingMessageHandlerFactoryBean {
|
||||
/**
|
||||
* Sets whether the connection is implicit. Local testing reveals this to be a good choice.
|
||||
*/
|
||||
protected volatile Boolean implicit = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* "TLS" or "SSL"
|
||||
*/
|
||||
protected volatile String protocol;
|
||||
|
||||
/**
|
||||
* "P"
|
||||
*/
|
||||
protected volatile String prot;
|
||||
private KeyManager keyManager;
|
||||
private TrustManager trustManager;
|
||||
protected volatile String authValue;
|
||||
private Boolean sessionCreation;
|
||||
private Boolean useClientMode;
|
||||
private Boolean needClientAuth;
|
||||
private Boolean wantsClientAuth;
|
||||
private String[] cipherSuites;
|
||||
|
||||
public void setImplicit(Boolean implicit) {
|
||||
this.implicit = implicit;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public void setProt(String prot) {
|
||||
this.prot = prot;
|
||||
}
|
||||
|
||||
public void setKeyManager(KeyManager keyManager) {
|
||||
this.keyManager = keyManager;
|
||||
}
|
||||
|
||||
public void setTrustManager(TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
||||
public void setAuthValue(String authValue) {
|
||||
this.authValue = authValue;
|
||||
}
|
||||
|
||||
public void setSessionCreation(Boolean sessionCreation) {
|
||||
this.sessionCreation = sessionCreation;
|
||||
}
|
||||
|
||||
public void setUseClientMode(Boolean useClientMode) {
|
||||
this.useClientMode = useClientMode;
|
||||
}
|
||||
|
||||
public void setNeedClientAuth(Boolean needClientAuth) {
|
||||
this.needClientAuth = needClientAuth;
|
||||
}
|
||||
|
||||
public void setWantsClientAuth(Boolean wantsClientAuth) {
|
||||
this.wantsClientAuth = wantsClientAuth;
|
||||
}
|
||||
|
||||
public void setCipherSuites(String[] cipherSuites) {
|
||||
this.cipherSuites = cipherSuites;
|
||||
}
|
||||
|
||||
private int fileType ;
|
||||
|
||||
public void setFileType(int fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFtpClientFactory clientFactory() {
|
||||
DefaultFtpsClientFactory factory = ClientFactorySupport.ftpsClientFactory(
|
||||
this.host, (this.port), this.remoteDirectory, this.username, this.password, this.fileType,
|
||||
this.clientMode, this.prot, this.protocol, this.authValue, this.implicit, this.trustManager, this.keyManager, this.sessionCreation, this.useClientMode, this.wantsClientAuth,
|
||||
this.needClientAuth, this.cipherSuites);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ftp;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
|
||||
/**
|
||||
* FtpClientPool implementation based on a Queue. This implementation has a
|
||||
* default pool size of 5, but this is configurable with a constructor argument.
|
||||
* <p/>
|
||||
* This implementation pools released clients, but gives no guarantee to the
|
||||
* number of clients open at the same time.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
public class QueuedFtpClientPool implements FtpClientPool {
|
||||
private static final Log log = LogFactory.getLog(QueuedFtpClientPool.class);
|
||||
private static final int DEFAULT_POOL_SIZE = 5;
|
||||
private final Queue<FTPClient> pool;
|
||||
private final FtpClientFactory factory;
|
||||
|
||||
public QueuedFtpClientPool(FtpClientFactory factory) {
|
||||
this(DEFAULT_POOL_SIZE, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxPoolSize the maximum size of the pool
|
||||
*/
|
||||
public QueuedFtpClientPool(int maxPoolSize, FtpClientFactory factory) {
|
||||
Assert.notNull(factory);
|
||||
this.factory = factory;
|
||||
pool = new ArrayBlockingQueue<FTPClient>(maxPoolSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an active FTPClient connected to the configured server. When no
|
||||
* clients are available in the queue a new client is created with the
|
||||
* factory.
|
||||
* <p/>
|
||||
* It is possible that released clients are disconnected by the remote
|
||||
* server (@see {@link FTPClient#sendNoOp()}. In this case getClient is
|
||||
* called recursively to obtain a client that is still alive. For this
|
||||
* reason large pools are not recommended in poor networking conditions.
|
||||
*/
|
||||
public FTPClient getClient() throws SocketException, IOException {
|
||||
FTPClient client = pool.poll();
|
||||
|
||||
if (client == null) {
|
||||
client = factory.getClient();
|
||||
}
|
||||
|
||||
return prepareClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the client before it is returned through
|
||||
* <code>getClient()</code>. The default implementation will check the
|
||||
* connection using a noOp and replace the client with a new one if it
|
||||
* encounters a problem.
|
||||
* <p/>
|
||||
* In more exotic environments subclasses can override this method to
|
||||
* implement their own preparation strategy.
|
||||
*
|
||||
* @param client the unprepared client
|
||||
* @return
|
||||
* @throws SocketException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected FTPClient prepareClient(FTPClient client)
|
||||
throws SocketException, IOException {
|
||||
return isClientAlive(client) ? client : getClient();
|
||||
}
|
||||
|
||||
private boolean isClientAlive(FTPClient client) {
|
||||
try {
|
||||
if (client.sendNoOp()) {
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Client [" + client + "] discarded: ", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void releaseClient(FTPClient client) {
|
||||
if ((client != null) && !pool.offer(client)) {
|
||||
try {
|
||||
client.disconnect();
|
||||
} catch (IOException e) {
|
||||
log.warn("Error disconnecting ftpclient", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.ftp.FtpSendingMessageHandlerFactoryBean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* Logic for parsing the ftp:outbound-channel-adapter
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpMessageSendingConsumerBeanDefinitionParser extends AbstractOutboundChannelAdapterParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpSendingMessageHandlerFactoryBean.class.getName());
|
||||
|
||||
FtpNamespaceParserSupport.configureCoreFtpClient(builder, element, parserContext);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ftp.impl.FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Logic that configures an ftp:inbound-channel-adapter
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpMessageSourceBeanDefinitionParser extends AbstractPollingInboundChannelAdapterParser {
|
||||
private Set<String> receiveAttrs = new HashSet<String>(Arrays.asList("auto-delete-remote-files-on-sync,filename-pattern,local-working-directory".split(",")));
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class.getName());
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "filter");
|
||||
|
||||
for (String a : receiveAttrs)
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, a);
|
||||
|
||||
FtpNamespaceParserSupport.configureCoreFtpClient(builder, element, parserContext);
|
||||
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 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.ftp.config;
|
||||
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Provides namespace support for using FTP
|
||||
* <p/>
|
||||
* This is *heavily* influenced by the good work done by Iwein before.
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class FtpNamespaceHandler extends NamespaceHandlerSupport {
|
||||
static public Map<String, Integer> FILE_TYPES = new HashMap<String, Integer>();
|
||||
static public Map<String, Integer> CLIENT_MODES = new HashMap<String, Integer>();
|
||||
|
||||
static {
|
||||
// file types
|
||||
FILE_TYPES.put("ebcdic-file-type" , FTP.EBCDIC_FILE_TYPE);
|
||||
FILE_TYPES.put("ascii-file-type" , FTP.ASCII_FILE_TYPE);
|
||||
FILE_TYPES.put("binary-file-type" , FTP.BINARY_FILE_TYPE);
|
||||
|
||||
// client modes
|
||||
CLIENT_MODES.put("active-local-data-connection-mode", 0);
|
||||
CLIENT_MODES.put("active-remote-data-connection-mode", 1);
|
||||
CLIENT_MODES.put("passive-local-data-connection-mode", 2);
|
||||
CLIENT_MODES.put("passive-remote-data-connection-mode", 3);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new FtpMessageSourceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new FtpMessageSendingConsumerBeanDefinitionParser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* A lot of parsers need to support the same set of core attributes, so I'm hiding that logic here
|
||||
*
|
||||
* @author Josh Long
|
||||
*
|
||||
*/
|
||||
public class FtpNamespaceParserSupport {
|
||||
/**
|
||||
* lots of values are supported across all adapters, let this code handle it initially
|
||||
*
|
||||
* @param builder a builder
|
||||
* @param element an element
|
||||
* @param parserContext a parser context
|
||||
*/
|
||||
public static void configureCoreFtpClient(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
|
||||
for (String p : "auto-create-directories,username,port,password,host,remote-directory".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
|
||||
if (element.hasAttribute("file-type")) {
|
||||
int fileType = FtpNamespaceHandler.FILE_TYPES.get(element.getAttribute("file-type"));
|
||||
builder.addPropertyValue("fileType", fileType);
|
||||
}
|
||||
|
||||
if (element.hasAttribute("client-mode")) {
|
||||
int clientMode = FtpNamespaceHandler.CLIENT_MODES.get(element.getAttribute("client-mode"));
|
||||
builder.addPropertyValue("clientMode", clientMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.ftp.FtpSendingMessageHandlerFactoryBean;
|
||||
import org.springframework.integration.ftp.FtpsSendingMessageHandlerFactoryBean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* Logic for parsing the ftp:outbound-channel-adapter
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpsMessageSendingConsumerBeanDefinitionParser extends AbstractOutboundChannelAdapterParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpsSendingMessageHandlerFactoryBean.class.getName());
|
||||
|
||||
FtpNamespaceParserSupport.configureCoreFtpClient(builder, element, parserContext);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ftp.impl.FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean;
|
||||
import org.springframework.integration.ftp.impl.FtpsRemoteFileSystemSynchronizingMessageSourceFactoryBean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Logic that configures an ftp:inbound-channel-adapter
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpsMessageSourceBeanDefinitionParser extends AbstractPollingInboundChannelAdapterParser {
|
||||
private Set<String> receiveAttrs = new HashSet<String>(Arrays.asList("auto-delete-remote-files-on-sync,filename-pattern,local-working-directory".split(",")));
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpsRemoteFileSystemSynchronizingMessageSourceFactoryBean.class.getName());
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "filter");
|
||||
|
||||
for (String a : receiveAttrs)
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, a);
|
||||
|
||||
FtpNamespaceParserSupport.configureCoreFtpClient(builder, element, parserContext);
|
||||
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 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.ftp.config;
|
||||
|
||||
/**
|
||||
* Provides namespace support for using FTP
|
||||
* <p/>
|
||||
* This is *heavily* influenced by the good work done by Iwein before.
|
||||
*
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class FtpsNamespaceHandler extends FtpNamespaceHandler {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.registerBeanDefinitionParser( "inbound-channel-adapter", new FtpsMessageSourceBeanDefinitionParser());
|
||||
|
||||
// todo test this
|
||||
this.registerBeanDefinitionParser( "outbound-channel-adapter", new FtpsMessageSendingConsumerBeanDefinitionParser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* 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,35 @@
|
||||
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,173 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
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.entries.CompositeEntryListFilter;
|
||||
import org.springframework.integration.file.entries.EntryListFilter;
|
||||
import org.springframework.integration.file.entries.PatternMatchingEntryListFilter;
|
||||
import org.springframework.integration.ftp.*;
|
||||
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 {
|
||||
protected volatile String port;
|
||||
protected volatile String autoCreateDirectories;
|
||||
protected volatile String filenamePattern;
|
||||
protected volatile String username;
|
||||
protected volatile String password;
|
||||
protected volatile String host;
|
||||
protected volatile String remoteDirectory;
|
||||
protected volatile String localWorkingDirectory;
|
||||
protected volatile ResourceLoader resourceLoader;
|
||||
protected volatile Resource localDirectoryResource;
|
||||
protected volatile EntryListFilter<FTPFile> filter;
|
||||
protected volatile int clientMode = FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE;
|
||||
protected volatile int fileType = FTP.BINARY_FILE_TYPE;
|
||||
|
||||
public void setFileType(int fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
private volatile String autoDeleteRemoteFilesOnSync;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
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();
|
||||
}
|
||||
|
||||
protected AbstractFtpClientFactory defaultClientFactory() throws Exception {
|
||||
return ClientFactorySupport.ftpClientFactory( this.host , Integer.parseInt(this.port) , this.remoteDirectory , this.username ,this.password, this.clientMode );
|
||||
}
|
||||
|
||||
protected String defaultFtpInboundFolderName = "ftpInbound";
|
||||
|
||||
@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(), defaultFtpInboundFolderName);
|
||||
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, defaultClientFactory());
|
||||
|
||||
FtpInboundRemoteFileSystemSynchronizer ftpRemoteFileSystemSynchronizer = new FtpInboundRemoteFileSystemSynchronizer();
|
||||
ftpRemoteFileSystemSynchronizer.setClientPool(queuedFtpClientPool);
|
||||
ftpRemoteFileSystemSynchronizer.setLocalDirectory(this.localDirectoryResource);
|
||||
ftpRemoteFileSystemSynchronizer.setShouldDeleteSourceFile(ackRemoteDir);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setPort(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setAutoCreateDirectories(String autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilenamePattern(String filenamePattern) {
|
||||
this.filenamePattern = filenamePattern;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setRemoteDirectory(String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setLocalWorkingDirectory(String localWorkingDirectory) {
|
||||
this.localWorkingDirectory = localWorkingDirectory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilter(EntryListFilter<FTPFile> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setClientMode(int clientMode) {
|
||||
this.clientMode = clientMode;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.springframework.integration.ftp.impl;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
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.entries.CompositeEntryListFilter;
|
||||
import org.springframework.integration.file.entries.EntryListFilter;
|
||||
import org.springframework.integration.file.entries.PatternMatchingEntryListFilter;
|
||||
import org.springframework.integration.ftp.*;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
|
||||
/**
|
||||
* Factory to make building the namespace easier
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpsRemoteFileSystemSynchronizingMessageSourceFactoryBean extends FtpRemoteFileSystemSynchronizingMessageSourceFactoryBean {
|
||||
/**
|
||||
* Sets whether the connection is implicit. Local testing reveals this to be a good choice.
|
||||
*/
|
||||
protected volatile Boolean implicit = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* "TLS" or "SSL"
|
||||
*/
|
||||
protected volatile String protocol;
|
||||
|
||||
/**
|
||||
* "P"
|
||||
*/
|
||||
protected volatile String prot;
|
||||
private KeyManager keyManager;
|
||||
private TrustManager trustManager;
|
||||
protected volatile String authValue;
|
||||
private Boolean sessionCreation;
|
||||
private Boolean useClientMode;
|
||||
private Boolean needClientAuth;
|
||||
private Boolean wantsClientAuth;
|
||||
private String[] cipherSuites;
|
||||
|
||||
public FtpsRemoteFileSystemSynchronizingMessageSourceFactoryBean() {
|
||||
this.defaultFtpInboundFolderName = "ftpsInbound";
|
||||
this.clientMode = FTPClient.PASSIVE_LOCAL_DATA_CONNECTION_MODE;
|
||||
}
|
||||
|
||||
public void setKeyManager(KeyManager keyManager) {
|
||||
this.keyManager = keyManager;
|
||||
}
|
||||
|
||||
public void setTrustManager(TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
||||
public void setImplicit(Boolean implicit) {
|
||||
this.implicit = implicit;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public void setProt(String prot) {
|
||||
this.prot = prot;
|
||||
}
|
||||
|
||||
public void setAuthValue(String authValue) {
|
||||
this.authValue = authValue;
|
||||
}
|
||||
|
||||
public void setSessionCreation(Boolean sessionCreation) {
|
||||
this.sessionCreation = sessionCreation;
|
||||
}
|
||||
|
||||
public void setUseClientMode(Boolean useClientMode) {
|
||||
this.useClientMode = useClientMode;
|
||||
}
|
||||
|
||||
public void setNeedClientAuth(Boolean needClientAuth) {
|
||||
this.needClientAuth = needClientAuth;
|
||||
}
|
||||
|
||||
public void setWantsClientAuth(Boolean wantsClientAuth) {
|
||||
this.wantsClientAuth = wantsClientAuth;
|
||||
}
|
||||
|
||||
protected AbstractFtpClientFactory defaultClientFactory()
|
||||
throws Exception {
|
||||
DefaultFtpsClientFactory factory = ClientFactorySupport.ftpsClientFactory(this.host, Integer.parseInt(this.port), this.remoteDirectory, this.username, this.password, this.fileType,
|
||||
this.clientMode, this.prot, this.protocol, this.authValue, this.implicit, this.trustManager, this.keyManager, this.sessionCreation, this.useClientMode, this.wantsClientAuth,
|
||||
this.needClientAuth, this.cipherSuites);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void setCipherSuites(String[] cipherSuites) {
|
||||
this.cipherSuites = cipherSuites;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
http\://www.springframework.org/schema/integration/ftp=org.springframework.integration.ftp.config.FtpNamespaceHandler
|
||||
http\://www.springframework.org/schema/integration/ftps=org.springframework.integration.ftp.config.FtpsNamespaceHandler
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
http\://www.springframework.org/schema/integration/ftp/spring-integration-ftp-2.0.xsd=org/springframework/integration/ftp/config/spring-integration-ftp-2.0.xsd
|
||||
http\://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd=org/springframework/integration/ftp/config/spring-integration-ftp-2.0.xsd
|
||||
http\://www.springframework.org/schema/integration/ftp/spring-integration-ftps-2.0.xsd=org/springframework/integration/ftp/config/spring-integration-ftps-2.0.xsd
|
||||
http\://www.springframework.org/schema/integration/ftp/spring-integration-ftps.xsd=org/springframework/integration/ftp/config/spring-integration-ftps-2.0.xsd
|
||||
@@ -0,0 +1,249 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 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.
|
||||
-->
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/ftp"
|
||||
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/ftp"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"/>
|
||||
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an outbound-channel-adapter that writes files to a remote FTP endpoint.
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="channel" use="required" 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="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="host" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute use="optional" name="client-mode" default="active-local-data-connection-mode">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
the FTP Client-Mode.
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* should connect to the client's data port to initiate a data transfer.
|
||||
* This is the default data connection mode when and FTPClient instance
|
||||
* is created.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to should connect to the other server's
|
||||
* data port to initiate a data transfer.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 1
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* is in passive mode, requiring the client to connect to the
|
||||
* server's data port to initiate a transfer.
|
||||
***/
|
||||
PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to is in passive mode, requiring the other
|
||||
* server to connect to the first server's data port to initiate a data
|
||||
* transfer.
|
||||
***/
|
||||
PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3
|
||||
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="active-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="active-remote-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-remote-data-connection-mode"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute use="optional" name="file-type" default="binary-file-type">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Binary, ASCII, or EBDIC. Binary's a good default
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="ebcdic-file-type"/>
|
||||
<xsd:enumeration value="ascii-file-type"/>
|
||||
<xsd:enumeration value="binary-file-type"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an inbound-channel-adapter that synchronizes a local directory with the contents of a remote FTP endpoint.
|
||||
|
||||
]]></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" use="required" 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 use="optional" name="file-type" default="binary-file-type">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Binary, ASCII, or EBDIC. Binary's a good default
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="ebcdic-file-type"/>
|
||||
<xsd:enumeration value="ascii-file-type"/>
|
||||
<xsd:enumeration value="binary-file-type"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</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.entries.EntryListFilter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string"/>
|
||||
|
||||
|
||||
<xsd:attribute name="local-working-directory" type="xsd:string"/>
|
||||
<xsd:attribute name="auto-create-directories" type="xsd:boolean"/>
|
||||
<xsd:attribute name="auto-delete-remote-files-on-sync" type="xsd:boolean"/>
|
||||
|
||||
|
||||
<xsd:attribute name="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="host" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute use="optional" name="client-mode" default="active-local-data-connection-mode">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
the FTP Client-Mode.
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* should connect to the client's data port to initiate a data transfer.
|
||||
* This is the default data connection mode when and FTPClient instance
|
||||
* is created.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to should connect to the other server's
|
||||
* data port to initiate a data transfer.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 1
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* is in passive mode, requiring the client to connect to the
|
||||
* server's data port to initiate a transfer.
|
||||
***/
|
||||
PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to is in passive mode, requiring the other
|
||||
* server to connect to the first server's data port to initiate a data
|
||||
* transfer.
|
||||
***/
|
||||
PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3
|
||||
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="active-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="active-remote-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-remote-data-connection-mode"/>
|
||||
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,252 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 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.
|
||||
-->
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/ftps"
|
||||
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/ftps"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"/>
|
||||
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an outbound-channel-adapter that writes files to a remote FTPS endpoint.
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="channel" use="required" 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="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="host" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute use="optional" name="client-mode" default="active-local-data-connection-mode">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
the FTP Client-Mode.
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* should connect to the client's data port to initiate a data transfer.
|
||||
* This is the default data connection mode when and FTPClient instance
|
||||
* is created.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to should connect to the other server's
|
||||
* data port to initiate a data transfer.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 1
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* is in passive mode, requiring the client to connect to the
|
||||
* server's data port to initiate a transfer.
|
||||
***/
|
||||
PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to is in passive mode, requiring the other
|
||||
* server to connect to the first server's data port to initiate a data
|
||||
* transfer.
|
||||
***/
|
||||
PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3
|
||||
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="active-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="active-remote-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-remote-data-connection-mode"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute use="optional" name="file-type" default="binary-file-type">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Binary, ASCII, or EBDIC. Binary's a good default
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="ebcdic-file-type"/>
|
||||
<xsd:enumeration value="ascii-file-type"/>
|
||||
<xsd:enumeration value="binary-file-type"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an inbound-channel-adapter that synchronizes a local directory with the contents of a remote FTP endpoint.
|
||||
|
||||
]]></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" use="required" 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 use="optional" name="file-type" default="binary-file-type">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Binary, ASCII, or EBDIC. Binary's a good default
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="ebcdic-file-type"/>
|
||||
<xsd:enumeration value="ascii-file-type"/>
|
||||
<xsd:enumeration value="binary-file-type"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</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.entries.EntryListFilter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string"/>
|
||||
|
||||
|
||||
<xsd:attribute name="local-working-directory" type="xsd:string"/>
|
||||
<xsd:attribute name="auto-create-directories" type="xsd:boolean"/>
|
||||
<xsd:attribute name="auto-delete-remote-files-on-sync" type="xsd:boolean"/>
|
||||
|
||||
|
||||
<xsd:attribute name="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="host" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute use="optional" name="client-mode" default="passive-local-data-connection-mode">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
the FTP Client-Mode.
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* should connect to the client's data port to initiate a data transfer.
|
||||
* This is the default data connection mode when and FTPClient instance
|
||||
* is created.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to should connect to the other server's
|
||||
* data port to initiate a data transfer.
|
||||
***/
|
||||
ACTIVE_LOCAL_DATA_CONNECTION_MODE = 1
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between the client (local) and server and that the server
|
||||
* is in passive mode, requiring the client to connect to the
|
||||
* server's data port to initiate a transfer.
|
||||
***/
|
||||
PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2
|
||||
|
||||
/***
|
||||
* A constant indicating the FTP session is expecting all transfers
|
||||
* to occur between two remote servers and that the server
|
||||
* the client is connected to is in passive mode, requiring the other
|
||||
* server to connect to the first server's data port to initiate a data
|
||||
* transfer.
|
||||
***/
|
||||
PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3
|
||||
|
||||
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="active-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="active-remote-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-local-data-connection-mode"/>
|
||||
<xsd:enumeration value="passive-remote-data-connection-mode"/>
|
||||
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
/**
|
||||
* the goal here is to sketch out what a simple FTPS client looks like
|
||||
*/
|
||||
public class FtpsExample {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* Simple component to test the inbound integration
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
|
||||
public class InboundFtpFileServiceActivator {
|
||||
|
||||
@ServiceActivator
|
||||
public void onNewRemoteFTPFile(Message<File> file)
|
||||
throws Throwable {
|
||||
System.out.println(StringUtils.repeat("=", 100));
|
||||
System.out.println("A new file has appeared: " + file.getPayload().getAbsolutePath());
|
||||
|
||||
for (String h : file.getHeaders().keySet())
|
||||
System.out.println(String.format("%s = %s", h, file.getHeaders().get(h)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext =
|
||||
new ClassPathXmlApplicationContext("inbound-ftp-context.xml");
|
||||
classPathXmlApplicationContext.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* Simple component to test the inbound integration
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
|
||||
public class InboundFtpsFileServiceActivator {
|
||||
|
||||
@ServiceActivator
|
||||
public void onNewRemoteFTPFile(Message<File> file)
|
||||
throws Throwable {
|
||||
System.out.println(StringUtils.repeat("=", 100));
|
||||
System.out.println("A new file has appeared: " + file.getPayload().getAbsolutePath());
|
||||
|
||||
for (String h : file.getHeaders().keySet())
|
||||
System.out.println(String.format("%s = %s", h, file.getHeaders().get(h)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext =
|
||||
new ClassPathXmlApplicationContext("inbound-ftps-context.xml");
|
||||
classPathXmlApplicationContext.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* This simple example demonstrates sending a file to a remote FTP server using the ftp:outbound-channel-adapter
|
||||
* <p/>
|
||||
* It reads files from a directory on your computer and systematically puts them on the remote FTP server,
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class OutboundFtpExample {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("outbound-ftp-context.xml");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* This simple example demonstrates sending a file to a remote FTP server using the ftp:outbound-channel-adapter
|
||||
* <p/>
|
||||
* It reads files from a directory on your computer and systematically puts them on the remote FTP server,
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class OutboundFtpsExample {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("outbound-ftps-context.xml");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ftp="http://www.springframework.org/schema/integration/ftp"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
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/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/ftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
|
||||
<ftp:inbound-channel-adapter remote-directory="${ftp.remotedir}" channel="ftpIn" auto-create-directories="true"
|
||||
host="${ftp.host}" auto-delete-remote-files-on-sync="false"
|
||||
username="${ftp.username}" password="${ftp.password}" port="21"
|
||||
file-type="binary-file-type"
|
||||
filename-pattern=".*?jpg"
|
||||
>
|
||||
<int:poller>
|
||||
<int:interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</int:poller>
|
||||
</ftp:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="ftpIn"/>
|
||||
|
||||
<bean id="inboundFTPFileServiceActivator"
|
||||
class="org.springframework.integration.ftp.InboundFtpFileServiceActivator"/>
|
||||
|
||||
<int:service-activator input-channel="ftpIn" ref="inboundFTPFileServiceActivator"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ftps="http://www.springframework.org/schema/integration/ftps"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
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/ftps http://www.springframework.org/schema/integration/ftp/spring-integration-ftps.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/ftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
|
||||
<ftps:inbound-channel-adapter remote-directory="${ftp.remotedir}"
|
||||
channel="ftpIn"
|
||||
auto-create-directories="true"
|
||||
host="${ftp.host}"
|
||||
auto-delete-remote-files-on-sync="false"
|
||||
username="${ftp.username}"
|
||||
password="${ftp.password}"
|
||||
port="21"
|
||||
file-type="binary-file-type"
|
||||
filename-pattern=".*?java"
|
||||
client-mode="passive-local-data-connection-mode"
|
||||
|
||||
>
|
||||
<int:poller>
|
||||
<int:interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</int:poller>
|
||||
</ftps:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="ftpIn"/>
|
||||
|
||||
<bean id="inboundFtpsFileServiceActivator"
|
||||
class="org.springframework.integration.ftp.InboundFtpsFileServiceActivator"/>
|
||||
|
||||
<int:service-activator input-channel="ftpIn" ref="inboundFtpsFileServiceActivator"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ftp="http://www.springframework.org/schema/integration/ftp"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:file="http://www.springframework.org/schema/integration/file"
|
||||
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/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd">
|
||||
|
||||
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/ftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
<file:inbound-channel-adapter channel="ftpOutbound"
|
||||
filename-pattern=".*?jpg"
|
||||
directory="#{systemProperties['user.home']}/Desktop/imagesToSendViaFTP"
|
||||
auto-create-directory="true">
|
||||
<int:poller>
|
||||
<int:interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</int:poller>
|
||||
</file:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="ftpOutbound"/>
|
||||
|
||||
<ftp:outbound-channel-adapter
|
||||
remote-directory="${ftp.remotedir}"
|
||||
channel="ftpOutbound"
|
||||
host="${ftp.host}"
|
||||
username="${ftp.username}"
|
||||
password="${ftp.password}" port="2222"
|
||||
client-mode="passive-local-data-connection-mode"
|
||||
/>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ftp="http://www.springframework.org/schema/integration/ftp"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:file="http://www.springframework.org/schema/integration/file" xmlns:ftps="http://www.springframework.org/schema/integration/ftps"
|
||||
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/ftps http://www.springframework.org/schema/integration/ftp/spring-integration-ftps.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd">
|
||||
|
||||
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/ftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
<file:inbound-channel-adapter channel="ftpOutbound"
|
||||
filename-pattern=".*?jpg"
|
||||
directory="#{systemProperties['user.home']}/Desktop/imagesToSendViaFTP"
|
||||
auto-create-directory="true">
|
||||
<int:poller>
|
||||
<int:interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</int:poller>
|
||||
</file:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="ftpOutbound"/>
|
||||
|
||||
<ftps:outbound-channel-adapter
|
||||
remote-directory="${ftp.remotedir}"
|
||||
channel="ftpOutbound"
|
||||
host="${ftp.host}"
|
||||
username="${ftp.username}"
|
||||
password="${ftp.password}" port="21"
|
||||
client-mode="passive-local-data-connection-mode"
|
||||
/>
|
||||
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user