Skip to content

Commit 06140cb

Browse files
garyrussellartembilan
authored andcommitted
SFTP: Add channelConnectTimeout
While investigating an SI build failure, I noticed that there is a timeout available for when connecting channels. This won't resolve the build issue (where the session closed) but worth adding as a property.
1 parent bcff9d4 commit 06140cb

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/DefaultSftpSessionFactory.java

+15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.integration.sftp.session;
1818

1919
import java.io.IOException;
20+
import java.time.Duration;
2021
import java.util.Arrays;
2122
import java.util.Properties;
2223
import java.util.concurrent.locks.Lock;
@@ -108,6 +109,8 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
108109

109110
private boolean allowUnknownKeys = false;
110111

112+
private Duration channelConnectTimeout;
113+
111114
private volatile JSchSessionWrapper sharedJschSession;
112115

113116

@@ -353,6 +356,16 @@ public void setAllowUnknownKeys(boolean allowUnknownKeys) {
353356
this.allowUnknownKeys = allowUnknownKeys;
354357
}
355358

359+
/**
360+
* Set the connect timeout.
361+
* @param timeout the timeout to set.
362+
* @since 5.2
363+
*/
364+
public void setChannelConnectTimeout(Duration timeout) {
365+
Assert.notNull(timeout, "'connectTimeout' cannot be null");
366+
this.channelConnectTimeout = timeout;
367+
}
368+
356369
@Override
357370
public SftpSession getSession() {
358371
JSchSessionWrapper jschSession = this.sharedJschSession;
@@ -367,6 +380,8 @@ public SftpSession getSession() {
367380
freshJschSession = true;
368381
}
369382
sftpSession = new SftpSession(jschSession);
383+
JavaUtils.INSTANCE
384+
.acceptIfNotNull(this.channelConnectTimeout, sftpSession::setChannelConnectTimeout);
370385
sftpSession.connect();
371386
if (this.isSharedSession && freshJschSession) {
372387
this.sharedJschSession = jschSession;

spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java

+19-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.io.InputStream;
2121
import java.io.OutputStream;
22+
import java.time.Duration;
2223
import java.util.ArrayList;
2324
import java.util.List;
2425
import java.util.Vector;
@@ -51,12 +52,16 @@ public class SftpSession implements Session<LsEntry> {
5152

5253
private static final String SESSION_IS_NOT_CONNECTED = "session is not connected";
5354

55+
private static final Duration DEFAULT_CHANNEL_CONNECT_TIMEOUT = Duration.ofSeconds(5);
56+
5457
private final Log logger = LogFactory.getLog(this.getClass());
5558

5659
private final com.jcraft.jsch.Session jschSession;
5760

5861
private final JSchSessionWrapper wrapper;
5962

63+
private int channelConnectTimeout = (int) DEFAULT_CHANNEL_CONNECT_TIMEOUT.toMillis();
64+
6065
private volatile ChannelSftp channel;
6166

6267
private volatile boolean closed;
@@ -74,6 +79,16 @@ public SftpSession(JSchSessionWrapper wrapper) {
7479
this.wrapper = wrapper;
7580
}
7681

82+
/**
83+
* Set the connect timeout.
84+
* @param timeout the timeout to set.
85+
* @since 5.2
86+
*/
87+
public void setChannelConnectTimeout(Duration timeout) {
88+
Assert.notNull(timeout, "'timeout' cannot be null");
89+
this.channelConnectTimeout = (int) timeout.toMillis();
90+
}
91+
7792
@Override
7893
public boolean remove(String path) throws IOException {
7994
Assert.state(this.channel != null, SESSION_IS_NOT_CONNECTED);
@@ -146,7 +161,7 @@ public InputStream readRaw(String source) throws IOException {
146161
}
147162

148163
@Override
149-
public boolean finalizeRaw() throws IOException {
164+
public boolean finalizeRaw() {
150165
return true;
151166
}
152167

@@ -258,7 +273,7 @@ public boolean exists(String path) {
258273
this.channel.lstat(path);
259274
return true;
260275
}
261-
catch (SftpException e) {
276+
catch (@SuppressWarnings("unused") SftpException e) {
262277
// ignore
263278
}
264279
return false;
@@ -271,7 +286,7 @@ void connect() {
271286
}
272287
this.channel = (ChannelSftp) this.jschSession.openChannel("sftp");
273288
if (this.channel != null && !this.channel.isConnected()) {
274-
this.channel.connect();
289+
this.channel.connect(this.channelConnectTimeout);
275290
}
276291
}
277292
catch (JSchException e) {
@@ -295,7 +310,7 @@ private boolean doTest() {
295310
this.channel.lstat(this.channel.getHome());
296311
return true;
297312
}
298-
catch (Exception e) {
313+
catch (@SuppressWarnings("unused") Exception e) {
299314
return false;
300315
}
301316
}

spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.mockito.ArgumentMatchers.anyString;
2121
import static org.mockito.BDDMockito.willAnswer;
2222
import static org.mockito.Mockito.doAnswer;
23+
import static org.mockito.Mockito.doNothing;
2324
import static org.mockito.Mockito.doReturn;
2425
import static org.mockito.Mockito.mock;
2526
import static org.mockito.Mockito.never;
@@ -380,7 +381,7 @@ public void testSharedSessionCachedReset() throws Exception {
380381
}
381382

382383
private void noopConnect(ChannelSftp channel1) throws JSchException {
383-
doAnswer(invocation -> null).when(channel1).connect();
384+
doNothing().when(channel1).connect(5000);
384385
}
385386

386387
public static class TestSftpSessionFactory extends DefaultSftpSessionFactory {

spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpSessionFactoryTests.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.io.File;
2626
import java.io.IOException;
2727
import java.net.ConnectException;
28+
import java.time.Duration;
2829
import java.util.Collections;
2930

3031
import org.apache.sshd.server.SshServer;
@@ -153,8 +154,11 @@ public void testDefaultUserInfoTrue() throws Exception {
153154
SshServer server = SshServer.setUpDefaultServer();
154155
try {
155156
DefaultSftpSessionFactory f = createServerAndClient(server);
157+
f.setChannelConnectTimeout(Duration.ofSeconds(6));
156158
f.setAllowUnknownKeys(true);
157-
f.getSession().close();
159+
SftpSession session = f.getSession();
160+
assertThat(TestUtils.getPropertyValue(session, "channelConnectTimeout", Integer.class)).isEqualTo(6_000);
161+
session.close();
158162
}
159163
finally {
160164
server.stop(true);

0 commit comments

Comments
 (0)