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(')')
