Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 409   Methods: 22
NCLOC: 149   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Target.java 66.7% 84.6% 86.4% 80.3%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2002 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;
 56   
 
 57   
 import java.util.Enumeration;
 58   
 import java.util.StringTokenizer;
 59   
 import java.util.Vector;
 60   
 
 61   
 /**
 62   
  * Class to implement a target object with required parameters.
 63   
  *
 64   
  * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
 65   
  */
 66   
 public class Target implements TaskContainer {
 67   
 
 68   
     /** Name of this target. */
 69   
     private String name;
 70   
     /** The "if" condition to test on execution. */
 71   
     private String ifCondition = "";
 72   
     /** The "unless" condition to test on execution. */
 73   
     private String unlessCondition = "";
 74   
     /** List of targets this target is dependent on. */
 75   
     private Vector dependencies = new Vector(2);
 76   
     /** Children of this target (tasks and data types). */
 77   
     private Vector children = new Vector(5);
 78   
     /** Project this target belongs to. */
 79   
     private Project project;
 80   
     /** Description of this target, if any. */
 81   
     private String description = null;
 82   
 
 83   
     /** Sole constructor. */
 84  8526
     public Target() {
 85   
     }
 86   
     
 87   
     /** 
 88   
      * Sets the project this target belongs to. 
 89   
      * 
 90   
      * @param project The project this target belongs to. 
 91   
      *                Must not be <code>null</code>.
 92   
      */
 93  8526
     public void setProject(Project project) {
 94  8526
         this.project = project;
 95   
     }
 96   
 
 97   
     /**
 98   
      * Returns the project this target belongs to.
 99   
      * 
 100   
      * @return The project this target belongs to, or <code>null</code> if 
 101   
      *         the project has not been set yet.
 102   
      */
 103  2084
     public Project getProject() {
 104  2084
         return project;
 105   
     }
 106   
 
 107   
     /**
 108   
      * Sets the list of targets this target is dependent on.
 109   
      * The targets themselves are not resolved at this time.
 110   
      * 
 111   
      * @param depS A comma-separated list of targets this target
 112   
      *             depends on. Must not be <code>null</code>.
 113   
      */
 114  1246
     public void setDepends(String depS) {
 115  1246
         if (depS.length() > 0) {
 116  1246
             StringTokenizer tok =
 117   
                 new StringTokenizer(depS, ",", true);
 118  1246
             while (tok.hasMoreTokens()) {
 119  1591
                 String token = tok.nextToken().trim();
 120   
 
 121   
                 // Make sure the dependency is not empty string
 122  1591
                 if (token.equals("") || token.equals(",")) {
 123  0
                     throw new BuildException("Syntax Error: Depend "
 124   
                         + "attribute for target \"" + getName() 
 125   
                         + "\" has an empty string for dependency.");
 126   
                 }
 127   
 
 128  1591
                 addDependency(token);
 129   
                 
 130   
                 // Make sure that depends attribute does not
 131   
                 // end in a ,
 132  1591
                 if (tok.hasMoreTokens()) {
 133  345
                     token = tok.nextToken();
 134  345
                     if (!tok.hasMoreTokens() || !token.equals(",")) {
 135  0
                         throw new BuildException("Syntax Error: Depend " 
 136   
                             + "attribute for target \"" + getName() 
 137   
                             + "\" ends with a , character");
 138   
                     }
 139   
                 }
 140   
             }
 141   
         }
 142   
     }
 143   
 
 144   
     /**
 145   
      * Sets the name of this target.
 146   
      * 
 147   
      * @param name The name of this target. Should not be <code>null</code>.
 148   
      */
 149  8526
     public void setName(String name) {
 150  8526
         this.name = name;
 151   
     }
 152   
 
 153   
     /**
 154   
      * Returns the name of this target.
 155   
      * 
 156   
      * @return the name of this target, or <code>null</code> if the
 157   
      *         name has not been set yet.
 158   
      */
 159  986
     public String getName() {
 160  986
         return name;
 161   
     }
 162   
 
 163   
     /**
 164   
      * Adds a task to this target.
 165   
      * 
 166   
      * @param task The task to be added. Must not be <code>null</code>.
 167   
      */
 168  14637
     public void addTask(Task task) {
 169  14637
         children.addElement(task);
 170   
     }
 171   
 
 172   
     /**
 173   
      * Adds the wrapper for a data type element to this target.
 174   
      * 
 175   
      * @param r The wrapper for the data type element to be added. 
 176   
      *          Must not be <code>null</code>.
 177   
      */
 178  0
     public void addDataType(RuntimeConfigurable r) {
 179  0
         children.addElement(r);
 180   
     }
 181   
 
 182   
     /** 
 183   
      * Returns the current set of tasks to be executed by this target.
 184   
      * 
 185   
      * @return an array of the tasks currently within this target
 186   
      */
 187  8
     public Task[] getTasks() {
 188  8
         Vector tasks = new Vector(children.size());
 189  8
         Enumeration enum = children.elements();
 190  8
         while (enum.hasMoreElements()) {
 191  6
             Object o = enum.nextElement();
 192  6
             if (o instanceof Task) {
 193  6
                 tasks.addElement(o);
 194   
             }
 195   
         }
 196   
         
 197  8
         Task[] retval = new Task[tasks.size()];
 198  8
         tasks.copyInto(retval);
 199  8
         return retval;
 200   
     }
 201   
 
 202   
     /**
 203   
      * Adds a dependency to this target.
 204   
      * 
 205   
      * @param dependency The name of a target this target is dependent on.
 206   
      *                   Must not be <code>null</code>.
 207   
      */
 208  1591
     public void addDependency(String dependency) {
 209  1591
         dependencies.addElement(dependency);
 210   
     }
 211   
 
 212   
     /**
 213   
      * Returns an enumeration of the dependencies of this target.
 214   
      * 
 215   
      * @return an enumeration of the dependencies of this target
 216   
      */
 217  14936
     public Enumeration getDependencies() {
 218  14936
         return dependencies.elements();
 219   
     }
 220   
 
 221   
     /**
 222   
      * Sets the "if" condition to test on execution. This is the
 223   
      * name of a property to test for existence - if the property
 224   
      * is not set, the task will not execute. The property goes
 225   
      * through property substitution once before testing, so if
 226   
      * property <code>foo</code> has value <code>bar</code>, setting
 227   
      * the "if" condition to <code>${foo}_x</code> will mean that the
 228   
      * task will only execute if property <code>bar_x</code> is set.
 229   
      * 
 230   
      * @param property The property condition to test on execution.
 231   
      *                 May be <code>null</code>, in which case
 232   
      *                 no "if" test is performed.
 233   
      */
 234  8
     public void setIf(String property) {
 235  8
         this.ifCondition = (property == null) ? "" : property;
 236   
     }
 237   
  
 238   
     /**
 239   
      * Sets the "unless" condition to test on execution. This is the
 240   
      * name of a property to test for existence - if the property
 241   
      * is set, the task will not execute. The property goes
 242   
      * through property substitution once before testing, so if
 243   
      * property <code>foo</code> has value <code>bar</code>, setting
 244   
      * the "unless" condition to <code>${foo}_x</code> will mean that the
 245   
      * task will only execute if property <code>bar_x</code> isn't set.
 246   
      * 
 247   
      * @param property The property condition to test on execution.
 248   
      *                 May be <code>null</code>, in which case
 249   
      *                 no "unless" test is performed.
 250   
      */
 251  4
     public void setUnless(String property) {
 252  4
         this.unlessCondition = (property == null) ? "" : property;
 253   
     }
 254   
 
 255   
     /**
 256   
      * Sets the description of this target.
 257   
      * 
 258   
      * @param description The description for this target. 
 259   
      *                    May be <code>null</code>, indicating that no 
 260   
      *                    description is available.
 261   
      */
 262  34
     public void setDescription(String description) {
 263  34
         this.description = description;
 264   
     }
 265   
 
 266   
     /**
 267   
      * Returns the description of this target.
 268   
      * 
 269   
      * @return the description of this target, or <code>null</code> if no
 270   
      *         description is available.
 271   
      */
 272  0
     public String getDescription() {
 273  0
         return description;
 274   
     }
 275   
 
 276   
     /**
 277   
      * Returns the name of this target.
 278   
      * 
 279   
      * @return the name of this target, or <code>null</code> if the
 280   
      *         name has not been set yet.
 281   
      */
 282  16547
     public String toString() {
 283  16547
         return name;
 284   
     }
 285   
 
 286   
     /**
 287   
      * Executes the target if the "if" and "unless" conditions are
 288   
      * satisfied. Dependency checking should be done before calling this
 289   
      * method, as it does no checking of its own. If either the "if"
 290   
      * or "unless" test prevents this target from being executed, a verbose
 291   
      * message is logged giving the reason. It is recommended that clients
 292   
      * of this class call performTasks rather than this method so that 
 293   
      * appropriate build events are fired.
 294   
      * 
 295   
      * @exception BuildException if any of the tasks fail or if a data type
 296   
      *                           configuration fails.
 297   
      * 
 298   
      * @see #performTasks()
 299   
      * @see #setIf(String)
 300   
      * @see #setUnless(String)
 301   
      */
 302  1605
     public void execute() throws BuildException {
 303  1605
         if (testIfCondition() && testUnlessCondition()) {
 304  1603
             Enumeration enum = children.elements();
 305  1603
             while (enum.hasMoreElements()) {
 306  3189
                 Object o = enum.nextElement();
 307  3189
                 if (o instanceof Task) {
 308  3189
                     Task task = (Task) o;
 309  3189
                     task.perform();
 310   
                 } else {
 311  0
                     RuntimeConfigurable r = (RuntimeConfigurable) o;
 312  0
                     r.maybeConfigure(project);
 313   
                 }
 314   
             }
 315  2
         } else if (!testIfCondition()) {
 316  0
             project.log(this, "Skipped because property '" 
 317   
                         + project.replaceProperties(this.ifCondition) 
 318   
                         + "' not set.", Project.MSG_VERBOSE);
 319   
         } else {
 320  2
             project.log(this, "Skipped because property '" 
 321   
                         + project.replaceProperties(this.unlessCondition) 
 322   
                         + "' set.", Project.MSG_VERBOSE);
 323   
         }
 324   
     }
 325   
 
 326   
     /**
 327   
      * Performs the tasks within this target (if the conditions are met),
 328   
      * firing target started/target finished messages around a call to 
 329   
      * execute.
 330   
      * 
 331   
      * @see #execute()
 332   
      */
 333  1041
     public final void performTasks() {
 334  1041
         try {
 335  1041
             project.fireTargetStarted(this);
 336  1041
             execute();
 337  895
             project.fireTargetFinished(this, null);
 338   
         } catch (RuntimeException exc) {
 339  146
             project.fireTargetFinished(this, exc);
 340  146
             throw exc;
 341   
         }
 342   
     }
 343   
     
 344   
     /**
 345   
      * Replaces all occurrences of the given task in the list
 346   
      * of children with the replacement data type wrapper.
 347   
      * 
 348   
      * @param el The task to replace.
 349   
      *           Must not be <code>null</code>.
 350   
      * @param o  The data type wrapper to replace <code>el</code> with.
 351   
      */
 352  0
     void replaceChild(Task el, RuntimeConfigurable o) {
 353  0
         int index;
 354  0
         while ((index = children.indexOf(el)) >= 0) {
 355  0
             children.setElementAt(o, index);
 356   
         }
 357   
     }
 358   
 
 359   
     /**
 360   
      * Replaces all occurrences of the given task in the list
 361   
      * of children with the replacement task.
 362   
      * 
 363   
      * @param el The task to replace.
 364   
      *           Must not be <code>null</code>.
 365   
      * @param o  The task to replace <code>el</code> with.
 366   
      */
 367  3062
     void replaceChild(Task el, Task o) {
 368  3062
         int index;
 369  ?
         while ((index = children.indexOf(el)) >= 0) {
 370  2978
             children.setElementAt(o, index);
 371   
         }
 372   
     }
 373   
 
 374   
     /**
 375   
      * Tests whether or not the "if" condition is satisfied.
 376   
      * 
 377   
      * @return whether or not the "if" condition is satisfied. If no
 378   
      *         condition (or an empty condition) has been set,
 379   
      *         <code>true</code> is returned.
 380   
      *
 381   
      * @see #setIf(String)
 382   
      */
 383  1607
     private boolean testIfCondition() {
 384  1607
         if ("".equals(ifCondition)) {
 385  1602
             return true;
 386   
         }
 387   
         
 388  5
         String test = project.replaceProperties(ifCondition);
 389  5
         return project.getProperty(test) != null;
 390   
     }
 391   
 
 392   
     /**
 393   
      * Tests whether or not the "unless" condition is satisfied.
 394   
      * 
 395   
      * @return whether or not the "unless" condition is satisfied. If no
 396   
      *         condition (or an empty condition) has been set,
 397   
      *         <code>true</code> is returned.
 398   
      *
 399   
      * @see #setUnless(String)
 400   
      */
 401  1605
     private boolean testUnlessCondition() {
 402  1605
         if ("".equals(unlessCondition)) {
 403  1603
             return true;
 404   
         }
 405  2
         String test = project.replaceProperties(unlessCondition);
 406  2
         return project.getProperty(test) == null;
 407   
     }
 408   
 }
 409