Repository: mina-sshd Updated Branches: refs/heads/master 2c320737b -> 306bef267
Added ClientSession#executeRemoteCommand overload with both STDOUT and STDERR streams Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/306bef26 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/306bef26 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/306bef26 Branch: refs/heads/master Commit: 306bef267acbb8fe2ee31fef71c791a86f092a6c Parents: 2c32073 Author: Goldstein Lyor <l...@c-b4.com> Authored: Mon Aug 28 09:47:35 2017 +0300 Committer: Goldstein Lyor <l...@c-b4.com> Committed: Mon Aug 28 09:47:58 2017 +0300 ---------------------------------------------------------------------- .../sshd/client/channel/ClientChannel.java | 19 +++++++++ .../sshd/client/session/ClientSession.java | 43 ++++++++++++++++---- 2 files changed, 53 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/306bef26/sshd-core/src/main/java/org/apache/sshd/client/channel/ClientChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ClientChannel.java index 2b221c4..6da4a4f 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ClientChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ClientChannel.java @@ -21,6 +21,8 @@ package org.apache.sshd.client.channel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.rmi.RemoteException; +import java.rmi.ServerException; import java.util.Collection; import java.util.Set; @@ -110,4 +112,21 @@ public interface ClientChannel extends Channel { * - {@code null} if not signaled */ String getExitSignal(); + + /** + * Makes sure remote command exit status has been provided and it is zero + * + * @param command The command string - used only for exception text + * @param exitStatus The exit status value + * @throws RemoteException If <tt>exitStatus</tt> is {@code null} or non-zero + */ + static void validateCommandExitStatusCode(String command, Integer exitStatus) throws RemoteException { + if (exitStatus == null) { + throw new RemoteException("No exit status returned for command=" + command); + } + if (exitStatus.intValue() != 0) { + throw new RemoteException("Remote command failed (" + exitStatus + "): " + command, new ServerException(exitStatus.toString())); + } + } + } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/306bef26/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java index bac1218..8c074f2 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java @@ -197,15 +197,45 @@ public interface ClientSession * but does check the reported exit status (if any) for non-zero value. If * non-zero exit status received then a {@link RemoteException} is thrown with' * a {@link ServerException} cause containing the exits value + * @see #executeRemoteCommand(String, OutputStream, OutputStream, Charset) */ default String executeRemoteCommand(String command, OutputStream stderr, Charset charset) throws IOException { if (charset == null) { charset = StandardCharsets.US_ASCII; } - try (ByteArrayOutputStream channelOut = new ByteArrayOutputStream(Byte.MAX_VALUE); - OutputStream channelErr = (stderr == null) ? new NullOutputStream() : new NoCloseOutputStream(stderr); - ClientChannel channel = createExecChannel(command)) { + try (ByteArrayOutputStream stdout = new ByteArrayOutputStream(Byte.MAX_VALUE)) { + executeRemoteCommand(command, stdout, stderr, charset); + byte[] outBytes = stdout.toByteArray(); + return new String(outBytes, charset); + } + } + + /** + * Execute a command that requires no input and redirects its STDOUT/STDERR + * streams to the user-provided ones + * + * @param command The command to execute - without a terminating LF + * @param stdout Standard output stream - if {@code null} then + * stream data is ignored. <B>Note:</B> if the stream is not {@code null} + * then it will be left <U>open</U> when this method returns or exception + * is thrown + * @param stderr Error output stream - if {@code null} then stream data is ignored. + * <B>Note:</B> if the stream is not {@code null} then it will be left <U>open</U> + * when this method returns or exception is thrown + * @param charset The command {@link Charset} for output/error - if + * {@code null} then US_ASCII is assumed + * @throws IOException If failed to execute the command or got a non-zero exit status + * @see ClientChannel#validateCommandExitStatusCode(String, Integer) validateCommandExitStatusCode + */ + default void executeRemoteCommand(String command, OutputStream stdout, OutputStream stderr, Charset charset) throws IOException { + if (charset == null) { + charset = StandardCharsets.US_ASCII; + } + + try (OutputStream channelErr = (stderr == null) ? new NullOutputStream() : new NoCloseOutputStream(stderr); + OutputStream channelOut = (stdout == null) ? new NullOutputStream() : new NoCloseOutputStream(stdout); + ClientChannel channel = createExecChannel(command)) { channel.setOut(channelOut); channel.setErr(channelErr); channel.open().await(); // TODO use verify and a configurable timeout @@ -217,12 +247,7 @@ public interface ClientSession } Integer exitStatus = channel.getExitStatus(); - if ((exitStatus != null) && (exitStatus != 0)) { - throw new RemoteException("Remote command failed (" + exitStatus + "): " + command, new ServerException(exitStatus.toString())); - } - - byte[] response = channelOut.toByteArray(); - return new String(response, charset); + ClientChannel.validateCommandExitStatusCode(command, exitStatus); } }