Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 496   Methods: 30
NCLOC: 155   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Task.java 38.9% 41.8% 53.3% 44.3%
 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;
 56   
 
 57   
 import java.util.Enumeration;
 58   
 import java.io.IOException;
 59   
 
 60   
 /**
 61   
  * Base class for all tasks.
 62   
  *
 63   
  * Use Project.createTask to create a new task instance rather than
 64   
  * using this class directly for construction.
 65   
  *
 66   
  * @see Project#createTask
 67   
  */
 68   
 public abstract class Task extends ProjectComponent {
 69   
     /**
 70   
      * Target this task belongs to, if any.
 71   
      * @deprecated You should not be accessing this variable directly.
 72   
      *   Please use the {@link #getOwningTarget()} method.
 73   
      */
 74   
     protected Target target;
 75   
 
 76   
     /**
 77   
      * Description of this task, if any.
 78   
      * @deprecated You should not be accessing this variable directly.
 79   
      */
 80   
     protected String description;
 81   
 
 82   
     /**
 83   
      * Location within the build file of this task definition.
 84   
      * @deprecated You should not be accessing this variable directly.
 85   
      *   Please use the {@link #getLocation()} method.
 86   
      */
 87   
     protected Location location = Location.UNKNOWN_LOCATION;
 88   
 
 89   
     /**
 90   
      * Name of this task to be used for logging purposes.
 91   
      * This defaults to the same as the type, but may be
 92   
      * overridden by the user. For instance, the name "java"
 93   
      * isn't terribly descriptive for a task used within
 94   
      * another task - the outer task code can probably
 95   
      * provide a better one.
 96   
      * @deprecated You should not be accessing this variable directly.
 97   
      *   Please use the {@link #getTaskName()} method.
 98   
      */
 99   
     protected String taskName;
 100   
 
 101   
     /**
 102   
      * Type of this task.
 103   
      *
 104   
      * @deprecated You should not be accessing this variable directly.
 105   
      *   Please use the {@link #getTaskType()} method.
 106   
      */
 107   
     protected String taskType;
 108   
 
 109   
     /**
 110   
      * Wrapper for this object, used to configure it at runtime.
 111   
      *
 112   
      * @deprecated You should not be accessing this variable directly.
 113   
      *   Please use the {@link #getWrapper()} method.
 114   
      */
 115   
     protected RuntimeConfigurable wrapper;
 116   
 
 117   
     /**
 118   
      * Whether or not this task is invalid. A task becomes invalid
 119   
      * if a conflicting class is specified as the implementation for
 120   
      * its type.
 121   
      */
 122   
     private boolean invalid;
 123   
 
 124   
     /** Sole constructor. */
 125  25237
     public Task() {
 126   
     }
 127   
 
 128   
     /**
 129   
      * Sets the target container of this task.
 130   
      *
 131   
      * @param target Target in whose scope this task belongs.
 132   
      *               May be <code>null</code>, indicating a top-level task.
 133   
      */
 134  25151
     public void setOwningTarget(Target target) {
 135  25151
         this.target = target;
 136   
     }
 137   
 
 138   
     /**
 139   
      * Returns the container target of this task.
 140   
      *
 141   
      * @return The target containing this task, or <code>null</code> if
 142   
      *         this task is a top-level task.
 143   
      */
 144  21713
     public Target getOwningTarget() {
 145  21713
         return target;
 146   
     }
 147   
 
 148   
     /**
 149   
      * Sets the name to use in logging messages.
 150   
      *
 151   
      * @param name The name to use in logging messages.
 152   
      *             Should not be <code>null</code>.
 153   
      */
 154  25243
     public void setTaskName(String name) {
 155  25243
         this.taskName = name;
 156   
     }
 157   
 
 158   
     /**
 159   
      * Returns the name to use in logging messages.
 160   
      *
 161   
      * @return the name to use in logging messages.
 162   
      */
 163  23229
     public String getTaskName() {
 164  23229
         return taskName;
 165   
     }
 166   
 
 167   
     /**
 168   
      * Sets the name with which the task has been invoked.
 169   
      *
 170   
      * @param type The name the task has been invoked as.
 171   
      *             Should not be <code>null</code>.
 172   
      */
 173  3107
     public void setTaskType(String type) {
 174  3107
         this.taskType = type;
 175   
     }
 176   
 
 177   
     /**
 178   
      * Sets a description of the current action. This may be used for logging
 179   
      * purposes.
 180   
      *
 181   
      * @param desc Description of the current action.
 182   
      *             May be <code>null</code>, indicating that no description is
 183   
      *             available.
 184   
      *
 185   
      */
 186  0
     public void setDescription(String desc) {
 187  0
         description = desc;
 188   
     }
 189   
 
 190   
     /**
 191   
      * Returns the description of the current action.
 192   
      *
 193   
      * @return the description of the current action, or <code>null</code> if
 194   
      *         no description is available.
 195   
      */
 196  0
     public String getDescription() {
 197  0
         return description;
 198   
     }
 199   
 
 200   
     /**
 201   
      * Called by the project to let the task initialize properly.
 202   
      * The default implementation is a no-op.
 203   
      *
 204   
      * @exception BuildException if someting goes wrong with the build
 205   
      */
 206  3016
     public void init() throws BuildException {}
 207   
 
 208   
     /**
 209   
      * Called by the project to let the task do its work. This method may be
 210   
      * called more than once, if the task is invoked more than once.
 211   
      * For example,
 212   
      * if target1 and target2 both depend on target3, then running
 213   
      * "ant target1 target2" will run all tasks in target3 twice.
 214   
      *
 215   
      * @exception BuildException if something goes wrong with the build
 216   
      */
 217  0
     public void execute() throws BuildException {}
 218   
 
 219   
     /**
 220   
      * Returns the file/location where this task was defined.
 221   
      *
 222   
      * @return the file/location where this task was defined.
 223   
      *         Should not return <code>null</code>. Location.UNKNOWN_LOCATION
 224   
      *         is used for unknown locations.
 225   
      *
 226   
      * @see Location#UNKNOWN_LOCATION
 227   
      */
 228  3239
     public Location getLocation() {
 229  3239
         return location;
 230   
     }
 231   
 
 232   
     /**
 233   
      * Sets the file/location where this task was defined.
 234   
      *
 235   
      * @param location The file/location where this task was defined.
 236   
      *                 Should not be <code>null</code> - use
 237   
      *                 Location.UNKNOWN_LOCATION if the location isn't known.
 238   
      *
 239   
      * @see Location#UNKNOWN_LOCATION
 240   
      */
 241  25155
     public void setLocation(Location location) {
 242  25155
         this.location = location;
 243   
     }
 244   
 
 245   
     /**
 246   
      * Returns the wrapper used for runtime configuration.
 247   
      *
 248   
      * @return the wrapper used for runtime configuration. This
 249   
      *         method will generate a new wrapper (and cache it)
 250   
      *         if one isn't set already.
 251   
      */
 252  0
     public RuntimeConfigurable getRuntimeConfigurableWrapper() {
 253  0
         if (wrapper == null) {
 254  0
             wrapper = new RuntimeConfigurable(this, getTaskName());
 255   
         }
 256  0
         return wrapper;
 257   
     }
 258   
 
 259   
     /**
 260   
      * Sets the wrapper to be used for runtime configuration.
 261   
      *
 262   
      * This method should be used only by the ProjectHelper and ant internals.
 263   
      * It is public to allow helper plugins to operate on tasks, normal tasks
 264   
      * should never use it.
 265   
      *
 266   
      * @param wrapper The wrapper to be used for runtime configuration.
 267   
      *                May be <code>null</code>, in which case the next call
 268   
      *                to getRuntimeConfigurableWrapper will generate a new
 269   
      *                wrapper.
 270   
      */
 271  25291
     public void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) {
 272  25291
         this.wrapper = wrapper;
 273   
     }
 274   
 
 275   
     // XXX: (Jon Skeet) The comment "if it hasn't been done already" may
 276   
     // not be strictly true. wrapper.maybeConfigure() won't configure the same
 277   
     // attributes/text more than once, but it may well add the children again,
 278   
     // unless I've missed something.
 279   
     /**
 280   
      * Configures this task - if it hasn't been done already.
 281   
      * If the task has been invalidated, it is replaced with an
 282   
      * UnknownElement task which uses the new definition in the project.
 283   
      *
 284   
      * @exception BuildException if the task cannot be configured.
 285   
      */
 286  41
     public void maybeConfigure() throws BuildException {
 287  41
         if (!invalid) {
 288  41
             if (wrapper != null) {
 289  41
                 wrapper.maybeConfigure(getProject());
 290   
             }
 291   
         } else {
 292  0
             getReplacement();
 293   
         }
 294   
     }
 295   
 
 296   
     /**
 297   
      * Force the task to be reconfigured from it's RuntimeConfigurable
 298   
      *
 299   
      */
 300  1
     public void reconfigure() {
 301  1
         if (wrapper != null) {
 302  1
             wrapper.reconfigure(getProject());
 303   
         }
 304   
     }
 305   
     
 306   
     /**
 307   
      * Handles a line of output by logging it with the INFO priority.
 308   
      *
 309   
      * @param line The line of output to log. Should not be <code>null</code>.
 310   
      */
 311  0
     protected void handleOutput(String line) {
 312  0
         log(line, Project.MSG_INFO);
 313   
     }
 314   
 
 315   
     /**
 316   
      * Handles a line of output by logging it with the INFO priority.
 317   
      *
 318   
      * @param line The line of output to log. Should not be <code>null</code>.
 319   
      *
 320   
      * @since Ant 1.5.2
 321   
      */
 322  0
     protected void handleFlush(String line) {
 323  0
         handleOutput(line);
 324   
     }
 325   
 
 326   
     /**
 327   
      * Handle an input request by this task
 328   
      *
 329   
      * @param buffer the buffer into which data is to be read.
 330   
      * @param offset the offset into the buffer at which data is stored.
 331   
      * @param length the amount of data to read
 332   
      *
 333   
      * @return the number of bytes read
 334   
      * 
 335   
      * @exception IOException if the data cannot be read
 336   
      * @since Ant 1.6
 337   
      */
 338  0
     protected int handleInput(byte[] buffer, int offset, int length) 
 339   
         throws IOException {
 340  0
         return getProject().defaultInput(buffer, offset, length);
 341   
     }
 342   
     
 343   
     /**
 344   
      * Handles an error line by logging it with the INFO priority.
 345   
      *
 346   
      * @param line The error line to log. Should not be <code>null</code>.
 347   
      */
 348  0
     protected void handleErrorOutput(String line) {
 349  0
         log(line, Project.MSG_ERR);
 350   
     }
 351   
 
 352   
     /**
 353   
      * Handles an error line by logging it with the INFO priority.
 354   
      *
 355   
      * @param line The error line to log. Should not be <code>null</code>.
 356   
      *
 357   
      * @since Ant 1.5.2
 358   
      */
 359  0
     protected void handleErrorFlush(String line) {
 360  0
         handleErrorOutput(line);
 361   
     }
 362   
 
 363   
     /**
 364   
      * Logs a message with the default (INFO) priority.
 365   
      *
 366   
      * @param msg The message to be logged. Should not be <code>null</code>.
 367   
      */
 368  712
     public void log(String msg) {
 369  712
         log(msg, Project.MSG_INFO);
 370   
     }
 371   
 
 372   
     /**
 373   
      * Logs a mesage with the given priority. This delegates
 374   
      * the actual logging to the project.
 375   
      *
 376   
      * @param msg The message to be logged. Should not be <code>null</code>.
 377   
      * @param msgLevel The message priority at which this message is to
 378   
      *                 be logged.
 379   
      */
 380  8992
     public void log(String msg, int msgLevel) {
 381  8992
         getProject().log(this, msg, msgLevel);
 382   
     }
 383   
 
 384   
     /**
 385   
      * Performs this task if it's still valid, or gets a replacement
 386   
      * version and performs that otherwise.
 387   
      *
 388   
      * Performing a task consists of firing a task started event,
 389   
      * configuring the task, executing it, and then firing task finished
 390   
      * event. If a runtime exception is thrown, the task finished event
 391   
      * is still fired, but with the exception as the cause.
 392   
      */
 393  3274
     public final void perform() {
 394  3274
         if (!invalid) {
 395  3274
             try {
 396  3274
                 getProject().fireTaskStarted(this);
 397  3274
                 maybeConfigure();
 398  3257
                 execute();
 399  3127
                 getProject().fireTaskFinished(this, null);
 400   
             } catch (RuntimeException exc) {
 401  147
                 if (exc instanceof BuildException) {
 402  147
                     BuildException be = (BuildException) exc;
 403  147
                     if (be.getLocation() == Location.UNKNOWN_LOCATION) {
 404  87
                         be.setLocation(getLocation());
 405   
                     }
 406   
                 }
 407  147
                 getProject().fireTaskFinished(this, exc);
 408  147
                 throw exc;
 409   
             }
 410   
         } else {
 411  0
             UnknownElement ue = getReplacement();
 412  0
             Task task = ue.getTask();
 413  0
             task.perform();
 414   
         }
 415   
     }
 416   
 
 417   
     /**
 418   
      * Marks this task as invalid. Any further use of this task
 419   
      * will go through a replacement with the updated definition.
 420   
      */
 421  0
     final void markInvalid() {
 422  0
         invalid = true;
 423   
     }
 424   
 
 425   
     /**
 426   
      * Has this task been marked invalid?
 427   
      *
 428   
      * @return true if this task is no longer valid. A new task should be 
 429   
      * configured in this case.
 430   
      *
 431   
      * @since Ant 1.5
 432   
      */
 433  0
     protected final boolean isInvalid() {
 434  0
         return invalid;
 435   
     }
 436   
 
 437   
     /**
 438   
      * Replacement element used if this task is invalidated.
 439   
      */
 440   
     private UnknownElement replacement;
 441   
 
 442   
     /**
 443   
      * Creates an UnknownElement that can be used to replace this task.
 444   
      * Once this has been created once, it is cached and returned by
 445   
      * future calls.
 446   
      *
 447   
      * @return the UnknownElement instance for the new definition of this task.
 448   
      */
 449  0
     private UnknownElement getReplacement() {
 450  0
         if (replacement == null) {
 451  0
             replacement = new UnknownElement(taskType);
 452  0
             replacement.setProject(getProject());
 453  0
             replacement.setTaskType(taskType);
 454  0
             replacement.setTaskName(taskName);
 455  0
             replacement.setLocation(location);
 456  0
             replacement.setOwningTarget(target);
 457  0
             replacement.setRuntimeConfigurableWrapper(wrapper);
 458  0
             wrapper.setProxy(replacement);
 459  0
             replaceChildren(wrapper, replacement);
 460  0
             target.replaceChild(this, replacement);
 461  0
             replacement.maybeConfigure();
 462   
         }
 463  0
         return replacement;
 464   
     }
 465   
 
 466   
     /**
 467   
      * Recursively adds an UnknownElement instance for each child
 468   
      * element of replacement.
 469   
      *
 470   
      * @since Ant 1.5.1
 471   
      */
 472  0
     private void replaceChildren(RuntimeConfigurable wrapper,
 473   
                                  UnknownElement parentElement) {
 474  0
         Enumeration enum = wrapper.getChildren();
 475  0
         while (enum.hasMoreElements()) {
 476  0
             RuntimeConfigurable childWrapper =
 477   
                 (RuntimeConfigurable) enum.nextElement();
 478  0
             UnknownElement childElement =
 479   
                 new UnknownElement(childWrapper.getElementTag());
 480  0
             parentElement.addChild(childElement);
 481  0
             childElement.setProject(getProject());
 482  0
             childElement.setRuntimeConfigurableWrapper(childWrapper);
 483  0
             childWrapper.setProxy(childElement);
 484  0
             replaceChildren(childWrapper, childElement);
 485   
         }
 486   
     }
 487   
 
 488  28
     protected String getTaskType() {
 489  28
         return taskType;
 490   
     }
 491   
 
 492  0
     protected RuntimeConfigurable getWrapper() {
 493  0
         return wrapper;
 494   
     }
 495   
 }
 496