INT-4243: Upgrade to sshd 1.4
JIRA: https://jira.spring.io/browse/INT-4243 Remove newline char from key exchange. Fix CR and Add Windows Delete Diagnostics Fix For Windows More diagnostics. It appears the new server doesn't close the file when the session is closed. In the streaming test, consume the stream before closing the session. Polishing - PR Comments * More polishing according PR comments
This commit is contained in:
committed by
Artem Bilan
parent
3aa830b7c0
commit
4bb3f5041f
@@ -89,7 +89,7 @@ subprojects { subproject ->
|
||||
ext {
|
||||
activeMqVersion = '5.14.3'
|
||||
aspectjVersion = '1.8.9'
|
||||
apacheSshdVersion = '0.14.0'
|
||||
apacheSshdVersion = '1.4.0'
|
||||
boonVersion = '0.33'
|
||||
chronicleVersion = '3.5.3'
|
||||
commonsDbcpVersion = '1.4'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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.
|
||||
@@ -19,10 +19,15 @@ package org.springframework.integration.file.remote;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
/**
|
||||
* Abstract base class for tests requiring remote file servers, e.g. (S)FTP.
|
||||
@@ -33,6 +38,8 @@ import org.junit.rules.TemporaryFolder;
|
||||
*/
|
||||
public abstract class RemoteFileTestSupport {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected static int port;
|
||||
|
||||
@ClassRule
|
||||
@@ -41,6 +48,9 @@ public abstract class RemoteFileTestSupport {
|
||||
@ClassRule
|
||||
public static final TemporaryFolder localTemporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public final TestName testName = new TestName();
|
||||
|
||||
protected volatile File sourceRemoteDirectory;
|
||||
|
||||
protected volatile File targetRemoteDirectory;
|
||||
@@ -162,15 +172,24 @@ public abstract class RemoteFileTestSupport {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File fyle : files) {
|
||||
logger.info("Deleting: " + fyle + " in " + testName.getMethodName());
|
||||
if (fyle.isDirectory()) {
|
||||
recursiveDelete(fyle);
|
||||
}
|
||||
else {
|
||||
fyle.delete();
|
||||
if (!fyle.delete()) {
|
||||
logger.error("Couldn't delete: " + fyle + " in " + testName.getMethodName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
logger.info("Deleting: " + file + " in " + testName.getMethodName());
|
||||
if (!file.delete()) {
|
||||
logger.error("Couldn't delete: " + file + " in " + testName.getMethodName());
|
||||
if (file.isDirectory()) {
|
||||
logger.error("Contents: " + Arrays.toString(file.listFiles()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -95,7 +95,7 @@ public class RedisInboundChannelAdapterParserTests extends RedisAvailableTests {
|
||||
|
||||
QueueChannel receiveChannel = context.getBean("receiveChannel", QueueChannel.class);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Message<?> receive = receiveChannel.receive(2000);
|
||||
Message<?> receive = receiveChannel.receive(10000);
|
||||
assertNotNull(receive);
|
||||
assertThat(receive.getPayload(), Matchers.<Object>isOneOf("Hello Redis from foo", "Hello Redis from bar"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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.
|
||||
@@ -19,12 +19,12 @@ package org.springframework.integration.sftp;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.sshd.SshServer;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
|
||||
import org.apache.sshd.server.Command;
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.apache.sshd.server.sftp.SftpSubsystem;
|
||||
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
@@ -46,6 +46,7 @@ public class SftpTestSupport extends RemoteFileTestSupport {
|
||||
|
||||
private static SshServer server;
|
||||
|
||||
@Override
|
||||
public String getTargetLocalDirectoryName() {
|
||||
return targetLocalDirectory.getAbsolutePath() + File.separator;
|
||||
}
|
||||
@@ -60,9 +61,9 @@ public class SftpTestSupport extends RemoteFileTestSupport {
|
||||
server = SshServer.setUpDefaultServer();
|
||||
server.setPasswordAuthenticator((username, password, session) -> true);
|
||||
server.setPort(0);
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(remoteTemporaryFolder.getRoot().getAbsolutePath()));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostkey.ser")));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(remoteTemporaryFolder.getRoot().toPath()));
|
||||
server.start();
|
||||
port = server.getPort();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -75,15 +75,15 @@ public class SftpTests extends SftpTestSupport {
|
||||
public void testSftpInboundFlow() {
|
||||
QueueChannel out = new QueueChannel();
|
||||
IntegrationFlow flow = IntegrationFlows
|
||||
.from(Sftp.inboundAdapter(sessionFactory())
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("sftpSource")
|
||||
.regexFilter(".*\\.txt$")
|
||||
.localFilenameExpression("#this.toUpperCase() + '.a'")
|
||||
.localDirectory(getTargetLocalDirectory()),
|
||||
e -> e.id("sftpInboundAdapter").poller(Pollers.fixedDelay(100)))
|
||||
.channel(out)
|
||||
.get();
|
||||
.from(Sftp.inboundAdapter(sessionFactory())
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("sftpSource")
|
||||
.regexFilter(".*\\.txt$")
|
||||
.localFilenameExpression("#this.toUpperCase() + '.a'")
|
||||
.localDirectory(getTargetLocalDirectory()),
|
||||
e -> e.id("sftpInboundAdapter").poller(Pollers.fixedDelay(100)))
|
||||
.channel(out)
|
||||
.get();
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
Message<?> message = out.receive(10_000);
|
||||
assertNotNull(message);
|
||||
@@ -110,19 +110,21 @@ public class SftpTests extends SftpTestSupport {
|
||||
.remoteDirectory("sftpSource")
|
||||
.regexFilter(".*\\.txt$"),
|
||||
e -> e.id("sftpInboundAdapter").poller(Pollers.fixedDelay(100)))
|
||||
.channel(out)
|
||||
.get();
|
||||
.channel(out)
|
||||
.get();
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
Message<?> message = out.receive(10_000);
|
||||
assertNotNull(message);
|
||||
assertThat(message.getPayload(), instanceOf(InputStream.class));
|
||||
assertThat(message.getHeaders().get(FileHeaders.REMOTE_FILE), isOneOf(" sftpSource1.txt", "sftpSource2.txt"));
|
||||
((InputStream) message.getPayload()).close();
|
||||
new IntegrationMessageHeaderAccessor(message).getCloseableResource().close();
|
||||
|
||||
message = out.receive(10_000);
|
||||
assertNotNull(message);
|
||||
assertThat(message.getPayload(), instanceOf(InputStream.class));
|
||||
assertThat(message.getHeaders().get(FileHeaders.REMOTE_FILE), isOneOf("sftpSource1.txt", "sftpSource2.txt"));
|
||||
((InputStream) message.getPayload()).close();
|
||||
new IntegrationMessageHeaderAccessor(message).getCloseableResource().close();
|
||||
|
||||
registration.destroy();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -16,10 +16,16 @@
|
||||
|
||||
package org.springframework.integration.sftp.session;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -81,10 +87,15 @@ public class SftpRemoteFileTemplateTests extends SftpTestSupport {
|
||||
}
|
||||
});
|
||||
template.execute((SessionCallbackWithoutResult<LsEntry>) session -> {
|
||||
LsEntry[] files = session.list("foo/");
|
||||
assertEquals(4, files.length);
|
||||
assertTrue(session.remove("foo/foobar.txt"));
|
||||
assertTrue(session.rmdir("foo/bar/"));
|
||||
LsEntry[] files = session.list("foo/");
|
||||
assertEquals(0, files.length);
|
||||
files = session.list("foo/");
|
||||
assertEquals(2, files.length);
|
||||
List<LsEntry> list = Arrays.asList(files);
|
||||
assertThat(list.stream().map(l -> l.getFilename()).collect(Collectors.toList()),
|
||||
containsInAnyOrder(".", ".."));
|
||||
assertTrue(session.rmdir("foo/"));
|
||||
});
|
||||
assertFalse(template.exists("foo"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -25,23 +25,25 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.sshd.SshServer;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
|
||||
import org.apache.sshd.common.util.Base64;
|
||||
import org.apache.sshd.server.Command;
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.apache.sshd.server.sftp.SftpSubsystem;
|
||||
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import com.jcraft.jsch.ChannelSftp.LsEntry;
|
||||
@@ -62,11 +64,11 @@ public class SftpServerTests {
|
||||
try {
|
||||
server.setPasswordAuthenticator((arg0, arg1, arg2) -> true);
|
||||
server.setPort(0);
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostkey.ser")));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
|
||||
final String pathname = System.getProperty("java.io.tmpdir") + File.separator + "sftptest" + File.separator;
|
||||
new File(pathname).mkdirs();
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(pathname));
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(Paths.get(pathname)));
|
||||
server.start();
|
||||
|
||||
DefaultSftpSessionFactory f = new DefaultSftpSessionFactory();
|
||||
@@ -100,11 +102,11 @@ public class SftpServerTests {
|
||||
try {
|
||||
server.setPublickeyAuthenticator((username, key, session) -> key.equals(allowedKey));
|
||||
server.setPort(0);
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostkey.ser")));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
|
||||
final String pathname = System.getProperty("java.io.tmpdir") + File.separator + "sftptest" + File.separator;
|
||||
new File(pathname).mkdirs();
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(pathname));
|
||||
server.setFileSystemFactory(new VirtualFileSystemFactory(Paths.get(pathname)));
|
||||
server.start();
|
||||
|
||||
DefaultSftpSessionFactory f = new DefaultSftpSessionFactory();
|
||||
@@ -125,7 +127,12 @@ public class SftpServerTests {
|
||||
|
||||
private PublicKey decodePublicKey(String key) throws Exception {
|
||||
InputStream stream = new ClassPathResource(key).getInputStream();
|
||||
byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream));
|
||||
byte[] keyBytes = StreamUtils.copyToByteArray(stream);
|
||||
// strip any newline chars
|
||||
while (keyBytes[keyBytes.length - 1] == 0x0a || keyBytes[keyBytes.length - 1] == 0x0d) {
|
||||
keyBytes = Arrays.copyOf(keyBytes, keyBytes.length - 1);
|
||||
}
|
||||
byte[] decodeBuffer = Base64Utils.decode(keyBytes);
|
||||
ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
|
||||
int len = bb.getInt();
|
||||
byte[] type = new byte[len];
|
||||
@@ -157,7 +164,7 @@ public class SftpServerTests {
|
||||
}
|
||||
session.write(new ByteArrayInputStream("foo".getBytes()), "bar");
|
||||
list = session.list(".");
|
||||
assertEquals("bar", list[0].getFilename());
|
||||
assertEquals("bar", list[1].getFilename());
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
session.read("bar", outputStream);
|
||||
assertEquals("foo", new String(outputStream.toByteArray()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -28,15 +28,16 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.sshd.SshServer;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.server.Command;
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.apache.sshd.server.sftp.SftpSubsystem;
|
||||
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@@ -63,7 +64,7 @@ public class SftpSessionFactoryTests {
|
||||
try {
|
||||
server.setPasswordAuthenticator((arg0, arg1, arg2) -> true);
|
||||
server.setPort(0);
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostkey.ser")));
|
||||
server.start();
|
||||
|
||||
DefaultSftpSessionFactory f = new DefaultSftpSessionFactory();
|
||||
@@ -212,8 +213,8 @@ public class SftpSessionFactoryTests {
|
||||
private DefaultSftpSessionFactory createServerAndClient(SshServer server) throws IOException {
|
||||
server.setPublickeyAuthenticator((username, key, session) -> true);
|
||||
server.setPort(0);
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystem.Factory()));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
|
||||
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(new SftpSubsystemFactory()));
|
||||
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostkey.ser")));
|
||||
server.start();
|
||||
|
||||
DefaultSftpSessionFactory f = new DefaultSftpSessionFactory();
|
||||
|
||||
Reference in New Issue
Block a user