You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/11/11 16:50:55 UTC

[7/8] mina-sshd git commit: [SSHD-861] Added SftpFileSystemClientSessionInitializer hook in SftpFileSystemProvider

[SSHD-861] Added SftpFileSystemClientSessionInitializer hook in SftpFileSystemProvider


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/e3b8acd7
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/e3b8acd7
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/e3b8acd7

Branch: refs/heads/master
Commit: e3b8acd7e068fdc586f1f825eb675a335eb42824
Parents: c24635d
Author: Lyor Goldstein <lg...@apache.org>
Authored: Sun Nov 11 10:43:16 2018 +0200
Committer: Lyor Goldstein <lg...@apache.org>
Committed: Sun Nov 11 18:56:28 2018 +0200

----------------------------------------------------------------------
 CHANGES.md                                      |    4 +
 README.md                                       |   34 +-
 .../apache/sshd/cli/client/SftpCommandMain.java |    2 +-
 .../java.nio.file.spi.FileSystemProvider        |    2 +-
 .../sftp/SftpAclFileAttributeView.java          |   67 -
 .../subsystem/sftp/SftpClientFactory.java       |   16 +-
 .../subsystem/sftp/SftpDirectoryStream.java     |   65 -
 .../client/subsystem/sftp/SftpFileStore.java    |  105 --
 .../client/subsystem/sftp/SftpFileSystem.java   |  600 --------
 .../subsystem/sftp/SftpFileSystemChannel.java   |   37 -
 .../subsystem/sftp/SftpFileSystemProvider.java  | 1312 -----------------
 .../sshd/client/subsystem/sftp/SftpPath.java    |   43 -
 .../client/subsystem/sftp/SftpPathIterator.java |   82 --
 .../sftp/SftpPosixFileAttributeView.java        |   94 --
 .../subsystem/sftp/SftpPosixFileAttributes.java |  113 --
 .../sftp/fs/SftpAclFileAttributeView.java       |   68 +
 .../subsystem/sftp/fs/SftpDirectoryStream.java  |   67 +
 .../client/subsystem/sftp/fs/SftpFileStore.java |  105 ++
 .../subsystem/sftp/fs/SftpFileSystem.java       |  604 ++++++++
 .../sftp/fs/SftpFileSystemChannel.java          |   40 +
 .../SftpFileSystemClientSessionInitializer.java |   97 ++
 .../fs/SftpFileSystemInitializationContext.java |  142 ++
 .../sftp/fs/SftpFileSystemProvider.java         | 1340 ++++++++++++++++++
 .../sshd/client/subsystem/sftp/fs/SftpPath.java |   43 +
 .../subsystem/sftp/fs/SftpPathIterator.java     |   84 ++
 .../sftp/fs/SftpPosixFileAttributeView.java     |   95 ++
 .../sftp/fs/SftpPosixFileAttributes.java        |  113 ++
 .../impl/AbstractSftpFileAttributeView.java     |    6 +-
 .../sftp/impl/DefaultSftpClientFactory.java     |    4 +-
 .../subsystem/sftp/SftpFileSystemTest.java      |  497 -------
 .../subsystem/sftp/SftpFileSystemURITest.java   |  121 --
 .../subsystem/sftp/fs/SftpFileSystemTest.java   |  532 +++++++
 .../sftp/fs/SftpFileSystemURITest.java          |  121 ++
 33 files changed, 3503 insertions(+), 3152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index f909f44..2a338cc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -27,6 +27,10 @@ user to try and repeat an encrypted private key decoding using a different passw
 
 * `SshAgent#getIdentities` returns an `Iterable` rather than a `List`
 
