private void executeCommand()

in src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHExec.java [353:476]


    private void executeCommand(final Session session, final String cmd, final StringBuilder sb)
        throws BuildException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final ByteArrayOutputStream errout = new ByteArrayOutputStream();
        final OutputStream teeErr = suppressSystemErr ? errout : new TeeOutputStream(errout, KeepAliveOutputStream.wrapSystemErr());
        final OutputStream tee = suppressSystemOut ? out : new TeeOutputStream(out, KeepAliveOutputStream.wrapSystemOut());

        InputStream istream = null;
        if (inputFile != null) {
            try {
                istream = Files.newInputStream(inputFile.toPath());
            } catch (final IOException e) {
                // because we checked the existence before, this one
                // shouldn't happen What if the file exists, but there
                // are no read permissions?
                log("Failed to read " + inputFile + " because of: "
                    + e.getMessage(), Project.MSG_WARN);
            }
        }
        if (inputProperty != null) {
            final String inputData = getProject().getProperty(inputProperty);
            if (inputData != null) {
                istream = new ByteArrayInputStream(inputData.getBytes());
            }
        }
        if (inputString != null) {
            istream = new ByteArrayInputStream(inputString.getBytes());
        }

        if (useSystemIn) {
            istream = KeepAliveInputStream.wrapSystemIn();
        }

        try {
            final ChannelExec channel;
            session.setTimeout((int) maxwait);
            /* execute the command */
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(cmd);
            channel.setOutputStream(tee);
            channel.setExtOutputStream(tee);
            channel.setErrStream(teeErr);
            if (istream != null) {
                channel.setInputStream(istream);
            }
            channel.setPty(usePty);
            channel.connect();
            // wait for it to finish
            thread =
                    new Thread(() -> {
                        while (!channel.isClosed()) {
                            if (thread == null) {
                                return;
                            }
                            try {
                                Thread.sleep(RETRY_INTERVAL);
                            } catch (final Exception e) {
                                // ignored
                            }
                        }
                    });

            thread.start();
            thread.join(maxwait);

            if (thread.isAlive()) {
                // ran out of time
                thread = null;
                if (getFailonerror()) {
                    throw new BuildException(TIMEOUT_MESSAGE);
                }
                log(TIMEOUT_MESSAGE, Project.MSG_ERR);
            } else {
                // stdout to outputFile
                if (outputFile != null) {
                    writeToFile(out.toString(), append, outputFile);
                }
                // set errorProperty
                if (errorProperty != null) {
                    getProject().setNewProperty(errorProperty, errout.toString());
                }
                // stderr to errorFile
                if (errorFile != null) {
                    writeToFile(errout.toString(), appenderr, errorFile);
                }
                // this is the wrong test if the remote OS is OpenVMS,
                // but there doesn't seem to be a way to detect it.
                final int ec = channel.getExitStatus();
                // set resultproperty
                if (resultProperty != null) {
                    getProject().setNewProperty(resultProperty, Integer.toString(ec));
                }
                if (ec != 0) {
                    final String msg = "Remote command failed with exit status " + ec;
                    if (getFailonerror()) {
                        throw new BuildException(msg);
                    }
                    log(msg, Project.MSG_ERR);
                }
            }
        } catch (final BuildException e) {
            throw e;
        } catch (final JSchException e) {
            if (e.getMessage().contains("session is down")) {
                if (getFailonerror()) {
                    throw new BuildException(TIMEOUT_MESSAGE, e);
                }
                log(TIMEOUT_MESSAGE, Project.MSG_ERR);
            } else {
                if (getFailonerror()) {
                    throw new BuildException(e);
                }
                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
            }
        } catch (final Exception e) {
            if (getFailonerror()) {
                throw new BuildException(e);
            }
            log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
        } finally {
            sb.append(out.toString());
            FileUtils.close(istream);
        }
    }