From c718f8be43b6ee3b1ba111c2a22c9037e35b872f Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 8 Sep 2019 18:43:53 +0200 Subject: [PATCH] Simplify SFTP usage. --- .../src/org/argeo/ssh/AbstractSsh.java | 44 +++++++++++++++++-- ...mpleSshServer.java => BasicSshServer.java} | 8 ++-- org.argeo.core/src/org/argeo/ssh/Sftp.java | 5 +++ org.argeo.core/src/org/argeo/ssh/Ssh.java | 34 +++----------- 4 files changed, 56 insertions(+), 35 deletions(-) rename org.argeo.core/src/org/argeo/ssh/{SimpleSshServer.java => BasicSshServer.java} (90%) diff --git a/org.argeo.core/src/org/argeo/ssh/AbstractSsh.java b/org.argeo.core/src/org/argeo/ssh/AbstractSsh.java index 588c16b01..261ac2460 100644 --- a/org.argeo.core/src/org/argeo/ssh/AbstractSsh.java +++ b/org.argeo.core/src/org/argeo/ssh/AbstractSsh.java @@ -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 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/SimpleSshServer.java b/org.argeo.core/src/org/argeo/ssh/BasicSshServer.java similarity index 90% rename from org.argeo.core/src/org/argeo/ssh/SimpleSshServer.java rename to org.argeo.core/src/org/argeo/ssh/BasicSshServer.java index e63b989a4..3333c7fb8 100644 --- a/org.argeo.core/src/org/argeo/ssh/SimpleSshServer.java +++ b/org.argeo.core/src/org/argeo/ssh/BasicSshServer.java @@ -12,13 +12,13 @@ import org.argeo.util.os.OS; /** A simple SSH server with some defaults. Supports SCP. */ @SuppressWarnings("restriction") -public class SimpleSshServer { +public class BasicSshServer { private Integer port; private Path hostKeyPath; private SshServer sshd = null; - public SimpleSshServer(Integer port, Path hostKeyPath) { + public BasicSshServer(Integer port, Path hostKeyPath) { this.port = port; this.hostKeyPath = hostKeyPath; } @@ -77,7 +77,7 @@ public class SimpleSshServer { printUsage(); } - SimpleSshServer sshServer = new SimpleSshServer(port, hostKeyPath); + BasicSshServer sshServer = new BasicSshServer(port, hostKeyPath); sshServer.init(); Runtime.getRuntime().addShutdownHook(new Thread("Shutdown SSH server") { @@ -97,7 +97,7 @@ public class SimpleSshServer { } public static void printUsage() { - System.out.println("java " + SimpleSshServer.class.getName() + " [port] [server key path]"); + System.out.println("java " + BasicSshServer.class.getName() + " [port] [server key path]"); } } diff --git a/org.argeo.core/src/org/argeo/ssh/Sftp.java b/org.argeo.core/src/org/argeo/ssh/Sftp.java index df4dd3a01..da10b961f 100644 --- a/org.argeo.core/src/org/argeo/ssh/Sftp.java +++ b/org.argeo.core/src/org/argeo/ssh/Sftp.java @@ -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/Ssh.java b/org.argeo.core/src/org/argeo/ssh/Ssh.java index 044309877..68dd912ec 100644 --- a/org.argeo.core/src/org/argeo/ssh/Ssh.java +++ b/org.argeo.core/src/org/argeo/ssh/Ssh.java @@ -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 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 } -- 2.30.2