Simplify SFTP usage.
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 8 Sep 2019 16:43:53 +0000 (18:43 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 8 Sep 2019 16:43:53 +0000 (18:43 +0200)
org.argeo.core/src/org/argeo/ssh/AbstractSsh.java
org.argeo.core/src/org/argeo/ssh/BasicSshServer.java [new file with mode: 0644]
org.argeo.core/src/org/argeo/ssh/Sftp.java
org.argeo.core/src/org/argeo/ssh/SimpleSshServer.java [deleted file]
org.argeo.core/src/org/argeo/ssh/Ssh.java

index 588c16b01bd426a8a08e20aca5d051a8d9686cbb..261ac246028bab5707dd9df4c99cfbaec610f1e4 100644 (file)
@@ -3,16 +3,24 @@ package org.argeo.ssh;
 import java.io.Console;
 import java.io.IOException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Scanner;
+import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.channel.ClientChannelEvent;
 import org.apache.sshd.client.future.ConnectFuture;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystemProvider;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.apache.sshd.common.util.io.NoCloseOutputStream;
 
+@SuppressWarnings("restriction")
 abstract class AbstractSsh {
        private final static Log log = LogFactory.getLog(AbstractSsh.class);
 
@@ -44,7 +52,6 @@ abstract class AbstractSsh {
                return sftpFileSystemProvider;
        }
 
-       @SuppressWarnings("restriction")
        void authenticate() {
                try {
                        if (sshKeyPair != null) {
@@ -97,7 +104,6 @@ abstract class AbstractSsh {
                openSession(uri.getUserInfo(), uri.getHost(), uri.getPort() > 0 ? uri.getPort() : null);
        }
 
-       @SuppressWarnings("restriction")
        void openSession(String login, String host, Integer port) {
                if (session != null)
                        throw new IllegalStateException("Session is already open");
@@ -131,7 +137,6 @@ abstract class AbstractSsh {
                }
        }
 
-       @SuppressWarnings("restriction")
        void closeSession() {
                if (session == null)
                        throw new IllegalStateException("No session is open");
@@ -148,4 +153,37 @@ abstract class AbstractSsh {
                return session;
        }
 
+       public void setSshKeyPair(SshKeyPair sshKeyPair) {
+               this.sshKeyPair = sshKeyPair;
+       }
+
+       public static void openShell(ClientSession session) {
+               try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
+                       channel.setIn(new NoCloseInputStream(System.in));
+                       channel.setOut(new NoCloseOutputStream(System.out));
+                       channel.setErr(new NoCloseOutputStream(System.err));
+                       channel.open();
+
+                       Set<ClientChannelEvent> events = new HashSet<>();
+                       events.add(ClientChannelEvent.CLOSED);
+                       channel.waitFor(events, 0);
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } finally {
+                       session.close(false);
+               }
+       }
+
+       static URI toUri(String username, String host, int port) {
+               try {
+                       if (username == null)
+                               username = "root";
+                       return new URI("ssh://" + username + "@" + host + ":" + port);
+               } catch (URISyntaxException e) {
+                       throw new IllegalArgumentException("Cannot generate SSH URI to " + host + ":" + port + " for " + username,
+                                       e);
+               }
+       }
+
 }
diff --git a/org.argeo.core/src/org/argeo/ssh/BasicSshServer.java b/org.argeo.core/src/org/argeo/ssh/BasicSshServer.java
new file mode 100644 (file)
index 0000000..3333c7f
--- /dev/null
@@ -0,0 +1,103 @@
+package org.argeo.ssh;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.scp.ScpCommandFactory;
+import org.apache.sshd.server.shell.ProcessShellFactory;
+import org.argeo.util.os.OS;
+
+/** A simple SSH server with some defaults. Supports SCP. */
+@SuppressWarnings("restriction")
+public class BasicSshServer {
+       private Integer port;
+       private Path hostKeyPath;
+
+       private SshServer sshd = null;
+
+       public BasicSshServer(Integer port, Path hostKeyPath) {
+               this.port = port;
+               this.hostKeyPath = hostKeyPath;
+       }
+
+       public void init() {
+               try {
+                       sshd = SshServer.setUpDefaultServer();
+                       sshd.setPort(port);
+                       if (hostKeyPath == null)
+                               throw new IllegalStateException("An SSH server key must be set");
+                       sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKeyPath));
+                       // sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i",
+                       // "-l" }));
+                       String[] shellCommand = OS.LOCAL.getDefaultShellCommand();
+                       sshd.setShellFactory(new ProcessShellFactory(shellCommand));
+                       sshd.setCommandFactory(new ScpCommandFactory());
+                       sshd.start();
+               } catch (Exception e) {
+                       throw new RuntimeException("Cannot start SSH server on port " + port, e);
+               }
+       }
+
+       public void destroy() {
+               try {
+                       sshd.stop();
+               } catch (IOException e) {
+                       throw new RuntimeException("Cannot stop SSH server on port " + port, e);
+               }
+       }
+
+       public Integer getPort() {
+               return port;
+       }
+
+       public void setPort(Integer port) {
+               this.port = port;
+       }
+
+       public Path getHostKeyPath() {
+               return hostKeyPath;
+       }
+
+       public void setHostKeyPath(Path hostKeyPath) {
+               this.hostKeyPath = hostKeyPath;
+       }
+
+       public static void main(String[] args) {
+               int port = 2222;
+               Path hostKeyPath = Paths.get("hostkey.ser");
+               try {
+                       if (args.length > 0)
+                               port = Integer.parseInt(args[0]);
+                       if (args.length > 1)
+                               hostKeyPath = Paths.get(args[1]);
+               } catch (Exception e1) {
+                       printUsage();
+               }
+
+               BasicSshServer sshServer = new BasicSshServer(port, hostKeyPath);
+               sshServer.init();
+               Runtime.getRuntime().addShutdownHook(new Thread("Shutdown SSH server") {
+
+                       @Override
+                       public void run() {
+                               sshServer.destroy();
+                       }
+               });
+               try {
+                       synchronized (sshServer) {
+                               sshServer.wait();
+                       }
+               } catch (InterruptedException e) {
+                       sshServer.destroy();
+               }
+
+       }
+
+       public static void printUsage() {
+               System.out.println("java " + BasicSshServer.class.getName() + " [port] [server key path]");
+       }
+
+}
index df4dd3a01d1a3354e1477b0914aa053f110fd085..da10b961fd3792fbedf14f959c1fb1dce853d411 100644 (file)
@@ -7,11 +7,16 @@ import java.nio.file.Path;
 
 import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystem;
 
+/** Create an SFTP {@link FileSystem}. */
 public class Sftp extends AbstractSsh {
        private URI uri;
 
        private SftpFileSystem fileSystem;
 
+       public Sftp(String username, String host, int port) {
+               this(AbstractSsh.toUri(username, host, port));
+       }
+
        public Sftp(URI uri) {
                this.uri = uri;
                openSession(uri);
diff --git a/org.argeo.core/src/org/argeo/ssh/SimpleSshServer.java b/org.argeo.core/src/org/argeo/ssh/SimpleSshServer.java
deleted file mode 100644 (file)
index e63b989..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.argeo.ssh;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import org.apache.sshd.server.scp.ScpCommandFactory;
-import org.apache.sshd.server.shell.ProcessShellFactory;
-import org.argeo.util.os.OS;
-
-/** A simple SSH server with some defaults. Supports SCP. */
-@SuppressWarnings("restriction")
-public class SimpleSshServer {
-       private Integer port;
-       private Path hostKeyPath;
-
-       private SshServer sshd = null;
-
-       public SimpleSshServer(Integer port, Path hostKeyPath) {
-               this.port = port;
-               this.hostKeyPath = hostKeyPath;
-       }
-
-       public void init() {
-               try {
-                       sshd = SshServer.setUpDefaultServer();
-                       sshd.setPort(port);
-                       if (hostKeyPath == null)
-                               throw new IllegalStateException("An SSH server key must be set");
-                       sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKeyPath));
-                       // sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i",
-                       // "-l" }));
-                       String[] shellCommand = OS.LOCAL.getDefaultShellCommand();
-                       sshd.setShellFactory(new ProcessShellFactory(shellCommand));
-                       sshd.setCommandFactory(new ScpCommandFactory());
-                       sshd.start();
-               } catch (Exception e) {
-                       throw new RuntimeException("Cannot start SSH server on port " + port, e);
-               }
-       }
-
-       public void destroy() {
-               try {
-                       sshd.stop();
-               } catch (IOException e) {
-                       throw new RuntimeException("Cannot stop SSH server on port " + port, e);
-               }
-       }
-
-       public Integer getPort() {
-               return port;
-       }
-
-       public void setPort(Integer port) {
-               this.port = port;
-       }
-
-       public Path getHostKeyPath() {
-               return hostKeyPath;
-       }
-
-       public void setHostKeyPath(Path hostKeyPath) {
-               this.hostKeyPath = hostKeyPath;
-       }
-
-       public static void main(String[] args) {
-               int port = 2222;
-               Path hostKeyPath = Paths.get("hostkey.ser");
-               try {
-                       if (args.length > 0)
-                               port = Integer.parseInt(args[0]);
-                       if (args.length > 1)
-                               hostKeyPath = Paths.get(args[1]);
-               } catch (Exception e1) {
-                       printUsage();
-               }
-
-               SimpleSshServer sshServer = new SimpleSshServer(port, hostKeyPath);
-               sshServer.init();
-               Runtime.getRuntime().addShutdownHook(new Thread("Shutdown SSH server") {
-
-                       @Override
-                       public void run() {
-                               sshServer.destroy();
-                       }
-               });
-               try {
-                       synchronized (sshServer) {
-                               sshServer.wait();
-                       }
-               } catch (InterruptedException e) {
-                       sshServer.destroy();
-               }
-
-       }
-
-       public static void printUsage() {
-               System.out.println("java " + SimpleSshServer.class.getName() + " [port] [server key path]");
-       }
-
-}
index 0443098770ab8f44155fb7dec1d7c1157092d3af..68dd912ec1ff0753d38abf963294e6651c1ac01a 100644 (file)
@@ -1,11 +1,8 @@
 package org.argeo.ssh;
 
-import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
@@ -13,39 +10,20 @@ import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
-import org.apache.sshd.client.channel.ClientChannel;
-import org.apache.sshd.client.channel.ClientChannelEvent;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseOutputStream;
 
-@SuppressWarnings("restriction")
+/** Create an SSH shell. */
 public class Ssh extends AbstractSsh {
        private final URI uri;
 
+       public Ssh(String username, String host, int port) {
+               this(AbstractSsh.toUri(username, host, port));
+       }
+
        public Ssh(URI uri) {
                this.uri = uri;
                openSession(uri);
        }
 
-       static void openShell(ClientSession session) {
-               try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
-                       channel.setIn(new NoCloseInputStream(System.in));
-                       channel.setOut(new NoCloseOutputStream(System.out));
-                       channel.setErr(new NoCloseOutputStream(System.err));
-                       channel.open();
-
-                       Set<ClientChannelEvent> events = new HashSet<>();
-                       events.add(ClientChannelEvent.CLOSED);
-                       channel.waitFor(events, 0);
-               } catch (IOException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               } finally {
-                       session.close(false);
-               }
-       }
-
        public static void main(String[] args) {
                Options options = getOptions();
                CommandLineParser parser = new DefaultParser();
@@ -70,7 +48,7 @@ public class Ssh extends AbstractSsh {
                        ssh.authenticate();
 
                        if (command.size() == 0) {// shell
-                               openShell(ssh.getSession());
+                               AbstractSsh.openShell(ssh.getSession());
                        } else {// execute command
 
                        }