INTSAMPLES-134: SFTP: Use Apache SSHD SshServer

JIRA: https://jira.spring.io/browse/INTSAMPLES-134

INTSAMPLES-134: `sun.misc.BASE64Decoder` -> `org.apache.sshd.common.util.Base64`

INTSAMPLES-134: PR comments and fix for Windows

INTSAMPLES-134 Test Samples with Remote Server

- change 'user' property to 'username' to avoid conflict with environment variable.
- create temporary files using the remote file template in 'si.sftp.sample'.
- clean up after test completion.
- use a caching session factory.
This commit is contained in:
Artem Bilan
2014-07-29 15:22:46 +03:00
committed by Gary Russell
parent 35e5156bdb
commit 90d5ee9282
19 changed files with 494 additions and 110 deletions

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.samples.sftp;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.Collections;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.file.FileSystemView;
import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
import org.apache.sshd.common.file.nativefs.NativeFileSystemView;
import org.apache.sshd.common.util.Base64;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.util.SocketUtils;
import org.springframework.util.StreamUtils;
/**
* @author Artem Bilan
*/
public class EmbeddedSftpServer implements InitializingBean, SmartLifecycle {
public static final int PORT = SocketUtils.findAvailableTcpPort();
private final SshServer server = SshServer.setUpDefaultServer();
private volatile int port;
private volatile boolean running;
public void setPort(int port) {
this.port = port;
}
@Override
public void afterPropertiesSet() throws Exception {
final PublicKey allowedKey = decodePublicKey();
this.server.setPublickeyAuthenticator(new PublickeyAuthenticator() {
@Override
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return key.equals(allowedKey);
}
});
this.server.setPort(this.port);
this.server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
this.server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
final String virtualDir = new FileSystemResource("").getFile().getAbsolutePath();
this.server.setFileSystemFactory(new NativeFileSystemFactory() {
@Override
public FileSystemView createFileSystemView(org.apache.sshd.common.Session session) {
return new NativeFileSystemView(session.getUsername(), false) {
@Override
public String getVirtualUserDir() {
return virtualDir;
}
};
}
});
}
private PublicKey decodePublicKey() throws Exception {
InputStream stream = new ClassPathResource("META-INF/keys/sftp_rsa.pub").getInputStream();
byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream));
ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
int len = bb.getInt();
byte[] type = new byte[len];
bb.get(type);
if ("ssh-rsa".equals(new String(type))) {
BigInteger e = decodeBigInt(bb);
BigInteger m = decodeBigInt(bb);
RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
else {
throw new IllegalArgumentException("Only supports RSA");
}
}
private BigInteger decodeBigInt(ByteBuffer bb) {
int len = bb.getInt();
byte[] bytes = new byte[len];
bb.get(bytes);
return new BigInteger(bytes);
}
@Override
public boolean isAutoStartup() {
return PORT == this.port;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
@Override
public void start() {
try {
server.start();
this.running = true;
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
@Override
public void stop() {
if (this.running) {
try {
server.stop(true);
}
catch (InterruptedException e) {
throw new IllegalStateException(e);
}
finally {
this.running = false;
}
}
}
@Override
public boolean isRunning() {
return this.running;
}
}

View File

@@ -15,24 +15,68 @@
*/
package org.springframework.integration.samples.sftp;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import com.jcraft.jsch.ChannelSftp.LsEntry;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*
*/
public class SftpInboundReceiveSample {
@Test
public void runDemo(){
ApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/integration/SftpInboundReceiveSample-context.xml", this.getClass());
PollableChannel localFileChannel = context.getBean("receiveChannel", PollableChannel.class);
System.out.println("Received first file message: " + localFileChannel.receive());
System.out.println("Received second file message: " + localFileChannel.receive());
System.out.println("No third file was received " + localFileChannel.receive(1000));
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("/META-INF/spring/integration/SftpInboundReceiveSample-context.xml", this.getClass());
RemoteFileTemplate<LsEntry> template = null;
String file1 = "a.txt";
String file2 = "b.txt";
String file3 = "c.bar";
new File("local-dir", file1).delete();
new File("local-dir", file2).delete();
try {
PollableChannel localFileChannel = context.getBean("receiveChannel", PollableChannel.class);
@SuppressWarnings("unchecked")
SessionFactory<LsEntry> sessionFactory = context.getBean(CachingSessionFactory.class);
template = new RemoteFileTemplate<LsEntry>(sessionFactory);
SftpTestUtils.createTestFiles(template, file1, file2, file3);
SourcePollingChannelAdapter adapter = context.getBean(SourcePollingChannelAdapter.class);
adapter.start();
Message<?> received = localFileChannel.receive();
assertNotNull("Expected file", received);
System.out.println("Received first file message: " + received);
received = localFileChannel.receive();
assertNotNull("Expected file", received);
System.out.println("Received second file message: " + received);
received = localFileChannel.receive(1000);
assertNull("Expected null", received);
System.out.println("No third file was received as expected");
}
finally {
SftpTestUtils.cleanUp(template, file1, file2, file3);
context.close();
assertTrue("Could note delete retrieved file", new File("local-dir", file1).delete());
assertTrue("Could note delete retrieved file", new File("local-dir", file2).delete());
}
}
}

View File

@@ -20,11 +20,16 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
import java.util.Random;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import com.jcraft.jsch.ChannelSftp.LsEntry;
/**
* Demonstrates use of the outbound gateway to use ls, get and rm.
@@ -40,24 +45,23 @@ public class SftpOutboundGatewaySample {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:/META-INF/spring/integration/SftpOutboundGatewaySample-context.xml");
ToSftpFlowGateway toFtpFlow = ctx.getBean(ToSftpFlowGateway.class);
RemoteFileTemplate<LsEntry> template = null;
String file1 = "1.ftptest";
String file2 = "2.ftptest";
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
try {
String tmpDir = System.getProperty("java.io.tmpdir");
// remove the previous output files if necessary
new File(new File(tmpDir), "1.ftptest").delete();
new File(new File(tmpDir), "2.ftptest").delete();
// create a couple of files in a temp dir
File dir = new File(tmpDir + "/" + new Random().nextInt());
dir.mkdir();
File f1 = new File(dir, "1.ftptest");
f1.createNewFile();
File f2 = new File(dir, "2.ftptest");
f2.createNewFile();
new File(tmpDir, file1).delete();
new File(tmpDir, file2).delete();
@SuppressWarnings("unchecked")
SessionFactory<LsEntry> sessionFactory = ctx.getBean(CachingSessionFactory.class);
template = new RemoteFileTemplate<LsEntry>(sessionFactory);
SftpTestUtils.createTestFiles(template, file1, file2);
// execute the flow (ls, get, rm, aggregate results)
List<Boolean> rmResults = toFtpFlow.lsGetAndRmFiles(dir.getAbsolutePath());
List<Boolean> rmResults = toFtpFlow.lsGetAndRmFiles("si.sftp.sample");
//Check everything went as expected, and clean up
@@ -65,13 +69,16 @@ public class SftpOutboundGatewaySample {
for (Boolean result : rmResults) {
assertTrue(result);
}
assertTrue("Expected remote dir to be empty", dir.delete());
assertTrue("Could note delete retrieved file", new File(new File(tmpDir), "1.ftptest").delete());
assertTrue("Could note delete retrieved file", new File(new File(tmpDir), "2.ftptest").delete());
} finally {
}
finally {
SftpTestUtils.cleanUp(template, file1, file2);
ctx.close();
assertTrue("Could note delete retrieved file", new File(tmpDir, file1).delete());
assertTrue("Could note delete retrieved file", new File(tmpDir, file2).delete());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,15 +20,21 @@ import java.io.File;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.util.Assert;
import com.jcraft.jsch.ChannelSftp.LsEntry;
/**
*
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Gary Russell
*
*/
public class SftpOutboundTransferSample {
@@ -38,29 +44,34 @@ public class SftpOutboundTransferSample {
final String sourceFileName = "README.md";
final String destinationFileName = sourceFileName +"_foo";
final String destinationFilePath = "remote-target-dir/" + destinationFileName;
final ClassPathXmlApplicationContext ac =
new ClassPathXmlApplicationContext("/META-INF/spring/integration/SftpOutboundTransferSample-context.xml", SftpOutboundTransferSample.class);
ac.start();
@SuppressWarnings("unchecked")
SessionFactory<LsEntry> sessionFactory = ac.getBean(CachingSessionFactory.class);
RemoteFileTemplate<LsEntry> template = new RemoteFileTemplate<LsEntry>(sessionFactory);
SftpTestUtils.createTestFiles(template); // Just the directory
final File file = new File(sourceFileName);
try {
final File file = new File(sourceFileName);
Assert.isTrue(file.exists(), String.format("File '%s' does not exist.", sourceFileName));
Assert.isTrue(file.exists(), String.format("File '%s' does not exist.", sourceFileName));
final Message<File> message = MessageBuilder.withPayload(file).build();
final MessageChannel inputChannel = ac.getBean("inputChannel", MessageChannel.class);
final Message<File> message = MessageBuilder.withPayload(file).build();
final MessageChannel inputChannel = ac.getBean("inputChannel", MessageChannel.class);
inputChannel.send(message);
Thread.sleep(2000);
inputChannel.send(message);
Thread.sleep(2000);
Assert.isTrue(new File(destinationFilePath).exists(), String.format("File '%s' does not exist.", destinationFilePath));
System.out.println(String.format("Successfully transferred '%s' file to a " +
"remote location under the name '%s'", sourceFileName, destinationFileName));
ac.stop();
Assert.isTrue(SftpTestUtils.fileExists(template, destinationFileName));
System.out.println(String.format("Successfully transferred '%s' file to a " +
"remote location under the name '%s'", sourceFileName, destinationFileName));
}
finally {
SftpTestUtils.cleanUp(template, destinationFileName);
ac.close();
}
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.samples.sftp;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.SessionCallback;
import org.springframework.integration.file.remote.session.Session;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
/**
* @author Gary Russell
* @since 4.1
*
*/
public class SftpTestUtils {
public static void createTestFiles(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
if (template != null) {
final ByteArrayInputStream stream = new ByteArrayInputStream("foo".getBytes());
template.execute(new SessionCallback<LsEntry, Void>() {
@Override
public Void doInSession(Session<LsEntry> session) throws IOException {
try {
session.mkdir("si.sftp.sample");
}
catch (Exception e) {
assertThat(e.getMessage(), containsString("failed to create"));
}
for (int i = 0; i < fileNames.length; i++) {
stream.reset();
session.write(stream, "si.sftp.sample/" + fileNames[i]);
}
return null;
}
});
}
}
public static void cleanUp(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
if (template != null) {
template.execute(new SessionCallback<LsEntry, Void>() {
@Override
public Void doInSession(Session<LsEntry> session) throws IOException {
// TODO: avoid DFAs with Spring 4.1 (INT-3412)
ChannelSftp channel = (ChannelSftp) new DirectFieldAccessor(new DirectFieldAccessor(session)
.getPropertyValue("targetSession")).getPropertyValue("channel");
for (int i = 0; i < fileNames.length; i++) {
try {
session.remove("si.sftp.sample/" + fileNames[i]);
}
catch (IOException e) {}
}
try {
// should be empty
channel.rmdir("si.sftp.sample");
}
catch (SftpException e) {
fail("Expected remote directory to be empty " + e.getMessage());
}
return null;
}
});
}
}
public static boolean fileExists(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
if (template != null) {
return template.execute(new SessionCallback<LsEntry, Boolean>() {
@Override
public Boolean doInSession(Session<LsEntry> session) throws IOException {
// TODO: avoid DFAs with Spring 4.1 (INT-3412)
ChannelSftp channel = (ChannelSftp) new DirectFieldAccessor(new DirectFieldAccessor(session)
.getPropertyValue("targetSession")).getPropertyValue("channel");
for (int i = 0; i < fileNames.length; i++) {
try {
SftpATTRS stat = channel.stat("si.sftp.sample/" + fileNames[i]);
if (stat == null) {
System.out.println("stat returned null for " + fileNames[i]);
return false;
}
}
catch (SftpException e) {
System.out.println("Remote file not present: " + e.getMessage() + ": " + fileNames[i]);
return false;
}
}
return true;
}
});
}
else {
return false;
}
}
}

View File

@@ -1,30 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,89FEB82756CA8E56
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
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1 @@
AAAAB3NzaC1yc2EAAAADAQABAAABAQDMQB/vTCY6QEF+/P73ZQZzgj5LBUG8gKPbAXdWcE/X0g3jgsPpxb7+NGiqNpP+oVIQsL9Q7TBsv1/X7xc6sd6SmM/UTP8LF0zlf0GSvEehC2BT98GCiDqI8BKpZjG6O8+pPEBY8M5iGOLtDUSzlhzyV7kPcADYLHl/z1fssU+x2UML7BoSmgh0XPc2u+Gv6+58SVk2ipAZOmaWZDyzWAc3sczz/DkQeR/cpj047HVc1Zb/M5a4ajYI18Ka+mVhKeiQnHc3NKwE6ZxcwlacbVK/feypfperHQOlj6Ee6f6huhnVx9x42V11A41Toh98WI2EVDequ4EcTxHHJntJhpbd

View File

@@ -3,29 +3,31 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">
<context:property-placeholder location="classpath:user.properties"/>
<import resource="SftpSampleCommon.xml"/>
<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="privateKey" value="classpath:META-INF/keys/sftp_rsa"/>
<bean id="sftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="defaultSftpSessionFactory" />
</bean>
<bean id="defaultSftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${host}"/>
<property name="privateKey" value="${private.keyfile}"/>
<property name="privateKeyPassphrase" value="${passphrase}"/>
<property name="port" value="22"/>
<property name="user" value="${user}"/>
<property name="port" value="#{serverPort}"/>
<property name="user" value="${username}"/>
</bean>
<int-sftp:inbound-channel-adapter id="sftpInbondAdapter"
auto-startup="false"
channel="receiveChannel"
session-factory="sftpSessionFactory"
local-directory="file:local-dir"
remote-directory="${remote.directory}"
remote-directory="si.sftp.sample"
auto-create-local-directory="true"
delete-remote-files="false"
filename-regex=".*\.txt$">

View File

@@ -1,26 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">
<context:property-placeholder location="classpath:user.properties"/>
<import resource="SftpSampleCommon.xml"/>
<int:gateway id="gw" service-interface="org.springframework.integration.samples.sftp.ToSftpFlowGateway"
default-request-channel="inbound"/>
<bean id="sftpSessionFactory"
<bean id="sftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="defaultSftpSessionFactory" />
</bean>
<bean id="defaultSftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="host" value="${host}"/>
<property name="privateKey" value="${private.keyfile}"/>
<property name="privateKeyPassphrase" value="${passphrase}"/>
<property name="port" value="22"/>
<property name="user" value="${user}"/>
<property name="port" value="#{serverPort}"/>
<property name="user" value="${username}"/>
</bean>
<int-sftp:outbound-gateway id="gatewayLS"
@@ -40,11 +42,11 @@
reply-channel="toRm"
command="get"
command-options="-P"
expression="payload.remoteDirectory + '/' + payload.filename"/>
expression="payload.remoteDirectory + payload.filename"/>
<int-sftp:outbound-gateway id="gatewayRM" reply-channel="aggregateResultsChannel"
session-factory="sftpSessionFactory"
expression="headers['file_remoteDirectory'] + '/' + headers['file_remoteFile']"
expression="headers['file_remoteDirectory'] + headers['file_remoteFile']"
request-channel="toRm"
command="rm"/>

View File

@@ -3,20 +3,23 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">
<context:property-placeholder location="classpath:user.properties"/>
<import resource="SftpSampleCommon.xml"/>
<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
<property name="privateKey" value="classpath:META-INF/keys/sftp_rsa"/>
<bean id="sftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="defaultSftpSessionFactory" />
</bean>
<bean id="defaultSftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${host}"/>
<property name="privateKey" value="${private.keyfile}"/>
<property name="privateKeyPassphrase" value="${passphrase}"/>
<property name="port" value="22"/>
<property name="user" value="${user}"/>
<property name="port" value="#{serverPort}"/>
<property name="user" value="${username}"/>
</bean>
<int:channel id="inputChannel"/>
@@ -25,6 +28,6 @@
session-factory="sftpSessionFactory"
channel="inputChannel"
remote-filename-generator-expression="payload.getName() + '_foo'"
remote-directory="${remote.directory}"/>
remote-directory="si.sftp.sample"/>
</beans>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:user.properties"/>
<bean id="serverPort" class="java.lang.String">
<constructor-arg value="#{'${port}' == '-1' ? T(org.springframework.integration.samples.sftp.EmbeddedSftpServer).PORT : '${port}'}"/>
</bean>
<bean class="org.springframework.integration.samples.sftp.EmbeddedSftpServer">
<property name="port" value="#{serverPort}"/>
</bean>
</beans>

View File

@@ -1,5 +1,7 @@
user=
passphrase=
host=localhost
# -1 means the embedded Apache MINA SshServer. Change it to any real port, if you are going to test sample against real SFTP Server
port=-1
username=user
passphrase=password
#private.keyfile=file:/home/someuser/.ssh/id_rsa
private.keyfile=classpath:META-INF/keys/sftp_rsa
remote.directory=<<SPECIFY REMOTE DIRECTORY (e.g., /{workspace}/samples/basic/sftp/remote-target-dir)>>