Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 455   Methods: 17
NCLOC: 259   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ExecuteOn.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights 
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs;
 56   
 
 57   
 import java.io.File;
 58   
 import java.io.IOException;
 59   
 import java.util.Hashtable;
 60   
 import java.util.Vector;
 61   
 import org.apache.tools.ant.BuildException;
 62   
 import org.apache.tools.ant.DirectoryScanner;
 63   
 import org.apache.tools.ant.Project;
 64   
 import org.apache.tools.ant.types.Commandline;
 65   
 import org.apache.tools.ant.types.EnumeratedAttribute;
 66   
 import org.apache.tools.ant.types.FileSet;
 67   
 import org.apache.tools.ant.types.Mapper;
 68   
 import org.apache.tools.ant.util.FileNameMapper;
 69   
 import org.apache.tools.ant.util.SourceFileScanner;
 70   
 
 71   
 /**
 72   
  * Executes a given command, supplying a set of files as arguments. 
 73   
  *
 74   
  * @author Stefan Bodewig 
 75   
  * @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a>
 76   
  *
 77   
  * @since Ant 1.2
 78   
  *
 79   
  * @ant.task category="control" name="apply"
 80   
  */
 81   
 public class ExecuteOn extends ExecTask {
 82   
 
 83   
     protected Vector filesets = new Vector();
 84   
     private boolean relative = false;
 85   
     private boolean parallel = false;
 86   
     private boolean forwardSlash = false;
 87   
     protected String type = "file";
 88   
     protected Commandline.Marker srcFilePos = null;
 89   
     private boolean skipEmpty = false;
 90   
     protected Commandline.Marker targetFilePos = null;
 91   
     protected Mapper mapperElement = null;
 92   
     protected FileNameMapper mapper = null;
 93   
     protected File destDir = null;
 94   
 
 95   
     /**
 96   
      * Has &lt;srcfile&gt; been specified before &lt;targetfile&gt;
 97   
      */
 98   
     protected boolean srcIsFirst = true;
 99   
 
 100   
     /**
 101   
      * Source files to operate upon.
 102   
      */
 103  0
     public void addFileset(FileSet set) {
 104  0
         filesets.addElement(set);
 105   
     }
 106   
 
 107   
     /**
 108   
      * Whether the filenames should be passed on the command line as
 109   
      * absolute or relative pathnames. Paths are relative to the base
 110   
      * directory of the corresponding fileset for source files or the
 111   
      * dest attribute for target files.
 112   
      */
 113  0
     public void setRelative(boolean relative) {
 114  0
         this.relative = relative;
 115   
     }
 116   
 
 117   
 
 118   
     /**
 119   
      * If true, run the command only once, appending all files as arguments.
 120   
      * If false, command will be executed once for every file. Defaults to false.
 121   
      */
 122  0
     public void setParallel(boolean parallel) {
 123  0
         this.parallel = parallel;
 124   
     }
 125   
 
 126   
     /**
 127   
      * Whether the command works only on files, directories or both?
 128   
      */
 129  0
     public void setType(FileDirBoth type) {
 130  0
         this.type = type.getValue();
 131   
     }
 132   
 
 133   
     /**
 134   
      * If no source files have been found or are newer than their
 135   
      * corresponding target files, do not run the command.
 136   
      */
 137  0
     public void setSkipEmptyFilesets(boolean skip) {
 138  0
         skipEmpty = skip;
 139   
     }
 140   
 
 141   
     /**
 142   
      * The directory where target files are to be placed.
 143   
      */
 144  0
     public void setDest(File destDir) {
 145  0
         this.destDir = destDir;
 146   
     }
 147   
 
 148   
     /**
 149   
      * The source and target file names on Windows and OS/2 must use
 150   
      * forward slash as file separator.
 151   
      */
 152  0
     public void setForwardslash(boolean forwardSlash) {
 153  0
         this.forwardSlash = forwardSlash;
 154   
     }
 155   
 
 156   
     /**
 157   
      * Marker that indicates where the name of the source file should
 158   
      * be put on the command line.
 159   
      */
 160  0
     public Commandline.Marker createSrcfile() {
 161  0
         if (srcFilePos != null) {
 162  0
             throw new BuildException(getTaskType() + " doesn\'t support multiple "
 163   
                                      + "srcfile elements.", getLocation());
 164   
         }
 165  0
         srcFilePos = cmdl.createMarker();
 166  0
         return srcFilePos;
 167   
     }
 168   
 
 169   
     /**
 170   
      * Marker that indicates where the name of the target file should
 171   
      * be put on the command line.
 172   
      */
 173  0
     public Commandline.Marker createTargetfile() {
 174  0
         if (targetFilePos != null) {
 175  0
             throw new BuildException(getTaskType() + " doesn\'t support multiple "
 176   
                                      + "targetfile elements.", getLocation());
 177   
         }
 178  0
         targetFilePos = cmdl.createMarker();
 179  0
         srcIsFirst = (srcFilePos != null);
 180  0
         return targetFilePos;
 181   
     }
 182   
 
 183   
     /**
 184   
      * Mapper to use for mapping source files to target files.
 185   
      */
 186  0
     public Mapper createMapper() throws BuildException {
 187  0
         if (mapperElement != null) {
 188  0
             throw new BuildException("Cannot define more than one mapper",
 189   
                                      getLocation());
 190   
         }
 191  0
         mapperElement = new Mapper(getProject());
 192  0
         return mapperElement;
 193   
     }
 194   
 
 195   
     /**
 196   
      * @todo using taskName here is brittle, as a user could override it.
 197   
      *       this should probably be modified to use the classname instead.
 198   
      */
 199  0
     protected void checkConfiguration() {
 200  0
         if ("execon".equals(getTaskName())) {
 201  0
             log("!! execon is deprecated. Use apply instead. !!");
 202   
         }
 203   
         
 204  0
         super.checkConfiguration();
 205  0
         if (filesets.size() == 0) {
 206  0
             throw new BuildException("no filesets specified", getLocation());
 207   
         }
 208   
 
 209  0
         if (targetFilePos != null || mapperElement != null 
 210   
             || destDir != null) {
 211   
 
 212  0
             if (mapperElement == null) {
 213  0
                 throw new BuildException("no mapper specified", getLocation());
 214   
             }
 215  0
             if (destDir == null) {
 216  0
                 throw new BuildException("no dest attribute specified", 
 217   
                                          getLocation());
 218   
             }
 219  0
             mapper = mapperElement.getImplementation();
 220   
         }
 221   
     }
 222   
 
 223  0
     protected void runExec(Execute exe) throws BuildException {
 224  0
         try {
 225   
 
 226  0
             Vector fileNames = new Vector();
 227  0
             Vector baseDirs = new Vector();
 228  0
             for (int i = 0; i < filesets.size(); i++) {
 229  0
                 FileSet fs = (FileSet) filesets.elementAt(i);
 230  0
                 File base = fs.getDir(getProject());
 231  0
                 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
 232   
 
 233  0
                 if (!"dir".equals(type)) {
 234  0
                     String[] s = getFiles(base, ds);
 235  0
                     for (int j = 0; j < s.length; j++) {
 236  0
                         fileNames.addElement(s[j]);
 237  0
                         baseDirs.addElement(base);
 238   
                     }
 239   
                 }
 240   
 
 241  0
                 if (!"file".equals(type)) {
 242  0
                     String[] s = getDirs(base, ds);;
 243  0
                     for (int j = 0; j < s.length; j++) {
 244  0
                         fileNames.addElement(s[j]);
 245  0
                         baseDirs.addElement(base);
 246   
                     }
 247   
                 }
 248   
 
 249  0
                 if (fileNames.size() == 0 && skipEmpty) {
 250  0
                     log("Skipping fileset for directory "
 251   
                         + base + ". It is empty.", Project.MSG_INFO);
 252  0
                     continue;
 253   
                 }
 254   
 
 255  0
                 if (!parallel) {
 256  0
                     String[] s = new String[fileNames.size()];
 257  0
                     fileNames.copyInto(s);
 258  0
                     for (int j = 0; j < s.length; j++) {
 259  0
                         String[] command = getCommandline(s[j], base);
 260  0
                         log(Commandline.describeCommand(command), 
 261   
                             Project.MSG_VERBOSE);
 262  0
                         exe.setCommandline(command);
 263  0
                         runExecute(exe);
 264   
                     }
 265  0
                     fileNames.removeAllElements();
 266  0
                     baseDirs.removeAllElements();
 267   
                 }
 268   
             }
 269   
 
 270  0
             if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
 271  0
                 String[] s = new String[fileNames.size()];
 272  0
                 fileNames.copyInto(s);
 273  0
                 File[] b = new File[baseDirs.size()];
 274  0
                 baseDirs.copyInto(b);
 275  0
                 String[] command = getCommandline(s, b);
 276  0
                 log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
 277  0
                 exe.setCommandline(command);
 278  0
                 runExecute(exe);
 279   
             }
 280   
 
 281   
         } catch (IOException e) {
 282  0
             throw new BuildException("Execute failed: " + e, e, getLocation());
 283   
         } finally {
 284   
             // close the output file if required
 285  0
             logFlush();
 286   
         }
 287   
     }
 288   
 
 289   
     /**
 290   
      * Construct the command line for parallel execution.
 291   
      *
 292   
      * @param srcFiles The filenames to add to the commandline
 293   
      * @param baseDir filenames are relative to this dir
 294   
      */
 295  0
     protected String[] getCommandline(String[] srcFiles, File[] baseDirs) {
 296  0
         final char fileSeparator = File.separatorChar;
 297  0
         Vector targets = new Vector();
 298  0
         if (targetFilePos != null) {
 299  0
             Hashtable addedFiles = new Hashtable();
 300  0
             for (int i = 0; i < srcFiles.length; i++) {
 301  0
                 String[] subTargets = mapper.mapFileName(srcFiles[i]);
 302  0
                 if (subTargets != null) {
 303  0
                     for (int j = 0; j < subTargets.length; j++) {
 304  0
                         String name = null;
 305  0
                         if (!relative) {
 306  0
                             name = (new File(destDir, subTargets[j])).getAbsolutePath();
 307   
                         } else {
 308  0
                             name = subTargets[j];
 309   
                         }
 310  0
                         if (forwardSlash && fileSeparator != '/') {
 311  0
                             name = name.replace(fileSeparator, '/');
 312   
                         }
 313  0
                         if (!addedFiles.contains(name)) {
 314  0
                             targets.addElement(name);
 315  0
                             addedFiles.put(name, name);
 316   
                         }
 317   
                     }
 318   
                 }
 319   
             }
 320   
         }
 321  0
         String[] targetFiles = new String[targets.size()];
 322  0
         targets.copyInto(targetFiles);
 323   
         
 324  0
         String[] orig = cmdl.getCommandline();
 325  0
         String[] result 
 326   
             = new String[orig.length + srcFiles.length + targetFiles.length];
 327   
 
 328  0
         int srcIndex = orig.length;
 329  0
         if (srcFilePos != null) {
 330  0
             srcIndex = srcFilePos.getPosition();
 331   
         }
 332   
 
 333  0
         if (targetFilePos != null) {
 334  0
             int targetIndex = targetFilePos.getPosition();
 335   
 
 336  0
             if (srcIndex < targetIndex 
 337   
                 || (srcIndex == targetIndex && srcIsFirst)) {
 338   
 
 339   
                 // 0 --> srcIndex
 340  0
                 System.arraycopy(orig, 0, result, 0, srcIndex);
 341   
                 
 342   
                 // srcIndex --> targetIndex
 343  0
                 System.arraycopy(orig, srcIndex, result, 
 344   
                                  srcIndex + srcFiles.length,
 345   
                                  targetIndex - srcIndex);
 346   
                 
 347   
                 // targets are already absolute file names
 348  0
                 System.arraycopy(targetFiles, 0, result, 
 349   
                                  targetIndex + srcFiles.length, 
 350   
                                  targetFiles.length);
 351   
                 
 352   
                 // targetIndex --> end
 353  0
                 System.arraycopy(orig, targetIndex, result, 
 354   
                     targetIndex + srcFiles.length + targetFiles.length,
 355   
                     orig.length - targetIndex);
 356   
             } else {
 357   
                 // 0 --> targetIndex
 358  0
                 System.arraycopy(orig, 0, result, 0, targetIndex);
 359   
                 
 360   
                 // targets are already absolute file names
 361  0
                 System.arraycopy(targetFiles, 0, result, 
 362   
                                  targetIndex,
 363   
                                  targetFiles.length);
 364   
                 
 365   
                 // targetIndex --> srcIndex
 366  0
                 System.arraycopy(orig, targetIndex, result, 
 367   
                                  targetIndex + targetFiles.length,
 368   
                                  srcIndex - targetIndex);
 369   
                 
 370   
                 // srcIndex --> end
 371  0
                 System.arraycopy(orig, srcIndex, result, 
 372   
                     srcIndex + srcFiles.length + targetFiles.length,
 373   
                     orig.length - srcIndex);
 374  0
                 srcIndex += targetFiles.length;
 375   
             }
 376   
 
 377   
         } else { // no targetFilePos
 378   
 
 379   
             // 0 --> srcIndex
 380  0
             System.arraycopy(orig, 0, result, 0, srcIndex);
 381   
             // srcIndex --> end
 382  0
             System.arraycopy(orig, srcIndex, result, 
 383   
                              srcIndex + srcFiles.length,
 384   
                              orig.length - srcIndex);
 385   
 
 386   
         }
 387   
 
 388   
         // fill in source file names
 389  0
         for (int i = 0; i < srcFiles.length; i++) {
 390  0
             if (!relative) {
 391  0
                 result[srcIndex + i] = 
 392   
                     (new File(baseDirs[i], srcFiles[i])).getAbsolutePath();
 393   
             } else {
 394  0
                 result[srcIndex + i] = srcFiles[i];
 395   
             }
 396  0
             if (forwardSlash && fileSeparator != '/') {
 397  0
                 result[srcIndex + i] = 
 398   
                     result[srcIndex + i].replace(fileSeparator, '/');
 399   
             }
 400   
         }
 401  0
         return result;
 402   
     }
 403   
 
 404   
     /**
 405   
      * Construct the command line for serial execution.
 406   
      *
 407   
      * @param srcFile The filename to add to the commandline
 408   
      * @param baseDir filename is relative to this dir
 409   
      */
 410  0
     protected String[] getCommandline(String srcFile, File baseDir) {
 411  0
         return getCommandline(new String[] {srcFile}, new File[] {baseDir});
 412   
     }
 413   
 
 414   
     /**
 415   
      * Return the list of files from this DirectoryScanner that should
 416   
      * be included on the command line.
 417   
      */
 418  0
     protected String[] getFiles(File baseDir, DirectoryScanner ds) {
 419  0
         if (mapper != null) {
 420  0
             SourceFileScanner sfs = new SourceFileScanner(this);
 421  0
             return sfs.restrict(ds.getIncludedFiles(), baseDir, destDir, 
 422   
                                 mapper);
 423   
         } else {
 424  0
             return ds.getIncludedFiles();
 425   
         }
 426   
     }
 427   
 
 428   
     /**
 429   
      * Return the list of Directories from this DirectoryScanner that
 430   
      * should be included on the command line.
 431   
      */
 432  0
     protected String[] getDirs(File baseDir, DirectoryScanner ds) {
 433  0
         if (mapper != null) {
 434  0
             SourceFileScanner sfs = new SourceFileScanner(this);
 435  0
             return sfs.restrict(ds.getIncludedDirectories(), baseDir, destDir, 
 436   
                                 mapper);
 437   
         } else {
 438  0
             return ds.getIncludedDirectories();
 439   
         }
 440   
     }
 441   
 
 442   
     /**
 443   
      * Enumerated attribute with the values "file", "dir" and "both"
 444   
      * for the type attribute.  
 445   
      */
 446   
     public static class FileDirBoth extends EnumeratedAttribute {
 447   
         /**
 448   
          * @see EnumeratedAttribute#getValues
 449   
          */
 450  0
         public String[] getValues() {
 451  0
             return new String[] {"file", "dir", "both"};
 452   
         }
 453   
     }
 454   
 }
 455