You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@apache.org on 2003/05/13 16:37:04 UTC
cvs commit: ant/src/main/org/apache/tools/ant/taskdefs/optional/net RExecTask.java TelnetTask.java
bodewig 2003/05/13 07:37:04
Modified: . WHATSNEW build.xml
docs/manual install.html optionaltasklist.html
src/main/org/apache/tools/ant/taskdefs defaults.properties
src/main/org/apache/tools/ant/taskdefs/optional/net
TelnetTask.java
Added: docs/manual/OptionalTasks rexec.html
src/main/org/apache/tools/ant/taskdefs/optional/net
RExecTask.java
Log:
Add <rexec> to accompany <telnet> and/or <sshexec>.
PR: 19541
Submitted by: Fran�ois Rey <francois dot rey at capco dot com>
Revision Changes Path
1.416 +3 -0 ant/WHATSNEW
Index: WHATSNEW
===================================================================
RCS file: /home/cvs/ant/WHATSNEW,v
retrieving revision 1.415
retrieving revision 1.416
diff -u -r1.415 -r1.416
--- WHATSNEW 13 May 2003 07:22:02 -0000 1.415
+++ WHATSNEW 13 May 2003 14:36:56 -0000 1.416
@@ -316,6 +316,9 @@
* <rpm> will detect the rpmbuild executable of RedHat 8.0 and newer
and use that if it is on your PATH. Bugzilla Report 14650.
+* A new task <rexec> has been added that requires commons-net to work.
+ Bugzilla Report 19541.
+
Changes from Ant 1.5.2 to Ant 1.5.3
===================================
1.376 +1 -0 ant/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/ant/build.xml,v
retrieving revision 1.375
retrieving revision 1.376
diff -u -r1.375 -r1.376
--- build.xml 6 May 2003 15:19:16 -0000 1.375
+++ build.xml 13 May 2003 14:36:59 -0000 1.376
@@ -234,6 +234,7 @@
<selector id="needs.commons.net">
<or>
<filename name="${optional.package}/net/FTP*"/>
+ <filename name="${optional.package}/net/RExec*"/>
<filename name="${optional.package}/net/TelnetTask*"/>
</or>
</selector>
1.52 +1 -1 ant/docs/manual/install.html
Index: install.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/install.html,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- install.html 23 Apr 2003 15:57:43 -0000 1.51
+++ install.html 13 May 2003 14:37:00 -0000 1.52
@@ -378,7 +378,7 @@
</tr>
<tr>
<td>commons-net.jar</td>
- <td>ftp and telnet tasks</td>
+ <td>ftp, rexec and telnet tasks</td>
<td><a href="http://jakarta.apache.org/commons/net/index.html"
target="_top">http://jakarta.apache.org/commons/net/index.html</a></td>
</tr>
1.38 +1 -0 ant/docs/manual/optionaltasklist.html
Index: optionaltasklist.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/optionaltasklist.html,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- optionaltasklist.html 16 Apr 2003 12:44:44 -0000 1.37
+++ optionaltasklist.html 13 May 2003 14:37:00 -0000 1.38
@@ -53,6 +53,7 @@
<a href="OptionalTasks/pvcstask.html">Pvcs</a><br>
<a href="OptionalTasks/renameextensions.html"><i>RenameExtensions</i></a><br>
<a href="OptionalTasks/replaceregexp.html">ReplaceRegExp</a><br>
+<a href="OptionalTasks/rexec.html">RExec</a><br>
<a href="OptionalTasks/rpm.html">Rpm</a><br>
<a href="OptionalTasks/serverdeploy.html">ServerDeploy</a><br>
<a href="OptionalTasks/setproxy.html">Setproxy</a><br>
1.1 ant/docs/manual/OptionalTasks/rexec.html
Index: rexec.html
===================================================================
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<title>RExec Task</title>
</head>
<body>
<h2><a name="rexec">RExec</a></h2>
<h3>Description</h3>
Task to automate a remote rexec session. Just like the Telnet task,
it uses nested <tt><read></tt> to indicate strings to wait for, and
<tt><write></tt> tags to specify text to send to the remote process.
<p><b>Note:</b> This task depends on external libraries not included in the Ant distribution.
See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<th>Attribute</th>
<th>Values</th>
<th>Required</th>
</tr>
<tr>
<td>userid</td>
<td>the login id to use on the remote server.</td>
<td>Yes</td>
</tr>
<tr>
<td>password</td>
<td>the login password to use on the remote server.</td>
<td>Yes</td>
</tr>
<tr>
<td>server</td>
<td>the address of the remote rexec server.</td>
<td>Yes</td>
</tr>
<tr>
<td>command</td>
<td>the command to execute on the remote server.</td>
<td>Yes</td>
</tr>
<tr>
<td>port</td>
<td>the port number of the remote rexec server. Defaults to port 512 in BSD Unix systems.</td>
<td>No</td>
</tr>
<tr>
<td>timeout</td>
<td>set a default timeout to wait for a response. Specified in seconds. Default is no timeout.</td>
<td>No</td>
</tr>
</table>
<h3><a name="nested">Nested Elements</a></h3>
The input to send to the server, and responses to wait for, are
described as nested elements.
<h4>read</h4>
<p>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 <tt>string</tt>
attribute, which is an alternative to specifying the string as
a text element.
</p>
<i>It is not necessary to declare a closing <read> element like for the Telnet task. The connection is not broken until the command has completed and
the input stream (output of the command) is terminated.
</i>
<h4>write</h4>
<p>describes the text to send to the server. The <tt>echo</tt> boolean
attribute controls whether the string is echoed to the local log;
this is "true" by default
</p>
<h3>Example</h3>
A simple example of connecting to a server and running a command.
<blockquote><pre>
<rexec userid="bob" password="badpass" server="localhost" command="ls"/>
</pre></blockquote>
The task can be used with other ports as well:
<blockquote><pre>
<rexec port="80" userid="bob" password="badpass" server="localhost" command="ls"/>
</pre></blockquote>
<hr>
<p align="center">Copyright © 2003 Apache Software Foundation. All rights
Reserved.</p>
</body>
</html>
1.147 +1 -0 ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
Index: defaults.properties
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
retrieving revision 1.146
retrieving revision 1.147
diff -u -r1.146 -r1.147
--- defaults.properties 9 May 2003 12:10:36 -0000 1.146
+++ defaults.properties 13 May 2003 14:37:03 -0000 1.147
@@ -189,6 +189,7 @@
scp=org.apache.tools.ant.taskdefs.optional.ssh.Scp
sshexec=org.apache.tools.ant.taskdefs.optional.ssh.SSHExec
jsharpc=org.apache.tools.ant.taskdefs.optional.dotnet.JSharp
+rexec=org.apache.tools.ant.taskdefs.optional.net.RExecTask
# deprecated ant tasks (kept for back compatibility)
starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut
1.20 +4 -4 ant/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
Index: TelnetTask.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- TelnetTask.java 24 Feb 2003 08:25:19 -0000 1.19
+++ TelnetTask.java 13 May 2003 14:37:04 -0000 1.20
@@ -330,7 +330,7 @@
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 @@
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());
1.1 ant/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
Index: RExecTask.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs.optional.net;
import org.apache.commons.net.bsd.RExecClient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
/**
* Automates the rexec protocol.
*
* @since Ant 1.6
*/
public class RExecTask extends Task {
/**
* The userid to login with, if automated login is used
*/
private String userid = null;
/**
* The password to login with, if automated login is used
*/
private String password = null;
/**
* The command to execute
*/
private String command = null;
/**
* The server to connect to.
*/
private String server = null;
/**
* The tcp port to connect to.
*/
private int port = RExecClient.DEFAULT_PORT;
/**
* The Object which handles the rexec session.
*/
private AntRExecClient rexec = null;
/**
* The list of read/write commands for this session
*/
private Vector rexecTasks = new Vector();
/**
* If true, adds a CR to beginning of login script
*/
private boolean addCarriageReturn = false;
/**
* Default time allowed for waiting for a valid response
* for all child reads. A value of 0 means no limit.
*/
private Integer defaultTimeout = null;
/**
* This class is the parent of the Read and Write tasks.
* It handles the common attributes for both.
*/
public class RExecSubTask {
protected String taskString = "";
public void execute(AntRExecClient rexec)
throws BuildException {
throw new BuildException("Shouldn't be able instantiate a SubTask directly");
}
/**
* the message as nested text
*/
public void addText(String s) {
setString(getProject().replaceProperties(s));
}
/**
* the message as an attribute
*/
public void setString(String s) {
taskString += s;
}
}
/**
* Sends text to the connected server
*/
public class RExecWrite extends RExecSubTask {
private boolean echoString = true;
public void execute(AntRExecClient rexec)
throws BuildException {
rexec.sendString(taskString, echoString);
}
/**
* Whether or not the message should be echoed to the log.
* Defaults to <code>true</code>.
*/
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 <a
* href="http://jakarta.apache.org/commons/net/index.html">Jakarta
* Commons Net</a>.
*/
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 <tt>userid</tt> 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 <tt>password</tt> is set.
*/
public void setUserid(String u) { this.userid = u; }
}