moved spaces to tabs for the sftp package
This commit is contained in:
@@ -1,99 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-sftp</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Integration SFTP Support</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-file</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.42</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>${cglib.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymockclassextension</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-stream</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<!-- <plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins> -->
|
||||
</build>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-sftp</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Integration SFTP Support</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-file</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.42</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>${cglib.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymockclassextension</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-stream</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<!-- <plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins> -->
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -31,68 +31,68 @@ import java.util.concurrent.ArrayBlockingQueue;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class QueuedSftpSessionPool implements SftpSessionPool, InitializingBean {
|
||||
public static final int DEFAULT_POOL_SIZE = 10;
|
||||
private Queue<SftpSession> queue;
|
||||
private final SftpSessionFactory sftpSessionFactory;
|
||||
private int maxPoolSize;
|
||||
public static final int DEFAULT_POOL_SIZE = 10;
|
||||
private Queue<SftpSession> queue;
|
||||
private final SftpSessionFactory sftpSessionFactory;
|
||||
private int maxPoolSize;
|
||||
|
||||
public QueuedSftpSessionPool(SftpSessionFactory factory) {
|
||||
this(DEFAULT_POOL_SIZE, factory);
|
||||
}
|
||||
public QueuedSftpSessionPool(SftpSessionFactory factory) {
|
||||
this(DEFAULT_POOL_SIZE, factory);
|
||||
}
|
||||
|
||||
public QueuedSftpSessionPool(int maxPoolSize, SftpSessionFactory sessionFactory) {
|
||||
this.sftpSessionFactory = sessionFactory;
|
||||
this.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
public QueuedSftpSessionPool(int maxPoolSize, SftpSessionFactory sessionFactory) {
|
||||
this.sftpSessionFactory = sessionFactory;
|
||||
this.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
assert maxPoolSize > 0 : "poolSize must be greater than 0!";
|
||||
queue = new ArrayBlockingQueue<SftpSession>(maxPoolSize, true); // size, faireness to avoid starvation
|
||||
assert sftpSessionFactory != null : "sftpSessionFactory must not be null!";
|
||||
}
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
assert maxPoolSize > 0 : "poolSize must be greater than 0!";
|
||||
queue = new ArrayBlockingQueue<SftpSession>(maxPoolSize, true); // size, faireness to avoid starvation
|
||||
assert sftpSessionFactory != null : "sftpSessionFactory must not be null!";
|
||||
}
|
||||
|
||||
public SftpSession getSession() throws Exception {
|
||||
SftpSession session = this.queue.poll();
|
||||
public SftpSession getSession() throws Exception {
|
||||
SftpSession session = this.queue.poll();
|
||||
|
||||
if (null == session) {
|
||||
session = this.sftpSessionFactory.getObject();
|
||||
if (null == session) {
|
||||
session = this.sftpSessionFactory.getObject();
|
||||
|
||||
if (queue.size() < maxPoolSize) {
|
||||
queue.add(session);
|
||||
}
|
||||
}
|
||||
if (queue.size() < maxPoolSize) {
|
||||
queue.add(session);
|
||||
}
|
||||
}
|
||||
|
||||
if (null == session) {
|
||||
session = queue.poll();
|
||||
}
|
||||
if (null == session) {
|
||||
session = queue.poll();
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
public void release(SftpSession session) {
|
||||
if (queue.size() < maxPoolSize) {
|
||||
queue.add(session); // somehow one snuck in before <code>session</code> was finished!
|
||||
} else {
|
||||
dispose(session);
|
||||
}
|
||||
}
|
||||
public void release(SftpSession session) {
|
||||
if (queue.size() < maxPoolSize) {
|
||||
queue.add(session); // somehow one snuck in before <code>session</code> was finished!
|
||||
} else {
|
||||
dispose(session);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispose(SftpSession s) {
|
||||
if (s == null) {
|
||||
return;
|
||||
}
|
||||
private void dispose(SftpSession s) {
|
||||
if (s == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (queue.contains(s)) //this should never happen, but if it does ...
|
||||
{
|
||||
queue.remove(s);
|
||||
}
|
||||
if (queue.contains(s)) //this should never happen, but if it does ...
|
||||
{
|
||||
queue.remove(s);
|
||||
}
|
||||
|
||||
if ((s.getChannel() != null) && s.getChannel().isConnected()) {
|
||||
s.getChannel().disconnect();
|
||||
}
|
||||
if ((s.getChannel() != null) && s.getChannel().isConnected()) {
|
||||
s.getChannel().disconnect();
|
||||
}
|
||||
|
||||
if (s.getSession().isConnected()) {
|
||||
s.getSession().disconnect();
|
||||
}
|
||||
}
|
||||
if (s.getSession().isConnected()) {
|
||||
s.getSession().disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@ package org.springframework.integration.sftp;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpConstants {
|
||||
public static final String SFTP_REMOTE_DIRECTORY_HEADER = "SFTP_REMOTE_DIRECTORY_HEADER";
|
||||
public static final String SFTP_REMOTE_DIRECTORY_HEADER = "SFTP_REMOTE_DIRECTORY_HEADER";
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import org.springframework.integration.file.entries.EntryNamer;
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpEntryNamer implements EntryNamer<ChannelSftp.LsEntry>{
|
||||
public class SftpEntryNamer implements EntryNamer<ChannelSftp.LsEntry> {
|
||||
|
||||
public String nameOf(ChannelSftp.LsEntry entry) {
|
||||
return entry.getFilename() ;
|
||||
}
|
||||
public String nameOf(ChannelSftp.LsEntry entry) {
|
||||
return entry.getFilename();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,179 +41,178 @@ import java.io.*;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpSendingMessageHandler implements MessageHandler, InitializingBean {
|
||||
private SftpSessionPool pool;
|
||||
private String remoteDirectory;
|
||||
private volatile boolean afterPropertiesSetRan;
|
||||
private SftpSessionPool pool;
|
||||
private String remoteDirectory;
|
||||
private volatile boolean afterPropertiesSetRan;
|
||||
|
||||
public SftpSendingMessageHandler(SftpSessionPool pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
public SftpSendingMessageHandler(SftpSessionPool pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state( this.pool != null , "the pool can't be null!");
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(this.pool != null, "the pool can't be null!");
|
||||
|
||||
temporaryBufferFolderFile = this.temporaryBufferFolder.getFile();
|
||||
temporaryBufferFolderFile = this.temporaryBufferFolder.getFile();
|
||||
|
||||
if (!afterPropertiesSetRan) {
|
||||
if (StringUtils.isEmpty(this.remoteDirectory)) {
|
||||
remoteDirectory = null;
|
||||
}
|
||||
if (!afterPropertiesSetRan) {
|
||||
if (StringUtils.isEmpty(this.remoteDirectory)) {
|
||||
remoteDirectory = null;
|
||||
}
|
||||
|
||||
this.afterPropertiesSetRan = true;
|
||||
}
|
||||
}
|
||||
this.afterPropertiesSetRan = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String getRemoteDirectory() {
|
||||
return remoteDirectory;
|
||||
}
|
||||
public String getRemoteDirectory() {
|
||||
return remoteDirectory;
|
||||
}
|
||||
|
||||
/* Ugh this needs to be put in a convenient place accessible for all the file:, sftp:, and ftp:* adapters */
|
||||
/* 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;
|
||||
}
|
||||
private File handleFileMessage(File sourceFile, File tempFile, File resultFile)
|
||||
throws IOException {
|
||||
if (sourceFile.renameTo(resultFile)) {
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
FileCopyUtils.copy(sourceFile, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
FileCopyUtils.copy(sourceFile, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private File handleByteArrayMessage(byte[] bytes, File tempFile, File resultFile)
|
||||
throws IOException {
|
||||
FileCopyUtils.copy(bytes, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
private File handleByteArrayMessage(byte[] bytes, File tempFile, File resultFile)
|
||||
throws IOException {
|
||||
FileCopyUtils.copy(bytes, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return 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);
|
||||
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;
|
||||
}
|
||||
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());
|
||||
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 setTemporaryBufferFolder(Resource temporaryBufferFolder) {
|
||||
this.temporaryBufferFolder = temporaryBufferFolder;
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
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 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;
|
||||
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 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(final Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException, MessageDeliveryException {
|
||||
Assert.state(this.pool != null, "need a working pool");
|
||||
File inboundFilePayload = this.redeemForStorableFile(message);
|
||||
try {
|
||||
|
||||
public void handleMessage(final Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException, MessageDeliveryException {
|
||||
Assert.state(this.pool != null , "need a working pool");
|
||||
File inboundFilePayload = this.redeemForStorableFile( message);
|
||||
try {
|
||||
if ((inboundFilePayload != null) && inboundFilePayload.exists()) {
|
||||
sendFileToRemoteEndpoint(message, inboundFilePayload);
|
||||
}
|
||||
} catch (Throwable thr) {
|
||||
// logger.debug("recieved an exception.", thr);
|
||||
throw new MessageDeliveryException(message, "couldn't deliver the message!", thr);
|
||||
} finally {
|
||||
if (inboundFilePayload != null && inboundFilePayload.exists())
|
||||
inboundFilePayload.delete();
|
||||
|
||||
if ((inboundFilePayload != null) && inboundFilePayload.exists()) {
|
||||
sendFileToRemoteEndpoint(message, inboundFilePayload);
|
||||
}
|
||||
} catch (Throwable thr) {
|
||||
// logger.debug("recieved an exception.", thr);
|
||||
throw new MessageDeliveryException(message, "couldn't deliver the message!", thr);
|
||||
} finally {
|
||||
if(inboundFilePayload!=null&&inboundFilePayload.exists())
|
||||
inboundFilePayload.delete() ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public void setRemoteDirectory(final String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
|
||||
public void setRemoteDirectory(final String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
private boolean sendFileToRemoteEndpoint(Message<?> message, File file)
|
||||
throws Throwable {
|
||||
assert this.pool != null : "need a working pool";
|
||||
|
||||
private boolean sendFileToRemoteEndpoint(Message<?> message, File file)
|
||||
throws Throwable {
|
||||
assert this.pool != null : "need a working pool";
|
||||
SftpSession session = this.pool.getSession();
|
||||
|
||||
SftpSession session = this.pool.getSession();
|
||||
if (session == null) {
|
||||
throw new RuntimeException("the session returned from the pool is null, can't possibly proceed.");
|
||||
}
|
||||
|
||||
if (session == null) {
|
||||
throw new RuntimeException("the session returned from the pool is null, can't possibly proceed.");
|
||||
}
|
||||
session.start();
|
||||
|
||||
session.start();
|
||||
ChannelSftp sftp = session.getChannel();
|
||||
|
||||
ChannelSftp sftp = session.getChannel();
|
||||
InputStream fileInputStream = null;
|
||||
|
||||
InputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(file);
|
||||
|
||||
try {
|
||||
fileInputStream = new FileInputStream(file);
|
||||
String baseOfRemotePath = StringUtils.isEmpty(this.remoteDirectory) ? StringUtils.EMPTY : remoteDirectory; // the safe default
|
||||
|
||||
String baseOfRemotePath = StringUtils.isEmpty(this.remoteDirectory) ? StringUtils.EMPTY : remoteDirectory; // the safe default
|
||||
// logger.debug("going to send " + file.getAbsolutePath() + " to a remote sftp endpoint");
|
||||
String dynRd = null;
|
||||
MessageHeaders messageHeaders = null;
|
||||
|
||||
// logger.debug("going to send " + file.getAbsolutePath() + " to a remote sftp endpoint");
|
||||
String dynRd = null;
|
||||
MessageHeaders messageHeaders = null;
|
||||
if (message != null) {
|
||||
messageHeaders = message.getHeaders();
|
||||
|
||||
if (message != null) {
|
||||
messageHeaders = message.getHeaders();
|
||||
if ((messageHeaders != null) && messageHeaders.containsKey(SftpConstants.SFTP_REMOTE_DIRECTORY_HEADER)) {
|
||||
dynRd = (String) messageHeaders.get(SftpConstants.SFTP_REMOTE_DIRECTORY_HEADER);
|
||||
|
||||
if ((messageHeaders != null) && messageHeaders.containsKey(SftpConstants.SFTP_REMOTE_DIRECTORY_HEADER)) {
|
||||
dynRd = (String) messageHeaders.get(SftpConstants.SFTP_REMOTE_DIRECTORY_HEADER);
|
||||
if (!StringUtils.isEmpty(dynRd)) {
|
||||
baseOfRemotePath = dynRd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(dynRd)) {
|
||||
baseOfRemotePath = dynRd;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!StringUtils.defaultString(baseOfRemotePath).endsWith("/")) {
|
||||
baseOfRemotePath += "/";
|
||||
}
|
||||
|
||||
if (!StringUtils.defaultString(baseOfRemotePath).endsWith("/")) {
|
||||
baseOfRemotePath += "/";
|
||||
}
|
||||
sftp.put(fileInputStream, baseOfRemotePath + file.getName());
|
||||
|
||||
sftp.put(fileInputStream, baseOfRemotePath + file.getName());
|
||||
return true;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileInputStream);
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileInputStream);
|
||||
|
||||
if (pool != null) {
|
||||
pool.release(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pool != null) {
|
||||
pool.release(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,133 +25,132 @@ import org.apache.commons.lang.StringUtils;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
/** c
|
||||
/**
|
||||
* c
|
||||
* There are many ways to create a {@link SftpSession} just as there are many ways to SSH into a remote system.
|
||||
* You may use a username and password, you may use a username and private key, you may use a username and a private key with a password, etc.
|
||||
*
|
||||
* <p/>
|
||||
* This object represents the connection to the remote server, and to use it you must provide it with all the components you'd normally provide an
|
||||
* incantation of the <code>ssh</code> command.
|
||||
*
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Mario Gray
|
||||
*/
|
||||
public class SftpSession {
|
||||
private volatile ChannelSftp channel;
|
||||
private volatile Session session;
|
||||
private String privateKey;
|
||||
private String privateKeyPassphrase;
|
||||
private volatile UserInfo userInfo;
|
||||
private volatile ChannelSftp channel;
|
||||
private volatile Session session;
|
||||
private String privateKey;
|
||||
private String privateKeyPassphrase;
|
||||
private volatile UserInfo userInfo;
|
||||
|
||||
|
||||
/**
|
||||
* @param userName the name of the account being logged into.
|
||||
* @param hostName this should be the host. I found values like <code>foo.com</code> work, where
|
||||
* <code>http://foo.com</code> don't.
|
||||
* @param userPassword if you are not using key based authentication, then you are likely being prompted
|
||||
* for a password each time you login. This is that password. It is <em>not</em> the
|
||||
* passphrase for the private key!
|
||||
* @param port the default is 22, and if you specify N<0 for this value we'll default it to 22
|
||||
* @param knownHostsFile this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>
|
||||
* @param knownHostsInputStream this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>. Note
|
||||
* that you may specify this <em>or</em> the #knownHostsFile - not both!
|
||||
* @param privateKey this is usually used when you want passwordless automation (obviously, for this
|
||||
* integration it's useless since this lets you specify a password once, anyway, but
|
||||
* still good to have if required). This file might be ~/.ssh/id_dsa, or a
|
||||
* <code>.pem</code> for your remote server (for example, on EC2)
|
||||
* @param pvKeyPassPhrase sometimes, to be extra secure, the private key itself is extra encrypted. In order
|
||||
* to surmount that, we need the private key passphrase. Specify that here.
|
||||
*
|
||||
* @throws Exception thrown if any of a myriad of scenarios plays out
|
||||
*/
|
||||
public SftpSession(String userName, String hostName, String userPassword, int port, String knownHostsFile, InputStream knownHostsInputStream, String privateKey, String pvKeyPassPhrase)
|
||||
throws Exception {
|
||||
JSch jSch = new JSch();
|
||||
/**
|
||||
* @param userName the name of the account being logged into.
|
||||
* @param hostName this should be the host. I found values like <code>foo.com</code> work, where
|
||||
* <code>http://foo.com</code> don't.
|
||||
* @param userPassword if you are not using key based authentication, then you are likely being prompted
|
||||
* for a password each time you login. This is that password. It is <em>not</em> the
|
||||
* passphrase for the private key!
|
||||
* @param port the default is 22, and if you specify N<0 for this value we'll default it to 22
|
||||
* @param knownHostsFile this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>
|
||||
* @param knownHostsInputStream this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>. Note
|
||||
* that you may specify this <em>or</em> the #knownHostsFile - not both!
|
||||
* @param privateKey this is usually used when you want passwordless automation (obviously, for this
|
||||
* integration it's useless since this lets you specify a password once, anyway, but
|
||||
* still good to have if required). This file might be ~/.ssh/id_dsa, or a
|
||||
* <code>.pem</code> for your remote server (for example, on EC2)
|
||||
* @param pvKeyPassPhrase sometimes, to be extra secure, the private key itself is extra encrypted. In order
|
||||
* to surmount that, we need the private key passphrase. Specify that here.
|
||||
* @throws Exception thrown if any of a myriad of scenarios plays out
|
||||
*/
|
||||
public SftpSession(String userName, String hostName, String userPassword, int port, String knownHostsFile, InputStream knownHostsInputStream, String privateKey, String pvKeyPassPhrase)
|
||||
throws Exception {
|
||||
JSch jSch = new JSch();
|
||||
|
||||
if (port <= 0) {
|
||||
port = 22;
|
||||
}
|
||||
if (port <= 0) {
|
||||
port = 22;
|
||||
}
|
||||
|
||||
this.privateKey = privateKey;
|
||||
this.privateKeyPassphrase = pvKeyPassPhrase;
|
||||
this.privateKey = privateKey;
|
||||
this.privateKeyPassphrase = pvKeyPassPhrase;
|
||||
|
||||
if (!StringUtils.isEmpty(knownHostsFile)) {
|
||||
jSch.setKnownHosts(knownHostsFile);
|
||||
} else if (null != knownHostsInputStream) {
|
||||
jSch.setKnownHosts(knownHostsInputStream);
|
||||
}
|
||||
if (!StringUtils.isEmpty(knownHostsFile)) {
|
||||
jSch.setKnownHosts(knownHostsFile);
|
||||
} else if (null != knownHostsInputStream) {
|
||||
jSch.setKnownHosts(knownHostsInputStream);
|
||||
}
|
||||
|
||||
// private key
|
||||
if (!StringUtils.isEmpty(this.privateKey)) {
|
||||
if (!StringUtils.isEmpty(privateKeyPassphrase)) {
|
||||
jSch.addIdentity(this.privateKey, privateKeyPassphrase);
|
||||
} else {
|
||||
jSch.addIdentity(this.privateKey);
|
||||
}
|
||||
}
|
||||
// private key
|
||||
if (!StringUtils.isEmpty(this.privateKey)) {
|
||||
if (!StringUtils.isEmpty(privateKeyPassphrase)) {
|
||||
jSch.addIdentity(this.privateKey, privateKeyPassphrase);
|
||||
} else {
|
||||
jSch.addIdentity(this.privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
session = jSch.getSession(userName, hostName, port);
|
||||
session = jSch.getSession(userName, hostName, port);
|
||||
|
||||
if (!StringUtils.isEmpty(userPassword)) {
|
||||
session.setPassword(userPassword);
|
||||
}
|
||||
if (!StringUtils.isEmpty(userPassword)) {
|
||||
session.setPassword(userPassword);
|
||||
}
|
||||
|
||||
userInfo = new OptimisticUserInfoImpl(userPassword);
|
||||
session.setUserInfo(userInfo);
|
||||
session.connect();
|
||||
channel = (ChannelSftp) session.openChannel("sftp");
|
||||
}
|
||||
userInfo = new OptimisticUserInfoImpl(userPassword);
|
||||
session.setUserInfo(userInfo);
|
||||
session.connect();
|
||||
channel = (ChannelSftp) session.openChannel("sftp");
|
||||
}
|
||||
|
||||
public ChannelSftp getChannel() {
|
||||
return channel;
|
||||
}
|
||||
public ChannelSftp getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
if (!channel.isConnected()) {
|
||||
channel.connect();
|
||||
}
|
||||
}
|
||||
public void start() throws Exception {
|
||||
if (!channel.isConnected()) {
|
||||
channel.connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this is a simple, optimistic implementation of this interface. It simply returns in the positive where possible
|
||||
* and handles interactive authentication (ie, 'Please enter your password: ' prompts are dispatched automatically using this)
|
||||
*/
|
||||
private static class OptimisticUserInfoImpl implements UserInfo {
|
||||
private String pw;
|
||||
/**
|
||||
* this is a simple, optimistic implementation of this interface. It simply returns in the positive where possible
|
||||
* and handles interactive authentication (ie, 'Please enter your password: ' prompts are dispatched automatically using this)
|
||||
*/
|
||||
private static class OptimisticUserInfoImpl implements UserInfo {
|
||||
private String pw;
|
||||
|
||||
public OptimisticUserInfoImpl(String password) {
|
||||
this.pw = password;
|
||||
}
|
||||
public OptimisticUserInfoImpl(String password) {
|
||||
this.pw = password;
|
||||
}
|
||||
|
||||
public String getPassphrase() {
|
||||
return null; // pass
|
||||
}
|
||||
public String getPassphrase() {
|
||||
return null; // pass
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return pw;
|
||||
}
|
||||
public String getPassword() {
|
||||
return pw;
|
||||
}
|
||||
|
||||
public boolean promptPassphrase(String string) {
|
||||
return true;
|
||||
}
|
||||
public boolean promptPassphrase(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptPassword(String string) {
|
||||
return true;
|
||||
}
|
||||
public boolean promptPassword(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptYesNo(String string) {
|
||||
return true;
|
||||
}
|
||||
public boolean promptYesNo(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMessage(String string) {
|
||||
}
|
||||
}
|
||||
public void showMessage(String string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,59 +30,59 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mario Gray
|
||||
*/
|
||||
public class SftpSessionFactory implements FactoryBean<SftpSession>, InitializingBean {
|
||||
private volatile String knownHosts;
|
||||
private volatile String password;
|
||||
private volatile String privateKey;
|
||||
private volatile String privateKeyPassphrase;
|
||||
private volatile String remoteHost;
|
||||
private volatile String user;
|
||||
private volatile int port = 22; // the default
|
||||
private volatile String knownHosts;
|
||||
private volatile String password;
|
||||
private volatile String privateKey;
|
||||
private volatile String privateKeyPassphrase;
|
||||
private volatile String remoteHost;
|
||||
private volatile String user;
|
||||
private volatile int port = 22; // the default
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasText(this.remoteHost, "remoteHost can't be empty!");
|
||||
Assert.hasText(this.user, "user can't be empty!");
|
||||
Assert.state(StringUtils.hasText(this.password) || StringUtils.hasText(this.privateKey) || StringUtils.hasText(this.privateKeyPassphrase),
|
||||
"you must configure either a password or a private key and/or a private key passphrase!");
|
||||
Assert.state(this.port >= 0, "port must be a valid number! ");
|
||||
}
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasText(this.remoteHost, "remoteHost can't be empty!");
|
||||
Assert.hasText(this.user, "user can't be empty!");
|
||||
Assert.state(StringUtils.hasText(this.password) || StringUtils.hasText(this.privateKey) || StringUtils.hasText(this.privateKeyPassphrase),
|
||||
"you must configure either a password or a private key and/or a private key passphrase!");
|
||||
Assert.state(this.port >= 0, "port must be a valid number! ");
|
||||
}
|
||||
|
||||
public SftpSession getObject() throws Exception {
|
||||
return new SftpSession( this.user, this.remoteHost , this.password ,this.port, this.knownHosts, null, this.privateKey , this.privateKeyPassphrase);
|
||||
}
|
||||
public SftpSession getObject() throws Exception {
|
||||
return new SftpSession(this.user, this.remoteHost, this.password, this.port, this.knownHosts, null, this.privateKey, this.privateKeyPassphrase);
|
||||
}
|
||||
|
||||
public Class<?extends SftpSession> getObjectType() {
|
||||
return SftpSession.class;
|
||||
}
|
||||
public Class<? extends SftpSession> getObjectType() {
|
||||
return SftpSession.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setKnownHosts(String knownHosts) {
|
||||
this.knownHosts = knownHosts;
|
||||
}
|
||||
public void setKnownHosts(String knownHosts) {
|
||||
this.knownHosts = knownHosts;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
|
||||
this.privateKeyPassphrase = privateKeyPassphrase;
|
||||
}
|
||||
public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
|
||||
this.privateKeyPassphrase = privateKeyPassphrase;
|
||||
}
|
||||
|
||||
public void setRemoteHost(String remoteHost) {
|
||||
this.remoteHost = remoteHost;
|
||||
}
|
||||
public void setRemoteHost(String remoteHost) {
|
||||
this.remoteHost = remoteHost;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,28 +17,26 @@
|
||||
package org.springframework.integration.sftp;
|
||||
|
||||
/**
|
||||
*
|
||||
* Holds instances of {@link SftpSession} since they're stateful
|
||||
* and might be in use while another run happens.
|
||||
*
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Josh Long
|
||||
*/
|
||||
public interface SftpSessionPool {
|
||||
/**
|
||||
* this returns a session that can be used to connct to an sftp instance and perform operations
|
||||
*
|
||||
* @return the session from the pool ready to be connected to.
|
||||
* @throws Exception thrown if theres any of the numerous faults possible when trying to connect to the remote
|
||||
* server
|
||||
*/
|
||||
SftpSession getSession() throws Exception;
|
||||
/**
|
||||
* this returns a session that can be used to connct to an sftp instance and perform operations
|
||||
*
|
||||
* @return the session from the pool ready to be connected to.
|
||||
* @throws Exception thrown if theres any of the numerous faults possible when trying to connect to the remote
|
||||
* server
|
||||
*/
|
||||
SftpSession getSession() throws Exception;
|
||||
|
||||
/**
|
||||
* Frees up the client. Im not sure what the meaningful semantics of this are. Perhaps it just calls <code>(session
|
||||
* ,channel).disconnect()</code> ?
|
||||
*
|
||||
* @param session the session to relinquish / renew
|
||||
*/
|
||||
void release(SftpSession session);
|
||||
/**
|
||||
* Frees up the client. Im not sure what the meaningful semantics of this are. Perhaps it just calls <code>(session
|
||||
* ,channel).disconnect()</code> ?
|
||||
*
|
||||
* @param session the session to relinquish / renew
|
||||
*/
|
||||
void release(SftpSession session);
|
||||
}
|
||||
|
||||
@@ -28,66 +28,66 @@ import org.springframework.integration.sftp.SftpSessionFactory;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpMessageSendingConsumerFactoryBean implements FactoryBean<SftpSendingMessageHandler> {
|
||||
private String host;
|
||||
private String keyFile;
|
||||
private String keyFilePassword;
|
||||
private String password;
|
||||
private String remoteDirectory;
|
||||
private String username;
|
||||
private boolean autoCreateDirectories;
|
||||
private int port;
|
||||
private String host;
|
||||
private String keyFile;
|
||||
private String keyFilePassword;
|
||||
private String password;
|
||||
private String remoteDirectory;
|
||||
private String username;
|
||||
private boolean autoCreateDirectories;
|
||||
private int port;
|
||||
|
||||
public SftpSendingMessageHandler getObject() throws Exception {
|
||||
SftpSessionFactory sessionFactory = SftpSessionUtils.buildSftpSessionFactory(
|
||||
this.host, this.password, this.username, this.keyFile , this.keyFilePassword, this.port);
|
||||
public SftpSendingMessageHandler getObject() throws Exception {
|
||||
SftpSessionFactory sessionFactory = SftpSessionUtils.buildSftpSessionFactory(
|
||||
this.host, this.password, this.username, this.keyFile, this.keyFilePassword, this.port);
|
||||
|
||||
QueuedSftpSessionPool queuedSFTPSessionPool = new QueuedSftpSessionPool(15, sessionFactory);
|
||||
queuedSFTPSessionPool.afterPropertiesSet();
|
||||
QueuedSftpSessionPool queuedSFTPSessionPool = new QueuedSftpSessionPool(15, sessionFactory);
|
||||
queuedSFTPSessionPool.afterPropertiesSet();
|
||||
|
||||
SftpSendingMessageHandler sftpSendingMessageHandler = new SftpSendingMessageHandler(queuedSFTPSessionPool);
|
||||
sftpSendingMessageHandler.setRemoteDirectory(this.remoteDirectory);
|
||||
sftpSendingMessageHandler.afterPropertiesSet();
|
||||
SftpSendingMessageHandler sftpSendingMessageHandler = new SftpSendingMessageHandler(queuedSFTPSessionPool);
|
||||
sftpSendingMessageHandler.setRemoteDirectory(this.remoteDirectory);
|
||||
sftpSendingMessageHandler.afterPropertiesSet();
|
||||
|
||||
return sftpSendingMessageHandler;
|
||||
}
|
||||
return sftpSendingMessageHandler;
|
||||
}
|
||||
|
||||
public Class<?extends SftpSendingMessageHandler> getObjectType() {
|
||||
return SftpSendingMessageHandler.class;
|
||||
}
|
||||
public Class<? extends SftpSendingMessageHandler> getObjectType() {
|
||||
return SftpSendingMessageHandler.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAutoCreateDirectories(final boolean autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
public void setAutoCreateDirectories(final boolean autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
|
||||
public void setHost(final String host) {
|
||||
this.host = host;
|
||||
}
|
||||
public void setHost(final String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setKeyFile(final String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
}
|
||||
public void setKeyFile(final String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
}
|
||||
|
||||
public void setKeyFilePassword(final String keyFilePassword) {
|
||||
this.keyFilePassword = keyFilePassword;
|
||||
}
|
||||
public void setKeyFilePassword(final String keyFilePassword) {
|
||||
this.keyFilePassword = keyFilePassword;
|
||||
}
|
||||
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setRemoteDirectory(final String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
public void setRemoteDirectory(final String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,11 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.sftp.impl.SftpInboundRemoteFileSystemSynchronizingMessageSource;
|
||||
import org.springframework.integration.sftp.impl.SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides namespace support for using SFTP
|
||||
*
|
||||
* @author Josh Long
|
||||
@@ -37,44 +35,44 @@ import org.w3c.dom.Element;
|
||||
@SuppressWarnings("unused")
|
||||
public class SftpNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new SFTPMessageSourceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new SFTPMessageSendingConsumerBeanDefinitionParser());
|
||||
}
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new SFTPMessageSourceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new SFTPMessageSendingConsumerBeanDefinitionParser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an object that can take inbound messages and send them.
|
||||
*/
|
||||
private static class SFTPMessageSendingConsumerBeanDefinitionParser extends AbstractOutboundChannelAdapterParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SftpMessageSendingConsumerFactoryBean.class.getName());
|
||||
/**
|
||||
* Configures an object that can take inbound messages and send them.
|
||||
*/
|
||||
private static class SFTPMessageSendingConsumerBeanDefinitionParser extends AbstractOutboundChannelAdapterParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SftpMessageSendingConsumerFactoryBean.class.getName());
|
||||
|
||||
for (String p : "auto-create-directories,username,password,host,key-file,key-file-password,remote-directory".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
for (String p : "auto-create-directories,username,password,host,key-file,key-file-password,remote-directory".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an object that can recieve files from a remote SFTP endpoint and broadcast their arrival to the
|
||||
* consumer
|
||||
*/
|
||||
private static class SFTPMessageSourceBeanDefinitionParser extends AbstractPollingInboundChannelAdapterParser {
|
||||
@Override
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class.getName());
|
||||
/**
|
||||
* Configures an object that can recieve files from a remote SFTP endpoint and broadcast their arrival to the
|
||||
* consumer
|
||||
*/
|
||||
private static class SFTPMessageSourceBeanDefinitionParser extends AbstractPollingInboundChannelAdapterParser {
|
||||
@Override
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class.getName());
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "filter");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "filter");
|
||||
|
||||
for (String p : "filename-pattern,auto-create-directories,username,password,host,key-file,key-file-password,remote-directory,local-working-directory,auto-delete-remote-files-on-sync".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
for (String p : "filename-pattern,auto-create-directories,username,password,host,key-file,key-file-password,remote-directory,local-working-directory,auto-delete-remote-files-on-sync".split(",")) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, p);
|
||||
}
|
||||
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
}
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,32 +24,32 @@ import org.springframework.integration.sftp.SftpSessionFactory;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpSessionUtils {
|
||||
/**
|
||||
* This method hides the minutae required to build an #SftpSessionFactory.
|
||||
*
|
||||
* @param host the host to connect to.
|
||||
* @param usr this is required. It is the username of the credentials being authenticated.
|
||||
* @param pw if password authentication is being used (as opposed to key-based authentication) then this is
|
||||
* where you configure the password.
|
||||
* @param pvKey the file that is the private key
|
||||
* @param pvKeyPass the passphrase used to use the key file
|
||||
* @param port the default (22) is used if the value here is N< 0. The value should be only be set if the port
|
||||
* is non-standard (not 22)
|
||||
* @return the SftpSessionFactory that's used to create connections and get us in the right state to start issue
|
||||
* commands against a remote SFTP/SSH filesystem
|
||||
* @throws Exception thrown in case of darned near <em>anything</em>
|
||||
*/
|
||||
public static SftpSessionFactory buildSftpSessionFactory(String host, String pw, String usr, String pvKey, String pvKeyPass, int port)
|
||||
throws Exception {
|
||||
SftpSessionFactory sftpSessionFactory = new SftpSessionFactory();
|
||||
sftpSessionFactory.setPassword(pw);
|
||||
sftpSessionFactory.setPort(port);
|
||||
sftpSessionFactory.setRemoteHost(host);
|
||||
sftpSessionFactory.setUser(usr);
|
||||
sftpSessionFactory.setPrivateKey(pvKey);
|
||||
sftpSessionFactory.setPrivateKeyPassphrase(pvKeyPass);
|
||||
sftpSessionFactory.afterPropertiesSet();
|
||||
/**
|
||||
* This method hides the minutae required to build an #SftpSessionFactory.
|
||||
*
|
||||
* @param host the host to connect to.
|
||||
* @param usr this is required. It is the username of the credentials being authenticated.
|
||||
* @param pw if password authentication is being used (as opposed to key-based authentication) then this is
|
||||
* where you configure the password.
|
||||
* @param pvKey the file that is the private key
|
||||
* @param pvKeyPass the passphrase used to use the key file
|
||||
* @param port the default (22) is used if the value here is N< 0. The value should be only be set if the port
|
||||
* is non-standard (not 22)
|
||||
* @return the SftpSessionFactory that's used to create connections and get us in the right state to start issue
|
||||
* commands against a remote SFTP/SSH filesystem
|
||||
* @throws Exception thrown in case of darned near <em>anything</em>
|
||||
*/
|
||||
public static SftpSessionFactory buildSftpSessionFactory(String host, String pw, String usr, String pvKey, String pvKeyPass, int port)
|
||||
throws Exception {
|
||||
SftpSessionFactory sftpSessionFactory = new SftpSessionFactory();
|
||||
sftpSessionFactory.setPassword(pw);
|
||||
sftpSessionFactory.setPort(port);
|
||||
sftpSessionFactory.setRemoteHost(host);
|
||||
sftpSessionFactory.setUser(usr);
|
||||
sftpSessionFactory.setPrivateKey(pvKey);
|
||||
sftpSessionFactory.setPrivateKeyPassphrase(pvKeyPass);
|
||||
sftpSessionFactory.afterPropertiesSet();
|
||||
|
||||
return sftpSessionFactory;
|
||||
}
|
||||
return sftpSessionFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,117 +26,117 @@ import java.util.Collection;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpInboundRemoteFileSystemSynchronizer extends AbstractInboundRemoteFileSystemSychronizer<ChannelSftp.LsEntry> {
|
||||
/**
|
||||
* the path on the remote mount
|
||||
*/
|
||||
private volatile String remotePath;
|
||||
/**
|
||||
* the path on the remote mount
|
||||
*/
|
||||
private volatile String remotePath;
|
||||
|
||||
/**
|
||||
* the pool of {@link org.springframework.integration.sftp.SftpSessionPool} SFTP sessions
|
||||
*/
|
||||
private volatile SftpSessionPool clientPool;
|
||||
/**
|
||||
* the pool of {@link org.springframework.integration.sftp.SftpSessionPool} SFTP sessions
|
||||
*/
|
||||
private volatile SftpSessionPool clientPool;
|
||||
|
||||
public void setRemotePath(String remotePath) {
|
||||
this.remotePath = remotePath;
|
||||
}
|
||||
public void setRemotePath(String remotePath) {
|
||||
this.remotePath = remotePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
Assert.notNull(this.clientPool, "'clientPool' can't be null");
|
||||
Assert.notNull(this.remotePath, "'remotePath' can't be null");
|
||||
if (this.shouldDeleteSourceFile) {
|
||||
this.entryAcknowledgmentStrategy = new DeletionEntryAcknowledgmentStrategy();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
Assert.notNull(this.clientPool, "'clientPool' can't be null");
|
||||
Assert.notNull(this.remotePath, "'remotePath' can't be null");
|
||||
if (this.shouldDeleteSourceFile) {
|
||||
this.entryAcknowledgmentStrategy = new DeletionEntryAcknowledgmentStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setClientPool(SftpSessionPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
@Required
|
||||
public void setClientPool(SftpSessionPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ignored")
|
||||
private boolean copyFromRemoteToLocalDirectory(SftpSession sftpSession, ChannelSftp.LsEntry entry, Resource localDir)
|
||||
throws Exception {
|
||||
File fileForLocalDir = localDir.getFile();
|
||||
@SuppressWarnings("ignored")
|
||||
private boolean copyFromRemoteToLocalDirectory(SftpSession sftpSession, ChannelSftp.LsEntry entry, Resource localDir)
|
||||
throws Exception {
|
||||
File fileForLocalDir = localDir.getFile();
|
||||
|
||||
File localFile = new File(fileForLocalDir, entry.getFilename());
|
||||
File localFile = new File(fileForLocalDir, entry.getFilename());
|
||||
|
||||
if (!localFile.exists()) {
|
||||
InputStream in = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
if (!localFile.exists()) {
|
||||
InputStream in = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
|
||||
try {
|
||||
File tmpLocalTarget = new File(localFile.getAbsolutePath() +
|
||||
AbstractInboundRemoteFileSystemSynchronizingMessageSource.INCOMPLETE_EXTENSION);
|
||||
try {
|
||||
File tmpLocalTarget = new File(localFile.getAbsolutePath() +
|
||||
AbstractInboundRemoteFileSystemSynchronizingMessageSource.INCOMPLETE_EXTENSION);
|
||||
|
||||
fileOutputStream = new FileOutputStream(tmpLocalTarget);
|
||||
fileOutputStream = new FileOutputStream(tmpLocalTarget);
|
||||
|
||||
String remoteFqPath = this.remotePath + "/" + entry.getFilename();
|
||||
in = sftpSession.getChannel().get(remoteFqPath);
|
||||
IOUtils.copy(in, fileOutputStream);
|
||||
String remoteFqPath = this.remotePath + "/" + entry.getFilename();
|
||||
in = sftpSession.getChannel().get(remoteFqPath);
|
||||
IOUtils.copy(in, fileOutputStream);
|
||||
|
||||
if (tmpLocalTarget.renameTo(localFile)) {
|
||||
// last step
|
||||
this.acknowledge(sftpSession, entry);
|
||||
}
|
||||
if (tmpLocalTarget.renameTo(localFile)) {
|
||||
// last step
|
||||
this.acknowledge(sftpSession, entry);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Throwable th) {
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable th) {
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void syncRemoteToLocalFileSystem() throws Exception {
|
||||
SftpSession session = null;
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void syncRemoteToLocalFileSystem() throws Exception {
|
||||
SftpSession session = null;
|
||||
|
||||
try {
|
||||
session = clientPool.getSession();
|
||||
session.start();
|
||||
try {
|
||||
session = clientPool.getSession();
|
||||
session.start();
|
||||
|
||||
ChannelSftp channelSftp = session.getChannel();
|
||||
Collection<ChannelSftp.LsEntry> beforeFilter = channelSftp.ls(remotePath);
|
||||
ChannelSftp.LsEntry[] entries = (beforeFilter == null) ? new ChannelSftp.LsEntry[0] : beforeFilter.toArray(new ChannelSftp.LsEntry[beforeFilter.size()]);
|
||||
Collection<ChannelSftp.LsEntry> files = this.filter.filterEntries(entries);
|
||||
ChannelSftp channelSftp = session.getChannel();
|
||||
Collection<ChannelSftp.LsEntry> beforeFilter = channelSftp.ls(remotePath);
|
||||
ChannelSftp.LsEntry[] entries = (beforeFilter == null) ? new ChannelSftp.LsEntry[0] : beforeFilter.toArray(new ChannelSftp.LsEntry[beforeFilter.size()]);
|
||||
Collection<ChannelSftp.LsEntry> files = this.filter.filterEntries(entries);
|
||||
|
||||
for (ChannelSftp.LsEntry lsEntry : files) {
|
||||
if ((lsEntry != null) && !lsEntry.getAttrs().isDir() && !lsEntry.getAttrs().isLink()) {
|
||||
copyFromRemoteToLocalDirectory(session, lsEntry, this.localDirectory);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new MessagingException("couldn't synchronize remote to local directory", e);
|
||||
} finally {
|
||||
if ((session != null) && (clientPool != null)) {
|
||||
clientPool.release(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ChannelSftp.LsEntry lsEntry : files) {
|
||||
if ((lsEntry != null) && !lsEntry.getAttrs().isDir() && !lsEntry.getAttrs().isLink()) {
|
||||
copyFromRemoteToLocalDirectory(session, lsEntry, this.localDirectory);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new MessagingException("couldn't synchronize remote to local directory", e);
|
||||
} finally {
|
||||
if ((session != null) && (clientPool != null)) {
|
||||
clientPool.release(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Trigger getTrigger() {
|
||||
return new PeriodicTrigger(10 * 1000);
|
||||
}
|
||||
@Override
|
||||
protected Trigger getTrigger() {
|
||||
return new PeriodicTrigger(10 * 1000);
|
||||
}
|
||||
|
||||
class DeletionEntryAcknowledgmentStrategy implements AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy<ChannelSftp.LsEntry> {
|
||||
public void acknowledge(Object useful, ChannelSftp.LsEntry msg)
|
||||
throws Exception {
|
||||
SftpSession sftpSession = (SftpSession) useful;
|
||||
class DeletionEntryAcknowledgmentStrategy implements AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy<ChannelSftp.LsEntry> {
|
||||
public void acknowledge(Object useful, ChannelSftp.LsEntry msg)
|
||||
throws Exception {
|
||||
SftpSession sftpSession = (SftpSession) useful;
|
||||
|
||||
String remoteFqPath = remotePath + "/" + msg.getFilename();
|
||||
String remoteFqPath = remotePath + "/" + msg.getFilename();
|
||||
|
||||
sftpSession.getChannel().rm(remoteFqPath);
|
||||
sftpSession.getChannel().rm(remoteFqPath);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("deleted " + msg.getFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("deleted " + msg.getFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ package org.springframework.integration.sftp.impl;
|
||||
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.SftpATTRS;
|
||||
|
||||
import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource;
|
||||
import org.springframework.integration.sftp.SftpSession;
|
||||
import org.springframework.integration.sftp.SftpSessionPool;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@@ -16,86 +14,86 @@ import org.springframework.util.Assert;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpInboundRemoteFileSystemSynchronizingMessageSource extends AbstractInboundRemoteFileSystemSynchronizingMessageSource<ChannelSftp.LsEntry, SftpInboundRemoteFileSystemSynchronizer> {
|
||||
/**
|
||||
* the pool of sessions
|
||||
*/
|
||||
private volatile SftpSessionPool clientPool;
|
||||
/**
|
||||
* the pool of sessions
|
||||
*/
|
||||
private volatile SftpSessionPool clientPool;
|
||||
|
||||
|
||||
/**
|
||||
* the remote path on teh server
|
||||
*/
|
||||
private volatile String remotePath;
|
||||
|
||||
public void setClientPool(SftpSessionPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
/**
|
||||
* the remote path on teh server
|
||||
*/
|
||||
private volatile String remotePath;
|
||||
|
||||
public void setRemotePath(String remotePath) {
|
||||
this.remotePath = remotePath;
|
||||
}
|
||||
public void setClientPool(SftpSessionPool clientPool) {
|
||||
this.clientPool = clientPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.synchronizer.start();
|
||||
}
|
||||
public void setRemotePath(String remotePath) {
|
||||
this.remotePath = remotePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
this.synchronizer.stop();
|
||||
}
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.synchronizer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* there be dragons this way ... This method will check to ensure that the remote directory exists. If the directory
|
||||
* doesnt exist, and autoCreatePath is 'true,' then this method makes a few reasonably sane attempts
|
||||
* to create it. Otherwise, it fails fast.
|
||||
*
|
||||
* @param remotePath the path on the remote SSH / SFTP server to create.
|
||||
* @return whether or not the directory is there (regardless of whether we created it in this method or it already
|
||||
* existed.)
|
||||
*/
|
||||
private boolean checkThatRemotePathExists(String remotePath) {
|
||||
SftpSession session = null;
|
||||
ChannelSftp channelSftp = null;
|
||||
@Override
|
||||
protected void doStop() {
|
||||
this.synchronizer.stop();
|
||||
}
|
||||
|
||||
try {
|
||||
session = this.clientPool.getSession();
|
||||
Assert.state(session != null, "session as returned from the pool should not be null. " + "If it is, it is most likely an error in the pool implementation. ");
|
||||
session.start();
|
||||
channelSftp = session.getChannel();
|
||||
/**
|
||||
* there be dragons this way ... This method will check to ensure that the remote directory exists. If the directory
|
||||
* doesnt exist, and autoCreatePath is 'true,' then this method makes a few reasonably sane attempts
|
||||
* to create it. Otherwise, it fails fast.
|
||||
*
|
||||
* @param remotePath the path on the remote SSH / SFTP server to create.
|
||||
* @return whether or not the directory is there (regardless of whether we created it in this method or it already
|
||||
* existed.)
|
||||
*/
|
||||
private boolean checkThatRemotePathExists(String remotePath) {
|
||||
SftpSession session = null;
|
||||
ChannelSftp channelSftp = null;
|
||||
|
||||
SftpATTRS attrs = channelSftp.stat(remotePath);
|
||||
assert (attrs != null) && attrs.isDir() : "attrs can't be null, and should indicate that it's a directory!";
|
||||
try {
|
||||
session = this.clientPool.getSession();
|
||||
Assert.state(session != null, "session as returned from the pool should not be null. " + "If it is, it is most likely an error in the pool implementation. ");
|
||||
session.start();
|
||||
channelSftp = session.getChannel();
|
||||
|
||||
return true;
|
||||
} catch (Throwable th) {
|
||||
if (this.autoCreateDirectories && (this.clientPool != null) && (session != null)) {
|
||||
try {
|
||||
if (channelSftp != null) {
|
||||
channelSftp.mkdir(remotePath);
|
||||
SftpATTRS attrs = channelSftp.stat(remotePath);
|
||||
assert (attrs != null) && attrs.isDir() : "attrs can't be null, and should indicate that it's a directory!";
|
||||
|
||||
if (channelSftp.stat(remotePath).isDir()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if ((clientPool != null) && (session != null)) {
|
||||
clientPool.release(session);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable th) {
|
||||
if (this.autoCreateDirectories && (this.clientPool != null) && (session != null)) {
|
||||
try {
|
||||
if (channelSftp != null) {
|
||||
channelSftp.mkdir(remotePath);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (channelSftp.stat(remotePath).isDir()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if ((clientPool != null) && (session != null)) {
|
||||
clientPool.release(session);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
return false;
|
||||
}
|
||||
|
||||
this.checkThatRemotePathExists(this.remotePath);
|
||||
this.synchronizer.setClientPool(this.clientPool);
|
||||
}
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
|
||||
this.checkThatRemotePathExists(this.remotePath);
|
||||
this.synchronizer.setClientPool(this.clientPool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,164 +25,164 @@ import java.io.File;
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean extends AbstractFactoryBean<SftpInboundRemoteFileSystemSynchronizingMessageSource> implements ResourceLoaderAware {
|
||||
/**
|
||||
* injected by the container
|
||||
*/
|
||||
private volatile ResourceLoader resourceLoader;
|
||||
private volatile Resource localDirectoryResource;
|
||||
private volatile String localDirectoryPath;
|
||||
private volatile String autoCreateDirectories;
|
||||
private volatile String autoDeleteRemoteFilesOnSync;
|
||||
private volatile String filenamePattern;
|
||||
private volatile EntryListFilter<ChannelSftp.LsEntry> filter;
|
||||
private int port = 22;
|
||||
private String host;
|
||||
private String keyFile;
|
||||
private String keyFilePassword;
|
||||
private String password;
|
||||
private String remoteDirectory;
|
||||
private String username;
|
||||
/**
|
||||
* injected by the container
|
||||
*/
|
||||
private volatile ResourceLoader resourceLoader;
|
||||
private volatile Resource localDirectoryResource;
|
||||
private volatile String localDirectoryPath;
|
||||
private volatile String autoCreateDirectories;
|
||||
private volatile String autoDeleteRemoteFilesOnSync;
|
||||
private volatile String filenamePattern;
|
||||
private volatile EntryListFilter<ChannelSftp.LsEntry> filter;
|
||||
private int port = 22;
|
||||
private String host;
|
||||
private String keyFile;
|
||||
private String keyFilePassword;
|
||||
private String password;
|
||||
private String remoteDirectory;
|
||||
private String username;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setLocalDirectoryResource(Resource localDirectoryResource) {
|
||||
this.localDirectoryResource = localDirectoryResource;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setLocalDirectoryResource(Resource localDirectoryResource) {
|
||||
this.localDirectoryResource = localDirectoryResource;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setLocalDirectoryPath(String localDirectoryPath) {
|
||||
this.localDirectoryPath = localDirectoryPath;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setLocalDirectoryPath(String localDirectoryPath) {
|
||||
this.localDirectoryPath = localDirectoryPath;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setAutoCreateDirectories(String autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setAutoCreateDirectories(String autoCreateDirectories) {
|
||||
this.autoCreateDirectories = autoCreateDirectories;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setAutoDeleteRemoteFilesOnSync(String autoDeleteRemoteFilesOnSync) {
|
||||
this.autoDeleteRemoteFilesOnSync = autoDeleteRemoteFilesOnSync;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setAutoDeleteRemoteFilesOnSync(String autoDeleteRemoteFilesOnSync) {
|
||||
this.autoDeleteRemoteFilesOnSync = autoDeleteRemoteFilesOnSync;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilenamePattern(String filenamePattern) {
|
||||
this.filenamePattern = filenamePattern;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilenamePattern(String filenamePattern) {
|
||||
this.filenamePattern = filenamePattern;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilter(EntryListFilter<ChannelSftp.LsEntry> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setFilter(EntryListFilter<ChannelSftp.LsEntry> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setKeyFile(String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setKeyFile(String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setKeyFilePassword(String keyFilePassword) {
|
||||
this.keyFilePassword = keyFilePassword;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setKeyFilePassword(String keyFilePassword) {
|
||||
this.keyFilePassword = keyFilePassword;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setRemoteDirectory(String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setRemoteDirectory(String remoteDirectory) {
|
||||
this.remoteDirectory = remoteDirectory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class;
|
||||
}
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return SftpRemoteFileSystemSynchronizingMessageSourceFactoryBean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SftpInboundRemoteFileSystemSynchronizingMessageSource createInstance()
|
||||
throws Exception {
|
||||
boolean autoCreatDirs = Boolean.parseBoolean(this.autoCreateDirectories);
|
||||
boolean ackRemoteDir = Boolean.parseBoolean(this.autoDeleteRemoteFilesOnSync);
|
||||
@Override
|
||||
protected SftpInboundRemoteFileSystemSynchronizingMessageSource createInstance()
|
||||
throws Exception {
|
||||
boolean autoCreatDirs = Boolean.parseBoolean(this.autoCreateDirectories);
|
||||
boolean ackRemoteDir = Boolean.parseBoolean(this.autoDeleteRemoteFilesOnSync);
|
||||
|
||||
SftpInboundRemoteFileSystemSynchronizingMessageSource sftpMsgSrc = new SftpInboundRemoteFileSystemSynchronizingMessageSource();
|
||||
sftpMsgSrc.setAutoCreateDirectories(autoCreatDirs);
|
||||
SftpInboundRemoteFileSystemSynchronizingMessageSource sftpMsgSrc = new SftpInboundRemoteFileSystemSynchronizingMessageSource();
|
||||
sftpMsgSrc.setAutoCreateDirectories(autoCreatDirs);
|
||||
|
||||
// local directories
|
||||
if ((this.localDirectoryResource == null) || !StringUtils.hasText(this.localDirectoryPath)) {
|
||||
File tmp = SystemUtils.getJavaIoTmpDir();
|
||||
File sftpTmp = new File(tmp, "sftpInbound");
|
||||
this.localDirectoryPath = "file://" + sftpTmp.getAbsolutePath();
|
||||
}
|
||||
// local directories
|
||||
if ((this.localDirectoryResource == null) || !StringUtils.hasText(this.localDirectoryPath)) {
|
||||
File tmp = SystemUtils.getJavaIoTmpDir();
|
||||
File sftpTmp = new File(tmp, "sftpInbound");
|
||||
this.localDirectoryPath = "file://" + sftpTmp.getAbsolutePath();
|
||||
}
|
||||
|
||||
this.localDirectoryResource = this.fromText(localDirectoryPath);
|
||||
this.localDirectoryResource = this.fromText(localDirectoryPath);
|
||||
|
||||
// remote predicates
|
||||
SftpEntryNamer sftpEntryNamer = new SftpEntryNamer();
|
||||
CompositeEntryListFilter<ChannelSftp.LsEntry> compositeFtpFileListFilter = new CompositeEntryListFilter<ChannelSftp.LsEntry>();
|
||||
// remote predicates
|
||||
SftpEntryNamer sftpEntryNamer = new SftpEntryNamer();
|
||||
CompositeEntryListFilter<ChannelSftp.LsEntry> compositeFtpFileListFilter = new CompositeEntryListFilter<ChannelSftp.LsEntry>();
|
||||
|
||||
if (StringUtils.hasText(this.filenamePattern)) {
|
||||
PatternMatchingEntryListFilter<ChannelSftp.LsEntry> ftpFilePatternMatchingEntryListFilter = new PatternMatchingEntryListFilter<ChannelSftp.LsEntry>(sftpEntryNamer, filenamePattern);
|
||||
compositeFtpFileListFilter.addFilter(ftpFilePatternMatchingEntryListFilter);
|
||||
}
|
||||
if (StringUtils.hasText(this.filenamePattern)) {
|
||||
PatternMatchingEntryListFilter<ChannelSftp.LsEntry> ftpFilePatternMatchingEntryListFilter = new PatternMatchingEntryListFilter<ChannelSftp.LsEntry>(sftpEntryNamer, filenamePattern);
|
||||
compositeFtpFileListFilter.addFilter(ftpFilePatternMatchingEntryListFilter);
|
||||
}
|
||||
|
||||
if (this.filter != null) {
|
||||
compositeFtpFileListFilter.addFilter(this.filter);
|
||||
}
|
||||
if (this.filter != null) {
|
||||
compositeFtpFileListFilter.addFilter(this.filter);
|
||||
}
|
||||
|
||||
this.filter = compositeFtpFileListFilter;
|
||||
this.filter = compositeFtpFileListFilter;
|
||||
|
||||
// pools
|
||||
SftpSessionFactory sessionFactory = SftpSessionUtils.buildSftpSessionFactory(this.host, this.password, this.username, this.keyFile, this.keyFilePassword, this.port);
|
||||
// pools
|
||||
SftpSessionFactory sessionFactory = SftpSessionUtils.buildSftpSessionFactory(this.host, this.password, this.username, this.keyFile, this.keyFilePassword, this.port);
|
||||
|
||||
QueuedSftpSessionPool pool = new QueuedSftpSessionPool(15, sessionFactory);
|
||||
pool.afterPropertiesSet();
|
||||
QueuedSftpSessionPool pool = new QueuedSftpSessionPool(15, sessionFactory);
|
||||
pool.afterPropertiesSet();
|
||||
|
||||
SftpInboundRemoteFileSystemSynchronizer sftpSync = new SftpInboundRemoteFileSystemSynchronizer();
|
||||
sftpSync.setClientPool(pool);
|
||||
sftpSync.setLocalDirectory(this.localDirectoryResource);
|
||||
sftpSync.setShouldDeleteSourceFile(ackRemoteDir);
|
||||
sftpSync.setFilter(compositeFtpFileListFilter);
|
||||
sftpSync.setBeanFactory(this.getBeanFactory());
|
||||
sftpSync.setRemotePath(this.remoteDirectory);
|
||||
sftpSync.afterPropertiesSet(); // todo is this correct ?
|
||||
sftpSync.start(); //todo
|
||||
SftpInboundRemoteFileSystemSynchronizer sftpSync = new SftpInboundRemoteFileSystemSynchronizer();
|
||||
sftpSync.setClientPool(pool);
|
||||
sftpSync.setLocalDirectory(this.localDirectoryResource);
|
||||
sftpSync.setShouldDeleteSourceFile(ackRemoteDir);
|
||||
sftpSync.setFilter(compositeFtpFileListFilter);
|
||||
sftpSync.setBeanFactory(this.getBeanFactory());
|
||||
sftpSync.setRemotePath(this.remoteDirectory);
|
||||
sftpSync.afterPropertiesSet(); // todo is this correct ?
|
||||
sftpSync.start(); //todo
|
||||
|
||||
sftpMsgSrc.setRemotePredicate(compositeFtpFileListFilter);
|
||||
sftpMsgSrc.setSynchronizer(sftpSync);
|
||||
sftpMsgSrc.setClientPool(pool);
|
||||
sftpMsgSrc.setRemotePath(this.remoteDirectory);
|
||||
sftpMsgSrc.setLocalDirectory(this.localDirectoryResource);
|
||||
sftpMsgSrc.setBeanFactory(this.getBeanFactory());
|
||||
sftpMsgSrc.setAutoStartup(true);
|
||||
sftpMsgSrc.afterPropertiesSet();
|
||||
sftpMsgSrc.start();
|
||||
sftpMsgSrc.setRemotePredicate(compositeFtpFileListFilter);
|
||||
sftpMsgSrc.setSynchronizer(sftpSync);
|
||||
sftpMsgSrc.setClientPool(pool);
|
||||
sftpMsgSrc.setRemotePath(this.remoteDirectory);
|
||||
sftpMsgSrc.setLocalDirectory(this.localDirectoryResource);
|
||||
sftpMsgSrc.setBeanFactory(this.getBeanFactory());
|
||||
sftpMsgSrc.setAutoStartup(true);
|
||||
sftpMsgSrc.afterPropertiesSet();
|
||||
sftpMsgSrc.start();
|
||||
|
||||
return sftpMsgSrc;
|
||||
}
|
||||
return sftpMsgSrc;
|
||||
}
|
||||
|
||||
private Resource fromText(String path) {
|
||||
ResourceEditor resourceEditor = new ResourceEditor(this.resourceLoader);
|
||||
resourceEditor.setAsText(path);
|
||||
private Resource fromText(String path) {
|
||||
ResourceEditor resourceEditor = new ResourceEditor(this.resourceLoader);
|
||||
resourceEditor.setAsText(path);
|
||||
|
||||
return (Resource) resourceEditor.getValue();
|
||||
}
|
||||
return (Resource) resourceEditor.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,58 +16,57 @@
|
||||
-->
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/sftp"
|
||||
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/sftp"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
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/sftp"
|
||||
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: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[
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an outbound-channel-adapter that writes files to a remote SFTP 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: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="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 name="key-file" type="xsd:string"/>
|
||||
<xsd:attribute name="key-file-password" type="xsd:string"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute name="key-file" type="xsd:string"/>
|
||||
<xsd:attribute name="key-file-password" type="xsd:string"/>
|
||||
|
||||
<xsd:attribute name="auto-create-directories" type="xsd:boolean"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:attribute name="auto-create-directories" type="xsd:boolean"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
Builds an inbound-channel-adapter that synchronizes with a remote SFTP endpoint.
|
||||
You may configure a <code>poller</code> element to determine at what frequency to scan the remote directory.
|
||||
@@ -78,51 +77,51 @@
|
||||
<li> Key-based authentication: using this option, you may specify a key that will be used to authenticate. If they key itself is encrypted and requires a password, you may specify that, as well.</li>
|
||||
</ol>
|
||||
]]></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: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 name="filter" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ftp.FtpFileListFilter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="filter" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ftp.FtpFileListFilter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string"/>
|
||||
<xsd:attribute name="filename-pattern" type="xsd:string"/>
|
||||
|
||||
<xsd:attribute name="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="local-working-directory" type="xsd:string"/>
|
||||
<xsd:attribute name="host" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="username" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="remote-directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="local-working-directory" type="xsd:string"/>
|
||||
<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 name="key-file" type="xsd:string"/>
|
||||
<xsd:attribute name="key-file-password" type="xsd:string"/>
|
||||
<xsd:attribute name="password" type="xsd:string"/>
|
||||
<xsd:attribute name="port" type="xsd:int" default="22"/>
|
||||
<xsd:attribute name="key-file" type="xsd:string"/>
|
||||
<xsd:attribute name="key-file-password" 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="auto-create-directories" type="xsd:boolean"/>
|
||||
<xsd:attribute name="auto-delete-remote-files-on-sync" type="xsd:boolean"/>
|
||||
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
</xsd:schema>
|
||||
|
||||
@@ -7,14 +7,13 @@ import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Josh Long
|
||||
*
|
||||
*/
|
||||
@Component("sftpAnnouncer")
|
||||
public class SftpFileAnnouncer {
|
||||
|
||||
@ServiceActivator
|
||||
public void announceFile(File file){
|
||||
System.out.println( "New file from the remote host has arrived: " + file.getAbsolutePath()) ;
|
||||
}
|
||||
@ServiceActivator
|
||||
public void announceFile(File file) {
|
||||
System.out.println("New file from the remote host has arrived: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
*/
|
||||
public class TestInboundSftp {
|
||||
|
||||
static public void main(String [] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("TestInboundSftp.xml");
|
||||
classPathXmlApplicationContext.start();
|
||||
}
|
||||
static public void main(String[] args) throws Throwable {
|
||||
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("TestInboundSftp.xml");
|
||||
classPathXmlApplicationContext.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
-->
|
||||
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
|
||||
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-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
@@ -34,31 +34,31 @@
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp-2.0.xsd">
|
||||
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.sftp"/>
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/sftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.sftp"/>
|
||||
<context:property-placeholder
|
||||
location="file://${user.home}/Desktop/sftp.properties"
|
||||
ignore-unresolvable="true"/>
|
||||
|
||||
|
||||
<channel id="inboundFilesChannel"/>
|
||||
<channel id="inboundFilesChannel"/>
|
||||
|
||||
|
||||
<sftp:inbound-channel-adapter
|
||||
key-file="${sftp.key}"
|
||||
remote-directory="${sftp.remote-dir}"
|
||||
channel="inboundFilesChannel"
|
||||
filename-pattern=".*?jpg"
|
||||
username="${sftp.username}"
|
||||
auto-create-directories="true"
|
||||
auto-delete-remote-files-on-sync="true"
|
||||
host="${sftp.host}">
|
||||
<poller>
|
||||
<interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</poller>
|
||||
</sftp:inbound-channel-adapter>
|
||||
<sftp:inbound-channel-adapter
|
||||
key-file="${sftp.key}"
|
||||
remote-directory="${sftp.remote-dir}"
|
||||
channel="inboundFilesChannel"
|
||||
filename-pattern=".*?jpg"
|
||||
username="${sftp.username}"
|
||||
auto-create-directories="true"
|
||||
auto-delete-remote-files-on-sync="true"
|
||||
host="${sftp.host}">
|
||||
<poller>
|
||||
<interval-trigger interval="1000" time-unit="MILLISECONDS"/>
|
||||
</poller>
|
||||
</sftp:inbound-channel-adapter>
|
||||
|
||||
|
||||
<service-activator ref="sftpAnnouncer" input-channel="inboundFilesChannel"/>
|
||||
<service-activator ref="sftpAnnouncer" input-channel="inboundFilesChannel"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -16,18 +16,17 @@
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xmlns:sftp="http://www.springframework.org/schema/integration/sftp"
|
||||
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-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
@@ -36,20 +35,20 @@
|
||||
http://www.springframework.org/schema/integration/sftp
|
||||
http://www.springframework.org/schema/integration/sftp/spring-integration-sftp-2.0.xsd">
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.sftp"/>
|
||||
<context:component-scan base-package="org.springframework.integration.sftp"/>
|
||||
|
||||
|
||||
<channel id="inboundFilesChannel"/>
|
||||
<channel id="inboundFilesChannel"/>
|
||||
|
||||
<sftp:outbound-channel-adapter
|
||||
key-file="/home/user/user.pem"
|
||||
remote-directory="/home/ubuntu/remote_mount_key"
|
||||
auto-create-directories="true"
|
||||
channel="inboundFilesChannel"
|
||||
username="ubuntu"
|
||||
host="siteonec2usingubuntuami.com"
|
||||
/>
|
||||
<sftp:outbound-channel-adapter
|
||||
key-file="/home/user/user.pem"
|
||||
remote-directory="/home/ubuntu/remote_mount_key"
|
||||
auto-create-directories="true"
|
||||
channel="inboundFilesChannel"
|
||||
username="ubuntu"
|
||||
host="siteonec2usingubuntuami.com"
|
||||
/>
|
||||
|
||||
<service-activator input-channel="inboundFilesChannel" ref="sftpAnnouncer"/>
|
||||
<service-activator input-channel="inboundFilesChannel" ref="sftpAnnouncer"/>
|
||||
|
||||
</beans:beans>
|
||||
</beans:beans>
|
||||
|
||||
Reference in New Issue
Block a user