Save This Page
Home » apache-ant-1.8.1 » org.apache.tools » ant » [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   package org.apache.tools.ant;
   19   
   20   import java.util.ArrayList;
   21   import java.util.Collections;
   22   import java.util.Enumeration;
   23   import java.util.Hashtable;
   24   import java.util.Iterator;
   25   import java.util.List;
   26   import java.util.StringTokenizer;
   27   
   28   import org.apache.tools.ant.property.LocalProperties;
   29   
   30   /**
   31    * Class to implement a target object with required parameters.
   32    *
   33    * <p>If you are creating Targets programmatically, make sure you set
   34    * the Location to a useful value.  In particular all targets should
   35    * have different location values.</p>
   36    */
   37   public class Target implements TaskContainer {
   38   
   39       /** Name of this target. */
   40       private String name;
   41   
   42       /** The "if" condition to test on execution. */
   43       private String ifCondition = "";
   44   
   45       /** The "unless" condition to test on execution. */
   46       private String unlessCondition = "";
   47   
   48       /** List of targets this target is dependent on. */
   49       private List dependencies = null;
   50   
   51       /** Children of this target (tasks and data types). */
   52       private List children = new ArrayList();
   53   
   54       /** Since Ant 1.6.2 */
   55       private Location location = Location.UNKNOWN_LOCATION;
   56   
   57       /** Project this target belongs to. */
   58       private Project project;
   59   
   60       /** Description of this target, if any. */
   61       private String description = null;
   62   
   63       /** Default constructor. */
   64       public Target() {
   65           //empty
   66       }
   67   
   68       /**
   69        * Cloning constructor.
   70        * @param other the Target to clone.
   71        */
   72       public Target(Target other) {
   73           this.name = other.name;
   74           this.ifCondition = other.ifCondition;
   75           this.unlessCondition = other.unlessCondition;
   76           this.dependencies = other.dependencies;
   77           this.location = other.location;
   78           this.project = other.project;
   79           this.description = other.description;
   80           // The children are added to after this cloning
   81           this.children = other.children;
   82       }
   83   
   84       /**
   85        * Sets the project this target belongs to.
   86        *
   87        * @param project The project this target belongs to.
   88        *                Must not be <code>null</code>.
   89        */
   90       public void setProject(Project project) {
   91           this.project = project;
   92       }
   93   
   94       /**
   95        * Returns the project this target belongs to.
   96        *
   97        * @return The project this target belongs to, or <code>null</code> if
   98        *         the project has not been set yet.
   99        */
  100       public Project getProject() {
  101           return project;
  102       }
  103   
  104       /**
  105        * Sets the location of this target's definition.
  106        *
  107        * @param location   <code>Location</code>
  108        * @since 1.6.2
  109        */
  110       public void setLocation(Location location) {
  111           this.location = location;
  112       }
  113   
  114       /**
  115        * Get the location of this target's definition.
  116        *
  117        * @return <code>Location</code>
  118        * @since 1.6.2
  119        */
  120       public Location getLocation() {
  121           return location;
  122       }
  123   
  124       /**
  125        * Sets the list of targets this target is dependent on.
  126        * The targets themselves are not resolved at this time.
  127        *
  128        * @param depS A comma-separated list of targets this target
  129        *             depends on. Must not be <code>null</code>.
  130        */
  131       public void setDepends(String depS) {
  132           for (Iterator iter = parseDepends(depS, getName(), "depends").iterator();
  133                iter.hasNext(); ) {
  134               addDependency((String) iter.next());
  135           }
  136       }
  137   
  138       public static List/*<String>*/ parseDepends(String depends,
  139                                                   String targetName,
  140                                                   String attributeName) {
  141           ArrayList list = new ArrayList();
  142           if (depends.length() > 0) {
  143               StringTokenizer tok =
  144                   new StringTokenizer(depends, ",", true);
  145               while (tok.hasMoreTokens()) {
  146                   String token = tok.nextToken().trim();
  147   
  148                   // Make sure the dependency is not empty string
  149                   if ("".equals(token) || ",".equals(token)) {
  150                       throw new BuildException("Syntax Error: "
  151                                                + attributeName
  152                                                + " attribute of target \""
  153                                                + targetName
  154                                                + "\" contains an empty string.");
  155                   }
  156   
  157                   list.add(token);
  158   
  159                   // Make sure that depends attribute does not
  160                   // end in a ,
  161                   if (tok.hasMoreTokens()) {
  162                       token = tok.nextToken();
  163                       if (!tok.hasMoreTokens() || !",".equals(token)) {
  164                           throw new BuildException("Syntax Error: "
  165                                                    + attributeName
  166                                                    + " attribute for target \""
  167                                                    + targetName
  168                                                    + "\" ends with a \",\" "
  169                                                    + "character");
  170                       }
  171                   }
  172               }
  173           }
  174           return list;
  175       }
  176   
  177       /**
  178        * Sets the name of this target.
  179        *
  180        * @param name The name of this target. Should not be <code>null</code>.
  181        */
  182       public void setName(String name) {
  183           this.name = name;
  184       }
  185   
  186       /**
  187        * Returns the name of this target.
  188        *
  189        * @return the name of this target, or <code>null</code> if the
  190        *         name has not been set yet.
  191        */
  192       public String getName() {
  193           return name;
  194       }
  195   
  196       /**
  197        * Adds a task to this target.
  198        *
  199        * @param task The task to be added. Must not be <code>null</code>.
  200        */
  201       public void addTask(Task task) {
  202           children.add(task);
  203       }
  204   
  205       /**
  206        * Adds the wrapper for a data type element to this target.
  207        *
  208        * @param r The wrapper for the data type element to be added.
  209        *          Must not be <code>null</code>.
  210        */
  211       public void addDataType(RuntimeConfigurable r) {
  212           children.add(r);
  213       }
  214   
  215       /**
  216        * Returns the current set of tasks to be executed by this target.
  217        *
  218        * @return an array of the tasks currently within this target
  219        */
  220       public Task[] getTasks() {
  221           List tasks = new ArrayList(children.size());
  222           Iterator it = children.iterator();
  223           while (it.hasNext()) {
  224               Object o = it.next();
  225               if (o instanceof Task) {
  226                   tasks.add(o);
  227               }
  228           }
  229           return (Task[]) tasks.toArray(new Task[tasks.size()]);
  230       }
  231   
  232       /**
  233        * Adds a dependency to this target.
  234        *
  235        * @param dependency The name of a target this target is dependent on.
  236        *                   Must not be <code>null</code>.
  237        */
  238       public void addDependency(String dependency) {
  239           if (dependencies == null) {
  240               dependencies = new ArrayList(2);
  241           }
  242           dependencies.add(dependency);
  243       }
  244   
  245       /**
  246        * Returns an enumeration of the dependencies of this target.
  247        *
  248        * @return an enumeration of the dependencies of this target
  249        */
  250       public Enumeration getDependencies() {
  251           return Collections
  252                   .enumeration(dependencies == null ? Collections.EMPTY_LIST : dependencies);
  253       }
  254   
  255       /**
  256        * Does this target depend on the named target?
  257        * @param other the other named target.
  258        * @return true if the target does depend on the named target
  259        * @since Ant 1.6
  260        */
  261       public boolean dependsOn(String other) {
  262           Project p = getProject();
  263           Hashtable t = p == null ? null : p.getTargets();
  264           return p != null && p.topoSort(getName(), t, false).contains(t.get(other));
  265       }
  266   
  267       /**
  268        * Sets the "if" condition to test on execution. This is the
  269        * name of a property to test for existence - if the property
  270        * is not set, the task will not execute. The property goes
  271        * through property substitution once before testing, so if
  272        * property <code>foo</code> has value <code>bar</code>, setting
  273        * the "if" condition to <code>${foo}_x</code> will mean that the
  274        * task will only execute if property <code>bar_x</code> is set.
  275        *
  276        * @param property The property condition to test on execution.
  277        *                 May be <code>null</code>, in which case
  278        *                 no "if" test is performed.
  279        */
  280       public void setIf(String property) {
  281           ifCondition = property == null ? "" : property;
  282       }
  283   
  284       /**
  285        * Returns the "if" property condition of this target.
  286        *
  287        * @return the "if" property condition or <code>null</code> if no
  288        *         "if" condition had been defined.
  289        * @since 1.6.2
  290        */
  291       public String getIf() {
  292           return "".equals(ifCondition) ? null : ifCondition;
  293       }
  294   
  295       /**
  296        * Sets the "unless" condition to test on execution. This is the
  297        * name of a property to test for existence - if the property
  298        * is set, the task will not execute. The property goes
  299        * through property substitution once before testing, so if
  300        * property <code>foo</code> has value <code>bar</code>, setting
  301        * the "unless" condition to <code>${foo}_x</code> will mean that the
  302        * task will only execute if property <code>bar_x</code> isn't set.
  303        *
  304        * @param property The property condition to test on execution.
  305        *                 May be <code>null</code>, in which case
  306        *                 no "unless" test is performed.
  307        */
  308       public void setUnless(String property) {
  309           unlessCondition = property == null ? "" : property;
  310       }
  311   
  312       /**
  313        * Returns the "unless" property condition of this target.
  314        *
  315        * @return the "unless" property condition or <code>null</code>
  316        *         if no "unless" condition had been defined.
  317        * @since 1.6.2
  318        */
  319       public String getUnless() {
  320           return "".equals(unlessCondition) ? null : unlessCondition;
  321       }
  322   
  323       /**
  324        * Sets the description of this target.
  325        *
  326        * @param description The description for this target.
  327        *                    May be <code>null</code>, indicating that no
  328        *                    description is available.
  329        */
  330       public void setDescription(String description) {
  331           this.description = description;
  332       }
  333   
  334       /**
  335        * Returns the description of this target.
  336        *
  337        * @return the description of this target, or <code>null</code> if no
  338        *         description is available.
  339        */
  340       public String getDescription() {
  341           return description;
  342       }
  343   
  344       /**
  345        * Returns the name of this target.
  346        *
  347        * @return the name of this target, or <code>null</code> if the
  348        *         name has not been set yet.
  349        */
  350       public String toString() {
  351           return name;
  352       }
  353   
  354       /**
  355        * Executes the target if the "if" and "unless" conditions are
  356        * satisfied. Dependency checking should be done before calling this
  357        * method, as it does no checking of its own. If either the "if"
  358        * or "unless" test prevents this target from being executed, a verbose
  359        * message is logged giving the reason. It is recommended that clients
  360        * of this class call performTasks rather than this method so that
  361        * appropriate build events are fired.
  362        *
  363        * @exception BuildException if any of the tasks fail or if a data type
  364        *                           configuration fails.
  365        *
  366        * @see #performTasks()
  367        * @see #setIf(String)
  368        * @see #setUnless(String)
  369        */
  370       public void execute() throws BuildException {
  371           if (!testIfAllows()) {
  372               project.log(this, "Skipped because property '" + project.replaceProperties(ifCondition)
  373                       + "' not set.", Project.MSG_VERBOSE);
  374               return;
  375           }
  376           if (!testUnlessAllows()) {
  377               project.log(this, "Skipped because property '"
  378                       + project.replaceProperties(unlessCondition) + "' set.", Project.MSG_VERBOSE);
  379               return;
  380           }
  381           LocalProperties localProperties = LocalProperties.get(getProject());
  382           localProperties.enterScope();
  383           try {
  384               // use index-based approach to avoid ConcurrentModificationExceptions;
  385               // also account for growing target children
  386               for (int i = 0; i < children.size(); i++) {
  387                   Object o = children.get(i);
  388                   if (o instanceof Task) {
  389                       Task task = (Task) o;
  390                       task.perform();
  391                   } else {
  392                       ((RuntimeConfigurable) o).maybeConfigure(project);
  393                   }
  394               }
  395           } finally {
  396               localProperties.exitScope();
  397           }
  398       }
  399   
  400       /**
  401        * Performs the tasks within this target (if the conditions are met),
  402        * firing target started/target finished messages around a call to
  403        * execute.
  404        *
  405        * @see #execute()
  406        */
  407       public final void performTasks() {
  408           RuntimeException thrown = null;
  409           project.fireTargetStarted(this);
  410           try {
  411               execute();
  412           } catch (RuntimeException exc) {
  413               thrown = exc;
  414               throw exc;
  415           } finally {
  416               project.fireTargetFinished(this, thrown);
  417           }
  418       }
  419   
  420       /**
  421        * Replaces all occurrences of the given task in the list
  422        * of children with the replacement data type wrapper.
  423        *
  424        * @param el The task to replace.
  425        *           Must not be <code>null</code>.
  426        * @param o  The data type wrapper to replace <code>el</code> with.
  427        */
  428       void replaceChild(Task el, RuntimeConfigurable o) {
  429           int index;
  430           while ((index = children.indexOf(el)) >= 0) {
  431               children.set(index, o);
  432           }
  433       }
  434   
  435       /**
  436        * Replaces all occurrences of the given task in the list
  437        * of children with the replacement task.
  438        *
  439        * @param el The task to replace.
  440        *           Must not be <code>null</code>.
  441        * @param o  The task to replace <code>el</code> with.
  442        */
  443       void replaceChild(Task el, Task o) {
  444           int index;
  445           while ((index = children.indexOf(el)) >= 0) {
  446               children.set(index, o);
  447           }
  448       }
  449   
  450       /**
  451        * Tests whether or not the "if" condition allows the execution of this target.
  452        *
  453        * @return whether or not the "if" condition is satisfied. If no
  454        *         condition (or an empty condition) has been set,
  455        *         <code>true</code> is returned.
  456        *
  457        * @see #setIf(String)
  458        */
  459       private boolean testIfAllows() {
  460           PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
  461           Object o = propertyHelper.parseProperties(ifCondition);
  462           return propertyHelper.testIfCondition(o);
  463       }
  464   
  465       /**
  466        * Tests whether or not the "unless" condition allows the execution of this target.
  467        *
  468        * @return whether or not the "unless" condition is satisfied. If no
  469        *         condition (or an empty condition) has been set,
  470        *         <code>true</code> is returned.
  471        *
  472        * @see #setUnless(String)
  473        */
  474       private boolean testUnlessAllows() {
  475           PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
  476           Object o = propertyHelper.parseProperties(unlessCondition);
  477           return propertyHelper.testUnlessCondition(o);
  478       }
  479   }

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