KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > launcher > LaunchTask


1 /*
2  * Copyright 1999-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.commons.launcher;
18
19 import java.io.File JavaDoc;
20 import java.io.FileOutputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.net.URL JavaDoc;
23 import java.net.URLClassLoader JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28 import org.apache.commons.launcher.types.ArgumentSet;
29 import org.apache.commons.launcher.types.ConditionalArgument;
30 import org.apache.commons.launcher.types.ConditionalVariable;
31 import org.apache.commons.launcher.types.JVMArgumentSet;
32 import org.apache.commons.launcher.types.SysPropertySet;
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.Task;
35 import org.apache.tools.ant.types.Path;
36 import org.apache.tools.ant.types.Reference;
37
38 /**
39  * A class that eliminates the need for a batch or shell script to launch a Java
40  * class. Some situations where elimination of a batch or shell script may be
41  * desirable are:
42  * <ul>
43  * <li>You want to avoid having to determining where certain application paths
44  * are e.g. your application's home directory, etc. Determining this
45  * dynamically in a Windows batch scripts is very tricky on some versions of
46  * Windows or when softlinks are used on Unix platforms.
47  * <li>You want to avoid having to handle native file and path separators or
48  * native path quoting issues.
49  * <li>You need to enforce certain system properties e.g.
50  * <code>java.endorsed.dirs</code> when running with JDK 1.4.
51  * <li>You want to allow users to pass in custom JVM arguments or system
52  * properties without having to parse and reorder arguments in your script.
53  * This can be tricky and/or messy in batch and shell scripts.
54  * <li>You want to bootstrap system properties from a configuration file instead
55  * hard-coding them in your batch and shell scripts.
56  * <li>You want to provide localized error messages which is very tricky to do
57  * in batch and shell scripts.
58  * </ul>
59  *
60  * @author Patrick Luby
61  */

