001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.io.PrintWriter;
024: import java.io.StringWriter;
025: import java.util.Vector;
026: import org.apache.tools.ant.BuildException;
027: import org.apache.tools.ant.ExitException;
028: import org.apache.tools.ant.Project;
029: import org.apache.tools.ant.Task;
030: import org.apache.tools.ant.ExitStatusException;
031: import org.apache.tools.ant.types.Commandline;
032: import org.apache.tools.ant.types.CommandlineJava;
033: import org.apache.tools.ant.types.Environment;
034: import org.apache.tools.ant.types.Path;
035: import org.apache.tools.ant.types.PropertySet;
036: import org.apache.tools.ant.types.Reference;
037: import org.apache.tools.ant.types.Assertions;
038: import org.apache.tools.ant.types.Permissions;
039: import org.apache.tools.ant.types.RedirectorElement;
040: import org.apache.tools.ant.taskdefs.condition.Os;
041: import org.apache.tools.ant.util.KeepAliveInputStream;
042:
043: /**
044: * Launcher for Java applications. Allows use of
045: * the same JVM for the called application thus resulting in much
046: * faster operation.
047: *
048: * @since Ant 1.1
049: *
050: * @ant.task category="java"
051: */
052: public class Java extends Task {
053:
054: private CommandlineJava cmdl = new CommandlineJava();
055: private Environment env = new Environment();
056: private boolean fork = false;
057: private boolean newEnvironment = false;
058: private File dir = null;
059: private boolean failOnError = false;
060: private Long timeout = null;
061:
062: //include locally for screening purposes
063: private String inputString;
064: private File input;
065: private File output;
066: private File error;
067:
068: // CheckStyle:VisibilityModifier OFF - bc
069: protected Redirector redirector = new Redirector(this );
070: protected RedirectorElement redirectorElement;
071: // CheckStyle:VisibilityModifier ON
072:
073: private String resultProperty;
074: private Permissions perm = null;
075:
076: private boolean spawn = false;
077: private boolean incompatibleWithSpawn = false;
078:
079: /**
080: * Normal constructor
081: */
082: public Java() {
083: }
084:
085: /**
086: * create a bound task
087: * @param owner owner
088: */
089: public Java(Task owner) {
090: bindToOwner(owner);
091: }
092:
093: /**
094: * Do the execution.
095: * @throws BuildException if failOnError is set to true and the application
096: * returns a nonzero result code.
097: */
098: public void execute() throws BuildException {
099: File savedDir = dir;
100: Permissions savedPermissions = perm;
101:
102: int err = -1;
103: try {
104: err = executeJava();
105: if (err != 0) {
106: if (failOnError) {
107: throw new ExitStatusException("Java returned: "
108: + err, err, getLocation());
109: } else {
110: log("Java Result: " + err, Project.MSG_ERR);
111: }
112: }
113: maybeSetResultPropertyValue(err);
114: } finally {
115: dir = savedDir;
116: perm = savedPermissions;
117: }
118: }
119:
120: /**
121: * Do the execution and return a return code.
122: *
123: * @return the return code from the execute java class if it was
124: * executed in a separate VM (fork = "yes") or a security manager was
125: * installed that prohibits ExitVM (default).
126: *
127: * @throws BuildException if required parameters are missing.
128: */
129: public int executeJava() throws BuildException {
130: String classname = getCommandLine().getClassname();
131: if (classname == null && getCommandLine().getJar() == null) {
132: throw new BuildException("Classname must not be null.");
133: }
134: if (!fork && getCommandLine().getJar() != null) {
135: throw new BuildException(
136: "Cannot execute a jar in non-forked mode."
137: + " Please set fork='true'. ");
138: }
139: if (spawn && !fork) {
140: throw new BuildException(
141: "Cannot spawn a java process in non-forked mode."
142: + " Please set fork='true'. ");
143: }
144: if (getCommandLine().getClasspath() != null
145: && getCommandLine().getJar() != null) {
146: log(
147: "When using 'jar' attribute classpath-settings are ignored. "
148: + "See the manual for more information.",
149: Project.MSG_VERBOSE);
150: }
151: if (spawn && incompatibleWithSpawn) {
152: getProject().log(
153: "spawn does not allow attributes related to input, "
154: + "output, error, result", Project.MSG_ERR);
155: getProject().log("spawn also does not allow timeout",
156: Project.MSG_ERR);
157: getProject().log(
158: "finally, spawn is not compatible "
159: + "with a nested I/O <redirector>",
160: Project.MSG_ERR);
161: throw new BuildException(
162: "You have used an attribute "
163: + "or nested element which is not compatible with spawn");
164: }
165: if (getCommandLine().getAssertions() != null && !fork) {
166: log("Assertion statements are currently ignored in non-forked mode");
167: }
168: if (fork) {
169: if (perm != null) {
170: log(
171: "Permissions can not be set this way in forked mode.",
172: Project.MSG_WARN);
173: }
174: log(getCommandLine().describeCommand(), Project.MSG_VERBOSE);
175: } else {
176: if (getCommandLine().getVmCommand().size() > 1) {
177: log("JVM args ignored when same JVM is used.",
178: Project.MSG_WARN);
179: }
180: if (dir != null) {
181: log("Working directory ignored when same JVM is used.",
182: Project.MSG_WARN);
183: }
184: if (newEnvironment || null != env.getVariables()) {
185: log(
186: "Changes to environment variables are ignored when same "
187: + "JVM is used.", Project.MSG_WARN);
188: }
189: if (getCommandLine().getBootclasspath() != null) {
190: log("bootclasspath ignored when same JVM is used.",
191: Project.MSG_WARN);
192: }
193: if (perm == null) {
194: perm = new Permissions(true);
195: log("running " + this .getCommandLine().getClassname()
196: + " with default permissions (exit forbidden)",
197: Project.MSG_VERBOSE);
198: }
199: log("Running in same VM "
200: + getCommandLine().describeJavaCommand(),
201: Project.MSG_VERBOSE);
202: }
203: setupRedirector();
204: try {
205: if (fork) {
206: if (!spawn) {
207: return fork(getCommandLine().getCommandline());
208: } else {
209: spawn(getCommandLine().getCommandline());
210: return 0;
211: }
212: } else {
213: try {
214: run(getCommandLine());
215: return 0;
216: } catch (ExitException ex) {
217: return ex.getStatus();
218: }
219: }
220: } catch (BuildException e) {
221: if (e.getLocation() == null && getLocation() != null) {
222: e.setLocation(getLocation());
223: }
224: if (failOnError) {
225: throw e;
226: } else {
227: log(e);
228: return 0;
229: }
230: } catch (ThreadDeath t) {
231: throw t; // cf. NB #47191
232: } catch (Throwable t) {
233: if (failOnError) {
234: throw new BuildException(t, getLocation());
235: } else {
236: log(t);
237: return 0;
238: }
239: }
240: }
241:
242: /**
243: * Set whether or not you want the process to be spawned;
244: * default is not spawned.
245: * @param spawn if true you do not want Ant to wait for the end of the process.
246: * @since Ant 1.6
247: */
248: public void setSpawn(boolean spawn) {
249: this .spawn = spawn;
250: }
251:
252: /**
253: * Set the classpath to be used when running the Java class.
254: *
255: * @param s an Ant Path object containing the classpath.
256: */
257: public void setClasspath(Path s) {
258: createClasspath().append(s);
259: }
260:
261: /**
262: * Add a path to the classpath.
263: *
264: * @return created classpath.
265: */
266: public Path createClasspath() {
267: return getCommandLine().createClasspath(getProject())
268: .createPath();
269: }
270:
271: /**
272: * Add a path to the bootclasspath.
273: * @since Ant 1.6
274: *
275: * @return created bootclasspath.
276: */
277: public Path createBootclasspath() {
278: return getCommandLine().createBootclasspath(getProject())
279: .createPath();
280: }
281:
282: /**
283: * Set the permissions for the application run inside the same JVM.
284: * @since Ant 1.6
285: * @return Permissions.
286: */
287: public Permissions createPermissions() {
288: perm = (perm == null) ? new Permissions() : perm;
289: return perm;
290: }
291:
292: /**
293: * Set the classpath to use by reference.
294: *
295: * @param r a reference to an existing classpath.
296: */
297: public void setClasspathRef(Reference r) {
298: createClasspath().setRefid(r);
299: }
300:
301: /**
302: * Set the location of the JAR file to execute.
303: *
304: * @param jarfile the jarfile to execute.
305: *
306: * @throws BuildException if there is also a main class specified.
307: */
308: public void setJar(File jarfile) throws BuildException {
309: if (getCommandLine().getClassname() != null) {
310: throw new BuildException(
311: "Cannot use 'jar' and 'classname' "
312: + "attributes in same command.");
313: }
314: getCommandLine().setJar(jarfile.getAbsolutePath());
315: }
316:
317: /**
318: * Set the Java class to execute.
319: *
320: * @param s the name of the main class.
321: *
322: * @throws BuildException if the jar attribute has been set.
323: */
324: public void setClassname(String s) throws BuildException {
325: if (getCommandLine().getJar() != null) {
326: throw new BuildException(
327: "Cannot use 'jar' and 'classname' "
328: + "attributes in same command");
329: }
330: getCommandLine().setClassname(s);
331: }
332:
333: /**
334: * Deprecated: use nested arg instead.
335: * Set the command line arguments for the class.
336: *
337: * @param s arguments.
338: *
339: * @ant.attribute ignore="true"
340: */
341: public void setArgs(String s) {
342: log("The args attribute is deprecated. "
343: + "Please use nested arg elements.", Project.MSG_WARN);
344: getCommandLine().createArgument().setLine(s);
345: }
346:
347: /**
348: * If set, system properties will be copied to the cloned VM--as
349: * well as the bootclasspath unless you have explicitly specified
350: * a bootclaspath.
351: *
352: * <p>Doesn't have any effect unless fork is true.</p>
353: * @param cloneVm if true copy system properties.
354: * @since Ant 1.7
355: */
356: public void setCloneVm(boolean cloneVm) {
357: getCommandLine().setCloneVm(cloneVm);
358: }
359:
360: /**
361: * Add a command-line argument.
362: *
363: * @return created argument.
364: */
365: public Commandline.Argument createArg() {
366: return getCommandLine().createArgument();
367: }
368:
369: /**
370: * Set the name of the property in which the return code of the
371: * command should be stored. Only of interest if failonerror=false.
372: *
373: * @param resultProperty name of property.
374: *
375: * @since Ant 1.6
376: */
377: public void setResultProperty(String resultProperty) {
378: this .resultProperty = resultProperty;
379: incompatibleWithSpawn = true;
380: }
381:
382: /**
383: * Helper method to set result property to the
384: * passed in value if appropriate.
385: *
386: * @param result the exit code
387: */
388: protected void maybeSetResultPropertyValue(int result) {
389: String res = Integer.toString(result);
390: if (resultProperty != null) {
391: getProject().setNewProperty(resultProperty, res);
392: }
393: }
394:
395: /**
396: * If true, execute in a new VM.
397: *
398: * @param s do you want to run Java in a new VM.
399: */
400: public void setFork(boolean s) {
401: this .fork = s;
402: }
403:
404: /**
405: * Set the command line arguments for the JVM.
406: *
407: * @param s jvmargs.
408: */
409: public void setJvmargs(String s) {
410: log("The jvmargs attribute is deprecated. "
411: + "Please use nested jvmarg elements.",
412: Project.MSG_WARN);
413: getCommandLine().createVmArgument().setLine(s);
414: }
415:
416: /**
417: * Adds a JVM argument.
418: *
419: * @return JVM argument created.
420: */
421: public Commandline.Argument createJvmarg() {
422: return getCommandLine().createVmArgument();
423: }
424:
425: /**
426: * Set the command used to start the VM (only if forking).
427: *
428: * @param s command to start the VM.
429: */
430: public void setJvm(String s) {
431: getCommandLine().setVm(s);
432: }
433:
434: /**
435: * Add a system property.
436: *
437: * @param sysp system property.
438: */
439: public void addSysproperty(Environment.Variable sysp) {
440: getCommandLine().addSysproperty(sysp);
441: }
442:
443: /**
444: * Add a set of properties as system properties.
445: *
446: * @param sysp set of properties to add.
447: *
448: * @since Ant 1.6
449: */
450: public void addSyspropertyset(PropertySet sysp) {
451: getCommandLine().addSyspropertyset(sysp);
452: }
453:
454: /**
455: * If true, then fail if the command exits with a
456: * returncode other than zero.
457: *
458: * @param fail if true fail the build when the command exits with a
459: * nonzero returncode.
460: */
461: public void setFailonerror(boolean fail) {
462: failOnError = fail;
463: incompatibleWithSpawn |= fail;
464: }
465:
466: /**
467: * Set the working directory of the process.
468: *
469: * @param d working directory.
470: *
471: */
472: public void setDir(File d) {
473: this .dir = d;
474: }
475:
476: /**
477: * Set the File to which the output of the process is redirected.
478: *
479: * @param out the output File.
480: */
481: public void setOutput(File out) {
482: this .output = out;
483: incompatibleWithSpawn = true;
484: }
485:
486: /**
487: * Set the input to use for the task.
488: *
489: * @param input name of the input file.
490: */
491: public void setInput(File input) {
492: if (inputString != null) {
493: throw new BuildException(
494: "The \"input\" and \"inputstring\" "
495: + "attributes cannot both be specified");
496: }
497: this .input = input;
498: incompatibleWithSpawn = true;
499: }
500:
501: /**
502: * Set the string to use as input.
503: *
504: * @param inputString the string which is used as the input source.
505: */
506: public void setInputString(String inputString) {
507: if (input != null) {
508: throw new BuildException(
509: "The \"input\" and \"inputstring\" "
510: + "attributes cannot both be specified");
511: }
512: this .inputString = inputString;
513: incompatibleWithSpawn = true;
514: }
515:
516: /**
517: * Set whether error output of exec is logged. This is only useful
518: * when output is being redirected and error output is desired in the
519: * Ant log.
520: *
521: * @param logError get in the ant log the messages coming from stderr
522: * in the case that fork = true.
523: */
524: public void setLogError(boolean logError) {
525: redirector.setLogError(logError);
526: incompatibleWithSpawn |= logError;
527: }
528:
529: /**
530: * Set the File to which the error stream of the process is redirected.
531: *
532: * @param error file getting the error stream.
533: *
534: * @since Ant 1.6
535: */
536: public void setError(File error) {
537: this .error = error;
538: incompatibleWithSpawn = true;
539: }
540:
541: /**
542: * Set the property name whose value should be set to the output of
543: * the process.
544: *
545: * @param outputProp property name.
546: *
547: */
548: public void setOutputproperty(String outputProp) {
549: redirector.setOutputProperty(outputProp);
550: incompatibleWithSpawn = true;
551: }
552:
553: /**
554: * Set the property name whose value should be set to the error of
555: * the process.
556: *
557: * @param errorProperty property name.
558: *
559: * @since Ant 1.6
560: */
561: public void setErrorProperty(String errorProperty) {
562: redirector.setErrorProperty(errorProperty);
563: incompatibleWithSpawn = true;
564: }
565:
566: /**
567: * Corresponds to -mx or -Xmx depending on VM version.
568: *
569: * @param max max memory parameter.
570: */
571: public void setMaxmemory(String max) {
572: getCommandLine().setMaxmemory(max);
573: }
574:
575: /**
576: * Set the JVM version.
577: * @param value JVM version.
578: */
579: public void setJVMVersion(String value) {
580: getCommandLine().setVmversion(value);
581: }
582:
583: /**
584: * Add an environment variable.
585: *
586: * <p>Will be ignored if we are not forking a new VM.
587: *
588: * @param var new environment variable.
589: *
590: * @since Ant 1.5
591: */
592: public void addEnv(Environment.Variable var) {
593: env.addVariable(var);
594: }
595:
596: /**
597: * If true, use a completely new environment.
598: *
599: * <p>Will be ignored if we are not forking a new VM.
600: *
601: * @param newenv if true, use a completely new environment.
602: *
603: * @since Ant 1.5
604: */
605: public void setNewenvironment(boolean newenv) {
606: newEnvironment = newenv;
607: }
608:
609: /**
610: * If true, append output to existing file.
611: *
612: * @param append if true, append output to existing file.
613: *
614: * @since Ant 1.5
615: */
616: public void setAppend(boolean append) {
617: redirector.setAppend(append);
618: incompatibleWithSpawn = true;
619: }
620:
621: /**
622: * Set the timeout in milliseconds after which the process will be killed.
623: *
624: * @param value timeout in milliseconds.
625: *
626: * @since Ant 1.5
627: */
628: public void setTimeout(Long value) {
629: timeout = value;
630: incompatibleWithSpawn |= timeout != null;
631: }
632:
633: /**
634: * Add assertions to enable in this program (if fork=true).
635: * @param asserts assertion set.
636: * @since Ant 1.6
637: */
638: public void addAssertions(Assertions asserts) {
639: if (getCommandLine().getAssertions() != null) {
640: throw new BuildException(
641: "Only one assertion declaration is allowed");
642: }
643: getCommandLine().setAssertions(asserts);
644: }
645:
646: /**
647: * Add a <code>RedirectorElement</code> to this task.
648: * @param redirectorElement <code>RedirectorElement</code>.
649: */
650: public void addConfiguredRedirector(
651: RedirectorElement redirectorElement) {
652: if (this .redirectorElement != null) {
653: throw new BuildException(
654: "cannot have > 1 nested redirectors");
655: }
656: this .redirectorElement = redirectorElement;
657: incompatibleWithSpawn = true;
658: }
659:
660: /**
661: * Pass output sent to System.out to specified output file.
662: *
663: * @param output a string of output on its way to the handlers.
664: *
665: * @since Ant 1.5
666: */
667: protected void handleOutput(String output) {
668: if (redirector.getOutputStream() != null) {
669: redirector.handleOutput(output);
670: } else {
671: super .handleOutput(output);
672: }
673: }
674:
675: /**
676: * Handle an input request by this task.
677: *
678: * @param buffer the buffer into which data is to be read.
679: * @param offset the offset into the buffer at which data is stored.
680: * @param length the amount of data to read.
681: *
682: * @return the number of bytes read.
683: *
684: * @exception IOException if the data cannot be read.
685: * @since Ant 1.6
686: */
687: public int handleInput(byte[] buffer, int offset, int length)
688: throws IOException {
689: // Should work whether or not redirector.inputStream == null:
690: return redirector.handleInput(buffer, offset, length);
691: }
692:
693: /**
694: * Pass output sent to System.out to specified output file.
695: *
696: * @param output string of output on its way to its handlers.
697: *
698: * @since Ant 1.5.2
699: */
700: protected void handleFlush(String output) {
701: if (redirector.getOutputStream() != null) {
702: redirector.handleFlush(output);
703: } else {
704: super .handleFlush(output);
705: }
706: }
707:
708: /**
709: * Handle output sent to System.err.
710: *
711: * @param output string of stderr.
712: *
713: * @since Ant 1.5
714: */
715: protected void handleErrorOutput(String output) {
716: if (redirector.getErrorStream() != null) {
717: redirector.handleErrorOutput(output);
718: } else {
719: super .handleErrorOutput(output);
720: }
721: }
722:
723: /**
724: * Handle output sent to System.err and flush the stream.
725: *
726: * @param output string of stderr.
727: *
728: * @since Ant 1.5.2
729: */
730: protected void handleErrorFlush(String output) {
731: if (redirector.getErrorStream() != null) {
732: redirector.handleErrorFlush(output);
733: } else {
734: super .handleErrorOutput(output);
735: }
736: }
737:
738: /**
739: * Set up properties on the redirector that we needed to store locally.
740: */
741: protected void setupRedirector() {
742: redirector.setInput(input);
743: redirector.setInputString(inputString);
744: redirector.setOutput(output);
745: redirector.setError(error);
746: if (redirectorElement != null) {
747: redirectorElement.configure(redirector);
748: }
749: if (!spawn && input == null && inputString == null) {
750: // #24918: send standard input to the process by default.
751: redirector.setInputStream(new KeepAliveInputStream(
752: getProject().getDefaultInputStream()));
753: }
754: }
755:
756: /**
757: * Executes the given classname with the given arguments as it
758: * were a command line application.
759: * @param command CommandlineJava.
760: */
761: private void run(CommandlineJava command) throws BuildException {
762: try {
763: ExecuteJava exe = new ExecuteJava();
764: exe.setJavaCommand(command.getJavaCommand());
765: exe.setClasspath(command.getClasspath());
766: exe.setSystemProperties(command.getSystemProperties());
767: exe.setPermissions(perm);
768: exe.setTimeout(timeout);
769: redirector.createStreams();
770: exe.execute(getProject());
771: redirector.complete();
772: if (exe.killedProcess()) {
773: throw new BuildException(
774: "Timeout: killed the sub-process");
775: }
776: } catch (IOException e) {
777: throw new BuildException(e);
778: }
779: }
780:
781: /**
782: * Executes the given classname with the given arguments in a separate VM.
783: * @param command String[] of command-line arguments.
784: */
785: private int fork(String[] command) throws BuildException {
786: Execute exe = new Execute(redirector.createHandler(),
787: createWatchdog());
788: setupExecutable(exe, command);
789:
790: try {
791: int rc = exe.execute();
792: redirector.complete();
793: if (exe.killedProcess()) {
794: throw new BuildException(
795: "Timeout: killed the sub-process");
796: }
797: return rc;
798: } catch (IOException e) {
799: throw new BuildException(e, getLocation());
800: }
801: }
802:
803: /**
804: * Executes the given classname with the given arguments in a separate VM.
805: * @param command String[] of command-line arguments.
806: */
807: private void spawn(String[] command) throws BuildException {
808: Execute exe = new Execute();
809: setupExecutable(exe, command);
810: try {
811: exe.spawn();
812: } catch (IOException e) {
813: throw new BuildException(e, getLocation());
814: }
815: }
816:
817: /**
818: * Do all configuration for an executable that
819: * is common across the {@link #fork(String[])} and
820: * {@link #spawn(String[])} methods.
821: * @param exe executable.
822: * @param command command to execute.
823: */
824: private void setupExecutable(Execute exe, String[] command) {
825: exe.setAntRun(getProject());
826: setupWorkingDir(exe);
827: setupEnvironment(exe);
828: setupCommandLine(exe, command);
829: }
830:
831: /**
832: * Set up our environment variables.
833: * @param exe executable.
834: */
835: private void setupEnvironment(Execute exe) {
836: String[] environment = env.getVariables();
837: if (environment != null) {
838: for (int i = 0; i < environment.length; i++) {
839: log("Setting environment variable: " + environment[i],
840: Project.MSG_VERBOSE);
841: }
842: }
843: exe.setNewenvironment(newEnvironment);
844: exe.setEnvironment(environment);
845: }
846:
847: /**
848: * Set the working dir of the new process.
849: * @param exe executable.
850: * @throws BuildException if the dir doesn't exist.
851: */
852: private void setupWorkingDir(Execute exe) {
853: if (dir == null) {
854: dir = getProject().getBaseDir();
855: } else if (!dir.exists() || !dir.isDirectory()) {
856: throw new BuildException(dir.getAbsolutePath()
857: + " is not a valid directory", getLocation());
858: }
859: exe.setWorkingDirectory(dir);
860: }
861:
862: /**
863: * Set the command line for the exe.
864: * On VMS, hands off to {@link #setupCommandLineForVMS(Execute, String[])}.
865: * @param exe executable.
866: * @param command command to execute.
867: */
868: private void setupCommandLine(Execute exe, String[] command) {
869: //On VMS platform, we need to create a special java options file
870: //containing the arguments and classpath for the java command.
871: //The special file is supported by the "-V" switch on the VMS JVM.
872: if (Os.isFamily("openvms")) {
873: setupCommandLineForVMS(exe, command);
874: } else {
875: exe.setCommandline(command);
876: }
877: }
878:
879: /**
880: * On VMS platform, we need to create a special java options file
881: * containing the arguments and classpath for the java command.
882: * The special file is supported by the "-V" switch on the VMS JVM.
883: *
884: * @param exe executable.
885: * @param command command to execute.
886: */
887: private void setupCommandLineForVMS(Execute exe, String[] command) {
888: ExecuteJava.setupCommandLineForVMS(exe, command);
889: }
890:
891: /**
892: * Executes the given classname with the given arguments as if it
893: * were a command line application.
894: *
895: * @param classname the name of the class to run.
896: * @param args arguments for the class.
897: * @throws BuildException in case of IOException in the execution.
898: */
899: protected void run(String classname, Vector args)
900: throws BuildException {
901: CommandlineJava cmdj = new CommandlineJava();
902: cmdj.setClassname(classname);
903: for (int i = 0; i < args.size(); i++) {
904: cmdj.createArgument().setValue((String) args.elementAt(i));
905: }
906: run(cmdj);
907: }
908:
909: /**
910: * Clear out the arguments to this java task.
911: */
912: public void clearArgs() {
913: getCommandLine().clearJavaArgs();
914: }
915:
916: /**
917: * Create the Watchdog to kill a runaway process.
918: *
919: * @return new watchdog.
920: *
921: * @throws BuildException under unknown circumstances.
922: *
923: * @since Ant 1.5
924: */
925: protected ExecuteWatchdog createWatchdog() throws BuildException {
926: if (timeout == null) {
927: return null;
928: }
929: return new ExecuteWatchdog(timeout.longValue());
930: }
931:
932: /**
933: * Log the specified Throwable.
934: * @param t the Throwable to log.
935: * @since 1.6.2
936: */
937: private void log(Throwable t) {
938: StringWriter sw = new StringWriter();
939: PrintWriter w = new PrintWriter(sw);
940: t.printStackTrace(w);
941: w.close();
942: log(sw.toString(), Project.MSG_ERR);
943: }
944:
945: /**
946: * Accessor to the command line.
947: *
948: * @return the current command line.
949: * @since 1.6.3
950: */
951: public CommandlineJava getCommandLine() {
952: return cmdl;
953: }
954:
955: /**
956: * Get the system properties of the command line.
957: *
958: * @return the current properties of this java invocation.
959: * @since 1.6.3
960: */
961: public CommandlineJava.SysProperties getSysProperties() {
962: return getCommandLine().getSystemProperties();
963: }
964: }
|