From a2215afdf7486e1915f2987ba1902cfd39648e6a Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 7 May 2024 13:46:27 -0400 Subject: [PATCH] GH-9123: SFTP: Use `canonicalPath` for read operation Fixes: #9123 The `/` at the beginning of the remote dir path is not necessary when listing files, although it is necessary to download them The `SftpTemplate.get()` should work also with `remote-dir/MyFile.csv` as input. * Fix `SftpSession.readRaw()` to call `sftpClient.canonicalPath(source)` if the path does not start with a `/`. Something similar what is does * Delegate to `SftpSession.readRaw()` from the `SftpSession.read()` * Reuse `normalizePath()` for `doList()` **Auto-cherry-pick to `6.2.x` & `6.1.x`** --- .../integration/sftp/session/SftpSession.java | 15 ++++++++------- ...pInboundRemoteFileSystemSynchronizerTests.java | 9 ++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) 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 80883331af..a9c17d19d3 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -107,23 +107,24 @@ public class SftpSession implements Session { remoteDir = remotePath; } } - remoteDir = - !remoteDir.isEmpty() && remoteDir.charAt(0) == '/' - ? remoteDir - : this.sftpClient.canonicalPath(remoteDir); + remoteDir = normalizePath(remoteDir); return StreamSupport.stream(this.sftpClient.readDir(remoteDir).spliterator(), false) .filter((entry) -> !isPattern || PatternMatchUtils.simpleMatch(remoteFile, entry.getFilename())); } @Override public void read(String source, OutputStream os) throws IOException { - InputStream is = this.sftpClient.read(source); + InputStream is = readRaw(source); FileCopyUtils.copy(is, os); } @Override public InputStream readRaw(String source) throws IOException { - return this.sftpClient.read(source); + return this.sftpClient.read(normalizePath(source)); + } + + private String normalizePath(String path) throws IOException { + return !path.isEmpty() && path.charAt(0) == '/' ? path : this.sftpClient.canonicalPath(path); } @Override 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 f425c91191..acb1383ea7 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -193,8 +193,11 @@ public class SftpInboundRemoteFileSystemSynchronizerTests { 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)); + String remoteFilePath = "remote-test-dir/" + fileName; + when(sftpClient.canonicalPath(remoteFilePath)) + .thenReturn("/" + remoteFilePath); + when(sftpClient.read("/" + remoteFilePath)) + .thenReturn(new FileInputStream(remoteFilePath)); } when(sftpClient.readDir("/remote-test-dir")).thenReturn(this.sftpEntries);