62 public class LaunchTask extends Task {
63
64     //----------------------------------------------------------- Static Fields
65

66     /**
67      * The argument property name.
68      */

69     public final static String JavaDoc ARG_PROP_NAME = "launch.arg.";
70
71     /**
72      * The name of this task.
73      */

74     public final static String JavaDoc TASK_NAME = "launch";
75
76     /**
77      * Cached synchronous child processes for all instances of this class.
78      */

79     private static ArrayList JavaDoc childProcesses = new ArrayList JavaDoc();
80
81     //------------------------------------------------------------------ Fields
82

83     /**
84      * Cached appendOutput flag.
85      */

86     private boolean appendOutput = false;
87
88     /**
89      * Cached synchronously executing child process.
90      */

91     private Process JavaDoc childProc = null;
92
93     /**
94      * Cached classpath.
95      */

96     private Path classpath = null;
97
98     /**
99      * Cached debug flag.
100      */

101     private boolean debug = false;
102
103     /**
104      * Cached displayMinimizedWindow flag.
105      */

106     private boolean displayMinimizedWindow = false;
107
108     /**
109      * Cached disposeMinimizedWindow flag.
110      */

111     private boolean disposeMinimizedWindow = true;
112
113     /**
114      * Cached failOnError flag.
115      */

116     private boolean failOnError = false;
117
118     /**
119      * Cached filter instance.
120      */

121     private LaunchFilter filter = null;
122
123     /**
124      * Cached filterClassName.
125      */

126     private String JavaDoc filterClassName = null;
127
128     /**
129      * Cached filterClasspath.
130      */

131     private Path filterClasspath = null;
132
133     /**
134      * Cached main class name.
135      */

136     private String JavaDoc mainClassName = null;
137
138     /**
139      * Cached minimizedWindowIcon.
140      */

141     private File JavaDoc minimizedWindowIcon = null;
142
143     /**
144      * Cached minimizedWindowTitle.
145      */

146     private String JavaDoc minimizedWindowTitle = null;
147
148     /**
149      * Cached output file.
150      */

151     private File JavaDoc outputFile = null;
152
153     /**
154      * Cached print flag.
155      */

156     private boolean print = false;
157
158     /**
159      * Cached redirect flag.
160      */

161     private boolean redirect = false;
162
163     /**
164      * Cached requireTools flag.
165      */

166     private boolean requireTools = false;
167
168     /**
169      * Cached arg elements
170      */

171     private ArgumentSet taskArgumentSet = new ArgumentSet();
172
173     /**
174      * Cached jvmarg elements
175      */

176     private JVMArgumentSet taskJVMArgumentSet = new JVMArgumentSet();
177
178     /**
179      * Cached sysproperty elements
180      */

181     private SysPropertySet taskSysPropertySet = new SysPropertySet();
182
183     /**
184      * Cached useArgs flag.
185      */

186     private boolean useArgs = true;
187
188     /**
189      * Cached useSystemIn flag.
190      */

191     private boolean useSystemIn = true;
192
193     /**
194      * Cached waitForChild flag.
195      */

196     private boolean waitForChild = true;
197
198     //---------------------------------------------------------- Static Methods
199

200     /**
201      * Get the synchronous child processes for all instances of this class.
202      *
203      * @return the instances of this class.
204      */

205     public static Process JavaDoc[] getChildProcesses() {
206
207         return (Process JavaDoc[])childProcesses.toArray(new Process JavaDoc[childProcesses.size()]);
208
209     }
210
211     //----------------------------------------------------------------- Methods
212

213     /**
214      * Add a nested arg element. Note that Ant will not invoke the specified
215      * arg object's setter methods until after Ant invokes this method so
216      * processing of the specified arg object is handled in the
217      * {@link #execute()} method.
218      *
219      * @param arg the arg element
220      */

221     public void addArg(ConditionalArgument arg) {
222
223         taskArgumentSet.addArg(arg);
224
225     }
226
227     /**
228      * Add a nested argset element.
229      *
230      * @param set the argset element
231      */

232     public void addArgset(ArgumentSet set) {
233
234         taskArgumentSet.addArgset(set);
235
236     }
237
238     /**
239      * Add a nested jvmarg element. Note that Ant will not invoke the specified
240      * jvmarg object's setter methods until after Ant invokes this method so
241      * processing of the specified jvmarg object is handled in the
242      * {@link #execute()} method.
243      *
244      * @param jvmArg the jvmarg element
245      */

246     public void addJvmarg(ConditionalArgument jvmArg) {
247
248         taskJVMArgumentSet.addJvmarg(jvmArg);
249
250     }
251
252     /**
253      * Add a nested jvmargset element.
254      *
255      * @param set the jvmargset element
256      */

257     public void addJvmargset(JVMArgumentSet set) {
258
259         taskJVMArgumentSet.addJvmargset(set);
260
261     }
262
263     /**
264      * Add a nested sysproperty element. Note that Ant will not invoke the
265      * specified sysproperty object's setter methods until after Ant invokes
266      * this method so processing of the specified sysproperty object is handled
267      * in the {@link #execute()} method.
268      *
269      * @param var the sysproperty element
270      */

271     public void addSysproperty(ConditionalVariable var) {
272
273         taskSysPropertySet.addSysproperty(var);
274
275     }
276
277     /**
278      * Add a nested syspropertyset element.
279      *
280      * @param set the syspropertyset element
281      */

282     public void addSyspropertyset(SysPropertySet set) {
283
284         taskSysPropertySet.addSyspropertyset(set);
285
286     }
287
288     /**
289      * Create a nested classpath element.
290      *
291      * @return the Path object that contains all nested classpath elements
292      */

293     public Path createClasspath() {
294
295         if (classpath == null)
296             classpath = new Path(project);
297         return classpath;
298
299     }
300
301     /**
302      * Create a nested filter classpath element.
303      *
304      * @return the Path object that contains all nested filter classpath
305      * elements
306      */

307     public Path createFilterclasspath() {
308
309         if (filterClasspath == null)
310             filterClasspath = new Path(project);
311         return filterClasspath;
312
313     }
314
315     /**
316      * Construct a Java command and execute it using the settings that Ant
317      * parsed from the Launcher's XML file. This method is called by the Ant
318      * classes.
319      *
320      * @throws BuildException if there is a configuration or other error
321      */

322     public void execute() throws BuildException {
323
324         try {
325
326             // Check that the Launcher class was used to start Ant as this
327
// task is not designed to use in a standalone Ant installation
328
if (!Launcher.isStarted())
329                 throw new BuildException(Launcher.getLocalizedString("no.run.standalone", this.getClass().getName()));
330
331             // Don't do anything if the launching process has been stopped
332
if (Launcher.isStopped())
333                 throw new BuildException();
334
335             if (mainClassName == null)
336                 throw new BuildException(Launcher.getLocalizedString("classname.null", this.getClass().getName()));
337
338             // Copy all of the nested jvmarg elements into the jvmArgs object
339
ArrayList JavaDoc taskJVMArgs = taskJVMArgumentSet.getList();
340             ArrayList JavaDoc jvmArgs = new ArrayList JavaDoc(taskJVMArgs.size());
341             for (int i = 0; i < taskJVMArgs.size(); i++) {
342                 ConditionalArgument value = (ConditionalArgument)taskJVMArgs.get(i);
343                 // Test "if" and "unless" conditions
344
if (testIfCondition(value.getIf()) && testUnlessCondition(value.getUnless())) {
345                     String JavaDoc[] list = value.getParts();
346                     for (int j = 0; j < list.length; j++)
347                         jvmArgs.add(list[j]);
348                 }
349             }
350
351             // Copy all of the nested sysproperty elements into the sysProps
352
// object
353
ArrayList JavaDoc taskSysProps = taskSysPropertySet.getList();
354             HashMap JavaDoc sysProps = new HashMap JavaDoc(taskSysProps.size());
355             for (int i = 0; i < taskSysProps.size(); i++) {
356                 ConditionalVariable variable = (ConditionalVariable)taskSysProps.get(i);
357                 // Test "if" and "unless" conditions
358
if (testIfCondition(variable.getIf()) && testUnlessCondition(variable.getUnless()))
359                     sysProps.put(variable.getKey(), variable.getValue());
360             }
361
362             // Copy all of the nested arg elements into the appArgs object
363
ArrayList JavaDoc taskArgs = taskArgumentSet.getList();
364             ArrayList JavaDoc appArgs = new ArrayList JavaDoc(taskArgs.size());
365             for (int i = 0; i < taskArgs.size(); i++) {
366                 ConditionalArgument value = (ConditionalArgument)taskArgs.get(i);
367                 // Test "if" and "unless" conditions
368
if (testIfCondition(value.getIf()) && testUnlessCondition(value.getUnless())) {
369                     String JavaDoc[] list = value.getParts();
370                     for (int j = 0; j < list.length; j++)
371                         appArgs.add(list[j]);
372                 }
373             }
374
375             // Add the Launcher's command line arguments to the appArgs object
376
if (useArgs) {
377                 int currentArg = 0;
378                 String JavaDoc arg = null;
379                 while ((arg = project.getUserProperty(LaunchTask.ARG_PROP_NAME + Integer.toString(currentArg++))) != null)
380                     appArgs.add(arg);
381             }
382
383             // Make working copies of some of the flags since they may get
384
// changed by a filter class
385
String JavaDoc filteredClasspath = null;
386             if (classpath != null)
387                 filteredClasspath = classpath.toString();
388             String JavaDoc filteredMainClassName = mainClassName;
389             boolean filteredRedirect = redirect;
390             File JavaDoc filteredOutputFile = outputFile;
391             boolean filteredAppendOutput = appendOutput;
392             boolean filteredDebug = debug;
393             boolean filteredDisplayMinimizedWindow = displayMinimizedWindow;
394             boolean filteredDisposeMinimizedWindow = disposeMinimizedWindow;
395             boolean filteredFailOnError = failOnError;
396             String JavaDoc filteredMinimizedWindowTitle = minimizedWindowTitle;
397             File JavaDoc filteredMinimizedWindowIcon = minimizedWindowIcon;
398             boolean filteredPrint = print;
399             boolean filteredRequireTools = requireTools;
400             boolean filteredUseSystemIn = useSystemIn;
401             boolean filteredWaitForChild = waitForChild;
402
403             // If there is a filter in the filterclassname attribute, let it
404
// evaluate and edit the attributes and nested elements before we
405
// start evaluating them
406
if (filterClassName != null) {
407                  if (filter == null) {
408                      try {
409                          ClassLoader JavaDoc loader = this.getClass().getClassLoader();
410                          if (filterClasspath != null) {
411                              // Construct a class loader to load the class
412
String JavaDoc[] fileList = filterClasspath.list();
413                              URL JavaDoc[] urls = new URL JavaDoc[fileList.length];
414                              for (int i = 0; i < fileList.length; i++)
415                                  urls[i] = new File JavaDoc(fileList[i]).toURL();
416                              loader = new URLClassLoader JavaDoc(urls, loader);
417                          }
418                          Class JavaDoc filterClass = loader.loadClass(filterClassName);
419                          filter = (LaunchFilter)filterClass.newInstance();
420                          // Execute filter and save any changes
421
LaunchCommand command = new LaunchCommand();
422                          command.setJvmargs(jvmArgs);
423                          command.setSysproperties(sysProps);
424                          command.setArgs(appArgs);
425                          command.setClasspath(filteredClasspath);
426                          command.setClassname(filteredMainClassName);
427                          command.setRedirectoutput(filteredRedirect);
428                          command.setOutput(filteredOutputFile);
429                          command.setAppendoutput(filteredAppendOutput);
430                          command.setDebug(filteredDebug);
431                          command.setDisplayminimizedwindow(filteredDisplayMinimizedWindow);
432                          command.setDisposeminimizedwindow(filteredDisposeMinimizedWindow);
433                          command.setFailonerror(filteredFailOnError);
434                          command.setMinimizedwindowtitle(filteredMinimizedWindowTitle);
435                          command.setMinimizedwindowicon(filteredMinimizedWindowIcon);
436                          command.setPrint(filteredPrint);
437                          command.setRequiretools(filteredRequireTools);
438                          command.setUsesystemin(filteredUseSystemIn);
439                          command.setWaitforchild(filteredWaitForChild);
440                          filter.filter(command);
441                          jvmArgs = command.getJvmargs();
442                          sysProps = command.getSysproperties();
443                          appArgs = command.getArgs();
444                          filteredClasspath = command.getClasspath();
445                          filteredMainClassName = command.getClassname();
446                          filteredRedirect = command.getRedirectoutput();
447                          filteredOutputFile = command.getOutput();
448                          filteredAppendOutput = command.getAppendoutput();
449                          filteredDebug = command.getDebug();
450                          filteredDisplayMinimizedWindow = command.getDisplayminimizedwindow();
451                          filteredDisposeMinimizedWindow = command.getDisposeminimizedwindow();
452                          filteredFailOnError = command.getFailonerror();
453                          filteredMinimizedWindowTitle = command.getMinimizedwindowtitle();
454                          filteredMinimizedWindowIcon = command.getMinimizedwindowicon();
455                          filteredPrint = command.getPrint();
456                          filteredRequireTools = command.getRequiretools();
457                          filteredUseSystemIn = command.getUsesystemin();
458                          filteredWaitForChild = command.getWaitforchild();
459                          // Check changes
460
if (filteredMainClassName == null)
461                              throw new BuildException(Launcher.getLocalizedString("classname.null", this.getClass().getName()));
462                          if (jvmArgs == null)
463                              jvmArgs = new ArrayList JavaDoc();
464                          if (sysProps == null)
465                              sysProps = new HashMap JavaDoc();
466                          if (appArgs == null)
467                              appArgs = new ArrayList JavaDoc();
468                      } catch (BuildException be) {
469                          throw new BuildException(filterClassName + " " + Launcher.getLocalizedString("filter.exception", this.getClass().getName()), be);
470                      } catch (ClassCastException JavaDoc cce) {
471                          throw new BuildException(filterClassName + " " + Launcher.getLocalizedString("filter.not.filter", this.getClass().getName()));
472                      } catch (Exception JavaDoc e) {
473                          throw new BuildException(e);
474                      }
475                  }
476             }
477
478             // Force child JVM into foreground if running using JDB
479
if (filteredDebug) {
480                 filteredWaitForChild = true;
481                 filteredUseSystemIn = true;
482             }
483
484             // Prepend standard paths to classpath
485
StringBuffer JavaDoc fullClasspath = new StringBuffer JavaDoc(Launcher.getBootstrapFile().getPath());
486             if (filteredRequireTools) {
487                 fullClasspath.append(File.pathSeparator);
488                 fullClasspath.append(Launcher.getToolsClasspath());
489             }
490             if (filteredClasspath != null) {
491                 fullClasspath.append(File.pathSeparator);
492                 fullClasspath.append(filteredClasspath);
493             }
494
495             // Set ChildMain.WAIT_FOR_CHILD_PROP_NAME property for child JVM
496
sysProps.remove(ChildMain.WAIT_FOR_CHILD_PROP_NAME);
497             if (filteredWaitForChild)
498                 sysProps.put(ChildMain.WAIT_FOR_CHILD_PROP_NAME, "");
499
500             // Set minimized window properties for child JVM
501
sysProps.remove(ChildMain.DISPLAY_MINIMIZED_WINDOW_PROP_NAME);
502             sysProps.remove(ChildMain.MINIMIZED_WINDOW_TITLE_PROP_NAME);
503             sysProps.remove(ChildMain.MINIMIZED_WINDOW_ICON_PROP_NAME);
504             sysProps.remove(ChildMain.DISPOSE_MINIMIZED_WINDOW_PROP_NAME);
505             if (!filteredWaitForChild && filteredDisplayMinimizedWindow) {
506                 sysProps.put(ChildMain.DISPLAY_MINIMIZED_WINDOW_PROP_NAME, "");
507                 if (filteredMinimizedWindowTitle != null)
508                     sysProps.put(ChildMain.MINIMIZED_WINDOW_TITLE_PROP_NAME, filteredMinimizedWindowTitle);
509                 else
510                     sysProps.put(ChildMain.MINIMIZED_WINDOW_TITLE_PROP_NAME, getOwningTarget().getName());
511                 if (filteredMinimizedWindowIcon != null)
512                     sysProps.put(ChildMain.MINIMIZED_WINDOW_ICON_PROP_NAME, filteredMinimizedWindowIcon.getCanonicalPath());
513                 // Set ChildMain.DISPOSE_MINIMIZED_WINDOW_PROP_NAME property
514
if (filteredDisposeMinimizedWindow)
515                     sysProps.put(ChildMain.DISPOSE_MINIMIZED_WINDOW_PROP_NAME, "");
516             }
517
518             // Set ChildMain.OUTPUT_FILE_PROP_NAME property for child JVM
519
sysProps.remove(ChildMain.OUTPUT_FILE_PROP_NAME);
520             if (!filteredWaitForChild && filteredRedirect) {
521                 if (filteredOutputFile != null) {
522                     String JavaDoc outputFilePath = filteredOutputFile.getCanonicalPath();
523                     // Verify that we can write to the output file
524
try {
525             File JavaDoc parentFile = new File JavaDoc(filteredOutputFile.getParent());
526             // To take care of non-existent log directories
527
if ( !parentFile.exists() ) {
528                 //Trying to create non-existent parent directories
529
parentFile.mkdirs();
530                 //If this fails createNewFile also fails
531
//We can give more exact error message, if we choose
532
}
533                         filteredOutputFile.createNewFile();
534                     } catch (IOException JavaDoc ioe) {
535                         throw new BuildException(outputFilePath + " " + Launcher.getLocalizedString("output.file.not.creatable", this.getClass().getName()));
536                     }
537                     if (!filteredOutputFile.canWrite())
538                         throw new BuildException(outputFilePath + " " + Launcher.getLocalizedString("output.file.not.writable", this.getClass().getName()));
539                     sysProps.put(ChildMain.OUTPUT_FILE_PROP_NAME, outputFilePath);
540                     if (filteredAppendOutput)
541                         sysProps.put(ChildMain.APPEND_OUTPUT_PROP_NAME, "");
542                     Launcher.getLog().println(Launcher.getLocalizedString("redirect.notice", this.getClass().getName()) + " " + outputFilePath);
543                 } else {
544                     throw new BuildException(Launcher.getLocalizedString("output.file.null", this.getClass().getName()));
545                 }
546             }
547
548             // Create the heartbeatFile. This file is needed by the
549
// ParentListener class on Windows since the entire child JVM
550
// process will block on Windows machines using some versions of
551
// Unix shells such as MKS, etc.
552
File JavaDoc heartbeatFile = null;
553             FileOutputStream JavaDoc heartbeatOutputStream = null;
554             if (filteredWaitForChild) {
555                 File JavaDoc tmpDir = null;
556                 String JavaDoc tmpDirName = (String JavaDoc)sysProps.get("java.io.tmpdir");
557                 if (tmpDirName != null)
558                     tmpDir = new File JavaDoc(tmpDirName);
559                 heartbeatFile = File.createTempFile(ChildMain.HEARTBEAT_FILE_PROP_NAME + ".", "", tmpDir);
560                 // Open the heartbeat file for writing so that it the child JVM
561
// will not be able to delete it while this process is running
562
heartbeatOutputStream = new FileOutputStream JavaDoc(heartbeatFile);
563                 sysProps.put(ChildMain.HEARTBEAT_FILE_PROP_NAME, heartbeatFile.getCanonicalPath());
564             }
565
566             // Assemble child command
567
String JavaDoc[] cmd = new String JavaDoc[5 + jvmArgs.size() + sysProps.size() + appArgs.size()];
568             int nextCmdArg = 0;
569             if (filteredDebug)
570                 cmd[nextCmdArg++] = Launcher.getJDBCommand();
571             else
572                 cmd[nextCmdArg++] = Launcher.getJavaCommand();
573             // Add jvmArgs to command
574
for (int i = 0; i < jvmArgs.size(); i++)
575                 cmd[nextCmdArg++] = (String JavaDoc)jvmArgs.get(i);
576             // Add properties to command
577
Iterator JavaDoc sysPropsKeys = sysProps.keySet().iterator();
578             while (sysPropsKeys.hasNext()) {
579                 String JavaDoc key = (String JavaDoc)sysPropsKeys.next();
580                 if (key == null)
581                     continue;
582                 String JavaDoc value = (String JavaDoc)sysProps.get(key);
583                 if (value == null)
584                     value = "";
585                 cmd[nextCmdArg++] = "-D" + key + "=" + value;
586             }
587             // Add classpath to command. Note that it is after the jvmArgs
588
// and system properties to prevent the user from sneaking in an
589
// alterate classpath through the jvmArgs.
590
cmd[nextCmdArg++] = "-classpath";
591             cmd[nextCmdArg++] = fullClasspath.toString();
592             // Add main class to command
593
int mainClassArg = nextCmdArg;
594             cmd[nextCmdArg++] = ChildMain.class.getName();
595             cmd[nextCmdArg++] = filteredMainClassName;
596             // Add args to command
597
for (int i = 0; i < appArgs.size(); i++)
598         {
599                 cmd[nextCmdArg++] = (String JavaDoc)appArgs.get(i);
600         }
601             // Print command
602
if (filteredPrint) {
603                 // Quote the command arguments
604
String JavaDoc osname = System.getProperty("os.name").toLowerCase();
605                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc(cmd.length * 100);
606                 String JavaDoc quote = null;
607                 String JavaDoc replaceQuote = null;
608                 if (osname.indexOf("windows") >= 0) {
609                     // Use double-quotes to quote on Windows
610
quote = "\"";
611                     replaceQuote = quote + quote + quote;
612                 } else {
613                     // Use single-quotes to quote on Unix
614
quote = "'";
615                     replaceQuote = quote + "\\" + quote + quote;
616                 }
617                 for (int i = 0; i < cmd.length; i++) {
618                     // Pull ChildMain out of command as we want to print the
619
// real JVM command that can be executed by the user
620
if (i == mainClassArg)
621                         continue;
622                     if (i > 0)
623                         buf.append(" ");
624                     buf.append(quote);
625                     StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(cmd[i], quote, true);
626                     while (tokenizer.hasMoreTokens()) {
627                         String JavaDoc token = tokenizer.nextToken();
628                         if (quote.equals(token))
629                             buf.append(replaceQuote);
630                         else
631                             buf.append(token);
632                     }
633                     buf.append(quote);
634                 }
635                 // Print the quoted command
636
System.err.println(Launcher.getLocalizedString("executing.child.command", this.getClass().getName()) + ":");
637                 System.err.println(buf.toString());
638             }
639
640             // Create a child JVM
641
if (Launcher.isStopped())
642                 throw new BuildException();
643             Process JavaDoc proc = null;
644             synchronized (LaunchTask.childProcesses) {
645                 proc = Runtime.getRuntime().exec(cmd);
646                 // Add the synchronous child process
647
if (filteredWaitForChild) {
648                     childProc = proc;
649                     LaunchTask.childProcesses.add(proc);
650                 }
651             }
652             if (filteredWaitForChild) {
653                 StreamConnector stdout =
654                     new StreamConnector(proc.getInputStream(), System.out);
655                 StreamConnector stderr =
656                     new StreamConnector(proc.getErrorStream(), System.err);
657                 stdout.start();
658                 stderr.start();
659                 if (filteredUseSystemIn) {
660                     StreamConnector stdin =
661                         new StreamConnector(System.in, proc.getOutputStream());
662                     stdin.start();
663                 }
664                 proc.waitFor();
665                 // Let threads flush any unflushed output
666
stdout.join();
667                 stderr.join();
668                 if (heartbeatOutputStream != null)
669                     heartbeatOutputStream.close();
670                 if (heartbeatFile != null)
671                     heartbeatFile.delete();
672                 int exitValue = proc.exitValue();
673                 if (filteredFailOnError && exitValue != 0)
674                     throw new BuildException(Launcher.getLocalizedString("child.failed", this.getClass().getName()) + " " + exitValue);
675             }
676             // Need to check if the launching process has stopped because
677
// processes don't throw exceptions when they are terminated
678
if (Launcher.isStopped())
679                 throw new BuildException();
680
681         } catch (BuildException be) {
682             throw be;
683         } catch (Exception JavaDoc e) {
684             if (Launcher.isStopped())
685                 throw new BuildException(Launcher.getLocalizedString("launch.task.stopped", this.getClass().getName()));
686             else
687                 throw new BuildException(e);
688         }
689
690     }
691
692     /**
693      * Set the useArgs flag. Setting this flag to true will cause this
694      * task to append all of the command line arguments used to start the
695      * {@link Launcher#start(String[])} method to the arguments
696      * passed to the child JVM.
697      *
698      * @param useArgs the useArgs flag
699      */

700     public void setUseargs(boolean useArgs) {
701
702         this.useArgs = useArgs;
703
704     }
705
706     /**
707      * Set the useSystemIn flag. Setting this flag to false will cause this
708      * task to not read System.in. This will cause the child JVM to never
709      * receive any bytes when it reads System.in. Setting this flag to false
710      * is useful in some Unix environments where processes cannot be put in
711      * the background when they read System.in.
712      *
713      * @param useSystemIn the useSystemIn flag
714      */

715     public void setUsesystemin(boolean useSystemIn) {
716
717         this.useSystemIn = useSystemIn;
718
719     }
720
721     /**
722      * Set the waitForChild flag. Setting this flag to true will cause this
723      * task to wait for the child JVM to finish executing before the task
724      * completes. Setting this flag to false will cause this task to complete
725      * immediately after it starts the execution of the child JVM. Setting it
726      * false emulates the "&" background operator in most Unix shells and is
727      * most of set to false when launching server or GUI applications.
728      *
729      * @param waitForChild the waitForChild flag
730      */

731     public void setWaitforchild(boolean waitForChild) {
732
733         this.waitForChild = waitForChild;
734
735     }
736
737     /**
738      * Set the class name.
739      *
740      * @param mainClassName the class to execute <code>main(String[])</code>
741      */

742     public void setClassname(String JavaDoc mainClassName) {
743
744         this.mainClassName = mainClassName;
745
746     }
747
748     /**
749      * Set the classpath.
750      *
751      * @param classpath the classpath
752      */

753     public void setClasspath(Path classpath) {
754
755         createClasspath().append(classpath);
756
757     }
758
759     /**
760      * Adds a reference to a classpath defined elsewhere.
761      *
762      * @param ref reference to the classpath
763      */

764     public void setClasspathref(Reference ref) {
765
766         createClasspath().setRefid(ref);
767
768     }
769
770     /**
771      * Set the debug flag. Setting this flag to true will cause this
772      * task to run the child JVM using the JDB debugger.
773      *
774      * @param debug the debug flag
775      */

776     public void setDebug(boolean debug) {
777
778         this.debug = debug;
779
780     }
781
782     /**
783      * Set the displayMinimizedWindow flag. Note that this flag has no effect
784      * on non-Windows platforms. On Windows platform, setting this flag to true
785      * will cause a minimized window to be displayed in the Windows task bar
786      * while the child process is executing. This flag is usually set to true
787      * for server applications that also have their "waitForChild" attribute
788      * set to false via the {@link #setWaitforchild(boolean)} method.
789      *
790      * @param displayMinimizedWindow true if a minimized window should be
791      * displayed in the Windows task bar while the child process is executing
792      */

793     public void setDisplayminimizedwindow(boolean displayMinimizedWindow) {
794
795         this.displayMinimizedWindow = displayMinimizedWindow;
796
797     }
798
799     /**
800      * Set the disposeMinimizedWindow flag. Note that this flag has no effect
801      * on non-Windows platforms. On Windows platform, setting this flag to true
802      * will cause any minimized window that is display by setting the
803      * "displayMinimizedWindow" attribute to true via the
804      * {@link #setDisplayminimizedwindow(boolean)} to be automatically
805      * disposed of when the child JVM's <code>main(String[])</code> returns.
806      * This flag is normally used for applications that don't explicitly call
807      * {@link System#exit(int)}. If an application does not explicitly call
808      * {@link System#exit(int)}, an minimized windows need to be disposed of
809      * for the child JVM to exit.
810      *
811      * @param disposeMinimizedWindow true if a minimized window in the Windows
812      * taskbar should be automatically disposed of after the child JVM's
813      * <code>main(String[])</code> returns
814      */

815     public void setDisposeminimizedwindow(boolean disposeMinimizedWindow) {
816
817         this.disposeMinimizedWindow = disposeMinimizedWindow;
818
819     }
820
821     /**
822      * Set the failOnError flag.
823      *
824      * @param failOnError true if the launch process should stop if the child
825      * JVM returns an exit value other than 0
826      */

827     public void setFailonerror(boolean failOnError) {
828
829         this.failOnError = failOnError;
830
831     }
832     /**
833      * Set the filter class name.
834      *
835      * @param filterClassName the class that implements the
836      * {@link LaunchFilter} interface
837      */

838     public void setFilterclassname(String JavaDoc filterClassName) {
839
840         this.filterClassName = filterClassName;
841
842     }
843
844     /**
845      * Set the filter class' classpath.
846      *
847      * @param classpath the classpath for the filter class
848      */

849     public void setFilterclasspath(Path filterClasspath) {
850
851         createFilterclasspath().append(filterClasspath);
852
853     }
854
855     /**
856      * Set the title for the minimized window that will be displayed in the
857      * Windows taskbar. Note that this property has no effect on non-Windows
858      * platforms.
859      *
860      * @param minimizedWindowTitle the title to set for any minimized window
861      * that is displayed in the Windows taskbar
862      */

863     public void setMinimizedwindowtitle(String JavaDoc minimizedWindowTitle) {
864
865         this.minimizedWindowTitle = minimizedWindowTitle;
866
867     }
868
869     /**
870      * Set the icon file for the minimized window that will be displayed in the
871      * Windows taskbar. Note that this property has no effect on non-Windows
872      * platforms.
873      *
874      * @param minimizedWindowIcon the icon file to use for any minimized window
875      * that is displayed in the Windows taskbar
876      */

877     public void setMinimizedwindowicon(File JavaDoc minimizedWindowIcon) {
878
879         this.minimizedWindowIcon = minimizedWindowIcon;
880
881     }
882
883     /**
884      * Set the file that the child JVM's System.out and System.err will be
885      * redirected to. Output will only be redirected if the redirect flag
886      * is set to true via the {@link #setRedirectoutput(boolean)} method.
887      *
888      * @param outputFile a File to redirect System.out and System.err to
889      */

890     public void setOutput(File JavaDoc outputFile) {
891
892         this.outputFile = outputFile;
893
894     }
895
896     /**
897      * Set the print flag. Setting this flag to true will cause the full child
898      * JVM command to be printed to {@link System#out}.
899      *
900      * @param print the print flag
901      */

902     public void setPrint(boolean print) {
903
904         this.print = print;
905
906     }
907
908     /**
909      * Set the appendOutput flag. Setting this flag to true will cause the child
910      * JVM to append System.out and System.err to the file specified by the
911      * {@link #setOutput(File)} method. Setting this flag to false will cause
912      * the child to overwrite the file.
913      *
914      * @param appendOutput true if output should be appended to the output file
915      */

916     public void setAppendoutput(boolean appendOutput) {
917
918         this.appendOutput = appendOutput;
919
920     }
921
922     /**
923      * Set the redirect flag. Setting this flag to true will cause the child
924      * JVM's System.out and System.err to be redirected to file set using the
925      * {@link #setOutput(File)} method. Setting this flag to false will
926      * cause no redirection.
927      *
928      * @param redirect true if System.out and System.err should be redirected
929      */

930     public void setRedirectoutput(boolean redirect) {
931
932         this.redirect = redirect;
933
934     }
935
936     /**
937      * Set the requireTools flag. Setting this flag to true will cause the
938      * JVM's tools.jar to be added to the child JVM's classpath. This
939      * sets an explicit requirement that the user use a JDK instead of a
940      * JRE. Setting this flag to false explicitly allows the user to use
941      * a JRE.
942      *
943      * @param redirect true if a JDK is required and false if only a JRE
944      * is required
945      */

946     public void setRequiretools(boolean requireTools) {
947
948         this.requireTools = requireTools;
949
950     }
951
952     /**
953      * Determine if the "if" condition flag for a nested element meets all
954      * criteria for use.
955      *
956      * @param ifCondition the "if" condition flag for a nested element
957      * @return true if the nested element should be process and false if it
958      * should be ignored
959      */

960     private boolean testIfCondition(String JavaDoc ifCondition) {
961
962         if (ifCondition == null || "".equals(ifCondition))
963             return true;
964         return project.getProperty(ifCondition) != null;
965
966     }
967
968     /**
969      * Determine if the "unless" condition flag for a nested element meets all
970      * criteria for use.
971      *
972      * @param unlessCondition the "unless" condition flag for a nested element
973      * @return true if the nested element should be process and false if it
974      * should be ignored
975      */

976     private boolean testUnlessCondition(String JavaDoc unlessCondition) {
977
978         if (unlessCondition == null || "".equals(unlessCondition))
979             return true;
980         return project.getProperty(unlessCondition) == null;
981
982     }
983
984 }
985
Popular Tags