source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 13.6 KB
Line 
1/*
2 * Copyright 2003-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs.optional.net;
19
20import org.apache.commons.net.bsd.RExecClient;
21
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.OutputStream;
25import java.util.Calendar;
26import java.util.Enumeration;
27import java.util.Vector;
28import org.apache.tools.ant.BuildException;
29import org.apache.tools.ant.Project;
30import org.apache.tools.ant.Task;
31
32/**
33 * Automates the rexec protocol.
34 *
35 * @since Ant 1.6
36 */
37
38public class RExecTask extends Task {
39 /**
40 * The userid to login with, if automated login is used
41 */
42 private String userid = null;
43
44 /**
45 * The password to login with, if automated login is used
46 */
47 private String password = null;
48
49 /**
50 * The command to execute
51 */
52 private String command = null;
53
54 /**
55 * The server to connect to.
56 */
57 private String server = null;
58
59 /**
60 * The tcp port to connect to.
61 */
62 private int port = RExecClient.DEFAULT_PORT;
63
64 /**
65 * The list of read/write commands for this session
66 */
67 private Vector rexecTasks = new Vector();
68
69 /**
70 * If true, adds a CR to beginning of login script
71 */
72 private boolean addCarriageReturn = false;
73
74 /**
75 * Default time allowed for waiting for a valid response
76 * for all child reads. A value of 0 means no limit.
77 */
78 private Integer defaultTimeout = null;
79
80 /**
81 * This class is the parent of the Read and Write tasks.
82 * It handles the common attributes for both.
83 */
84 public class RExecSubTask {
85 protected String taskString = "";
86 public void execute(AntRExecClient rexec)
87 throws BuildException {
88 throw new BuildException("Shouldn't be able instantiate a SubTask directly");
89 }
90
91 /**
92 * the message as nested text
93 */
94 public void addText(String s) {
95 setString(getProject().replaceProperties(s));
96 }
97
98 /**
99 * the message as an attribute
100 */
101 public void setString(String s) {
102 taskString += s;
103 }
104 }
105
106 /**
107 * Sends text to the connected server
108 */
109 public class RExecWrite extends RExecSubTask {
110 private boolean echoString = true;
111 public void execute(AntRExecClient rexec)
112 throws BuildException {
113 rexec.sendString(taskString, echoString);
114 }
115
116 /**
117 * Whether or not the message should be echoed to the log.
118 * Defaults to <code>true</code>.
119 */
120 public void setEcho(boolean b) {
121 echoString = b;
122 }
123 }
124
125 /**
126 * Reads the output from the connected server
127 * until the required string is found or we time out.
128 */
129 public class RExecRead extends RExecSubTask {
130 private Integer timeout = null;
131 public void execute(AntRExecClient rexec)
132 throws BuildException {
133 rexec.waitForString(taskString, timeout);
134 }
135 /**
136 * a timeout value that overrides any task wide timeout.
137 */
138 public void setTimeout(Integer i) {
139 this.timeout = i;
140 }
141
142 /**
143 * Sets the default timeout if none has been set already
144 * @ant.attribute ignore="true"
145 */
146 public void setDefaultTimeout(Integer defaultTimeout) {
147 if (timeout == null) {
148 timeout = defaultTimeout;
149 }
150 }
151 }
152
153 /**
154 * This class handles the abstraction of the rexec protocol.
155 * Currently it is a wrapper around <a
156 * href="http://jakarta.apache.org/commons/net/index.html">Jakarta
157 * Commons Net</a>.
158 */
159 public class AntRExecClient extends RExecClient {
160 /**
161 * Read from the rexec session until the string we are
162 * waiting for is found
163 * @param s The string to wait on
164 */
165 public void waitForString(String s) {
166 waitForString(s, null);
167 }
168
169 /**
170 * Read from the rexec session until the string we are
171 * waiting for is found or the timeout has been reached
172 * @param s The string to wait on
173 * @param timeout The maximum number of seconds to wait
174 */
175 public void waitForString(String s, Integer timeout) {
176 InputStream is = this.getInputStream();
177 try {
178 StringBuffer sb = new StringBuffer();
179 if (timeout == null || timeout.intValue() == 0) {
180 while (sb.toString().indexOf(s) == -1) {
181 sb.append((char) is.read());
182 }
183 } else {
184 Calendar endTime = Calendar.getInstance();
185 endTime.add(Calendar.SECOND, timeout.intValue());
186 while (sb.toString().indexOf(s) == -1) {
187 while (Calendar.getInstance().before(endTime)
188 && is.available() == 0) {
189 Thread.sleep(250);
190 }
191 if (is.available() == 0) {
192 throw new BuildException(
193 "Response timed-out waiting for \"" + s + '\"',
194 getLocation());
195 }
196 sb.append((char) is.read());
197 }
198 }
199 log(sb.toString(), Project.MSG_INFO);
200 } catch (BuildException be) {
201 throw be;
202 } catch (Exception e) {
203 throw new BuildException(e, getLocation());
204 }
205 }
206
207 /**
208 * Write this string to the rexec session.
209 * @param echoString Logs string sent
210 */
211 public void sendString(String s, boolean echoString) {
212 OutputStream os = this.getOutputStream();
213 try {
214 os.write((s + "\n").getBytes());
215 if (echoString) {
216 log(s, Project.MSG_INFO);
217 }
218 os.flush();
219 } catch (Exception e) {
220 throw new BuildException(e, getLocation());
221 }
222 }
223 /**
224 * Read from the rexec session until the EOF is found or
225 * the timeout has been reached
226 * @param timeout The maximum number of seconds to wait
227 */
228 public void waitForEOF(Integer timeout) {
229 InputStream is = this.getInputStream();
230 try {
231 StringBuffer sb = new StringBuffer();
232 if (timeout == null || timeout.intValue() == 0) {
233 int read;
234 while ((read = is.read()) != -1) {
235 char c = (char) read;
236 sb.append(c);
237 if (c == '\n') {
238 log(sb.toString(), Project.MSG_INFO);
239 sb.delete(0, sb.length());
240 }
241 }
242 } else {
243 Calendar endTime = Calendar.getInstance();
244 endTime.add(Calendar.SECOND, timeout.intValue());
245 int read = 0;
246 while (read != -1) {
247 while (Calendar.getInstance().before(endTime) && is.available() == 0) {
248 Thread.sleep(250);
249 }
250 if (is.available() == 0) {
251 log(sb.toString(), Project.MSG_INFO);
252 throw new BuildException(
253 "Response timed-out waiting for EOF",
254 getLocation());
255 }
256 read = is.read();
257 if (read != -1) {
258 char c = (char) read;
259 sb.append(c);
260 if (c == '\n') {
261 log(sb.toString(), Project.MSG_INFO);
262 sb.delete(0, sb.length());
263 }
264 }
265 }
266 }
267 if (sb.length() > 0) {
268 log(sb.toString(), Project.MSG_INFO);
269 }
270 } catch (BuildException be) {
271 throw be;
272 } catch (Exception e) {
273 throw new BuildException(e, getLocation());
274 }
275 }
276
277 }
278 /**
279 * A string to wait for from the server.
280 * A subTask &lt;read&gt; tag was found. Create the object,
281 * Save it in our list, and return it.
282 */
283
284 public RExecSubTask createRead() {
285 RExecSubTask task = (RExecSubTask) new RExecRead();
286 rexecTasks.addElement(task);
287 return task;
288 }
289 /**
290 * Add text to send to the server
291 * A subTask &lt;write&gt; tag was found. Create the object,
292 * Save it in our list, and return it.
293 */
294 public RExecSubTask createWrite() {
295 RExecSubTask task = (RExecSubTask) new RExecWrite();
296 rexecTasks.addElement(task);
297 return task;
298 }
299 /**
300 * Verify that all parameters are included.
301 * Connect and possibly login
302 * Iterate through the list of Reads and writes
303 */
304 public void execute() throws BuildException {
305 /** A server name is required to continue */
306 if (server == null) {
307 throw new BuildException("No Server Specified");
308 }
309 /** A userid and password must appear together
310 * if they appear. They are not required.
311 */
312 if (userid == null && password != null) {
313 throw new BuildException("No Userid Specified");
314 }
315 if (password == null && userid != null) {
316 throw new BuildException("No Password Specified");
317 }
318
319 /** Create the telnet client object */
320 AntRExecClient rexec = null;
321 try {
322 rexec = new AntRExecClient();
323 try {
324 rexec.connect(server, port);
325 } catch (IOException e) {
326 throw new BuildException("Can't connect to " + server);
327 }
328 /** Login if userid and password were specified */
329 if (userid != null && password != null) {
330 login(rexec);
331 }
332 /** Process each sub command */
333 Enumeration tasksToRun = rexecTasks.elements();
334 while (tasksToRun != null && tasksToRun.hasMoreElements()) {
335 RExecSubTask task = (RExecSubTask) tasksToRun.nextElement();
336 if (task instanceof RExecRead && defaultTimeout != null) {
337 ((RExecRead) task).setDefaultTimeout(defaultTimeout);
338 }
339 task.execute(rexec);
340 }
341
342 /** Keep reading input stream until end of it or time-out */
343 rexec.waitForEOF(defaultTimeout);
344 } finally {
345 if (rexec != null && rexec.isConnected()) {
346 try {
347 rexec.disconnect();
348 } catch (IOException e) {
349 throw new BuildException("Error disconnecting from "
350 + server);
351 }
352 }
353 }
354 }
355 /**
356 * Process a 'typical' login. If it differs, use the read
357 * and write tasks explicitely
358 */
359 private void login(AntRExecClient rexec) {
360 if (addCarriageReturn) {
361 rexec.sendString("\n", true);
362 }
363 rexec.waitForString("ogin:");
364 rexec.sendString(userid, true);
365 rexec.waitForString("assword:");
366 rexec.sendString(password, false);
367 }
368 /**
369 * Set the the comand to execute on the server;
370 */
371 public void setCommand(String c) { this.command = c; }
372 /**
373 * send a carriage return after connecting; optional, defaults to false.
374 */
375 public void setInitialCR(boolean b) {
376 this.addCarriageReturn = b;
377 }
378 /**
379 * Set the the login password to use
380 * required if <tt>userid</tt> is set.
381 */
382 public void setPassword(String p) { this.password = p; }
383 /**
384 * Set the tcp port to connect to; default is 23.
385 */
386 public void setPort(int p) { this.port = p; }
387 /**
388 * Set the hostname or address of the remote server.
389 */
390 public void setServer(String m) { this.server = m; }
391 /**
392 * set a default timeout in seconds to wait for a response,
393 * zero means forever (the default)
394 */
395 public void setTimeout(Integer i) {
396 this.defaultTimeout = i;
397 }
398 /**
399 * Set the the login id to use on the server;
400 * required if <tt>password</tt> is set.
401 */
402 public void setUserid(String u) { this.userid = u; }
403}
Note: See TracBrowser for help on using the repository browser.