From 8b5e371c7b8720327aefff1461efdbfbac41fd6f Mon Sep 17 00:00:00 2001
From: Stefan Bodewig Note: This task depends on external libraries not included in the Ant distribution.
+See Library Dependencies for more information. declare (as a text child of this element) a string to wait for.
+The element supports the timeout attribute, which overrides any
+timeout specified for the task as a whole. It also has a string
+attribute, which is an alternative to specifying the string as
+a text element.
+ describes the text to send to the server. The echo boolean
+attribute controls whether the string is echoed to the local log;
+this is "true" by default
+ Copyright © 2003 Apache Software Foundation. All rights
+Reserved.RExec
+Description
+Task to automate a remote rexec session. Just like the Telnet task,
+it uses nested <read> to indicate strings to wait for, and
+<write> tags to specify text to send to the remote process.
+
+Parameters
+
+
+
+
+ Attribute
+ Values
+ Required
+
+
+ userid
+ the login id to use on the remote server.
+ Yes
+
+
+ password
+ the login password to use on the remote server.
+ Yes
+
+
+ server
+ the address of the remote rexec server.
+ Yes
+
+
+ command
+ the command to execute on the remote server.
+ Yes
+
+
+ port
+ the port number of the remote rexec server. Defaults to port 512 in BSD Unix systems.
+ No
+
+
+timeout
+ set a default timeout to wait for a response. Specified in seconds. Default is no timeout.
+ No
+ Nested Elements
+The input to send to the server, and responses to wait for, are
+described as nested elements.
+
+read
+
+write
+
+Example
+A simple example of connecting to a server and running a command.
+
+
+
+The task can be used with other ports as well:
+
+<rexec userid="bob" password="badpass" server="localhost" command="ls"/>
+
+
+
+<rexec port="80" userid="bob" password="badpass" server="localhost" command="ls"/>
+
+
true
.
+ */
+ public void setEcho(boolean b) {
+ echoString = b;
+ }
+ }
+
+ /**
+ * Reads the output from the connected server
+ * until the required string is found or we time out.
+ */
+ public class RExecRead extends RExecSubTask {
+ private Integer timeout = null;
+ public void execute(AntRExecClient rexec)
+ throws BuildException {
+ rexec.waitForString(taskString, timeout);
+ }
+ /**
+ * a timeout value that overrides any task wide timeout.
+ */
+ public void setTimeout(Integer i) {
+ this.timeout = i;
+ }
+
+ /**
+ * Sets the default timeout if none has been set already
+ * @ant.attribute ignore="true"
+ */
+ public void setDefaultTimeout(Integer defaultTimeout) {
+ if (timeout == null) {
+ timeout = defaultTimeout;
+ }
+ }
+ }
+
+ /**
+ * This class handles the abstraction of the rexec protocol.
+ * Currently it is a wrapper around Jakarta
+ * Commons Net.
+ */
+ public class AntRExecClient extends RExecClient {
+ /**
+ * Read from the rexec session until the string we are
+ * waiting for is found
+ * @param s The string to wait on
+ */
+ public void waitForString(String s) {
+ waitForString(s, null);
+ }
+
+ /**
+ * Read from the rexec session until the string we are
+ * waiting for is found or the timeout has been reached
+ * @param s The string to wait on
+ * @param timeout The maximum number of seconds to wait
+ */
+ public void waitForString(String s, Integer timeout) {
+ InputStream is = this.getInputStream();
+ try {
+ StringBuffer sb = new StringBuffer();
+ if (timeout == null || timeout.intValue() == 0) {
+ while (sb.toString().indexOf(s) == -1) {
+ sb.append((char) is.read());
+ }
+ } else {
+ Calendar endTime = Calendar.getInstance();
+ endTime.add(Calendar.SECOND, timeout.intValue());
+ while (sb.toString().indexOf(s) == -1) {
+ while (Calendar.getInstance().before(endTime) &&
+ is.available() == 0) {
+ Thread.sleep(250);
+ }
+ if (is.available() == 0) {
+ throw new BuildException(
+ "Response timed-out waiting for \"" + s + '\"',
+ getLocation());
+ }
+ sb.append((char) is.read());
+ }
+ }
+ log(sb.toString(), Project.MSG_INFO);
+ } catch (BuildException be) {
+ throw be;
+ } catch (Exception e) {
+ throw new BuildException(e, getLocation());
+ }
+ }
+
+ /**
+ * Write this string to the rexec session.
+ * @param echoString Logs string sent
+ */
+ public void sendString(String s, boolean echoString) {
+ OutputStream os = this.getOutputStream();
+ try {
+ os.write((s + "\n").getBytes());
+ if (echoString) {
+ log(s, Project.MSG_INFO);
+ }
+ os.flush();
+ } catch (Exception e) {
+ throw new BuildException(e, getLocation());
+ }
+ }
+ /**
+ * Read from the rexec session until the EOF is found or
+ * the timeout has been reached
+ * @param timeout The maximum number of seconds to wait
+ */
+ public void waitForEOF(Integer timeout) {
+ InputStream is = this.getInputStream();
+ try {
+ StringBuffer sb = new StringBuffer();
+ if (timeout == null || timeout.intValue() == 0) {
+ int read;
+ while ((read = is.read()) != -1) {
+ char c = (char) read;
+ sb.append(c);
+ if (c == '\n') {
+ log(sb.toString(), Project.MSG_INFO);
+ sb.delete(0, sb.length());
+ }
+ }
+ } else {
+ Calendar endTime = Calendar.getInstance();
+ endTime.add(Calendar.SECOND, timeout.intValue());
+ int read = 0;
+ while (read != -1) {
+ while (Calendar.getInstance().before(endTime) && is.available() == 0) {
+ Thread.sleep(250);
+ }
+ if (is.available() == 0) {
+ log(sb.toString(), Project.MSG_INFO);
+ throw new BuildException(
+ "Response timed-out waiting for EOF",
+ getLocation());
+ }
+ read = is.read();
+ if (read != -1) {
+ char c = (char) read;
+ sb.append(c);
+ if (c == '\n') {
+ log(sb.toString(), Project.MSG_INFO);
+ sb.delete(0, sb.length());
+ }
+ }
+ }
+ }
+ if (sb.length() > 0) {
+ log(sb.toString(), Project.MSG_INFO);
+ }
+ } catch (BuildException be) {
+ throw be;
+ } catch (Exception e) {
+ throw new BuildException(e, getLocation());
+ }
+ }
+
+ }
+ /**
+ * A string to wait for from the server.
+ * A subTask <read> tag was found. Create the object,
+ * Save it in our list, and return it.
+ */
+
+ public RExecSubTask createRead() {
+ RExecSubTask task = (RExecSubTask) new RExecRead();
+ rexecTasks.addElement(task);
+ return task;
+ }
+ /**
+ * Add text to send to the server
+ * A subTask <write> tag was found. Create the object,
+ * Save it in our list, and return it.
+ */
+ public RExecSubTask createWrite() {
+ RExecSubTask task = (RExecSubTask) new RExecWrite();
+ rexecTasks.addElement(task);
+ return task;
+ }
+ /**
+ * Verify that all parameters are included.
+ * Connect and possibly login
+ * Iterate through the list of Reads and writes
+ */
+ public void execute() throws BuildException {
+ /** A server name is required to continue */
+ if (server == null) {
+ throw new BuildException("No Server Specified");
+ }
+ /** A userid and password must appear together
+ * if they appear. They are not required.
+ */
+ if (userid == null && password != null) {
+ throw new BuildException("No Userid Specified");
+ }
+ if (password == null && userid != null) {
+ throw new BuildException("No Password Specified");
+ }
+
+ /** Create the telnet client object */
+ rexec = new AntRExecClient();
+ try {
+ rexec.connect(server, port);
+ } catch (IOException e) {
+ throw new BuildException("Can't connect to " + server);
+ }
+ /** Login if userid and password were specified */
+ if (userid != null && password != null) {
+ login();
+ }
+ /** Process each sub command */
+ Enumeration tasksToRun = rexecTasks.elements();
+ while (tasksToRun != null && tasksToRun.hasMoreElements()) {
+ RExecSubTask task = (RExecSubTask) tasksToRun.nextElement();
+ if (task instanceof RExecRead && defaultTimeout != null) {
+ ((RExecRead) task).setDefaultTimeout(defaultTimeout);
+ }
+ task.execute(rexec);
+ }
+
+ /** Keep reading input stream until end of it or time-out */
+ rexec.waitForEOF(defaultTimeout);
+ }
+ /**
+ * Process a 'typical' login. If it differs, use the read
+ * and write tasks explicitely
+ */
+ private void login() {
+ if (addCarriageReturn) {
+ rexec.sendString("\n", true);
+ }
+ rexec.waitForString("ogin:");
+ rexec.sendString(userid, true);
+ rexec.waitForString("assword:");
+ rexec.sendString(password, false);
+ }
+ /**
+ * Set the the comand to execute on the server;
+ */
+ public void setCommand(String c) { this.command = c; }
+ /**
+ * send a carriage return after connecting; optional, defaults to false.
+ */
+ public void setInitialCR(boolean b) {
+ this.addCarriageReturn = b;
+ }
+ /**
+ * Set the the login password to use
+ * required if userid is set.
+ */
+ public void setPassword(String p) { this.password = p; }
+ /**
+ * Set the tcp port to connect to; default is 23.
+ */
+ public void setPort(int p) { this.port = p; }
+ /**
+ * Set the hostname or address of the remote server.
+ */
+ public void setServer(String m) { this.server = m; }
+ /**
+ * set a default timeout in seconds to wait for a response,
+ * zero means forever (the default)
+ */
+ public void setTimeout(Integer i) {
+ this.defaultTimeout = i;
+ }
+ /**
+ * Set the the login id to use on the server;
+ * required if password is set.
+ */
+ public void setUserid(String u) { this.userid = u; }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
index 77e50dc0e..d670b4636 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
@@ -330,7 +330,7 @@ public class TelnetTask extends Task {
try {
StringBuffer sb = new StringBuffer();
if (timeout == null || timeout.intValue() == 0) {
- while (sb.toString().indexOf(s) == -1){
+ while (sb.toString().indexOf(s) == -1) {
sb.append((char) is.read());
}
} else {
@@ -338,12 +338,12 @@ public class TelnetTask extends Task {
endTime.add(Calendar.SECOND, timeout.intValue());
while (sb.toString().indexOf(s) == -1) {
while (Calendar.getInstance().before(endTime) &&
- is.available() == 0) {
+ is.available() == 0) {
Thread.sleep(250);
}
if (is.available() == 0) {
throw new BuildException(
- "Response timed-out waiting for \""+s+'\"',
+ "Response timed-out waiting for \"" + s + '\"',
getLocation());
}
sb.append((char) is.read());