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

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