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
The following commit(s) were added to refs/heads/master by this push: new a3648c7 [SSHD-1030] Added a NoneFileSystemFactory implementation a3648c7 is described below commit a3648c7e4f310f95ab7a47620aa047b4e47873ef Author: Lyor Goldstein <lgoldst...@apache.org> AuthorDate: Sun Jul 5 19:49:00 2020 +0300 [SSHD-1030] Added a NoneFileSystemFactory implementation --- CHANGES.md | 1 + docs/commands.md | 3 +- .../sshd/common/file/nonefs/NoneFileSystem.java | 102 +++++++++++++ .../common/file/nonefs/NoneFileSystemFactory.java | 51 +++++++ .../common/file/nonefs/NoneFileSystemProvider.java | 157 +++++++++++++++++++++ .../java/org/apache/sshd/common/util/OsUtils.java | 4 +- .../file/nonefs/NoneFileSystemFactoryTest.java | 51 +++++++ 7 files changed, 367 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 929dde1..6df3175 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ ## Minor code helpers * [SSHD-1040](https://issues.apache.org/jira/browse/SSHD-1040) Make server key available after KEX completed. +* [SSHD-1030](https://issues.apache.org/jira/browse/SSHD-1030) Added a NoneFileSystemFactory implementation ## Behavioral changes and enhancements diff --git a/docs/commands.md b/docs/commands.md index 2d0f6f9..50bfaf4 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -24,7 +24,8 @@ file system where the logged-in user can access only the files under the specifi The usage of a `FileSystemFactory` is not limited though to the server only - the `ScpClient` implementation also uses it in order to retrieve the *local* path for upload/download-ing files/folders. This means that the client side can also -be tailored to present different views for different clients +be tailored to present different views for different clients. A special "empty" `NoneFileSystemFactory` is provided in case +no files are expected to be accessed by the server. ## `ExecutorService`-s diff --git a/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystem.java b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystem.java new file mode 100644 index 0000000..407f7eb --- /dev/null +++ b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystem.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.file.nonefs; + +import java.io.IOException; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.WatchService; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.nio.file.spi.FileSystemProvider; +import java.util.Collections; +import java.util.Set; + +/** + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class NoneFileSystem extends FileSystem { + public static final NoneFileSystem INSTANCE = new NoneFileSystem(); + + public NoneFileSystem() { + super(); + } + + @Override + public FileSystemProvider provider() { + return NoneFileSystemProvider.INSTANCE; + } + + @Override + public void close() throws IOException { + // ignored + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public boolean isReadOnly() { + return true; + } + + @Override + public String getSeparator() { + return "/"; + } + + @Override + public Iterable<Path> getRootDirectories() { + return Collections.emptyList(); + } + + @Override + public Iterable<FileStore> getFileStores() { + return Collections.emptyList(); + } + + @Override + public Set<String> supportedFileAttributeViews() { + return Collections.emptySet(); + } + + @Override + public Path getPath(String first, String... more) { + throw new UnsupportedOperationException("No paths available"); + } + + @Override + public PathMatcher getPathMatcher(String syntaxAndPattern) { + return p -> false; + } + + @Override + public UserPrincipalLookupService getUserPrincipalLookupService() { + throw new UnsupportedOperationException("UserPrincipalLookupService N/A"); + } + + @Override + public WatchService newWatchService() throws IOException { + throw new UnsupportedOperationException("WatchService N/A"); + } +} diff --git a/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactory.java b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactory.java new file mode 100644 index 0000000..4775c43 --- /dev/null +++ b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactory.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.file.nonefs; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Path; + +import org.apache.sshd.common.file.FileSystemFactory; +import org.apache.sshd.common.session.SessionContext; + +/** + * Provides an "empty" file system that has no files/folders and throws exceptions on any attempt to access a + * file/folder on it + * + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class NoneFileSystemFactory implements FileSystemFactory { + public static final NoneFileSystemFactory INSTANCE = new NoneFileSystemFactory(); + + public NoneFileSystemFactory() { + super(); + } + + @Override + public Path getUserHomeDir(SessionContext session) throws IOException { + return null; + } + + @Override + public FileSystem createFileSystem(SessionContext session) throws IOException { + return NoneFileSystem.INSTANCE; + } +} diff --git a/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemProvider.java new file mode 100644 index 0000000..486af88 --- /dev/null +++ b/sshd-common/src/main/java/org/apache/sshd/common/file/nonefs/NoneFileSystemProvider.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.file.nonefs; + +import java.io.IOException; +import java.net.URI; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.AccessMode; +import java.nio.file.CopyOption; +import java.nio.file.DirectoryStream; +import java.nio.file.DirectoryStream.Filter; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.LinkOption; +import java.nio.file.NoSuchFileException; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.FileAttributeView; +import java.nio.file.spi.FileSystemProvider; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Provides an "empty" {@link FileSystemProvider} that has no files of any type. + * + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class NoneFileSystemProvider extends FileSystemProvider { + public static final String SCHEME = "none"; + + public static final NoneFileSystemProvider INSTANCE = new NoneFileSystemProvider(); + + public NoneFileSystemProvider() { + super(); + } + + @Override + public String getScheme() { + return SCHEME; + } + + @Override + public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException { + return getFileSystem(uri); + } + + @Override + public FileSystem getFileSystem(URI uri) { + if (!Objects.equals(getScheme(), uri.getScheme())) { + throw new IllegalArgumentException("Mismatched FS scheme"); + } + + return NoneFileSystem.INSTANCE; + } + + @Override + public Path getPath(URI uri) { + if (!Objects.equals(getScheme(), uri.getScheme())) { + throw new IllegalArgumentException("Mismatched FS scheme"); + } + + throw new UnsupportedOperationException("No paths available"); + } + + @Override + public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) + throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException { + throw new NoSuchFileException(dir.toString()); + } + + @Override + public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException { + throw new NoSuchFileException(dir.toString()); + } + + @Override + public void delete(Path path) throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public void copy(Path source, Path target, CopyOption... options) throws IOException { + throw new NoSuchFileException(source.toString(), target.toString(), "N/A"); + + } + + @Override + public void move(Path source, Path target, CopyOption... options) throws IOException { + throw new NoSuchFileException(source.toString(), target.toString(), "N/A"); + } + + @Override + public boolean isSameFile(Path path1, Path path2) throws IOException { + throw new NoSuchFileException(path1.toString(), path2.toString(), "N/A"); + } + + @Override + public boolean isHidden(Path path) throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public FileStore getFileStore(Path path) throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public void checkAccess(Path path, AccessMode... modes) throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) { + return null; + } + + @Override + public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) + throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException { + throw new NoSuchFileException(path.toString()); + } + + @Override + public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { + throw new NoSuchFileException(path.toString()); + } +} diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java index 4f98d7d..54ca86b 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java @@ -104,7 +104,7 @@ public final class OsUtils { } /** - * @return The O/S type string value (lowercase) + * @return The resolved O/S type string if not already set (lowercase) */ private static String getOS() { String typeValue; @@ -113,10 +113,12 @@ public final class OsUtils { if (typeValue != null) { // is it the 1st time return typeValue; } + String value = System.getProperty(OS_TYPE_OVERRIDE_PROP, System.getProperty("os.name")); typeValue = GenericUtils.trimToEmpty(value).toLowerCase(); OS_TYPE_HOLDER.set(typeValue); } + return typeValue; } diff --git a/sshd-common/src/test/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactoryTest.java b/sshd-common/src/test/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactoryTest.java new file mode 100644 index 0000000..854de5a --- /dev/null +++ b/sshd-common/src/test/java/org/apache/sshd/common/file/nonefs/NoneFileSystemFactoryTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.file.nonefs; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.spi.FileSystemProvider; + +import org.apache.sshd.util.test.JUnitTestSupport; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class NoneFileSystemFactoryTest extends JUnitTestSupport { + public NoneFileSystemFactoryTest() { + super(); + } + + @Test + public void testFileSystemCreation() throws IOException { + FileSystem fs = NoneFileSystemFactory.INSTANCE.createFileSystem(null); + FileSystemProvider provider = fs.provider(); + assertEquals("Mismatched provider scheme", NoneFileSystemProvider.SCHEME, provider.getScheme()); + } + + @Test + public void testUserHomeDirectory() throws IOException { + assertNull(NoneFileSystemFactory.INSTANCE.getUserHomeDir(null)); + } +}