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);
- }
-}