+* `SftpFileSystemProvider` and its associated helper classes have been moved to
+`org.apache.sshd.client.subsystem.sftp.fs` package
+
+* Added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider`
 
 ## Behavioral changes
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index c5edc53..f8bfa56 100644
--- a/README.md
+++ b/README.md
@@ -957,9 +957,16 @@ system.
 It is highly recommended to `close()` the mounted file system once no longer necessary in order to release the
 associated SFTP session sooner rather than later - e.g., via a `try-with-resource` code block.
 
+**Caveat:** Due to URI encoding of the username/password as a basic authentication, the system currently
+does not allow colon (`:`) in either one in order to avoid parsing confusion. See [RFC 3986 - section 3.2.1](https://tools.ietf.org/html/rfc3986#section-3.2.1):
+
+>> Use of the format "user:password" in the userinfo field is
+>> deprecated ... Applications may choose to ignore or reject such
+>> data when it is received as part of a reference...
+
 #### Configuring the `SftpFileSystemProvider`
 
-When "mounting" a new file system one can provide configuration parameters using either the
+When "mounting" a new file system one can provide extra configuration parameters using either the
 environment map in the [FileSystems#newFileSystem](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystems.html#newFileSystem)
 method or via the URI query parameters. See the `SftpFileSystemProvider` for the available
 configuration keys and values.
@@ -1005,6 +1012,31 @@ configuration keys and values.
 
 ```
 
+#### Configuring the client session used to create an `SftpFileSystem`
+
+It is possible to register a `SftpFileSystemClientSessionInitializer` with the provider instead of the default one
+and thus better control the `ClientSession` used to generate the file-system instance. The default implementation
+simply connects and authenticates before creating a default `SftpFileSystem` instance. Users may wish
+to override some options or provide their own - e.g., execute a password-less authentication instead of
+the (default) password-based one:
+
+```java
+
+    SftpFileSystemProvider provider = ... obtain/create a provider ...
+    provider.setSftpFileSystemClientSessionInitializer(new SftpFileSystemClientSessionInitializer() {
+        @Override
+        public void authenticateClientSession(
+                SftpFileSystemProvider provider, SftpFileSystemInitializationContext context, ClientSession session)
+                    throws IOException {
+            // Set up password-less login instead of password-based
+            KeyPair kp = ... obtain a registered key-pair...
+            session.addPublicKeyIdentity(kp);
+            return sesssion.auth().verify(context.getMaxAuthTime());
+        }
+    });
+
+```
+
 #### Tracking accessed location via `SftpFileSystemAccessor`
 
 One can override the default `SftpFileSystemAccessor` and thus be able to track all opened files and folders

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java
index e730448..99427ff 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java
@@ -47,9 +47,9 @@ import org.apache.sshd.client.subsystem.sftp.SftpClient;
 import org.apache.sshd.client.subsystem.sftp.SftpClient.Attributes;
 import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry;
 import org.apache.sshd.client.subsystem.sftp.SftpClientFactory;
-import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
 import org.apache.sshd.client.subsystem.sftp.extensions.openssh.OpenSSHStatExtensionInfo;
 import org.apache.sshd.client.subsystem.sftp.extensions.openssh.OpenSSHStatPathExtension;
+import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystemProvider;
 import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.channel.ChannelFactory;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/filtered-resources/META-INF/services/java.nio.file.spi.FileSystemProvider
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/filtered-resources/META-INF/services/java.nio.file.spi.FileSystemProvider b/sshd-sftp/src/main/filtered-resources/META-INF/services/java.nio.file.spi.FileSystemProvider
index 75fea68..6d92ee2 100644
--- a/sshd-sftp/src/main/filtered-resources/META-INF/services/java.nio.file.spi.FileSystemProvider
+++ b/sshd-sftp/src/main/filtered-resources/META-INF/services/java.nio.file.spi.FileSystemProvider
@@ -17,4 +17,4 @@
 ## under the License.
 ##
 
