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.

Java.java 26 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "Ant" and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant.taskdefs;
  55. import java.io.File;
  56. import java.io.IOException;
  57. import java.util.Vector;
  58. import org.apache.tools.ant.BuildException;
  59. import org.apache.tools.ant.ExitException;
  60. import org.apache.tools.ant.Project;
  61. import org.apache.tools.ant.Task;
  62. import org.apache.tools.ant.types.Commandline;
  63. import org.apache.tools.ant.types.CommandlineJava;
  64. import org.apache.tools.ant.types.Environment;
  65. import org.apache.tools.ant.types.Path;
  66. import org.apache.tools.ant.types.PropertySet;
  67. import org.apache.tools.ant.types.Reference;
  68. import org.apache.tools.ant.types.Assertions;
  69. import org.apache.tools.ant.types.Permissions;
  70. /**
  71. * Launcher for Java applications. Allows use of
  72. * the same JVM for the called application thus resulting in much
  73. * faster operation.
  74. *
  75. * @author Stefano Mazzocchi
  76. * <a href="mailto:stefano@apache.org">stefano@apache.org</a>
  77. * @author Stefan Bodewig
  78. * @author <a href="mailto:donal@savvion.com">Donal Quinlan</a>
  79. * @author <a href="mailto:martijn@kruithof.xs4all.nl">Martijn Kruithof</a>
  80. *
  81. * @since Ant 1.1
  82. *
  83. * @ant.task category="java"
  84. */
  85. public class Java extends Task {
  86. private CommandlineJava cmdl = new CommandlineJava();
  87. private Environment env = new Environment();
  88. private boolean fork = false;
  89. private boolean newEnvironment = false;
  90. private File dir = null;
  91. private boolean failOnError = false;
  92. private boolean append = false;
  93. private Long timeout = null;
  94. private Redirector redirector = new Redirector(this);
  95. private String resultProperty;
  96. private Permissions perm = null;
  97. private boolean spawn = false;
  98. private boolean incompatibleWithSpawn = false;
  99. /**
  100. * Do the execution.
  101. * @throws BuildException if failOnError is set to true and the application
  102. * returns a non 0 result code
  103. */
  104. public void execute() throws BuildException {
  105. File savedDir = dir;
  106. Permissions savedPermissions = perm;
  107. int err = -1;
  108. try {
  109. err = executeJava();
  110. if (err != 0) {
  111. if (failOnError) {
  112. throw new BuildException("Java returned: " + err, getLocation());
  113. } else {
  114. log("Java Result: " + err, Project.MSG_ERR);
  115. }
  116. }
  117. maybeSetResultPropertyValue(err);
  118. } finally {
  119. dir = savedDir;
  120. perm = savedPermissions;
  121. }
  122. }
  123. /**
  124. * Do the execution and return a return code.
  125. *
  126. * @return the return code from the execute java class if it was
  127. * executed in a separate VM (fork = "yes").
  128. *
  129. * @throws BuildException if required parameters are missing
  130. */
  131. public int executeJava() throws BuildException {
  132. String classname = cmdl.getClassname();
  133. if (classname == null && cmdl.getJar() == null) {
  134. throw new BuildException("Classname must not be null.");
  135. }
  136. if (!fork && cmdl.getJar() != null) {
  137. throw new BuildException("Cannot execute a jar in non-forked mode."
  138. + " Please set fork='true'. ");
  139. }
  140. if (spawn && !fork) {
  141. throw new BuildException("Cannot spawn a java process in non-forked mode."
  142. + " Please set fork='true'. ");
  143. }
  144. if (spawn && incompatibleWithSpawn) {
  145. getProject().log("spawn does not allow attributes related to input, "
  146. + "output, error, result", Project.MSG_ERR);
  147. getProject().log("spawn does not also not allow timeout", Project.MSG_ERR);
  148. throw new BuildException("You have used an attribute which is "
  149. + "not compatible with spawn");
  150. }
  151. if (cmdl.getAssertions() != null && !fork) {
  152. log("Assertion statements are currently ignored in non-forked mode");
  153. }
  154. if (fork) {
  155. if (perm != null) {
  156. log("Permissions can not be set this way in forked mode.", Project.MSG_WARN);
  157. }
  158. log(cmdl.describeCommand(), Project.MSG_VERBOSE);
  159. } else {
  160. if (cmdl.getVmCommand().size() > 1) {
  161. log("JVM args ignored when same JVM is used.",
  162. Project.MSG_WARN);
  163. }
  164. if (dir != null) {
  165. log("Working directory ignored when same JVM is used.",
  166. Project.MSG_WARN);
  167. }
  168. if (newEnvironment || null != env.getVariables()) {
  169. log("Changes to environment variables are ignored when same "
  170. + "JVM is used.", Project.MSG_WARN);
  171. }
  172. if (cmdl.getBootclasspath() != null) {
  173. log("bootclasspath ignored when same JVM is used.",
  174. Project.MSG_WARN);
  175. }
  176. if (perm == null && failOnError == true) {
  177. perm = new Permissions(true);
  178. log("running " + this.cmdl.getClassname()
  179. + " with default permissions (exit forbidden)", Project.MSG_VERBOSE);
  180. }
  181. log("Running in same VM " + cmdl.describeJavaCommand(),
  182. Project.MSG_VERBOSE);
  183. }
  184. try {
  185. if (fork) {
  186. if (!spawn) {
  187. return fork(cmdl.getCommandline());
  188. } else {
  189. spawn(cmdl.getCommandline());
  190. return 0;
  191. }
  192. } else {
  193. try {
  194. run(cmdl);
  195. return 0;
  196. } catch (ExitException ex) {
  197. return ex.getStatus();
  198. }
  199. }
  200. } catch (BuildException e) {
  201. if (failOnError) {
  202. throw e;
  203. } else {
  204. log(e.getMessage(), Project.MSG_ERR);
  205. return 0;
  206. }
  207. } catch (Throwable t) {
  208. if (failOnError) {
  209. throw new BuildException(t);
  210. } else {
  211. log(t.getMessage(), Project.MSG_ERR);
  212. return 0;
  213. }
  214. }
  215. }
  216. /**
  217. * set whether or not you want the process to be spawned
  218. * default is not spawned
  219. * @param spawn if true you do not want ant to wait for the end of the process
  220. * @since ant 1.6
  221. */
  222. public void setSpawn(boolean spawn) {
  223. this.spawn = spawn;
  224. }
  225. /**
  226. * Set the classpath to be used when running the Java class
  227. *
  228. * @param s an Ant Path object containing the classpath.
  229. */
  230. public void setClasspath(Path s) {
  231. createClasspath().append(s);
  232. }
  233. /**
  234. * Adds a path to the classpath.
  235. *
  236. * @return created classpath
  237. */
  238. public Path createClasspath() {
  239. return cmdl.createClasspath(getProject()).createPath();
  240. }
  241. /**
  242. * Adds a path to the bootclasspath.
  243. * @since Ant 1.6
  244. *
  245. * @return created bootclasspath
  246. */
  247. public Path createBootclasspath() {
  248. return cmdl.createBootclasspath(getProject()).createPath();
  249. }
  250. /**
  251. * Sets the permissions for the application run inside the same JVM.
  252. * @since Ant 1.6
  253. * @return .
  254. */
  255. public Permissions createPermissions() {
  256. if (perm == null) {
  257. perm = new Permissions();
  258. }
  259. return perm;
  260. }
  261. /**
  262. * Classpath to use, by reference.
  263. *
  264. * @param r a reference to an existing classpath
  265. */
  266. public void setClasspathRef(Reference r) {
  267. createClasspath().setRefid(r);
  268. }
  269. /**
  270. * The location of the JAR file to execute.
  271. *
  272. * @param jarfile the jarfile that one wants to execute
  273. *
  274. * @throws BuildException if there is also a main class specified
  275. */
  276. public void setJar(File jarfile) throws BuildException {
  277. if (cmdl.getClassname() != null) {
  278. throw new BuildException("Cannot use 'jar' and 'classname' "
  279. + "attributes in same command.");
  280. }
  281. cmdl.setJar(jarfile.getAbsolutePath());
  282. }
  283. /**
  284. * Sets the Java class to execute.
  285. *
  286. * @param s the name of the main class
  287. *
  288. * @throws BuildException if the jar attribute has been set
  289. */
  290. public void setClassname(String s) throws BuildException {
  291. if (cmdl.getJar() != null) {
  292. throw new BuildException("Cannot use 'jar' and 'classname' "
  293. + "attributes in same command");
  294. }
  295. cmdl.setClassname(s);
  296. }
  297. /**
  298. * Deprecated: use nested arg instead.
  299. * Set the command line arguments for the class.
  300. *
  301. * @param s arguments
  302. *
  303. * @ant.attribute ignore="true"
  304. */
  305. public void setArgs(String s) {
  306. log("The args attribute is deprecated. "
  307. + "Please use nested arg elements.", Project.MSG_WARN);
  308. cmdl.createArgument().setLine(s);
  309. }
  310. /**
  311. * If set, system properties will be copied to the cloned VM - as
  312. * well as the bootclasspath unless you have explicitly specified
  313. * a bootclaspath.
  314. *
  315. * <p>Doesn't have any effect unless fork is true.</p>
  316. *
  317. * @since Ant 1.7
  318. */
  319. public void setCloneVm(boolean cloneVm) {
  320. cmdl.setCloneVm(cloneVm);
  321. }
  322. /**
  323. * Adds a command-line argument.
  324. *
  325. * @return created argument
  326. */
  327. public Commandline.Argument createArg() {
  328. return cmdl.createArgument();
  329. }
  330. /**
  331. * The name of a property in which the return code of the
  332. * command should be stored. Only of interest if failonerror=false.
  333. *
  334. * @param resultProperty name of property
  335. *
  336. * @since Ant 1.6
  337. */
  338. public void setResultProperty(String resultProperty) {
  339. this.resultProperty = resultProperty;
  340. }
  341. /**
  342. * helper method to set result property to the
  343. * passed in value if appropriate
  344. *
  345. * @param result the exit code
  346. */
  347. protected void maybeSetResultPropertyValue(int result) {
  348. String res = Integer.toString(result);
  349. if (resultProperty != null) {
  350. getProject().setNewProperty(resultProperty, res);
  351. }
  352. }
  353. /**
  354. * If true, execute in a new VM.
  355. *
  356. * @param s do you want to run Java in a new VM.
  357. */
  358. public void setFork(boolean s) {
  359. this.fork = s;
  360. }
  361. /**
  362. * Set the command line arguments for the JVM.
  363. *
  364. * @param s jvmargs
  365. */
  366. public void setJvmargs(String s) {
  367. log("The jvmargs attribute is deprecated. "
  368. + "Please use nested jvmarg elements.", Project.MSG_WARN);
  369. cmdl.createVmArgument().setLine(s);
  370. }
  371. /**
  372. * Adds a JVM argument.
  373. *
  374. * @return JVM argument created
  375. */
  376. public Commandline.Argument createJvmarg() {
  377. return cmdl.createVmArgument();
  378. }
  379. /**
  380. * Set the command used to start the VM (only if not forking).
  381. *
  382. * @param s command to start the VM
  383. */
  384. public void setJvm(String s) {
  385. cmdl.setVm(s);
  386. }
  387. /**
  388. * Adds a system property.
  389. *
  390. * @param sysp system property
  391. */
  392. public void addSysproperty(Environment.Variable sysp) {
  393. cmdl.addSysproperty(sysp);
  394. }
  395. /**
  396. * Adds a set of properties as system properties.
  397. *
  398. * @param sysp set of properties to add
  399. *
  400. * @since Ant 1.6
  401. */
  402. public void addSyspropertyset(PropertySet sysp) {
  403. cmdl.addSyspropertyset(sysp);
  404. }
  405. /**
  406. * If true, then fail if the command exits with a
  407. * returncode other than 0
  408. *
  409. * @param fail if true fail the build when the command exits with a non
  410. * zero returncode
  411. */
  412. public void setFailonerror(boolean fail) {
  413. failOnError = fail;
  414. incompatibleWithSpawn = true;
  415. }
  416. /**
  417. * The working directory of the process
  418. *
  419. * @param d working directory
  420. *
  421. */
  422. public void setDir(File d) {
  423. this.dir = d;
  424. }
  425. /**
  426. * File the output of the process is redirected to.
  427. *
  428. * @param out name of the output file
  429. */
  430. public void setOutput(File out) {
  431. redirector.setOutput(out);
  432. incompatibleWithSpawn = true;
  433. }
  434. /**
  435. * Set the input to use for the task
  436. *
  437. * @param input name of the input file
  438. */
  439. public void setInput(File input) {
  440. redirector.setInput(input);
  441. incompatibleWithSpawn = true;
  442. }
  443. /**
  444. * Set the string to use as input
  445. *
  446. * @param inputString the string which is used as the input source
  447. */
  448. public void setInputString(String inputString) {
  449. redirector.setInputString(inputString);
  450. incompatibleWithSpawn = true;
  451. }
  452. /**
  453. * Controls whether error output of exec is logged. This is only useful
  454. * when output is being redirected and error output is desired in the
  455. * Ant log
  456. *
  457. * @param logError get in the ant log the messages coming from stderr
  458. * in the case that fork = true
  459. */
  460. public void setLogError(boolean logError) {
  461. redirector.setLogError(logError);
  462. incompatibleWithSpawn = true;
  463. }
  464. /**
  465. * File the error stream of the process is redirected to.
  466. *
  467. * @param error file getting the error stream
  468. *
  469. * @since ant 1.6
  470. */
  471. public void setError(File error) {
  472. redirector.setError(error);
  473. incompatibleWithSpawn = true;
  474. }
  475. /**
  476. * Property name whose value should be set to the output of
  477. * the process.
  478. *
  479. * @param outputProp property name
  480. *
  481. */
  482. public void setOutputproperty(String outputProp) {
  483. redirector.setOutputProperty(outputProp);
  484. incompatibleWithSpawn = true;
  485. }
  486. /**
  487. * Property name whose value should be set to the error of
  488. * the process.
  489. *
  490. * @param errorProperty property name
  491. *
  492. * @since ant 1.6
  493. */
  494. public void setErrorProperty(String errorProperty) {
  495. redirector.setErrorProperty(errorProperty);
  496. incompatibleWithSpawn = true;
  497. }
  498. /**
  499. * Corresponds to -mx or -Xmx depending on VM version.
  500. *
  501. * @param max max memory parameter
  502. */
  503. public void setMaxmemory(String max) {
  504. cmdl.setMaxmemory(max);
  505. }
  506. /**
  507. * Sets the JVM version.
  508. * @param value JVM version
  509. */
  510. public void setJVMVersion(String value) {
  511. cmdl.setVmversion(value);
  512. }
  513. /**
  514. * Adds an environment variable.
  515. *
  516. * <p>Will be ignored if we are not forking a new VM.
  517. *
  518. * @param var new environment variable
  519. *
  520. * @since Ant 1.5
  521. */
  522. public void addEnv(Environment.Variable var) {
  523. env.addVariable(var);
  524. }
  525. /**
  526. * If true, use a completely new environment.
  527. *
  528. * <p>Will be ignored if we are not forking a new VM.
  529. *
  530. * @param newenv if true, use a completely new environment.
  531. *
  532. * @since Ant 1.5
  533. */
  534. public void setNewenvironment(boolean newenv) {
  535. newEnvironment = newenv;
  536. }
  537. /**
  538. * If true, append output to existing file.
  539. *
  540. * @param append if true, append output to existing file
  541. *
  542. * @since Ant 1.5
  543. */
  544. public void setAppend(boolean append) {
  545. this.append = append;
  546. incompatibleWithSpawn = true;
  547. }
  548. /**
  549. * Timeout in milliseconds after which the process will be killed.
  550. *
  551. * @param value time out in milliseconds
  552. *
  553. * @since Ant 1.5
  554. */
  555. public void setTimeout(Long value) {
  556. timeout = value;
  557. incompatibleWithSpawn = true;
  558. }
  559. /**
  560. * assertions to enable in this program (if fork=true)
  561. * @since Ant 1.6
  562. * @param asserts assertion set
  563. */
  564. public void addAssertions(Assertions asserts) {
  565. if(cmdl.getAssertions() != null) {
  566. throw new BuildException("Only one assertion declaration is allowed");
  567. }
  568. cmdl.setAssertions(asserts);
  569. }
  570. /**
  571. * Pass output sent to System.out to specified output file.
  572. *
  573. * @param output a string of output on its way to the handlers
  574. *
  575. * @since Ant 1.5
  576. */
  577. protected void handleOutput(String output) {
  578. if (redirector.getOutputStream() != null) {
  579. redirector.handleOutput(output);
  580. } else {
  581. super.handleOutput(output);
  582. }
  583. }
  584. /**
  585. * Handle an input request by this task
  586. *
  587. * @param buffer the buffer into which data is to be read.
  588. * @param offset the offset into the buffer at which data is stored.
  589. * @param length the amount of data to read
  590. *
  591. * @return the number of bytes read
  592. *
  593. * @exception IOException if the data cannot be read
  594. * @since Ant 1.6
  595. */
  596. public int handleInput(byte[] buffer, int offset, int length)
  597. throws IOException {
  598. if (redirector.getInputStream() != null) {
  599. return redirector.handleInput(buffer, offset, length);
  600. } else {
  601. return super.handleInput(buffer, offset, length);
  602. }
  603. }
  604. /**
  605. * Pass output sent to System.out to specified output file.
  606. *
  607. * @param output string of output on its way to its handlers
  608. *
  609. * @since Ant 1.5.2
  610. */
  611. protected void handleFlush(String output) {
  612. if (redirector.getOutputStream() != null) {
  613. redirector.handleFlush(output);
  614. } else {
  615. super.handleFlush(output);
  616. }
  617. }
  618. /**
  619. * Handle output sent to System.err
  620. *
  621. * @param output string of stderr
  622. *
  623. * @since Ant 1.5
  624. */
  625. protected void handleErrorOutput(String output) {
  626. if (redirector.getErrorStream() != null) {
  627. redirector.handleErrorOutput(output);
  628. } else {
  629. super.handleErrorOutput(output);
  630. }
  631. }
  632. /**
  633. * Handle output sent to System.err and flush the stream.
  634. *
  635. * @param output string of stderr
  636. *
  637. * @since Ant 1.5.2
  638. */
  639. protected void handleErrorFlush(String output) {
  640. if (redirector.getErrorStream() != null) {
  641. redirector.handleErrorFlush(output);
  642. } else {
  643. super.handleErrorOutput(output);
  644. }
  645. }
  646. /**
  647. * Executes the given classname with the given arguments as it
  648. * was a command line application.
  649. */
  650. private void run(CommandlineJava command) throws BuildException {
  651. try {
  652. ExecuteJava exe = new ExecuteJava();
  653. exe.setJavaCommand(command.getJavaCommand());
  654. exe.setClasspath(command.getClasspath());
  655. exe.setSystemProperties(command.getSystemProperties());
  656. exe.setPermissions(perm);
  657. exe.setTimeout(timeout);
  658. redirector.createStreams();
  659. exe.execute(getProject());
  660. redirector.complete();
  661. if (exe.killedProcess()) {
  662. throw new BuildException("Timeout: killed the sub-process");
  663. }
  664. } catch (IOException e) {
  665. throw new BuildException(e);
  666. }
  667. }
  668. /**
  669. * Executes the given classname with the given arguments in a separate VM.
  670. */
  671. private int fork(String[] command) throws BuildException {
  672. Execute exe
  673. = new Execute(redirector.createHandler(), createWatchdog());
  674. exe.setAntRun(getProject());
  675. if (dir == null) {
  676. dir = getProject().getBaseDir();
  677. } else if (!dir.exists() || !dir.isDirectory()) {
  678. throw new BuildException(dir.getAbsolutePath()
  679. + " is not a valid directory",
  680. getLocation());
  681. }
  682. exe.setWorkingDirectory(dir);
  683. String[] environment = env.getVariables();
  684. if (environment != null) {
  685. for (int i = 0; i < environment.length; i++) {
  686. log("Setting environment variable: " + environment[i],
  687. Project.MSG_VERBOSE);
  688. }
  689. }
  690. exe.setNewenvironment(newEnvironment);
  691. exe.setEnvironment(environment);
  692. exe.setCommandline(command);
  693. try {
  694. int rc = exe.execute();
  695. redirector.complete();
  696. if (exe.killedProcess()) {
  697. throw new BuildException("Timeout: killed the sub-process");
  698. }
  699. return rc;
  700. } catch (IOException e) {
  701. throw new BuildException(e, getLocation());
  702. }
  703. }
  704. /**
  705. * Executes the given classname with the given arguments in a separate VM.
  706. */
  707. private void spawn(String[] command) throws BuildException {
  708. Execute exe
  709. = new Execute();
  710. exe.setAntRun(getProject());
  711. if (dir == null) {
  712. dir = getProject().getBaseDir();
  713. } else if (!dir.exists() || !dir.isDirectory()) {
  714. throw new BuildException(dir.getAbsolutePath()
  715. + " is not a valid directory",
  716. getLocation());
  717. }
  718. exe.setWorkingDirectory(dir);
  719. String[] environment = env.getVariables();
  720. if (environment != null) {
  721. for (int i = 0; i < environment.length; i++) {
  722. log("Setting environment variable: " + environment[i],
  723. Project.MSG_VERBOSE);
  724. }
  725. }
  726. exe.setNewenvironment(newEnvironment);
  727. exe.setEnvironment(environment);
  728. exe.setCommandline(command);
  729. try {
  730. exe.spawn();
  731. } catch (IOException e) {
  732. throw new BuildException(e, getLocation());
  733. }
  734. }
  735. /**
  736. * Executes the given classname with the given arguments as it
  737. * was a command line application.
  738. *
  739. * @param classname the name of the class to run
  740. * @param args arguments for the class
  741. * @throws BuildException in case of IO Exception in the execution
  742. */
  743. protected void run(String classname, Vector args) throws BuildException {
  744. CommandlineJava cmdj = new CommandlineJava();
  745. cmdj.setClassname(classname);
  746. for (int i = 0; i < args.size(); i++) {
  747. cmdj.createArgument().setValue((String) args.elementAt(i));
  748. }
  749. run(cmdj);
  750. }
  751. /**
  752. * Clear out the arguments to this java task.
  753. */
  754. public void clearArgs() {
  755. cmdl.clearJavaArgs();
  756. }
  757. /**
  758. * Create the Watchdog to kill a runaway process.
  759. *
  760. * @return new watchdog
  761. *
  762. * @throws BuildException under unknown circumstances
  763. *
  764. * @since Ant 1.5
  765. */
  766. protected ExecuteWatchdog createWatchdog() throws BuildException {
  767. if (timeout == null) {
  768. return null;
  769. }
  770. return new ExecuteWatchdog(timeout.longValue());
  771. }
  772. }