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 28 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. /*
  2. * Copyright 2000-2004 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. package org.apache.tools.ant.taskdefs;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.io.PrintWriter;
  21. import java.io.StringWriter;
  22. import java.util.Vector;
  23. import org.apache.tools.ant.BuildException;
  24. import org.apache.tools.ant.ExitException;
  25. import org.apache.tools.ant.Project;
  26. import org.apache.tools.ant.Task;
  27. import org.apache.tools.ant.types.Commandline;
  28. import org.apache.tools.ant.types.CommandlineJava;
  29. import org.apache.tools.ant.types.Environment;
  30. import org.apache.tools.ant.types.Path;
  31. import org.apache.tools.ant.types.PropertySet;
  32. import org.apache.tools.ant.types.Reference;
  33. import org.apache.tools.ant.types.Assertions;
  34. import org.apache.tools.ant.types.Permissions;
  35. import org.apache.tools.ant.types.RedirectorElement;
  36. import org.apache.tools.ant.taskdefs.condition.Os;
  37. import org.apache.tools.ant.util.JavaEnvUtils;
  38. /**
  39. * Launcher for Java applications. Allows use of
  40. * the same JVM for the called application thus resulting in much
  41. * faster operation.
  42. *
  43. * @since Ant 1.1
  44. *
  45. * @ant.task category="java"
  46. */
  47. public class Java extends Task {
  48. private CommandlineJava cmdl = new CommandlineJava();
  49. private Environment env = new Environment();
  50. private boolean fork = false;
  51. private boolean newEnvironment = false;
  52. private File dir = null;
  53. private boolean failOnError = false;
  54. private Long timeout = null;
  55. //include locally for screening purposes
  56. private String inputString;
  57. private File input;
  58. private File output;
  59. private File error;
  60. protected Redirector redirector = new Redirector(this);
  61. protected RedirectorElement redirectorElement;
  62. private String resultProperty;
  63. private Permissions perm = null;
  64. private boolean spawn = false;
  65. private boolean incompatibleWithSpawn = false;
  66. /**
  67. * Do the execution.
  68. * @throws BuildException if failOnError is set to true and the application
  69. * returns a non 0 result code
  70. */
  71. public void execute() throws BuildException {
  72. File savedDir = dir;
  73. Permissions savedPermissions = perm;
  74. int err = -1;
  75. try {
  76. err = executeJava();
  77. if (err != 0) {
  78. if (failOnError) {
  79. throw new BuildException("Java returned: " + err, getLocation());
  80. } else {
  81. log("Java Result: " + err, Project.MSG_ERR);
  82. }
  83. }
  84. maybeSetResultPropertyValue(err);
  85. } finally {
  86. dir = savedDir;
  87. perm = savedPermissions;
  88. }
  89. }
  90. /**
  91. * Do the execution and return a return code.
  92. *
  93. * @return the return code from the execute java class if it was
  94. * executed in a separate VM (fork = "yes").
  95. *
  96. * @throws BuildException if required parameters are missing
  97. */
  98. public int executeJava() throws BuildException {
  99. String classname = cmdl.getClassname();
  100. if (classname == null && cmdl.getJar() == null) {
  101. throw new BuildException("Classname must not be null.");
  102. }
  103. if (!fork && cmdl.getJar() != null) {
  104. throw new BuildException("Cannot execute a jar in non-forked mode."
  105. + " Please set fork='true'. ");
  106. }
  107. if (spawn && !fork) {
  108. throw new BuildException("Cannot spawn a java process in non-forked mode."
  109. + " Please set fork='true'. ");
  110. }
  111. if (spawn && incompatibleWithSpawn) {
  112. getProject().log("spawn does not allow attributes related to input, "
  113. + "output, error, result", Project.MSG_ERR);
  114. getProject().log("spawn also does not allow timeout", Project.MSG_ERR);
  115. getProject().log("finally, spawn is not compatible "
  116. + "with a nested I/O <redirector>", Project.MSG_ERR);
  117. throw new BuildException("You have used an attribute "
  118. + "or nested element which is not compatible with spawn");
  119. }
  120. if (cmdl.getAssertions() != null && !fork) {
  121. log("Assertion statements are currently ignored in non-forked mode");
  122. }
  123. if (fork) {
  124. if (perm != null) {
  125. log("Permissions can not be set this way in forked mode.", Project.MSG_WARN);
  126. }
  127. log(cmdl.describeCommand(), Project.MSG_VERBOSE);
  128. } else {
  129. if (cmdl.getVmCommand().size() > 1) {
  130. log("JVM args ignored when same JVM is used.",
  131. Project.MSG_WARN);
  132. }
  133. if (dir != null) {
  134. log("Working directory ignored when same JVM is used.",
  135. Project.MSG_WARN);
  136. }
  137. if (newEnvironment || null != env.getVariables()) {
  138. log("Changes to environment variables are ignored when same "
  139. + "JVM is used.", Project.MSG_WARN);
  140. }
  141. if (cmdl.getBootclasspath() != null) {
  142. log("bootclasspath ignored when same JVM is used.",
  143. Project.MSG_WARN);
  144. }
  145. if (perm == null && failOnError == true) {
  146. perm = new Permissions(true);
  147. log("running " + this.cmdl.getClassname()
  148. + " with default permissions (exit forbidden)", Project.MSG_VERBOSE);
  149. }
  150. log("Running in same VM " + cmdl.describeJavaCommand(),
  151. Project.MSG_VERBOSE);
  152. }
  153. setupRedirector();
  154. try {
  155. if (fork) {
  156. if (!spawn) {
  157. return fork(cmdl.getCommandline());
  158. } else {
  159. spawn(cmdl.getCommandline());
  160. return 0;
  161. }
  162. } else {
  163. try {
  164. run(cmdl);
  165. return 0;
  166. } catch (ExitException ex) {
  167. return ex.getStatus();
  168. }
  169. }
  170. } catch (BuildException e) {
  171. if (failOnError) {
  172. throw e;
  173. } else {
  174. log(e);
  175. return 0;
  176. }
  177. } catch (Throwable t) {
  178. if (failOnError) {
  179. throw new BuildException(t);
  180. } else {
  181. log(t);
  182. return 0;
  183. }
  184. }
  185. }
  186. /**
  187. * set whether or not you want the process to be spawned
  188. * default is not spawned
  189. * @param spawn if true you do not want ant to wait for the end of the process
  190. * @since ant 1.6
  191. */
  192. public void setSpawn(boolean spawn) {
  193. this.spawn = spawn;
  194. }
  195. /**
  196. * Set the classpath to be used when running the Java class
  197. *
  198. * @param s an Ant Path object containing the classpath.
  199. */
  200. public void setClasspath(Path s) {
  201. createClasspath().append(s);
  202. }
  203. /**
  204. * Adds a path to the classpath.
  205. *
  206. * @return created classpath
  207. */
  208. public Path createClasspath() {
  209. return cmdl.createClasspath(getProject()).createPath();
  210. }
  211. /**
  212. * Adds a path to the bootclasspath.
  213. * @since Ant 1.6
  214. *
  215. * @return created bootclasspath
  216. */
  217. public Path createBootclasspath() {
  218. return cmdl.createBootclasspath(getProject()).createPath();
  219. }
  220. /**
  221. * Sets the permissions for the application run inside the same JVM.
  222. * @since Ant 1.6
  223. * @return .
  224. */
  225. public Permissions createPermissions() {
  226. if (perm == null) {
  227. perm = new Permissions();
  228. }
  229. return perm;
  230. }
  231. /**
  232. * Classpath to use, by reference.
  233. *
  234. * @param r a reference to an existing classpath
  235. */
  236. public void setClasspathRef(Reference r) {
  237. createClasspath().setRefid(r);
  238. }
  239. /**
  240. * The location of the JAR file to execute.
  241. *
  242. * @param jarfile the jarfile that one wants to execute
  243. *
  244. * @throws BuildException if there is also a main class specified
  245. */
  246. public void setJar(File jarfile) throws BuildException {
  247. if (cmdl.getClassname() != null) {
  248. throw new BuildException("Cannot use 'jar' and 'classname' "
  249. + "attributes in same command.");
  250. }
  251. cmdl.setJar(jarfile.getAbsolutePath());
  252. }
  253. /**
  254. * Sets the Java class to execute.
  255. *
  256. * @param s the name of the main class
  257. *
  258. * @throws BuildException if the jar attribute has been set
  259. */
  260. public void setClassname(String s) throws BuildException {
  261. if (cmdl.getJar() != null) {
  262. throw new BuildException("Cannot use 'jar' and 'classname' "
  263. + "attributes in same command");
  264. }
  265. cmdl.setClassname(s);
  266. }
  267. /**
  268. * Deprecated: use nested arg instead.
  269. * Set the command line arguments for the class.
  270. *
  271. * @param s arguments
  272. *
  273. * @ant.attribute ignore="true"
  274. */
  275. public void setArgs(String s) {
  276. log("The args attribute is deprecated. "
  277. + "Please use nested arg elements.", Project.MSG_WARN);
  278. cmdl.createArgument().setLine(s);
  279. }
  280. /**
  281. * If set, system properties will be copied to the cloned VM - as
  282. * well as the bootclasspath unless you have explicitly specified
  283. * a bootclaspath.
  284. *
  285. * <p>Doesn't have any effect unless fork is true.</p>
  286. *
  287. * @since Ant 1.7
  288. */
  289. public void setCloneVm(boolean cloneVm) {
  290. cmdl.setCloneVm(cloneVm);
  291. }
  292. /**
  293. * Adds a command-line argument.
  294. *
  295. * @return created argument
  296. */
  297. public Commandline.Argument createArg() {
  298. return cmdl.createArgument();
  299. }
  300. /**
  301. * The name of a property in which the return code of the
  302. * command should be stored. Only of interest if failonerror=false.
  303. *
  304. * @param resultProperty name of property
  305. *
  306. * @since Ant 1.6
  307. */
  308. public void setResultProperty(String resultProperty) {
  309. this.resultProperty = resultProperty;
  310. incompatibleWithSpawn = true;
  311. }
  312. /**
  313. * helper method to set result property to the
  314. * passed in value if appropriate
  315. *
  316. * @param result the exit code
  317. */
  318. protected void maybeSetResultPropertyValue(int result) {
  319. String res = Integer.toString(result);
  320. if (resultProperty != null) {
  321. getProject().setNewProperty(resultProperty, res);
  322. }
  323. }
  324. /**
  325. * If true, execute in a new VM.
  326. *
  327. * @param s do you want to run Java in a new VM.
  328. */
  329. public void setFork(boolean s) {
  330. this.fork = s;
  331. }
  332. /**
  333. * Set the command line arguments for the JVM.
  334. *
  335. * @param s jvmargs
  336. */
  337. public void setJvmargs(String s) {
  338. log("The jvmargs attribute is deprecated. "
  339. + "Please use nested jvmarg elements.", Project.MSG_WARN);
  340. cmdl.createVmArgument().setLine(s);
  341. }
  342. /**
  343. * Adds a JVM argument.
  344. *
  345. * @return JVM argument created
  346. */
  347. public Commandline.Argument createJvmarg() {
  348. return cmdl.createVmArgument();
  349. }
  350. /**
  351. * Set the command used to start the VM (only if forking).
  352. *
  353. * @param s command to start the VM
  354. */
  355. public void setJvm(String s) {
  356. cmdl.setVm(s);
  357. }
  358. /**
  359. * Adds a system property.
  360. *
  361. * @param sysp system property
  362. */
  363. public void addSysproperty(Environment.Variable sysp) {
  364. cmdl.addSysproperty(sysp);
  365. }
  366. /**
  367. * Adds a set of properties as system properties.
  368. *
  369. * @param sysp set of properties to add
  370. *
  371. * @since Ant 1.6
  372. */
  373. public void addSyspropertyset(PropertySet sysp) {
  374. cmdl.addSyspropertyset(sysp);
  375. }
  376. /**
  377. * If true, then fail if the command exits with a
  378. * returncode other than 0
  379. *
  380. * @param fail if true fail the build when the command exits with a non
  381. * zero returncode
  382. */
  383. public void setFailonerror(boolean fail) {
  384. failOnError = fail;
  385. incompatibleWithSpawn |= fail;
  386. }
  387. /**
  388. * The working directory of the process
  389. *
  390. * @param d working directory
  391. *
  392. */
  393. public void setDir(File d) {
  394. this.dir = d;
  395. }
  396. /**
  397. * File the output of the process is redirected to.
  398. *
  399. * @param out name of the output file
  400. */
  401. public void setOutput(File out) {
  402. this.output = out;
  403. incompatibleWithSpawn = true;
  404. }
  405. /**
  406. * Set the input to use for the task
  407. *
  408. * @param input name of the input file
  409. */
  410. public void setInput(File input) {
  411. if (inputString != null) {
  412. throw new BuildException("The \"input\" and \"inputstring\" "
  413. + "attributes cannot both be specified");
  414. }
  415. this.input = input;
  416. incompatibleWithSpawn = true;
  417. }
  418. /**
  419. * Set the string to use as input
  420. *
  421. * @param inputString the string which is used as the input source
  422. */
  423. public void setInputString(String inputString) {
  424. if (input != null) {
  425. throw new BuildException("The \"input\" and \"inputstring\" "
  426. + "attributes cannot both be specified");
  427. }
  428. this.inputString = inputString;
  429. incompatibleWithSpawn = true;
  430. }
  431. /**
  432. * Controls whether error output of exec is logged. This is only useful
  433. * when output is being redirected and error output is desired in the
  434. * Ant log
  435. *
  436. * @param logError get in the ant log the messages coming from stderr
  437. * in the case that fork = true
  438. */
  439. public void setLogError(boolean logError) {
  440. redirector.setLogError(logError);
  441. incompatibleWithSpawn |= logError;
  442. }
  443. /**
  444. * File the error stream of the process is redirected to.
  445. *
  446. * @param error file getting the error stream
  447. *
  448. * @since ant 1.6
  449. */
  450. public void setError(File error) {
  451. this.error = error;
  452. incompatibleWithSpawn = true;
  453. }
  454. /**
  455. * Property name whose value should be set to the output of
  456. * the process.
  457. *
  458. * @param outputProp property name
  459. *
  460. */
  461. public void setOutputproperty(String outputProp) {
  462. redirector.setOutputProperty(outputProp);
  463. incompatibleWithSpawn = true;
  464. }
  465. /**
  466. * Property name whose value should be set to the error of
  467. * the process.
  468. *
  469. * @param errorProperty property name
  470. *
  471. * @since ant 1.6
  472. */
  473. public void setErrorProperty(String errorProperty) {
  474. redirector.setErrorProperty(errorProperty);
  475. incompatibleWithSpawn = true;
  476. }
  477. /**
  478. * Corresponds to -mx or -Xmx depending on VM version.
  479. *
  480. * @param max max memory parameter
  481. */
  482. public void setMaxmemory(String max) {
  483. cmdl.setMaxmemory(max);
  484. }
  485. /**
  486. * Sets the JVM version.
  487. * @param value JVM version
  488. */
  489. public void setJVMVersion(String value) {
  490. cmdl.setVmversion(value);
  491. }
  492. /**
  493. * Adds an environment variable.
  494. *
  495. * <p>Will be ignored if we are not forking a new VM.
  496. *
  497. * @param var new environment variable
  498. *
  499. * @since Ant 1.5
  500. */
  501. public void addEnv(Environment.Variable var) {
  502. env.addVariable(var);
  503. }
  504. /**
  505. * If true, use a completely new environment.
  506. *
  507. * <p>Will be ignored if we are not forking a new VM.
  508. *
  509. * @param newenv if true, use a completely new environment.
  510. *
  511. * @since Ant 1.5
  512. */
  513. public void setNewenvironment(boolean newenv) {
  514. newEnvironment = newenv;
  515. }
  516. /**
  517. * If true, append output to existing file.
  518. *
  519. * @param append if true, append output to existing file
  520. *
  521. * @since Ant 1.5
  522. */
  523. public void setAppend(boolean append) {
  524. redirector.setAppend(append);
  525. incompatibleWithSpawn = true;
  526. }
  527. /**
  528. * Timeout in milliseconds after which the process will be killed.
  529. *
  530. * @param value time out in milliseconds
  531. *
  532. * @since Ant 1.5
  533. */
  534. public void setTimeout(Long value) {
  535. timeout = value;
  536. incompatibleWithSpawn |= timeout != null;
  537. }
  538. /**
  539. * assertions to enable in this program (if fork=true)
  540. * @since Ant 1.6
  541. * @param asserts assertion set
  542. */
  543. public void addAssertions(Assertions asserts) {
  544. if (cmdl.getAssertions() != null) {
  545. throw new BuildException("Only one assertion declaration is allowed");
  546. }
  547. cmdl.setAssertions(asserts);
  548. }
  549. /**
  550. * Add a <CODE>RedirectorElement</CODE> to this task.
  551. * @param redirectorElement <CODE>RedirectorElement</CODE>.
  552. */
  553. public void addConfiguredRedirector(RedirectorElement redirectorElement) {
  554. if (this.redirectorElement != null) {
  555. throw new BuildException("cannot have > 1 nested <redirector>s");
  556. } else {
  557. this.redirectorElement = redirectorElement;
  558. incompatibleWithSpawn = true;
  559. }
  560. }
  561. /**
  562. * Pass output sent to System.out to specified output file.
  563. *
  564. * @param output a string of output on its way to the handlers
  565. *
  566. * @since Ant 1.5
  567. */
  568. protected void handleOutput(String output) {
  569. if (redirector.getOutputStream() != null) {
  570. redirector.handleOutput(output);
  571. } else {
  572. super.handleOutput(output);
  573. }
  574. }
  575. /**
  576. * Handle an input request by this task
  577. *
  578. * @param buffer the buffer into which data is to be read.
  579. * @param offset the offset into the buffer at which data is stored.
  580. * @param length the amount of data to read
  581. *
  582. * @return the number of bytes read
  583. *
  584. * @exception IOException if the data cannot be read
  585. * @since Ant 1.6
  586. */
  587. public int handleInput(byte[] buffer, int offset, int length)
  588. throws IOException {
  589. if (redirector.getInputStream() != null) {
  590. return redirector.handleInput(buffer, offset, length);
  591. } else {
  592. return super.handleInput(buffer, offset, length);
  593. }
  594. }
  595. /**
  596. * Pass output sent to System.out to specified output file.
  597. *
  598. * @param output string of output on its way to its handlers
  599. *
  600. * @since Ant 1.5.2
  601. */
  602. protected void handleFlush(String output) {
  603. if (redirector.getOutputStream() != null) {
  604. redirector.handleFlush(output);
  605. } else {
  606. super.handleFlush(output);
  607. }
  608. }
  609. /**
  610. * Handle output sent to System.err
  611. *
  612. * @param output string of stderr
  613. *
  614. * @since Ant 1.5
  615. */
  616. protected void handleErrorOutput(String output) {
  617. if (redirector.getErrorStream() != null) {
  618. redirector.handleErrorOutput(output);
  619. } else {
  620. super.handleErrorOutput(output);
  621. }
  622. }
  623. /**
  624. * Handle output sent to System.err and flush the stream.
  625. *
  626. * @param output string of stderr
  627. *
  628. * @since Ant 1.5.2
  629. */
  630. protected void handleErrorFlush(String output) {
  631. if (redirector.getErrorStream() != null) {
  632. redirector.handleErrorFlush(output);
  633. } else {
  634. super.handleErrorOutput(output);
  635. }
  636. }
  637. /**
  638. * Set up properties on the redirector that we needed to store locally.
  639. */
  640. protected void setupRedirector() {
  641. redirector.setInput(input);
  642. redirector.setInputString(inputString);
  643. redirector.setOutput(output);
  644. redirector.setError(error);
  645. if (redirectorElement != null) {
  646. redirectorElement.configure(redirector);
  647. }
  648. }
  649. /**
  650. * Executes the given classname with the given arguments as it
  651. * was a command line application.
  652. */
  653. private void run(CommandlineJava command) throws BuildException {
  654. try {
  655. ExecuteJava exe = new ExecuteJava();
  656. exe.setJavaCommand(command.getJavaCommand());
  657. exe.setClasspath(command.getClasspath());
  658. exe.setSystemProperties(command.getSystemProperties());
  659. exe.setPermissions(perm);
  660. exe.setTimeout(timeout);
  661. redirector.createStreams();
  662. exe.execute(getProject());
  663. redirector.complete();
  664. if (exe.killedProcess()) {
  665. throw new BuildException("Timeout: killed the sub-process");
  666. }
  667. } catch (IOException e) {
  668. throw new BuildException(e);
  669. }
  670. }
  671. /**
  672. * Executes the given classname with the given arguments in a separate VM.
  673. */
  674. private int fork(String[] command) throws BuildException {
  675. Execute exe
  676. = new Execute(redirector.createHandler(), createWatchdog());
  677. setupExecutable(exe, command);
  678. try {
  679. int rc = exe.execute();
  680. redirector.complete();
  681. if (exe.killedProcess()) {
  682. throw new BuildException("Timeout: killed the sub-process");
  683. }
  684. return rc;
  685. } catch (IOException e) {
  686. throw new BuildException(e, getLocation());
  687. }
  688. }
  689. /**
  690. * Executes the given classname with the given arguments in a separate VM.
  691. */
  692. private void spawn(String[] command) throws BuildException {
  693. Execute exe
  694. = new Execute();
  695. setupExecutable(exe, command);
  696. try {
  697. exe.spawn();
  698. } catch (IOException e) {
  699. throw new BuildException(e, getLocation());
  700. }
  701. }
  702. /**
  703. * Do all configuration for an executable that
  704. * is common across the {@link #fork(String[])} and
  705. * {@link #spawn(String[])} methods
  706. * @param exe executable
  707. * @param command command to execute
  708. */
  709. private void setupExecutable(Execute exe, String[] command) {
  710. exe.setAntRun(getProject());
  711. setupWorkingDir(exe);
  712. setupEnvironment(exe);
  713. setupCommandLine(exe, command);
  714. }
  715. /**
  716. * set up our environment variables
  717. * @param exe
  718. */
  719. private void setupEnvironment(Execute exe) {
  720. String[] environment = env.getVariables();
  721. if (environment != null) {
  722. for (int i = 0; i < environment.length; i++) {
  723. log("Setting environment variable: " + environment[i],
  724. Project.MSG_VERBOSE);
  725. }
  726. }
  727. exe.setNewenvironment(newEnvironment);
  728. exe.setEnvironment(environment);
  729. }
  730. /**
  731. * set the working dir of the new process
  732. * @param exe
  733. * @throws BuildException if the dir doesn't exist.
  734. */
  735. private void setupWorkingDir(Execute exe) {
  736. if (dir == null) {
  737. dir = getProject().getBaseDir();
  738. } else if (!dir.exists() || !dir.isDirectory()) {
  739. throw new BuildException(dir.getAbsolutePath()
  740. + " is not a valid directory",
  741. getLocation());
  742. }
  743. exe.setWorkingDirectory(dir);
  744. }
  745. /**
  746. * set the command line for the exe.
  747. * On VMS, hands off to {@link #setupCommandLineForVMS(Execute, String[])}
  748. * @param exe
  749. * @param command
  750. */
  751. private void setupCommandLine(Execute exe, String[] command) {
  752. //On VMS platform, we need to create a special java options file
  753. //containing the arguments and classpath for the java command.
  754. //The special file is supported by the "-V" switch on the VMS JVM.
  755. if (Os.isFamily("openvms")) {
  756. setupCommandLineForVMS(exe, command);
  757. } else {
  758. exe.setCommandline(command);
  759. }
  760. }
  761. /**
  762. * On VMS platform, we need to create a special java options file
  763. * containing the arguments and classpath for the java command.
  764. * The special file is supported by the "-V" switch on the VMS JVM.
  765. *
  766. * @param exe
  767. * @param command
  768. */
  769. private void setupCommandLineForVMS(Execute exe, String[] command) {
  770. //Use the VM launcher instead of shell launcher on VMS
  771. exe.setVMLauncher(true);
  772. File vmsJavaOptionFile = null;
  773. try {
  774. String [] args = new String[command.length - 1];
  775. System.arraycopy(command, 1, args, 0, command.length - 1);
  776. vmsJavaOptionFile = JavaEnvUtils.createVmsJavaOptionFile(args);
  777. //we mark the file to be deleted on exit.
  778. //the alternative would be to cache the filename and delete
  779. //after execution finished, which is much better for long-lived runtimes
  780. //though spawning complicates things...
  781. vmsJavaOptionFile.deleteOnExit();
  782. String [] vmsCmd = {command[0], "-V", vmsJavaOptionFile.getPath()};
  783. exe.setCommandline(vmsCmd);
  784. } catch (IOException e) {
  785. throw new BuildException("Failed to create a temporary file for \"-V\" switch");
  786. }
  787. }
  788. /**
  789. * Executes the given classname with the given arguments as it
  790. * was a command line application.
  791. *
  792. * @param classname the name of the class to run
  793. * @param args arguments for the class
  794. * @throws BuildException in case of IO Exception in the execution
  795. */
  796. protected void run(String classname, Vector args) throws BuildException {
  797. CommandlineJava cmdj = new CommandlineJava();
  798. cmdj.setClassname(classname);
  799. for (int i = 0; i < args.size(); i++) {
  800. cmdj.createArgument().setValue((String) args.elementAt(i));
  801. }
  802. run(cmdj);
  803. }
  804. /**
  805. * Clear out the arguments to this java task.
  806. */
  807. public void clearArgs() {
  808. cmdl.clearJavaArgs();
  809. }
  810. /**
  811. * Create the Watchdog to kill a runaway process.
  812. *
  813. * @return new watchdog
  814. *
  815. * @throws BuildException under unknown circumstances
  816. *
  817. * @since Ant 1.5
  818. */
  819. protected ExecuteWatchdog createWatchdog() throws BuildException {
  820. if (timeout == null) {
  821. return null;
  822. }
  823. return new ExecuteWatchdog(timeout.longValue());
  824. }
  825. /**
  826. * @since 1.6.2
  827. */
  828. private void log(Throwable t) {
  829. StringWriter sw = new StringWriter();
  830. PrintWriter w = new PrintWriter(sw);
  831. t.printStackTrace(w);
  832. w.close();
  833. log(sw.toString(), Project.MSG_ERR);
  834. }
  835. /**
  836. * accessor to the command line
  837. *
  838. * @return the current command line
  839. * @since 1.7
  840. */
  841. public CommandlineJava getCommandLine() {
  842. return cmdl;
  843. }
  844. /**
  845. * get the system properties of the command line
  846. *
  847. * @return the current properties of this java invocation
  848. * @since 1.7
  849. */
  850. public CommandlineJava.SysProperties getSysProperties() {
  851. return cmdl.getSystemProperties();
  852. }
  853. }