-org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider
+org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystemProvider

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpAclFileAttributeView.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpAclFileAttributeView.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpAclFileAttributeView.java
deleted file mode 100644
index 7cada6e..0000000
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpAclFileAttributeView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.client.subsystem.sftp;
-
-import java.io.IOException;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.nio.file.attribute.AclEntry;
-import java.nio.file.attribute.AclFileAttributeView;
-import java.nio.file.attribute.PosixFileAttributes;
-import java.nio.file.attribute.UserPrincipal;
-import java.util.List;
-
-import org.apache.sshd.client.subsystem.sftp.impl.AbstractSftpFileAttributeView;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SftpAclFileAttributeView extends AbstractSftpFileAttributeView implements AclFileAttributeView {
-    public SftpAclFileAttributeView(SftpFileSystemProvider provider, Path path, LinkOption... options) {
-        super(provider, path, options);
-    }
-
-    @Override
-    public UserPrincipal getOwner() throws IOException {
-        PosixFileAttributes v = provider.readAttributes(path, PosixFileAttributes.class, options);
-        return v.owner();
-    }
-
-    @Override
-    public void setOwner(UserPrincipal owner) throws IOException {
-        provider.setAttribute(path, "posix", "owner", owner, options);
-    }
-
-    @Override
-    public String name() {
-        return "acl";
-    }
-
-    @Override
-    public List<AclEntry> getAcl() throws IOException {
-        return readRemoteAttributes().getAcl();
-    }
-
-    @Override
-    public void setAcl(List<AclEntry> acl) throws IOException {
-        writeRemoteAttributes(new SftpClient.Attributes().acl(acl));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClientFactory.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClientFactory.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClientFactory.java
index 5497c91..0672482 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClientFactory.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClientFactory.java
@@ -19,9 +19,9 @@
 package org.apache.sshd.client.subsystem.sftp;
 
 import java.io.IOException;
-import java.nio.file.FileSystem;
 
 import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystem;
 import org.apache.sshd.client.subsystem.sftp.impl.DefaultSftpClientFactory;
 
 /**
@@ -67,23 +67,23 @@ public interface SftpClientFactory {
      */
     SftpClient createSftpClient(ClientSession session, SftpVersionSelector selector) throws IOException;
 
-    default FileSystem createSftpFileSystem(ClientSession session) throws IOException {
+    default SftpFileSystem createSftpFileSystem(ClientSession session) throws IOException {
         return createSftpFileSystem(session, SftpVersionSelector.CURRENT);
     }
 
-    default FileSystem createSftpFileSystem(ClientSession session, int version) throws IOException {
+    default SftpFileSystem createSftpFileSystem(ClientSession session, int version) throws IOException {
         return createSftpFileSystem(session, SftpVersionSelector.fixedVersionSelector(version));
     }
 
-    default FileSystem createSftpFileSystem(ClientSession session, SftpVersionSelector selector) throws IOException {
+    default SftpFileSystem createSftpFileSystem(ClientSession session, SftpVersionSelector selector) throws IOException {
         return createSftpFileSystem(session, selector, SftpClient.DEFAULT_READ_BUFFER_SIZE, SftpClient.DEFAULT_WRITE_BUFFER_SIZE);
     }
 
-    default FileSystem createSftpFileSystem(ClientSession session, int version, int readBufferSize, int writeBufferSize) throws IOException {
+    default SftpFileSystem createSftpFileSystem(ClientSession session, int version, int readBufferSize, int writeBufferSize) throws IOException {
         return createSftpFileSystem(session, SftpVersionSelector.fixedVersionSelector(version), readBufferSize, writeBufferSize);
     }
 
-    default FileSystem createSftpFileSystem(ClientSession session, int readBufferSize, int writeBufferSize) throws IOException {
+    default SftpFileSystem createSftpFileSystem(ClientSession session, int readBufferSize, int writeBufferSize) throws IOException {
         return createSftpFileSystem(session, SftpVersionSelector.CURRENT, readBufferSize, writeBufferSize);
     }
 
@@ -92,10 +92,10 @@ public interface SftpClientFactory {
      * @param selector The {@link SftpVersionSelector} to use in order to negotiate the SFTP version
      * @param readBufferSize Default I/O read buffer size
      * @param writeBufferSize Default I/O write buffer size
-     * @return The created {@link FileSystem} instance
+     * @return The created {@link SftpFileSystem} instance
      * @throws IOException If failed to create the instance
      */
-    FileSystem createSftpFileSystem(
+    SftpFileSystem createSftpFileSystem(
         ClientSession session, SftpVersionSelector selector, int readBufferSize, int writeBufferSize)
             throws IOException;
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
deleted file mode 100644
index 5f48966..0000000
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpDirectoryStream.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.client.subsystem.sftp;
-
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Path;
-import java.util.Iterator;
-
-/**
- * Implements a remote {@link DirectoryStream}
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SftpDirectoryStream implements DirectoryStream<Path> {
-    private final SftpClient sftp;
-    private final Iterable<SftpClient.DirEntry> iter;
-    private final SftpPath p;
-
-    /**
-     * @param path The remote {@link SftpPath}
-     * @throws IOException If failed to initialize the directory access handle
-     */
-    public SftpDirectoryStream(SftpPath path) throws IOException {
-        SftpFileSystem fs = path.getFileSystem();
-        p = path;
-        sftp = fs.getClient();
-        iter = sftp.readDir(path.toString());
-    }
-
-    /**
-     * Client instance used to access the remote directory
-     *
-     * @return The {@link SftpClient} instance used to access the remote directory
-     */
-    public final SftpClient getClient() {
-        return sftp;
-    }
-
-    @Override
-    public Iterator<Path> iterator() {
-        return new SftpPathIterator(p, iter);
-    }
-
-    @Override
-    public void close() throws IOException {
-        sftp.close();
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileStore.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileStore.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileStore.java
deleted file mode 100644
index 8a6f1f1..0000000
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileStore.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.client.subsystem.sftp;
-
-import java.io.IOException;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystem;
-import java.nio.file.attribute.FileAttributeView;
-import java.nio.file.attribute.FileStoreAttributeView;
-import java.util.Collection;
-
-import org.apache.sshd.common.subsystem.sftp.SftpConstants;
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SftpFileStore extends FileStore {
-    private final SftpFileSystem fs;
-    private final String name;
-
-    public SftpFileStore(String name, SftpFileSystem fs) {
-        this.name = name;
-        this.fs = fs;
-    }
-
-    public final SftpFileSystem getFileSystem() {
-        return fs;
-    }
-
-    @Override
-    public String name() {
-        return name;
-    }
-
-    @Override
-    public String type() {
-        return SftpConstants.SFTP_SUBSYSTEM_NAME;
-    }
-
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    @Override
-    public long getTotalSpace() throws IOException {
-        return Long.MAX_VALUE;  // TODO use SFTPv6 space-available extension
-    }
-
-    @Override
-    public long getUsableSpace() throws IOException {
-        return Long.MAX_VALUE;
-    }
-
-    @Override
-    public long getUnallocatedSpace() throws IOException {
-        return Long.MAX_VALUE;
-    }
-
-    @Override
-    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
-        SftpFileSystem sftpFs = getFileSystem();
-        SftpFileSystemProvider provider = sftpFs.provider();
-        return provider.isSupportedFileAttributeView(sftpFs, type);
-    }
-
-    @Override
-    public boolean supportsFileAttributeView(String name) {
-        if (GenericUtils.isEmpty(name)) {
-            return false;   // debug breakpoint
-        }
-
-        FileSystem sftpFs = getFileSystem();
-        Collection<String> views = sftpFs.supportedFileAttributeViews();
-        return !GenericUtils.isEmpty(views) && views.contains(name);
-    }
-
-    @Override
-    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
-        return null;    // no special views supported
-    }
-
-    @Override
-    public Object getAttribute(String attribute) throws IOException {
-        return null;    // no special attributes supported
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
deleted file mode 100644
index ed16a26..0000000
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * 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.client.subsystem.sftp;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.StreamCorruptedException;
-import java.nio.charset.Charset;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystemException;
-import java.nio.file.attribute.GroupPrincipal;
-import java.nio.file.attribute.UserPrincipal;
-import java.nio.file.attribute.UserPrincipalLookupService;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.Objects;
-import java.util.Queue;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.sshd.client.channel.ClientChannel;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.session.ClientSessionHolder;
-import org.apache.sshd.client.subsystem.sftp.impl.AbstractSftpClient;
-import org.apache.sshd.common.file.util.BaseFileSystem;
-import org.apache.sshd.common.subsystem.sftp.SftpConstants;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.buffer.Buffer;
-
-public class SftpFileSystem extends BaseFileSystem<SftpPath> implements ClientSessionHolder {
-    public static final String POOL_SIZE_PROP = "sftp-fs-pool-size";
-    public static final int DEFAULT_POOL_SIZE = 8;
-
-    public static final NavigableSet<String> UNIVERSAL_SUPPORTED_VIEWS =
-        Collections.unmodifiableNavigableSet(
-            GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER, "basic", "posix", "owner"));
-
-    private final String id;
-    private final ClientSession clientSession;
-    private final SftpClientFactory factory;
-    private final SftpVersionSelector selector;
-    private final Queue<SftpClient> pool;
-    private final ThreadLocal<Wrapper> wrappers = new ThreadLocal<>();
-    private final int version;
-    private final Set<String> supportedViews;
-    private SftpPath defaultDir;
-    private int readBufferSize = SftpClient.DEFAULT_READ_BUFFER_SIZE;
-    private int writeBufferSize = SftpClient.DEFAULT_WRITE_BUFFER_SIZE;
-    private final List<FileStore> stores;
-
-    public SftpFileSystem(
-            SftpFileSystemProvider provider, String id, ClientSession session,
-            SftpClientFactory factory, SftpVersionSelector selector)
-                throws IOException {
-        super(provider);
-        this.id = id;
-        this.clientSession = Objects.requireNonNull(session, "No client session");
-        this.factory = factory != null ? factory : SftpClientFactory.instance();
-        this.selector = selector;
-        this.stores = Collections.unmodifiableList(Collections.<FileStore>singletonList(new SftpFileStore(id, this)));
-        this.pool = new LinkedBlockingQueue<>(session.getIntProperty(POOL_SIZE_PROP, DEFAULT_POOL_SIZE));
-        try (SftpClient client = getClient()) {
-            version = client.getVersion();
-            defaultDir = getPath(client.canonicalPath("."));
-        }
-
-        if (version >= SftpConstants.SFTP_V4) {
-            Set<String> views = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-            views.addAll(UNIVERSAL_SUPPORTED_VIEWS);
-            views.add("acl");
-            supportedViews = Collections.unmodifiableSet(views);
-        } else {
-            supportedViews = UNIVERSAL_SUPPORTED_VIEWS;
-        }
-    }
-
-    public final SftpVersionSelector getSftpVersionSelector() {
-        return selector;
-    }
-
-    public final String getId() {
-        return id;
-    }
-
-    public final int getVersion() {
-        return version;
-    }
-
-    @Override
-    public SftpFileSystemProvider provider() {
-        return (SftpFileSystemProvider) super.provider();
-    }
-
-    @Override   // NOTE: co-variant return
-    public List<FileStore> getFileStores() {
-        return this.stores;
-    }
-
-    public int getReadBufferSize() {
-        return readBufferSize;
-    }
-
-    public void setReadBufferSize(int size) {
-        if (size < SftpClient.MIN_READ_BUFFER_SIZE) {
-            throw new IllegalArgumentException("Insufficient read buffer size: " + size + ", min.=" + SftpClient.MIN_READ_BUFFER_SIZE);
-        }
-
-        readBufferSize = size;
-    }
-
-    public int getWriteBufferSize() {
-        return writeBufferSize;
-    }
-
-    public void setWriteBufferSize(int size) {
-        if (size < SftpClient.MIN_WRITE_BUFFER_SIZE) {
-            throw new IllegalArgumentException("Insufficient write buffer size: " + size + ", min.=" + SftpClient.MIN_WRITE_BUFFER_SIZE);
-        }
-
-        writeBufferSize = size;
-    }
-
-    @Override
-    protected SftpPath create(String root, List<String> names) {
-        return new SftpPath(this, root, names);
-    }
-
-    @Override
-    public ClientSession getClientSession() {
-        return clientSession;
-    }
-
-    @SuppressWarnings("synthetic-access")
-    public SftpClient getClient() throws IOException {
-        Wrapper wrapper = wrappers.get();
-        if (wrapper == null) {
-            while (wrapper == null) {
-                SftpClient client = pool.poll();
-                if (client == null) {
-                    ClientSession session = getClientSession();
-                    client = factory.createSftpClient(session, getSftpVersionSelector());
-                }
-                if (!client.isClosing()) {
-                    wrapper = new Wrapper(client, getReadBufferSize(), getWriteBufferSize());
-                }
-            }
-            wrappers.set(wrapper);
-        } else {
-            wrapper.increment();
-        }
-        return wrapper;
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (isOpen()) {
-            SftpFileSystemProvider provider = provider();
-            String fsId = getId();
-            SftpFileSystem fs = provider.removeFileSystem(fsId);
-            ClientSession session = getClientSession();
-            session.close(true);
-
-            if ((fs != null) && (fs != this)) {
-                throw new FileSystemException(fsId, fsId, "Mismatched FS instance for id=" + fsId);
-            }
-        }
-    }
-
-    @Override
-    public boolean isOpen() {
-        ClientSession session = getClientSession();
-        return session.isOpen();
-    }
-
-    @Override
-    public Set<String> supportedFileAttributeViews() {
-        return supportedViews;
-    }
-
-    @Override
-    public UserPrincipalLookupService getUserPrincipalLookupService() {
-        return DefaultUserPrincipalLookupService.INSTANCE;
-    }
-
-    @Override
-    public SftpPath getDefaultDir() {
-        return defaultDir;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + getClientSession() + "]";
-    }
-
-    private final class Wrapper extends AbstractSftpClient {
-        private final SftpClient delegate;
-        private final AtomicInteger count = new AtomicInteger(1);
-        private final int readSize;
-        private final int writeSize;
-
-        private Wrapper(SftpClient delegate, int readSize, int writeSize) {
-            this.delegate = delegate;
-            this.readSize = readSize;
-            this.writeSize = writeSize;
-        }
-
-        @Override
-        public int getVersion() {
-            return delegate.getVersion();
-        }
-
-        @Override
-        public ClientSession getClientSession() {
-            return delegate.getClientSession();
-        }
-
-        @Override
-        public ClientChannel getClientChannel() {
-            return delegate.getClientChannel();
-        }
-
-        @Override
-        public NavigableMap<String, byte[]> getServerExtensions() {
-            return delegate.getServerExtensions();
-        }
-
-        @Override
-        public Charset getNameDecodingCharset() {
-            return delegate.getNameDecodingCharset();
-        }
-
-        @Override
-        public void setNameDecodingCharset(Charset cs) {
-            delegate.setNameDecodingCharset(cs);
-        }
-
-        @Override
-        public boolean isClosing() {
-            return false;
-        }
-
-        @Override
-        public boolean isOpen() {
-            return count.get() > 0;
-        }
-
-        @SuppressWarnings("synthetic-access")
-        @Override
-        public void close() throws IOException {
-            if (count.decrementAndGet() <= 0) {
-                if (!pool.offer(delegate)) {
-                    delegate.close();
-                }
-                wrappers.set(null);
-            }
-        }
-
-        public void increment() {
-            count.incrementAndGet();
-        }
-
-        @Override
-        public CloseableHandle open(String path, Collection<OpenMode> options) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("open(" + path + ")[" + options + "] client is closed");
-            }
-            return delegate.open(path, options);
-        }
-
-        @Override
-        public void close(Handle handle) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("close(" + handle + ") client is closed");
-            }
-            delegate.close(handle);
-        }
-
-        @Override
-        public void remove(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("remove(" + path + ") client is closed");
-            }
-            delegate.remove(path);
-        }
-
-        @Override
-        public void rename(String oldPath, String newPath, Collection<CopyMode> options) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("rename(" + oldPath + " => " + newPath + ")[" + options + "] client is closed");
-            }
-            delegate.rename(oldPath, newPath, options);
-        }
-
-        @Override
-        public int read(Handle handle, long fileOffset, byte[] dst, int dstOffset, int len) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("read(" + handle + "/" + fileOffset + ")[" + dstOffset + "/" + len + "] client is closed");
-            }
-            return delegate.read(handle, fileOffset, dst, dstOffset, len);
-        }
-
-        @Override
-        public void write(Handle handle, long fileOffset, byte[] src, int srcOffset, int len) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("write(" + handle + "/" + fileOffset + ")[" + srcOffset + "/" + len + "] client is closed");
-            }
-            delegate.write(handle, fileOffset, src, srcOffset, len);
-        }
-
-        @Override
-        public void mkdir(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("mkdir(" + path + ") client is closed");
-            }
-            delegate.mkdir(path);
-        }
-
-        @Override
-        public void rmdir(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("rmdir(" + path + ") client is closed");
-            }
-            delegate.rmdir(path);
-        }
-
-        @Override
-        public CloseableHandle openDir(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("openDir(" + path + ") client is closed");
-            }
-            return delegate.openDir(path);
-        }
-
-        @Override
-        public List<DirEntry> readDir(Handle handle) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("readDir(" + handle + ") client is closed");
-            }
-            return delegate.readDir(handle);
-        }
-
-        @Override
-        public Iterable<DirEntry> listDir(Handle handle) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("readDir(" + handle + ") client is closed");
-            }
-            return delegate.listDir(handle);
-        }
-
-        @Override
-        public String canonicalPath(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("canonicalPath(" + path + ") client is closed");
-            }
-            return delegate.canonicalPath(path);
-        }
-
-        @Override
-        public Attributes stat(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("stat(" + path + ") client is closed");
-            }
-            return delegate.stat(path);
-        }
-
-        @Override
-        public Attributes lstat(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("lstat(" + path + ") client is closed");
-            }
-            return delegate.lstat(path);
-        }
-
-        @Override
-        public Attributes stat(Handle handle) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("stat(" + handle + ") client is closed");
-            }
-            return delegate.stat(handle);
-        }
-
-        @Override
-        public void setStat(String path, Attributes attributes) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("setStat(" + path + ")[" + attributes + "] client is closed");
-            }
-            delegate.setStat(path, attributes);
-        }
-
-        @Override
-        public void setStat(Handle handle, Attributes attributes) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("setStat(" + handle + ")[" + attributes + "] client is closed");
-            }
-            delegate.setStat(handle, attributes);
-        }
-
-        @Override
-        public String readLink(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("readLink(" + path + ") client is closed");
-            }
-            return delegate.readLink(path);
-        }
-
-        @Override
-        public void symLink(String linkPath, String targetPath) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("symLink(" + linkPath + " => " + targetPath + ") client is closed");
-            }
-            delegate.symLink(linkPath, targetPath);
-        }
-
-        @Override
-        public Iterable<DirEntry> readDir(String path) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("readDir(" + path + ") client is closed");
-            }
-            return delegate.readDir(path);
-        }
-
-        @Override
-        public InputStream read(String path) throws IOException {
-            return read(path, readSize);
-        }
-
-        @Override
-        public InputStream read(String path, OpenMode... mode) throws IOException {
-            return read(path, readSize, mode);
-        }
-
-        @Override
-        public InputStream read(String path, Collection<OpenMode> mode) throws IOException {
-            return read(path, readSize, mode);
-        }
-
-        @Override
-        public InputStream read(String path, int bufferSize, Collection<OpenMode> mode) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("read(" + path + ")[" + mode + "] size=" + bufferSize + ": client is closed");
-            }
-            return delegate.read(path, bufferSize, mode);
-        }
-
-        @Override
-        public OutputStream write(String path) throws IOException {
-            return write(path, writeSize);
-        }
-
-        @Override
-        public OutputStream write(String path, OpenMode... mode) throws IOException {
-            return write(path, writeSize, mode);
-        }
-
-        @Override
-        public OutputStream write(String path, Collection<OpenMode> mode) throws IOException {
-            return write(path, writeSize, mode);
-        }
-
-        @Override
-        public OutputStream write(String path, int bufferSize, Collection<OpenMode> mode) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("write(" + path + ")[" + mode + "] size=" + bufferSize + ": client is closed");
-            }
-            return delegate.write(path, bufferSize, mode);
-        }
-
-        @Override
-        public void link(String linkPath, String targetPath, boolean symbolic) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("link(" + linkPath + " => " + targetPath + "] symbolic=" + symbolic + ": client is closed");
-            }
-            delegate.link(linkPath, targetPath, symbolic);
-        }
-
-        @Override
-        public void lock(Handle handle, long offset, long length, int mask) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("lock(" + handle + ")[offset=" + offset + ", length=" + length + ", mask=0x" + Integer.toHexString(mask) + "] client is closed");
-            }
-            delegate.lock(handle, offset, length, mask);
-        }
-
-        @Override
-        public void unlock(Handle handle, long offset, long length) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("unlock" + handle + ")[offset=" + offset + ", length=" + length + "] client is closed");
-            }
-            delegate.unlock(handle, offset, length);
-        }
-
-        @Override
-        public int send(int cmd, Buffer buffer) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("send(cmd=" + SftpConstants.getCommandMessageName(cmd) + ") client is closed");
-            }
-
-            if (delegate instanceof RawSftpClient) {
-                return ((RawSftpClient) delegate).send(cmd, buffer);
-            } else {
-                throw new StreamCorruptedException("send(cmd=" + SftpConstants.getCommandMessageName(cmd) + ") delegate is not a " + RawSftpClient.class.getSimpleName());
-            }
-        }
-
-        @Override
-        public Buffer receive(int id) throws IOException {
-            if (!isOpen()) {
-                throw new IOException("receive(id=" + id + ") client is closed");
-            }
-
-            if (delegate instanceof RawSftpClient) {
-                return ((RawSftpClient) delegate).receive(id);
-            } else {
-                throw new StreamCorruptedException("receive(id=" + id + ") delegate is not a " + RawSftpClient.class.getSimpleName());
-            }
-        }
-    }
-
-    public static class DefaultUserPrincipalLookupService extends UserPrincipalLookupService {
-        public static final DefaultUserPrincipalLookupService INSTANCE = new DefaultUserPrincipalLookupService();
-
-        public DefaultUserPrincipalLookupService() {
-            super();
-        }
-
-        @Override
-        public UserPrincipal lookupPrincipalByName(String name) throws IOException {
-            return new DefaultUserPrincipal(name);
-        }
-
-        @Override
-        public GroupPrincipal lookupPrincipalByGroupName(String group) throws IOException {
-            return new DefaultGroupPrincipal(group);
-        }
-    }
-
-    public static class DefaultUserPrincipal implements UserPrincipal {
-
-        private final String name;
-
-        public DefaultUserPrincipal(String name) {
-            this.name = Objects.requireNonNull(name, "name is null");
-        }
-
-        @Override
-        public final String getName() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            DefaultUserPrincipal that = (DefaultUserPrincipal) o;
-            return Objects.equals(this.getName(), that.getName());
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(getName());
-        }
-
-        @Override
-        public String toString() {
-            return getName();
-        }
-    }
-
-    public static class DefaultGroupPrincipal extends DefaultUserPrincipal implements GroupPrincipal {
-        public DefaultGroupPrincipal(String name) {
-            super(name);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3b8acd7/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemChannel.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemChannel.java b/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemChannel.java
deleted file mode 100644
index 40948bf..0000000
--- a/sshd-sftp/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemChannel.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.client.subsystem.sftp;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Objects;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class SftpFileSystemChannel extends SftpRemotePathChannel {
-    public SftpFileSystemChannel(SftpPath p, Collection<SftpClient.OpenMode> modes) throws IOException {
-        this(Objects.requireNonNull(p, "No target path").toString(), p.getFileSystem(), modes);
-    }
-
-    public SftpFileSystemChannel(String remotePath, SftpFileSystem fs, Collection<SftpClient.OpenMode> modes) throws IOException {
-        super(remotePath, Objects.requireNonNull(fs, "No SFTP file system").getClient(), true, modes);
-    }
-}