FileDocCategorySizeDatePackage
SSHExec.javaAPI DocApache Ant 1.708655Wed Dec 13 06:16:24 GMT 2006org.apache.tools.ant.taskdefs.optional.ssh

SSHExec

public class SSHExec extends SSHBase
Executes a command on a remote machine via ssh.
since
Ant 1.6 (created February 2, 2003)

Fields Summary
private String
command
the command to execute via ssh
private long
maxwait
units are milliseconds, default is 0=infinite
private Thread
thread
for waiting for the command to finish
private String
outputProperty
private File
outputFile
private boolean
append
private static final String
TIMEOUT_MESSAGE
Constructors Summary
public SSHExec()
Constructor for SSHExecTask.


            
      
        super();
    
Methods Summary
public voidexecute()
Execute the command on the remote host.

exception
BuildException Most likely a network error or bad parameter.

        if (getHost() == null) {
            throw new BuildException("Host is required.");
        }
        if (getUserInfo().getName() == null) {
            throw new BuildException("Username is required.");
        }
        if (getUserInfo().getKeyfile() == null
            && getUserInfo().getPassword() == null) {
            throw new BuildException("Password or Keyfile is required.");
        }
        if (command == null) {
            throw new BuildException("Command is required.");
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        TeeOutputStream tee = new TeeOutputStream(out, new KeepAliveOutputStream(System.out));

        Session session = null;
        try {
            // execute the command
            session = openSession();
            session.setTimeout((int) maxwait);
            final ChannelExec channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            channel.setOutputStream(tee);
            channel.setExtOutputStream(tee);
            channel.connect();

            // wait for it to finish
            thread =
                new Thread() {
                    public void run() {
                        while (!channel.isEOF()) {
                            if (thread == null) {
                                return;
                            }
                            try {
                                sleep(500);
                            } catch (Exception e) {
                                // ignored
                            }
                        }
                    }
                };

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

            if (thread.isAlive()) {
                // ran out of time
                thread = null;
                if (getFailonerror()) {
                    throw new BuildException(TIMEOUT_MESSAGE);
                } else {
                    log(TIMEOUT_MESSAGE, Project.MSG_ERR);
                }
            } else {
                // completed successfully
                if (outputProperty != null) {
                    getProject().setProperty(outputProperty, out.toString());
                }
                if (outputFile != null) {
                    writeToFile(out.toString(), append, outputFile);
                }

                // this is the wrong test if the remote OS is OpenVMS,
                // but there doesn't seem to be a way to detect it.
                int ec = channel.getExitStatus();
                if (ec != 0) {
                    String msg = "Remote command failed with exit status " + ec;
                    if (getFailonerror()) {
                        throw new BuildException(msg);
                    } else {
                        log(msg, Project.MSG_ERR);
                    }
                }
            }
        } catch (BuildException e) {
            throw e;
        } catch (JSchException e) {
            if (e.getMessage().indexOf("session is down") >= 0) {
                if (getFailonerror()) {
                    throw new BuildException(TIMEOUT_MESSAGE, e);
                } else {
                    log(TIMEOUT_MESSAGE, Project.MSG_ERR);
                }
            } else {
                if (getFailonerror()) {
                    throw new BuildException(e);
                } else {
                    log("Caught exception: " + e.getMessage(),
                        Project.MSG_ERR);
                }
            }
        } catch (Exception e) {
            if (getFailonerror()) {
                throw new BuildException(e);
            } else {
                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
            }
        } finally {
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    
public voidsetAppend(boolean append)
Determines if the output is appended to the file given in setOutput. Default is false, that is, overwrite the file.

param
append True to append to an existing file, false to overwrite.

        this.append = append;
    
public voidsetCommand(java.lang.String command)
Sets the command to execute on the remote host.

param
command The new command value

        this.command = command;
    
public voidsetOutput(java.io.File output)
If used, stores the output of the command to the given file.

param
output The file to write to.

        outputFile = output;
    
public voidsetOutputproperty(java.lang.String property)
If set, the output of the command will be stored in the given property.

param
property The name of the property in which the command output will be stored.

        outputProperty = property;
    
public voidsetTimeout(long timeout)
The connection can be dropped after a specified number of milliseconds. This is sometimes useful when a connection may be flaky. Default is 0, which means "wait forever".

param
timeout The new timeout value in seconds

        maxwait = timeout;
    
private voidwriteToFile(java.lang.String from, boolean append, java.io.File to)
Writes a string to a file. If destination file exists, it may be overwritten depending on the "append" value.

param
from string to write
param
to file to write to
param
append if true, append to existing file, else overwrite
exception
Exception most likely an IOException

        FileWriter out = null;
        try {
            out = new FileWriter(to.getAbsolutePath(), append);
            StringReader in = new StringReader(from);
            char[] buffer = new char[8192];
            int bytesRead;
            while (true) {
                bytesRead = in.read(buffer);
                if (bytesRead == -1) {
                    break;
                }
                out.write(buffer, 0, bytesRead);
            }
            out.flush();
        } finally {
            if (out != null) {
                out.close();
            }
        }