Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 389   Methods: 19
NCLOC: 164   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SubAnt.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 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 Foundation"
 27   
  *    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   
 
 60   
 import java.util.Vector;
 61   
 import java.util.Enumeration;
 62   
 
 63   
 import org.apache.tools.ant.Task;
 64   
 import org.apache.tools.ant.Project;
 65   
 import org.apache.tools.ant.BuildException;
 66   
 
 67   
 import org.apache.tools.ant.types.Path;
 68   
 import org.apache.tools.ant.types.DirSet;
 69   
 import org.apache.tools.ant.types.FileSet;
 70   
 import org.apache.tools.ant.types.FileList;
 71   
 import org.apache.tools.ant.types.Reference;
 72   
 
 73   
 import org.apache.tools.ant.taskdefs.Ant;
 74   
 import org.apache.tools.ant.taskdefs.Property;
 75   
 
 76   
 /**
 77   
  * <i>EXPERIMENTAL:</i> This task is experimental and may be under continual
 78   
  * change till Ant1.6 ships; it may even be omitted from the product.
 79   
  * <p>
 80   
  * Calls a given target for all defined sub-builds. This is an extension
 81   
  * of ant for bulk project execution.
 82   
  *
 83   
  * @since Ant1.6
 84   
  * @author <a href="mailto:ddevienne@lgc.com">Dominique Devienne</a>
 85   
  * @ant.task name="subant" category="control"
 86   
  */
 87   
 public class SubAnt
 88   
              extends Task {
 89   
 
 90   
     private Path buildpath;
 91   
 
 92   
     private String target = null;
 93   
     private String antfile = "build.xml";
 94   
     private boolean inheritAll = false;
 95   
     private boolean inheritRefs = false;
 96   
     private boolean failOnError = true;
 97   
 
 98   
     private Vector properties = new Vector();
 99   
     private Vector references = new Vector();
 100   
 
 101   
     /**
 102   
      * Runs the various sub-builds.
 103   
      */
 104  0
     public void execute()
 105   
                 throws BuildException {
 106  0
         if (buildpath == null) {
 107  0
             throw new BuildException("No buildpath specified");
 108   
         }
 109   
 
 110  0
         final String[] filenames = buildpath.list();
 111  0
         final int count = filenames.length;
 112  0
         if (count < 1) {
 113  0
             log("No sub-builds to iterate on", Project.MSG_WARN);
 114  0
             return;
 115   
         }
 116   
 /*
 117   
     //REVISIT: there must be cleaner way of doing this, if it is merited at all
 118   
         if (target == null) {
 119   
             target = getOwningTarget().getName();
 120   
         }
 121   
 */
 122  0
         for (int i=0; i<count; ++i) {
 123  0
             File file = new File(filenames[i]);
 124  0
             if (file.isDirectory()) {
 125  0
                 file = new File(file, antfile);
 126   
             }
 127  0
             execute(file);
 128   
         }
 129   
     }
 130   
 
 131   
     /**
 132   
      * Runs the given target on the provided build file.
 133   
      *
 134   
      * @param  file the build file to execute
 135   
      * @throws BuildException is the file cannot be found, read, is
 136   
      *         a directory, or the target called failed, but only if
 137   
      *         <code>failOnError</code> is <code>true</code>. Otherwise,
 138   
      *         a warning log message is simply output.
 139   
      */
 140  0
     private void execute(File file)
 141   
                 throws BuildException {
 142  0
         if (!file.exists() || file.isDirectory() || !file.canRead()) {
 143  0
             String msg = "Invalid file: "+file;
 144  0
             if (failOnError) {
 145  0
                 throw new BuildException(msg);
 146   
             }
 147  0
             log(msg, Project.MSG_WARN);
 148  0
             return;
 149   
         }
 150   
 
 151  0
         Ant ant = createAntTask();
 152  0
         String antfilename = null;
 153  0
         try {
 154  0
             antfilename = file.getCanonicalPath();
 155   
         } catch (IOException e) {
 156  0
             throw new BuildException(e);
 157   
         }
 158   
 
 159  0
         ant.setAntfile(antfilename);
 160  0
         try {
 161  0
             ant.execute();
 162   
         } catch (BuildException e) {
 163  0
             if (failOnError) {
 164  0
                 throw e;
 165   
             }
 166  0
             log("Failure for target '"+target
 167   
                +"' of: "+antfilename+"\n"
 168   
                +e.getMessage(), Project.MSG_WARN);
 169   
         }
 170   
     }
 171   
 
 172   
     /**
 173   
      * Sets the default build file name to append to directory
 174   
      * names found in the build path -default "build.xml"
 175   
      *
 176   
      * @param  antfile the short build file name. Defaults to "build.xml".
 177   
      */
 178  0
     public void setAntfile(String antfile) {
 179  0
         this.antfile = antfile;
 180   
     }
 181   
 
 182   
     /**
 183   
      * Sets whether to fail with a build exception on error, or go on.
 184   
      *
 185   
      * @param  failOnError the new value for this boolean flag.
 186   
      */
 187  0
     public void setFailonerror(boolean failOnError) {
 188  0
         this.failOnError = failOnError;
 189   
     }
 190   
 
 191   
     /**
 192   
      * The target to call on the different sub-builds. Set to "" to execute
 193   
      * the default target.
 194   
      * <p>
 195   
      */
 196   
     //     REVISIT: Defaults to the target name that contains this task if not specified.
 197  0
     public void setTarget(String target) {
 198  0
         this.target = target;
 199   
     }
 200   
 
 201   
     /**
 202   
      * Corresponds to <code>&lt;ant&gt;</code>'s
 203   
      * <code>inheritall</code> attribute.
 204   
      *
 205   
      * @param  b the new value for this boolean flag.
 206   
      */
 207  0
     public void setInheritall(boolean b) {
 208  0
         this.inheritAll = b;
 209   
     }
 210   
 
 211   
     /**
 212   
      * Corresponds to <code>&lt;ant&gt;</code>'s
 213   
      * <code>inheritrefs</code> attribute.
 214   
      *
 215   
      * @param  b the new value for this boolean flag.
 216   
      */
 217  0
     public void setInheritrefs(boolean b) {
 218  0
         this.inheritRefs = b;
 219   
     }
 220   
 
 221   
     /**
 222   
      * Corresponds to <code>&lt;ant&gt;</code>'s
 223   
      * nested <code>&lt;property&gt;</code> element.
 224   
      *
 225   
      * @param  p the property to pass on explicitly to the sub-build.
 226   
      */
 227  0
     public void addProperty(Property p) {
 228  0
         properties.addElement(p);
 229   
     }
 230   
 
 231   
     /**
 232   
      * Corresponds to <code>&lt;ant&gt;</code>'s
 233   
      * nested <code>&lt;reference&gt;</code> element.
 234   
      *
 235   
      * @param  r the reference to pass on explicitly to the sub-build.
 236   
      */
 237  0
     public void addReference(Ant.Reference r) {
 238  0
         references.addElement(r);
 239   
     }
 240   
 
 241   
     /**
 242   
      * Adds a directory set to the implicit build path.
 243   
      * <p>
 244   
      * <em>Note that the directories will be added to the build path
 245   
      * in no particular order, so if order is significant, one should
 246   
      * use a file list instead!</em>
 247   
      *
 248   
      * @param  set the directory set to add.
 249   
      */
 250  0
     public void addDirset(DirSet set) {
 251  0
         getBuildpath().addDirset(set);
 252   
     }
 253   
 
 254   
     /**
 255   
      * Adds a file set to the implicit build path.
 256   
      * <p>
 257   
      * <em>Note that the directories will be added to the build path
 258   
      * in no particular order, so if order is significant, one should
 259   
      * use a file list instead!</em>
 260   
      *
 261   
      * @param  set the file set to add.
 262   
      */
 263  0
     public void addFileset(FileSet set) {
 264  0
         getBuildpath().addFileset(set);
 265   
     }
 266   
 
 267   
     /**
 268   
      * Adds an ordered file list to the implicit build path.
 269   
      * <p>
 270   
      * <em>Note that contrary to file and directory sets, file lists
 271   
      * can reference non-existent files or directories!</em>
 272   
      *
 273   
      * @param  list the file list to add.
 274   
      */
 275  0
     public void addFilelist(FileList list) {
 276  0
         getBuildpath().addFilelist(list);
 277   
     }
 278   
 
 279   
     /**
 280   
      * Set the buildpath to be used to find sub-projects.
 281   
      * 
 282   
      * @param  s an Ant Path object containing the buildpath.
 283   
      */
 284  0
     public void setBuildpath(Path s) {
 285  0
         getBuildpath().append(s);
 286   
     }
 287   
     
 288   
     /**
 289   
      * Creates a nested build path, and add it to the implicit build path.
 290   
      *
 291   
      * @return the newly created nested build path.
 292   
      */
 293  0
     public Path createBuildpath() {
 294  0
         return getBuildpath().createPath();
 295   
     }
 296   
 
 297   
     /**
 298   
      * Creates a nested <code>&lt;buildpathelement&gt;</code>,
 299   
      * and add it to the implicit build path.
 300   
      *
 301   
      * @return the newly created nested build path element.
 302   
      */
 303  0
     public Path.PathElement createBuildpathElement()
 304   
                             throws BuildException {
 305  0
         return getBuildpath().createPathElement();
 306   
     }
 307   
 
 308   
     /**
 309   
      * Gets the implicit build path, creating it if <code>null</code>.
 310   
      *
 311   
      * @return the implicit build path.
 312   
      */
 313  0
     private Path getBuildpath() {
 314  0
         if (buildpath == null) {
 315  0
             buildpath = new Path(getProject());
 316   
         }
 317  0
         return buildpath;
 318   
     }
 319   
 
 320   
     /**
 321   
      * Buildpath to use, by reference.
 322   
      *
 323   
      * @param  r a reference to an Ant Path object containing the buildpath.
 324   
      */
 325  0
     public void setBuildpathRef(Reference r) {
 326  0
         createBuildpath().setRefid(r);
 327   
     }
 328   
 
 329   
     /**
 330   
      * Creates the &lt;ant&gt; task configured to run a specific target.
 331   
      *
 332   
      * @return the ant task, configured with the explicit properties and
 333   
      *         references necessary to run the sub-build.
 334   
      */
 335  0
     private Ant createAntTask() {
 336  0
         Ant ant = (Ant) getProject().createTask("ant");
 337  0
         ant.setOwningTarget(getOwningTarget());
 338  0
         ant.init();
 339  0
         if(target.length()>0) {
 340  0
             ant.setTarget(target);
 341   
         }
 342   
 
 343  0
         ant.setInheritAll(inheritAll);
 344  0
         for (Enumeration i = properties.elements(); i.hasMoreElements();) {
 345  0
             copyProperty(ant.createProperty(), (Property) i.nextElement());
 346   
         }
 347   
         
 348  0
         ant.setInheritRefs(inheritRefs);
 349  0
         for (Enumeration i = references.elements(); i.hasMoreElements();) {
 350  0
             ant.addReference((Ant.Reference) i.nextElement());
 351   
         }
 352   
 
 353  0
         return ant;
 354   
     }
 355   
 
 356   
     /**
 357   
      * Assigns an Ant property to another.
 358   
      *
 359   
      * @param  to the destination property whose content is modified.
 360   
      * @param  from the source property whose content is copied.
 361   
      */
 362  0
     private static void copyProperty(Property to, Property from) {
 363  0
         to.setName(from.getName());
 364   
 
 365  0
         if (from.getValue() != null) {
 366  0
             to.setValue(from.getValue());
 367   
         }
 368  0
         if (from.getFile() != null) {
 369  0
             to.setFile(from.getFile());
 370   
         }
 371  0
         if (from.getResource() != null) {
 372  0
             to.setResource(from.getResource());
 373   
         }
 374  0
         if (from.getPrefix() != null) {
 375  0
             to.setPrefix(from.getPrefix());
 376   
         }
 377  0
         if (from.getRefid() != null) {
 378  0
             to.setRefid(from.getRefid());
 379   
         }
 380  0
         if (from.getEnvironment() != null) {
 381  0
             to.setEnvironment(from.getEnvironment());
 382   
         }
 383  0
         if (from.getClasspath() != null) {
 384  0
             to.setClasspath(from.getClasspath());
 385   
         }
 386   
     }
 387   
 
 388   
 } // END class SubAnt
 389