KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > ssh > SSHExec


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs.optional.ssh;
20
21 import org.apache.tools.ant.BuildException;
22 import org.apache.tools.ant.Project;
23 import org.apache.tools.ant.util.TeeOutputStream;
24 import org.apache.tools.ant.util.KeepAliveOutputStream;
25
26 import java.io.ByteArrayOutputStream JavaDoc;
27 import java.io.File JavaDoc;
28 import java.io.FileWriter JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.StringReader JavaDoc;
31
32 import com.jcraft.jsch.ChannelExec;
33 import com.jcraft.jsch.JSchException;
34 import com.jcraft.jsch.Session;
35
36 /**
37  * Executes a command on a remote machine via ssh.
38  * @since Ant 1.6 (created February 2, 2003)
39  */

40 public class SSHExec extends SSHBase {
41
42     /** the command to execute via ssh */
43     private String JavaDoc command = null;
44
45     /** units are milliseconds, default is 0=infinite */
46     private long maxwait = 0;
47
48     /** for waiting for the command to finish */
49     private Thread JavaDoc thread = null;
50
51     private String JavaDoc outputProperty = null; // like <exec>
52
private File JavaDoc outputFile = null; // like <exec>
53
private boolean append = false; // like <exec>
54

55     private static final String JavaDoc TIMEOUT_MESSAGE =
56         "Timeout period exceeded, connection dropped.";
57
58     /**
59      * Constructor for SSHExecTask.
60      */

61     public SSHExec() {
62         super();
63     }
64
65     /**
66      * Sets the command to execute on the remote host.
67      *
68      * @param command The new command value
69      */

70     public void setCommand(String JavaDoc command) {
71         this.command = command;
72     }
73
74     /**
75      * The connection can be dropped after a specified number of
76      * milliseconds. This is sometimes useful when a connection may be
77      * flaky. Default is 0, which means &quot;wait forever&quot;.
78      *
79      * @param timeout The new timeout value in seconds
80      */

81     public void setTimeout(long timeout) {
82         maxwait = timeout;
83     }
84
85     /**
86      * If used, stores the output of the command to the given file.
87      *
88      * @param output The file to write to.
89      */

90     public void setOutput(File JavaDoc output) {
91         outputFile = output;
92     }
93
94     /**
95      * Determines if the output is appended to the file given in
96      * <code>setOutput</code>. Default is false, that is, overwrite
97      * the file.
98      *
99      * @param append True to append to an existing file, false to overwrite.
100      */

101     public void setAppend(boolean append) {
102         this.append = append;
103     }
104
105     /**
106      * If set, the output of the command will be stored in the given property.
107      *
108      * @param property The name of the property in which the command output
109      * will be stored.
110      */

111     public void setOutputproperty(String JavaDoc property) {
112         outputProperty = property;
113     }
114
115     /**
116      * Execute the command on the remote host.
117      *
118      * @exception BuildException Most likely a network error or bad parameter.
119      */

120     public void execute() throws BuildException {
121         if (getHost() == null) {
122             throw new BuildException("Host is required.");
123         }
124         if (getUserInfo().getName() == null) {
125             throw new BuildException("Username is required.");
126         }
127         if (getUserInfo().getKeyfile() == null
128             && getUserInfo().getPassword() == null) {
129             throw new BuildException("Password or Keyfile is required.");
130         }
131         if (command == null) {
132             throw new BuildException("Command is required.");
133         }
134
135         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
136         TeeOutputStream tee = new TeeOutputStream(out, new KeepAliveOutputStream(System.out));
137
138         Session session = null;
139         try {
140             // execute the command
141
session = openSession();
142             session.setTimeout((int) maxwait);
143             final ChannelExec channel = (ChannelExec) session.openChannel("exec");
144             channel.setCommand(command);
145             channel.setOutputStream(tee);
146             channel.setExtOutputStream(tee);
147             channel.connect();
148
149             // wait for it to finish
150
thread =
151                 new Thread JavaDoc() {
152                     public void run() {
153                         while (!channel.isEOF()) {
154                             if (thread == null) {
155                                 return;
156                             }
157                             try {
158                                 sleep(500);
159                             } catch (Exception JavaDoc e) {
160                                 // ignored
161
}
162                         }
163                     }
164                 };
165
166             thread.start();
167             thread.join(maxwait);
168
169             if (thread.isAlive()) {
170                 // ran out of time
171
thread = null;
172                 if (getFailonerror()) {
173                     throw new BuildException(TIMEOUT_MESSAGE);
174                 } else {
175                     log(TIMEOUT_MESSAGE, Project.MSG_ERR);
176                 }
177             } else {
178                 // completed successfully
179
if (outputProperty != null) {
180                     getProject().setProperty(outputProperty, out.toString());
181                 }
182                 if (outputFile != null) {
183                     writeToFile(out.toString(), append, outputFile);
184                 }
185
186                 // this is the wrong test if the remote OS is OpenVMS,
187
// but there doesn't seem to be a way to detect it.
188
int ec = channel.getExitStatus();
189                 if (ec != 0) {
190                     String JavaDoc msg = "Remote command failed with exit status " + ec;
191                     if (getFailonerror()) {
192                         throw new BuildException(msg);
193                     } else {
194                         log(msg, Project.MSG_ERR);
195                     }
196                 }
197             }
198         } catch (BuildException e) {
199             throw e;
200         } catch (JSchException e) {
201             if (e.getMessage().indexOf("session is down") >= 0) {
202                 if (getFailonerror()) {
203                     throw new BuildException(TIMEOUT_MESSAGE, e);
204                 } else {
205                     log(TIMEOUT_MESSAGE, Project.MSG_ERR);
206                 }
207             } else {
208                 if (getFailonerror()) {
209                     throw new BuildException(e);
210                 } else {
211                     log("Caught exception: " + e.getMessage(),
212                         Project.MSG_ERR);
213                 }
214             }
215         } catch (Exception JavaDoc e) {
216             if (getFailonerror()) {
217                 throw new BuildException(e);
218             } else {
219                 log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
220             }
221         } finally {
222             if (session != null && session.isConnected()) {
223                 session.disconnect();
224             }
225         }
226     }
227
228
229     /**
230      * Writes a string to a file. If destination file exists, it may be
231      * overwritten depending on the "append" value.
232      *
233      * @param from string to write
234      * @param to file to write to
235      * @param append if true, append to existing file, else overwrite
236      * @exception Exception most likely an IOException
237      */

238     private void writeToFile(String JavaDoc from, boolean append, File JavaDoc to)
239         throws IOException JavaDoc {
240         FileWriter JavaDoc out = null;
241         try {
242             out = new FileWriter JavaDoc(to.getAbsolutePath(), append);
243             StringReader JavaDoc in = new StringReader JavaDoc(from);
244             char[] buffer = new char[8192];
245             int bytesRead;
246             while (true) {
247                 bytesRead = in.read(buffer);
248                 if (bytesRead == -1) {
249                     break;
250                 }
251                 out.write(buffer, 0, bytesRead);
252             }
253             out.flush();
254         } finally {
255             if (out != null) {
256                 out.close();
257             }
258         }
259     }
260
261 }
262
Popular Tags