Repository: mina-sshd
Updated Branches:
  refs/heads/master 76fe82188 -> 04c579408


[SSHD-816] Added mechanism for specifying non-default SftpClientFactory for 
SFTP CLI code


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

Branch: refs/heads/master
Commit: 04c57940851f2a13347ea3c96eb4217ca8c13ca1
Parents: 2b7e22a
Author: Goldstein Lyor <[email protected]>
Authored: Tue Apr 17 13:10:08 2018 +0300
Committer: Goldstein Lyor <[email protected]>
Committed: Tue Apr 17 15:32:31 2018 +0300

----------------------------------------------------------------------
 README.md                                       | 16 ++++++-
 .../apache/sshd/cli/client/SftpCommandMain.java | 49 +++++++++++++++++++-
 .../sshd/cli/server/SshServerCliSupport.java    |  2 +-
 3 files changed, 63 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/04c57940/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index bb4f586..4878117 100644
--- a/README.md
+++ b/README.md
@@ -1293,6 +1293,18 @@ In order to use this CLI code as part of another 
project, one needs to include t
     </dependency>
 ```
 
+### Command line clients
+
+* **SftpCommandMain** - by default uses an internal `SftpClientFactory`. This 
can be overridden as follows:
+
+1. Provide a `-o SftpClientFactory=XXX` command line argument where the option 
specifies the fully-qualified name of
+the class that implements this interface.
+
+2. Add a 
`META-INF\services\org.apache.sshd.client.subsystem.sftp.SftpClientFactory` 
file containing the fully-qualified name of
+the class that implements this interface. **Note:** if more than one such 
instance is detected an exception is thrown.
+
+**Note:** The specified class(es) must be public and contain a public no-args 
constructor.
+
 ### Command line SSH daemon
 
 * **Port** - by default the SSH server sets up to list on port 8000 in order 
to avoid conflicts with any running SSH O/S daemon. This can be modified by 
providing a `-p NNNN`
@@ -1302,8 +1314,8 @@ or `-o Port=NNNN` command line option.
 This can be overwritten as follows (in this order):
 
 1. Provide a `org.apache.sshd.server.subsystem.SubsystemFactory` system 
property containing comma-separated fully-qualified names of classes 
implementing
-this interface. The implementations must have a public no-args constructor for 
instantiating them. The order of the provided subsystems will be according
-to their order in the specified list
+this interface. The implementations must be public and have a public no-args 
constructor for instantiating them. The order of the provided subsystems will
+be according to their order in the specified list.
 
 2. Provide a `-o Subsystem=xxx,yyy` command line argument where value is a 
comma-separated list of the **name**(s) of the auto-detected factories via
 the `ServiceLoader` mechanism. The special value `none` may be used to 
indicate that no subsystem is to be configured. **Note:** no specific order is

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/04c57940/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 1d982f2..09b440d 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
@@ -37,6 +37,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.TreeMap;
 import java.util.logging.Level;
 
@@ -61,6 +62,7 @@ import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
  * TODO Add javadoc
@@ -240,6 +242,51 @@ public class SftpCommandMain extends SshClientCliSupport 
implements Channel {
         return sb;
     }
 
+    public static SftpClientFactory resolveSftpClientFactory(String... args) {
+        int numArgs = GenericUtils.length(args);
+        ClassLoader cl = 
ThreadUtils.resolveDefaultClassLoader(SftpClientFactory.class);
+        for (int index = 0; index < numArgs; index++) {
+            String argVal = args[index];
+            if ("-o".equals(argVal)) {
+                index++;
+
+                String opt = args[index];
+                int idx = opt.indexOf('=');
+                ValidateUtils.checkTrue(idx > 0, "bad syntax for option: %s 
%s", argVal, opt);
+
+                String optName = opt.substring(0, idx);
+                String optValue = opt.substring(idx + 1);
+                if (!Objects.equals(SftpClientFactory.class.getSimpleName(), 
optName)) {
+                    continue;
+                }
+
+                try {
+                    Class<?> clazz = cl.loadClass(optValue);
+                    return SftpClientFactory.class.cast(clazz.newInstance());
+                } catch (Throwable t) {
+                    System.err.append("Failed 
(").append(t.getClass().getSimpleName()).append(')')
+                        .append(" to instantiate ").append(optValue)
+                        .append(": ").println(t.getMessage());
+                    System.err.flush();
+                    throw GenericUtils.toRuntimeException(t, true);
+                }
+            }
+        }
+
+        ServiceLoader<SftpClientFactory> loader = 
ServiceLoader.load(SftpClientFactory.class, cl);
+        SftpClientFactory factory = null;
+        for (SftpClientFactory f : loader) {
+            ValidateUtils.checkState(factory == null, "Multiple factories 
detected - select one");
+            factory = f;
+        }
+
+        if (factory != null) {
+            return factory;
+        }
+
+        return SftpClientFactory.instance();
+    }
+
     public static void main(String[] args) throws Exception {
         PrintStream stdout = System.out;
         PrintStream stderr = System.err;
@@ -262,7 +309,7 @@ public class SftpCommandMain extends SshClientCliSupport 
implements Channel {
 
             try {
                 // TODO allow command-line specification of SftpClientFactory
-                SftpClientFactory clientFactory = SftpClientFactory.instance();
+                SftpClientFactory clientFactory = 
resolveSftpClientFactory(args);
                 try (SftpClient sftpClient = 
clientFactory.createSftpClient(session);
                      SftpCommandMain sftp = new SftpCommandMain(sftpClient)) {
                     // TODO allow injection of extra CommandExecutor(s) via 
command line and/or service loading

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/04c57940/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
----------------------------------------------------------------------
diff --git 
a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java 
b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
index 903128a..585f4a9 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
@@ -144,7 +144,7 @@ public abstract class SshServerCliSupport extends 
CliSupport {
             for (String fqcn : classes) {
                 try {
                     Class<?> clazz = cl.loadClass(fqcn);
-                    SubsystemFactory factory = (SubsystemFactory) 
clazz.newInstance();
+                    SubsystemFactory factory = 
SubsystemFactory.class.cast(clazz.newInstance());
                     subsystems.add(factory);
                 } catch (Throwable t) {
                     System.err.append("Failed 
(").append(t.getClass().getSimpleName()).append(')')

Reply via email to