diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index b8886818269..bb73f991bab 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -78,7 +78,7 @@ public String[] listNames(String path) throws IOException { } public Stream doList(String path) throws IOException { - String remotePath = StringUtils.trimTrailingCharacter(StringUtils.trimLeadingCharacter(path, '/'), '/'); + String remotePath = StringUtils.trimTrailingCharacter(path, '/'); String remoteDir = remotePath; int lastIndex = remotePath.lastIndexOf('/'); if (lastIndex > 0) { @@ -96,7 +96,10 @@ public Stream doList(String path) throws IOException { remoteDir = remotePath; } } - remoteDir = remoteDir.length() == 0 ? this.sftpClient.canonicalPath("") : remoteDir; + remoteDir = + remoteDir.length() > 0 && remoteDir.charAt(0) == '/' + ? remoteDir + : this.sftpClient.canonicalPath(remoteDir); return StreamSupport.stream(this.sftpClient.readDir(remoteDir).spliterator(), false) .filter((entry) -> !isPattern || PatternMatchUtils.simpleMatch(remoteFile, entry.getFilename())); } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpInboundRemoteFileSystemSynchronizerTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpInboundRemoteFileSystemSynchronizerTests.java index 1c99b85f2aa..f425c91191b 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpInboundRemoteFileSystemSynchronizerTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpInboundRemoteFileSystemSynchronizerTests.java @@ -189,13 +189,14 @@ public SftpSession getSession() { try { SftpClient sftpClient = mock(SftpClient.class); + when(sftpClient.canonicalPath("remote-test-dir")).thenReturn("/remote-test-dir"); String[] files = new File("remote-test-dir").list(); for (String fileName : files) { when(sftpClient.read("remote-test-dir/" + fileName)) .thenReturn(new FileInputStream("remote-test-dir/" + fileName)); } - when(sftpClient.readDir("remote-test-dir")).thenReturn(this.sftpEntries); + when(sftpClient.readDir("/remote-test-dir")).thenReturn(this.sftpEntries); return SftpTestSessionFactory.createSftpSession(sftpClient); } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpMessageSourceTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpMessageSourceTests.java index 16ed45ee7e9..399738e9cd3 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpMessageSourceTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/inbound/SftpMessageSourceTests.java @@ -44,7 +44,7 @@ public class SftpMessageSourceTests extends SftpTestSupport { private ApplicationContext context; @Test - public void testMaxFetch() throws Exception { + public void testMaxFetch() { SftpInboundFileSynchronizingMessageSource messageSource = buildSource(); Message received = messageSource.receive(); assertThat(received).isNotNull(); @@ -52,9 +52,9 @@ public void testMaxFetch() throws Exception { .isIn(" sftpSource1.txt", "sftpSource2.txt"); } - private SftpInboundFileSynchronizingMessageSource buildSource() throws Exception { + private SftpInboundFileSynchronizingMessageSource buildSource() { SftpInboundFileSynchronizer sync = new SftpInboundFileSynchronizer(sessionFactory()); - sync.setRemoteDirectory("sftpSource/"); + sync.setRemoteDirectory("/sftpSource/"); sync.setBeanFactory(this.context); SftpInboundFileSynchronizingMessageSource messageSource = new SftpInboundFileSynchronizingMessageSource(sync); messageSource.setLocalDirectory(getTargetLocalDirectory()); diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java index 3aeef4d07ea..169b2d49b7f 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java @@ -174,14 +174,14 @@ public void testSftpOutboundChannelAdapterInsideChain() throws Exception { context.close(); } - @Test //INT-2275 + @Test public void testFtpOutboundGatewayInsideChain() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "SftpOutboundInsideChainTests-context.xml", getClass()); MessageChannel channel = context.getBean("outboundGatewayInsideChain", MessageChannel.class); - channel.send(MessageBuilder.withPayload("remote-test-dir").build()); + channel.send(MessageBuilder.withPayload("/remote-test-dir").build()); PollableChannel output = context.getBean("replyChannel", PollableChannel.class); @@ -308,7 +308,7 @@ public SftpSession getSession() { Arrays.stream(files) .map((file) -> new SftpClient.DirEntry(file, file, new SftpClient.Attributes())) .toList(); - when(sftpClient.readDir("remote-test-dir")).thenReturn(dirEntries); + when(sftpClient.readDir("/remote-test-dir")).thenReturn(dirEntries); return SftpTestSessionFactory.createSftpSession(sftpClient); } diff --git a/src/reference/asciidoc/sftp.adoc b/src/reference/asciidoc/sftp.adoc index 09d6a33dd12..e7b05eb7bc7 100644 --- a/src/reference/asciidoc/sftp.adoc +++ b/src/reference/asciidoc/sftp.adoc @@ -945,6 +945,8 @@ When using the recursive option (`-R`), the `fileName` includes any subdirectory If you use the `-dirs` option, each recursive directory is also returned as an element in the list. In this case, we recommend that you not use the `-1` option, because you would not be able to distinguish files from directories, which you can do when you use `FileInfo` objects. +If remote path to list starts with a `/` symbol, it is treated by SFTP as an absolute path; without - as a relative path in the current user home. + ==== Using `nlst` Command Version 5 introduced support for the `nlst` command. @@ -1341,7 +1343,7 @@ Currently, supported events are: * `PathRemovedEvent` - a file or directory was removed * `SessionClosedEvent` - the client has disconnected -Each of these is a subclass of `ApacheMinaSftpEvent`; you can configure a single listener to receive all of the event types. +Each of these is a subclass of `ApacheMinaSftpEvent`; you can configure a single listener to receive all the event types. The `source` property of each event is a `ServerSession`, from which you can obtain information such as the client address; a convenient `getSession()` method is provided on the abstract event. To configure the server with the listener (which must be a Spring bean), simply add it to the `SftpSubsystemFactory`: