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

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » taskdefs » [javadoc | source]