This is an automated email from the ASF dual-hosted git repository. lgoldstein pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit dbe5b447ef0d6b77a696334bee1341daaff5e875 Author: Lyor Goldstein <[email protected]> AuthorDate: Mon Feb 11 15:41:52 2019 +0200 [SSHD-893] Using Path(s) instead of String(s) as DirectoryScanner results --- CHANGES.md | 5 +++++ docs/scp.md | 8 ++++++++ .../sshd/common/util/io/DirectoryScanner.java | 22 +++++++++++----------- .../sshd/common/util/io/DirectoryScannerTest.java | 16 +++++++--------- .../org/apache/sshd/common/scp/ScpFileOpener.java | 2 +- .../java/org/apache/sshd/common/scp/ScpHelper.java | 11 ++++++----- .../java/org/apache/sshd/client/scp/ScpTest.java | 8 +++----- 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3ae98eb..0c43e89 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,9 @@ in a similar manner as the "regular" data. Please read the relevant section in t * The user can use a registered `SessionDisconnectHandler` in order be informed and also intervene in cases where the code decides to disconnect the session due to various protocol or configuration parameters violations. +* `ScpFileOpener#getMatchingFilesToSend` has been modified to accept a `Path` as the base directory +and also return an `Iterable<Path>`. + ## Behavioral changes and enhancements * [SSHD-882](https://issues.apache.org/jira/browse/SSHD-882) - Provide hooks to allow users to register a consumer @@ -17,3 +20,5 @@ for STDERR data sent via the `ChannelSession` - especially for the SFTP subsyste * [SSHD=892](https://issues.apache.org/jira/browse/SSHD-882) - Inform user about possible session disconnect prior to disconnecting and allow intervention via `SessionDisconnectHandler`. + +* [SSHD-893] Using Path(s) instead of String(s) as DirectoryScanner results diff --git a/docs/scp.md b/docs/scp.md index 05ef79e..7176e45 100644 --- a/docs/scp.md +++ b/docs/scp.md @@ -74,6 +74,14 @@ ScpClient client2 = creator.createScpClient(session, new SomeOtherOpener()); / **Note:** due to SCP protocol limitations one cannot change the **size** of the input/output since it is passed as part of the command **before** the file opener is invoked - so there are a few limitations on what one can do within this interface implementation. +In this context, note that patterns used in `ScpFileOpener#getMatchingFilesToSend` are matched using case sensitivity derived from the O/S: + +* `Windows` - case insensitive +* `Unix=true` - case sensitive + +as detected by the internal `OsUtils`. If a different behavior is required, then one needs to replace the default opener with one +that uses a different sensitivity via `DirectoryScanner#setCaseSensitive` call (or executes the pattern matching in another way). + #### ScpTransferEventListener(s) The `ScpClientCreator` can also be used to attach a default `ScpTransferEventListener` that will be attached to diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/DirectoryScanner.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/DirectoryScanner.java index c75c889..9758fac 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/io/DirectoryScanner.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/DirectoryScanner.java @@ -227,13 +227,13 @@ public class DirectoryScanner { * @return the matching files * @throws IllegalStateException if the base directory was set incorrectly * (i.e. if it is {@code null}, doesn't exist, or isn't a directory). - * @throws IOExcepion if failed to scan the directory (e.g., access denied) + * @throws IOException if failed to scan the directory (e.g., access denied) */ - public Collection<String> scan() throws IOException, IllegalStateException { + public Collection<Path> scan() throws IOException, IllegalStateException { return scan(LinkedList::new); } - public <C extends Collection<String>> C scan(Supplier<? extends C> factory) throws IOException, IllegalStateException { + public <C extends Collection<Path>> C scan(Supplier<? extends C> factory) throws IOException, IllegalStateException { Path dir = getBasedir(); if (dir == null) { throw new IllegalStateException("No basedir set"); @@ -248,7 +248,7 @@ public class DirectoryScanner { throw new IllegalStateException("No includes set for " + dir); } - return scandir(dir, "", factory.get()); + return scandir(dir, dir, factory.get()); } /** @@ -265,21 +265,21 @@ public class DirectoryScanner { * path matches * @throws IOException if failed to scan the directory */ - protected <C extends Collection<String>> C scandir(Path dir, String vpath, C filesList) throws IOException { + protected <C extends Collection<Path>> C scandir(Path rootDir, Path dir, C filesList) throws IOException { try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) { for (Path p : ds) { - Path n = p.getFileName(); - String name = vpath + n; + Path rel = rootDir.relativize(p); + String name = rel.toString(); if (Files.isDirectory(p)) { if (isIncluded(name)) { - filesList.add(name); - scandir(p, name + File.separator, filesList); + filesList.add(p); + scandir(rootDir, p, filesList); } else if (couldHoldIncluded(name)) { - scandir(p, name + File.separator, filesList); + scandir(rootDir, p, filesList); } } else if (Files.isRegularFile(p)) { if (isIncluded(name)) { - filesList.add(name); + filesList.add(p); } } } diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/io/DirectoryScannerTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/io/DirectoryScannerTest.java index 86f488b..0f7f27b 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/util/io/DirectoryScannerTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/util/io/DirectoryScannerTest.java @@ -53,23 +53,21 @@ public class DirectoryScannerTest extends JUnitTestSupport { Path rootDir = getTempTargetRelativeFile(getClass().getSimpleName(), getCurrentTestName()); CommonTestSupportUtils.deleteRecursive(rootDir); // start fresh - List<String> expected = new ArrayList<>(); + List<Path> expected = new ArrayList<>(); Path curLevel = rootDir; for (int level = 1; level <= 3; level++) { Path dir = Files.createDirectories(curLevel.resolve(Integer.toString(level))); - Path name = rootDir.relativize(dir); - expected.add(name.toString()); + expected.add(dir); Path file = dir.resolve(Integer.toString(level) + ".txt"); Files.write(file, Collections.singletonList(file.toString()), StandardCharsets.UTF_8); - name = rootDir.relativize(file); - expected.add(name.toString()); + expected.add(file); curLevel = dir; } Collections.sort(expected); DirectoryScanner ds = new DirectoryScanner(rootDir, "**/*"); - List<String> actual = ds.scan(ArrayList::new); + List<Path> actual = ds.scan(ArrayList::new); Collections.sort(actual); assertListEquals(getCurrentTestName(), expected, actual); } @@ -80,19 +78,19 @@ public class DirectoryScannerTest extends JUnitTestSupport { CommonTestSupportUtils.deleteRecursive(rootDir); // start fresh Files.createDirectories(rootDir); - List<String> expected = new ArrayList<>(); + List<Path> expected = new ArrayList<>(); for (int level = 1; level <= Byte.SIZE; level++) { Path file = rootDir.resolve(Integer.toString(level) + (((level & 0x03) == 0) ? ".csv" : ".txt")); Files.write(file, Collections.singletonList(file.toString()), StandardCharsets.UTF_8); String name = Objects.toString(file.getFileName()); if (name.endsWith(".txt")) { - expected.add(name); + expected.add(file); } } Collections.sort(expected); DirectoryScanner ds = new DirectoryScanner(rootDir, "*.txt"); - List<String> actual = ds.scan(ArrayList::new); + List<Path> actual = ds.scan(ArrayList::new); Collections.sort(actual); assertListEquals(getCurrentTestName(), expected, actual); } diff --git a/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpFileOpener.java b/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpFileOpener.java index 1d8f5cd..5f4c715 100644 --- a/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpFileOpener.java +++ b/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpFileOpener.java @@ -120,7 +120,7 @@ public interface ScpFileOpener { * @return The matching <U>relative paths</U> of the children to send * @throws IOException If failed to scan the directory */ - default Iterable<String> getMatchingFilesToSend(Session session, Path basedir, String pattern) throws IOException { + default Iterable<Path> getMatchingFilesToSend(Session session, Path basedir, String pattern) throws IOException { DirectoryScanner ds = new DirectoryScanner(basedir, pattern); return ds.scan(); } diff --git a/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpHelper.java b/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpHelper.java index fed18d5..f452ee3 100644 --- a/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpHelper.java +++ b/sshd-scp/src/main/java/org/apache/sshd/common/scp/ScpHelper.java @@ -402,25 +402,26 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess Session session = getSession(); Path basePath = resolveLocalPath(basedir); - Iterable<String> included = + Iterable<Path> included = opener.getMatchingFilesToSend(session, basePath, pattern); - for (String path : included) { - Path file = basePath.resolve(path); + for (Path file : included) { if (opener.sendAsRegularFile(session, file, options)) { sendFile(file, preserve, bufferSize); } else if (opener.sendAsDirectory(session, file, options)) { if (!recursive) { if (debugEnabled) { - log.debug("send({}) {}: not a regular file", this, path); + log.debug("send({}) {}: not a regular file", this, file); } + String path = basePath.relativize(file).toString(); sendWarning(path.replace(File.separatorChar, '/') + " not a regular file"); } else { sendDir(file, preserve, bufferSize); } } else { if (debugEnabled) { - log.debug("send({}) {}: unknown file type", this, path); + log.debug("send({}) {}: unknown file type", this, file); } + String path = basePath.relativize(file).toString(); sendWarning(path.replace(File.separatorChar, '/') + " unknown file type"); } } diff --git a/sshd-scp/src/test/java/org/apache/sshd/client/scp/ScpTest.java b/sshd-scp/src/test/java/org/apache/sshd/client/scp/ScpTest.java index 7f5955d..b6b27a9 100644 --- a/sshd-scp/src/test/java/org/apache/sshd/client/scp/ScpTest.java +++ b/sshd-scp/src/test/java/org/apache/sshd/client/scp/ScpTest.java @@ -591,9 +591,11 @@ public class ScpTest extends BaseTestSupport { @Test public void testScpVirtualOnDirWithPattern() throws Exception { - Path remoteDir = getTempTargetRelativeFile(getClass().getSimpleName(), getCurrentTestName(), ScpHelper.SCP_COMMAND_PREFIX, "virtual"); + Path remoteDir = getTempTargetRelativeFile( + getClass().getSimpleName(), getCurrentTestName(), ScpHelper.SCP_COMMAND_PREFIX, "virtual"); CommonTestSupportUtils.deleteRecursive(remoteDir); // start fresh Files.createDirectories(remoteDir); + sshd.setFileSystemFactory(new VirtualFileSystemFactory(remoteDir)); try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port) .verify(CONNECT_TIMEOUT, TimeUnit.SECONDS) @@ -601,8 +603,6 @@ public class ScpTest extends BaseTestSupport { session.addPasswordIdentity(getCurrentTestName()); session.auth().verify(AUTH_TIMEOUT, TimeUnit.SECONDS); - sshd.setFileSystemFactory(new VirtualFileSystemFactory(remoteDir)); - ScpClient scp = createScpClient(session); Path targetPath = detectTargetFolder(); Path scpRoot = CommonTestSupportUtils.resolve(targetPath, @@ -634,8 +634,6 @@ public class ScpTest extends BaseTestSupport { Files.delete(remote2); CommonTestSupportUtils.deleteRecursive(remoteDir); - } finally { - sshd.setFileSystemFactory(fileSystemFactory); // restore original } }
