You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Exec.java 8.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. package org.apache.tools.ant.taskdefs;
  19. import java.io.BufferedReader;
  20. import java.io.File;
  21. import java.io.FileWriter;
  22. import java.io.IOException;
  23. import java.io.InputStream;
  24. import java.io.InputStreamReader;
  25. import java.io.PrintWriter;
  26. import org.apache.tools.ant.BuildException;
  27. import org.apache.tools.ant.MagicNames;
  28. import org.apache.tools.ant.Project;
  29. import org.apache.tools.ant.Task;
  30. /**
  31. * Executes a given command if the os platform is appropriate.
  32. *
  33. * <p><strong>As of Ant 1.2, this class is no longer the
  34. * implementation of Ant's &lt;exec&gt; task - it is considered to be
  35. * dead code by the Ant developers and is unmaintained. Don't use
  36. * it.</strong></p>
  37. *
  38. * @deprecated since 1.2.
  39. * delegate to {@link org.apache.tools.ant.taskdefs.Execute Execute}
  40. * instead.
  41. */
  42. public class Exec extends Task {
  43. private String os;
  44. private String out;
  45. private File dir;
  46. private String command;
  47. // CheckStyle:VisibilityModifier OFF - bc
  48. protected PrintWriter fos = null;
  49. // CheckStyle:VisibilityModifier ON
  50. private boolean failOnError = false;
  51. /**
  52. * Constructor for Exec.
  53. * Prints a warning message to std error.
  54. */
  55. public Exec() {
  56. System.err.println("As of Ant 1.2 released in October 2000, "
  57. + "the Exec class");
  58. System.err.println("is considered to be dead code by the Ant "
  59. + "developers and is unmaintained.");
  60. System.err.println("Don\'t use it!");
  61. }
  62. /**
  63. * Execute the task.
  64. * @throws BuildException on error
  65. */
  66. public void execute() throws BuildException {
  67. run(command);
  68. }
  69. /**
  70. * Execute the command.
  71. * @param command the command to exec
  72. * @return the exit value of the command
  73. * @throws BuildException on error
  74. */
  75. protected int run(String command) throws BuildException {
  76. int err = -1; // assume the worst
  77. // test if os match
  78. String myos = System.getProperty("os.name");
  79. log("Myos = " + myos, Project.MSG_VERBOSE);
  80. if ((os != null) && (os.indexOf(myos) < 0)) {
  81. // this command will be executed only on the specified OS
  82. log("Not found in " + os, Project.MSG_VERBOSE);
  83. return 0;
  84. }
  85. // default directory to the project's base directory
  86. if (dir == null) {
  87. dir = getProject().getBaseDir();
  88. }
  89. if (myos.toLowerCase().indexOf("windows") >= 0) {
  90. if (!dir.equals(getProject().resolveFile("."))) {
  91. if (myos.toLowerCase().indexOf("nt") >= 0) {
  92. command = "cmd /c cd " + dir + " && " + command;
  93. } else {
  94. String ant = getProject().getProperty(MagicNames.ANT_HOME);
  95. if (ant == null) {
  96. throw new BuildException("Property '" + MagicNames.ANT_HOME + "' not "
  97. + "found", getLocation());
  98. }
  99. String antRun = getProject().resolveFile(ant + "/bin/antRun.bat").toString();
  100. command = antRun + " " + dir + " " + command;
  101. }
  102. }
  103. } else {
  104. String ant = getProject().getProperty(MagicNames.ANT_HOME);
  105. if (ant == null) {
  106. throw new BuildException("Property '" + MagicNames.ANT_HOME + "' not found",
  107. getLocation());
  108. }
  109. String antRun = getProject().resolveFile(ant + "/bin/antRun").toString();
  110. command = antRun + " " + dir + " " + command;
  111. }
  112. try {
  113. // show the command
  114. log(command, Project.MSG_VERBOSE);
  115. // exec command on system runtime
  116. Process proc = Runtime.getRuntime().exec(command);
  117. if (out != null) {
  118. fos = new PrintWriter(new FileWriter(out));
  119. log("Output redirected to " + out, Project.MSG_VERBOSE);
  120. }
  121. // copy input and error to the output stream
  122. StreamPumper inputPumper =
  123. new StreamPumper(proc.getInputStream(), Project.MSG_INFO);
  124. StreamPumper errorPumper =
  125. new StreamPumper(proc.getErrorStream(), Project.MSG_WARN);
  126. // starts pumping away the generated output/error
  127. inputPumper.start();
  128. errorPumper.start();
  129. // Wait for everything to finish
  130. proc.waitFor();
  131. inputPumper.join();
  132. errorPumper.join();
  133. proc.destroy();
  134. // close the output file if required
  135. logFlush();
  136. // check its exit value
  137. err = proc.exitValue();
  138. if (err != 0) {
  139. if (failOnError) {
  140. throw new BuildException("Exec returned: " + err, getLocation());
  141. } else {
  142. log("Result: " + err, Project.MSG_ERR);
  143. }
  144. }
  145. } catch (IOException ioe) {
  146. throw new BuildException("Error exec: " + command, ioe, getLocation());
  147. } catch (InterruptedException ex) {
  148. //ignore
  149. }
  150. return err;
  151. }
  152. /**
  153. * Set the directory.
  154. * @param d a <code>String</code> value
  155. */
  156. public void setDir(String d) {
  157. this.dir = getProject().resolveFile(d);
  158. }
  159. /**
  160. * Set the Operating System that this exec is to run in.
  161. * @param os a <code>String</code> value
  162. */
  163. public void setOs(String os) {
  164. this.os = os;
  165. }
  166. /**
  167. * Set the command to exec.
  168. * @param command a <code>String</code> value
  169. */
  170. public void setCommand(String command) {
  171. this.command = command;
  172. }
  173. /**
  174. * Set the output filename.
  175. * @param out a <code>String</code> value
  176. */
  177. public void setOutput(String out) {
  178. this.out = out;
  179. }
  180. /**
  181. * Set the failOnError attribute.
  182. * Default is false.
  183. * @param fail a <code>boolean</code> value
  184. */
  185. public void setFailonerror(boolean fail) {
  186. failOnError = fail;
  187. }
  188. /**
  189. * Log an output message.
  190. * @param line the line to putput
  191. * @param messageLevel the level of logging - ignored
  192. * if output is going to a file
  193. */
  194. protected void outputLog(String line, int messageLevel) {
  195. if (fos == null) {
  196. log(line, messageLevel);
  197. } else {
  198. fos.println(line);
  199. }
  200. }
  201. /**
  202. * Close output.
  203. */
  204. protected void logFlush() {
  205. if (fos != null) {
  206. fos.close();
  207. }
  208. }
  209. // Inner class for continually pumping the input stream during
  210. // Process's runtime.
  211. class StreamPumper extends Thread {
  212. private BufferedReader din;
  213. private int messageLevel;
  214. private boolean endOfStream = false;
  215. private static final int SLEEP_TIME = 5;
  216. public StreamPumper(InputStream is, int messageLevel) {
  217. this.din = new BufferedReader(new InputStreamReader(is));
  218. this.messageLevel = messageLevel;
  219. }
  220. public void pumpStream() throws IOException {
  221. if (!endOfStream) {
  222. String line = din.readLine();
  223. if (line != null) {
  224. outputLog(line, messageLevel);
  225. } else {
  226. endOfStream = true;
  227. }
  228. }
  229. }
  230. public void run() {
  231. try {
  232. try {
  233. while (!endOfStream) {
  234. pumpStream();
  235. sleep(SLEEP_TIME);
  236. }
  237. } catch (InterruptedException ie) {
  238. //ignore
  239. }
  240. din.close();
  241. } catch (IOException ioe) {
  242. // ignore
  243. }
  244. }
  245. }
  246. }