aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java479
1 files changed, 479 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
new file mode 100644
index 00000000..01cb4ba9
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
@@ -0,0 +1,479 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs.optional.net;
+
+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.commons.net.bsd.RExecClient;
+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 {
+
+ private static final int PAUSE_TIME = 250;
+
+ /**
+ * 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 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 {
+ // CheckStyle:VisibilityModifier OFF - bc
+ protected String taskString = "";
+ // CheckStyle:VisibilityModifier ON
+
+ /**
+ * Execute the subtask.
+ * @param rexec the client
+ * @throws BuildException always as it is not allowed to instantiate this object
+ */
+ public void execute(AntRExecClient rexec)
+ throws BuildException {
+ throw new BuildException("Shouldn't be able instantiate a SubTask directly");
+ }
+
+ /**
+ * the message as nested text
+ * @param s the nested text
+ */
+ public void addText(String s) {
+ setString(getProject().replaceProperties(s));
+ }
+
+ /**
+ * the message as an attribute
+ * @param s a <code>String</code> value
+ */
+ public void setString(String s) {
+ taskString += s;
+ }
+ }
+
+ /**
+ * Sends text to the connected server
+ */
+ public class RExecWrite extends RExecSubTask {
+ private boolean echoString = true;
+ /**
+ * Execute the write exec task.
+ * @param rexec the task to use
+ * @throws BuildException on error
+ */
+ 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>.
+ * @param b a <code>boolean</code> value
+ */
+ 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;
+ /**
+ * Execute the read exec task.
+ * @param rexec the task to use
+ * @throws BuildException on error
+ */
+ public void execute(AntRExecClient rexec)
+ throws BuildException {
+ rexec.waitForString(taskString, timeout);
+ }
+ /**
+ * a timeout value that overrides any task wide timeout.
+ * @param i an <code>Integer</code> value
+ */
+ public void setTimeout(Integer i) {
+ this.timeout = i;
+ }
+
+ /**
+ * Sets the default timeout if none has been set already
+ * @param defaultTimeout an <code>Integer</code> value
+ * @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();
+ int windowStart = -s.length();
+ if (timeout == null || timeout.intValue() == 0) {
+ while (windowStart < 0
+ || !sb.substring(windowStart).equals(s)) {
+ sb.append((char) is.read());
+ windowStart++;
+ }
+ } else {
+ Calendar endTime = Calendar.getInstance();
+ endTime.add(Calendar.SECOND, timeout.intValue());
+ while (windowStart < 0
+ || !sb.substring(windowStart).equals(s)) {
+ while (Calendar.getInstance().before(endTime)
+ && is.available() == 0) {
+ Thread.sleep(PAUSE_TIME);
+ }
+ if (is.available() == 0) {
+ throw new BuildException(
+ "Response timed-out waiting for \"" + s + '\"',
+ getLocation());
+ }
+ sb.append((char) is.read());
+ windowStart++;
+ }
+ }
+ 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 s the string to write
+ * @param echoString if true log the 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(PAUSE_TIME);
+ }
+ 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 &lt;read&gt; tag was found. Create the object,
+ * Save it in our list, and return it.
+ * @return a read sub task
+ */
+
+ public RExecSubTask createRead() {
+ RExecSubTask task = (RExecSubTask) new RExecRead();
+ rexecTasks.addElement(task);
+ return task;
+ }
+ /**
+ * Add text to send to the server
+ * A subTask &lt;write&gt; tag was found. Create the object,
+ * Save it in our list, and return it.
+ * @return a write sub task
+ */
+ 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.
+ * @throws BuildException on error
+ */
+ 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 */
+ AntRExecClient rexec = null;
+ try {
+ rexec = new AntRExecClient();
+ try {
+ rexec.connect(server, port);
+ } catch (IOException e) {
+ throw new BuildException("Can't connect to " + server);
+ }
+ if (userid != null && password != null && command != null
+ && rexecTasks.size() == 0) {
+ // simple one-shot execution
+ rexec.rexec(userid, password, command);
+ } else {
+ // need nested read/write elements
+ handleMultipleTasks(rexec);
+ }
+
+ /** Keep reading input stream until end of it or time-out */
+ rexec.waitForEOF(defaultTimeout);
+ } catch (IOException e) {
+ throw new BuildException("Error r-executing command", e);
+ } finally {
+ if (rexec != null && rexec.isConnected()) {
+ try {
+ rexec.disconnect();
+ } catch (IOException e) {
+ throw new BuildException("Error disconnecting from "
+ + server);
+ }
+ }
+ }
+ }
+ /**
+ * Process a 'typical' login. If it differs, use the read
+ * and write tasks explicitly
+ */
+ private void login(AntRExecClient rexec) {
+ if (addCarriageReturn) {
+ rexec.sendString("\n", true);
+ }
+ rexec.waitForString("ogin:");
+ rexec.sendString(userid, true);
+ rexec.waitForString("assword:");
+ rexec.sendString(password, false);
+ }
+ /**
+ * Set the the command to execute on the server;
+ * @param c a <code>String</code> value
+ */
+ public void setCommand(String c) {
+ this.command = c;
+ }
+
+ /**
+ * send a carriage return after connecting; optional, defaults to false.
+ * @param b a <code>boolean</code> value
+ */
+ public void setInitialCR(boolean b) {
+ this.addCarriageReturn = b;
+ }
+ /**
+ * Set the the login password to use
+ * required if <tt>userid</tt> is set.
+ * @param p a <code>String</code> value
+ */
+ public void setPassword(String p) {
+ this.password = p;
+ }
+
+ /**
+ * Set the tcp port to connect to; default is 23.
+ * @param p an <code>int</code> value
+ */
+ public void setPort(int p) {
+ this.port = p;
+ }
+
+ /**
+ * Set the hostname or address of the remote server.
+ * @param m a <code>String</code> value
+ */
+ public void setServer(String m) {
+ this.server = m;
+ }
+
+ /**
+ * set a default timeout in seconds to wait for a response,
+ * zero means forever (the default)
+ * @param i an <code>Integer</code> value
+ */
+ 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.
+ * @param u a <code>String</code> value
+ */
+ public void setUserid(String u) {
+ this.userid = u;
+ }
+
+ /**
+ * Deals with multiple read/write calls.
+ *
+ * @since Ant 1.6.3
+ */
+ private void handleMultipleTasks(AntRExecClient rexec) {
+
+ /** Login if userid and password were specified */
+ if (userid != null && password != null) {
+ login(rexec);
+ }
+ /** 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);
+ }
+ }
+}