/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.api;
import groovy.lang.Closure;
import groovy.lang.MissingPropertyException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.LoggingManager;
import org.gradle.api.plugins.Convention;
import org.gradle.api.plugins.ExtensionAware;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskDependency;
import org.gradle.api.tasks.TaskDestroyables;
import org.gradle.api.tasks.TaskInputs;
import org.gradle.api.tasks.TaskOutputs;
import org.gradle.api.tasks.TaskState;
import java.io.File;
import java.util.List;
import java.util.Set;
/**
* <p>A <code>Task</code> represents a single atomic piece of work for a build, such as compiling classes or generating
* javadoc.</p>
*
* <p>Each task belongs to a {@link Project}. You can use the various methods on {@link
* org.gradle.api.tasks.TaskContainer} to create and lookup task instances. For example, {@link
* org.gradle.api.tasks.TaskContainer#create(String)} creates an empty task with the given name. You can also use the
* {@code task} keyword in your build file: </p>
* <pre>
* task myTask
* task myTask { configure closure }
* task myTask(type: SomeType)
* task myTask(type: SomeType) { configure closure }
* </pre>
*
* <p>Each task has a name, which can be used to refer to the task within its owning project, and a fully qualified
* path, which is unique across all tasks in all projects. The path is the concatenation of the owning project's path
* and the task's name. Path elements are separated using the {@value org.gradle.api.Project#PATH_SEPARATOR}
* character.</p>
*
* <h3>Task Actions</h3>
*
* <p>A <code>Task</code> is made up of a sequence of {@link Action} objects. When the task is executed, each of the
* actions is executed in turn, by calling {@link Action#execute}. You can add actions to a task by calling {@link
* #doFirst(Action)} or {@link #doLast(Action)}.</p>
*
* <p>Groovy closures can also be used to provide a task action. When the action is executed, the closure is called with
* the task as parameter. You can add action closures to a task by calling {@link #doFirst(groovy.lang.Closure)} or
* {@link #doLast(groovy.lang.Closure)}.</p>
*
* <p>There are 2 special exceptions which a task action can throw to abort execution and continue without failing the
* build. A task action can abort execution of the action and continue to the next action of the task by throwing a
* {@link org.gradle.api.tasks.StopActionException}. A task action can abort execution of the task and continue to the
* next task by throwing a {@link org.gradle.api.tasks.StopExecutionException}. Using these exceptions allows you to
* have precondition actions which skip execution of the task, or part of the task, if not true.</p>
*
* <a name="dependencies"/><h3>Task Dependencies and Task Ordering</h3>
*
* <p>A task may have dependencies on other tasks or might be scheduled to always run after another task.
* Gradle ensures that all task dependencies and ordering rules are honored when executing tasks, so that the task is executed after
* all of its dependencies and any "must run after" tasks have been executed.</p>
*
* <p>Dependencies to a task are controlled using {@link #dependsOn(Object...)} or {@link #setDependsOn(Iterable)},
* and {@link #mustRunAfter(Object...)}, {@link #setMustRunAfter(Iterable)}, {@link #shouldRunAfter(Object...)} and
* {@link #setShouldRunAfter(Iterable)} are used to specify ordering between tasks. You can use objects of any of
* the following types to specify dependencies and ordering:</p>
*
* <ul>
*
* <li>A {@code String}, {@code CharSequence} or {@code groovy.lang.GString} task path or name. A relative path is interpreted relative to the task's {@link Project}. This
* allows you to refer to tasks in other projects.</li>
*
* <li>A {@link Task}.</li>
*
* <li>A closure. The closure may take a {@code Task} as parameter. It may return any of the types listed here. Its
* return value is recursively converted to tasks. A {@code null} return value is treated as an empty collection.</li>
*
* <li>A {@link TaskDependency} object.</li>
*
* <li>A {@link Buildable} object.</li>
*
* <li>A {@code Iterable}, {@code Collection}, {@code Map} or array. May contain any of the types listed here. The elements of the
* iterable/collection/map/array are recursively converted to tasks.</li>
*
* <li>A {@code Callable}. The {@code call()} method may return any of the types listed here. Its return value is
* recursively converted to tasks. A {@code null} return value is treated as an empty collection.</li>
*
* </ul>
*
* <h3>Using a Task in a Build File</h3>
*
* <a name="properties"/> <h4>Dynamic Properties</h4>
*
* <p>A {@code Task} has 4 'scopes' for properties. You can access these properties by name from the build file or by
* calling the {@link #property(String)} method. You can change the value of these properties by calling the {@link #setProperty(String, Object)} method.</p>
*
* <ul>
*
* <li>The {@code Task} object itself. This includes any property getters and setters declared by the {@code Task}
* implementation class. The properties of this scope are readable or writable based on the presence of the
* corresponding getter and setter methods.</li>
*
* <li>The <em>extensions</em> added to the task by plugins. Each extension is available as a read-only property with the same
* name as the extension.</li>
*
* <li>The <em>convention</em> properties added to the task by plugins. A plugin can add properties and methods to a task through
* the task's {@link Convention} object. The properties of this scope may be readable or writable, depending on the convention objects.</li>
*
* <li>The <em>extra properties</em> of the task. Each task object maintains a map of additional properties. These
* are arbitrary name -> value pairs which you can use to dynamically add properties to a task object. Once defined, the properties
* of this scope are readable and writable.</li>
*
* </ul>
*
* <h4>Dynamic Methods</h4>
*
* <p>A {@link Plugin} may add methods to a {@code Task} using its {@link Convention} object.</p>
*
* <h4>Parallel Execution</h4>
* <p>
* By default, tasks are not executed in parallel unless a task is waiting on asynchronous work and another task (which
* is not dependent) is ready to execute.
*
* Parallel execution can be enabled by the <code>--parallel</code> flag when the build is initiated.
* In parallel mode, the tasks of different projects (i.e. in a multi project build) are able to be executed in parallel.
*/
public interface Task extends Comparable<Task>, ExtensionAware {
String TASK_NAME = "name";
String TASK_DESCRIPTION = "description";
String TASK_GROUP = "group";
String TASK_TYPE = "type";
String TASK_DEPENDS_ON = "dependsOn";
String TASK_OVERWRITE = "overwrite";
String TASK_ACTION = "action";
/**
* <p>Returns the name of this task. The name uniquely identifies the task within its {@link Project}.</p>
*
* @return The name of the task. Never returns null.
*/
@Internal
String getName();
/**
* A {@link org.gradle.api.Namer} namer for tasks that returns {@link #getName()}.
*/
class Namer implements org.gradle.api.Namer<Task> {
public String determineName(Task c) {
return c.getName();
}
}
/**
* <p>Returns the {@link Project} which this task belongs to.</p>
*
* @return The project this task belongs to. Never returns null.
*/
@Internal
Project getProject();
/**
* <p>Returns the sequence of {@link Action} objects which will be executed by this task, in the order of
* execution.</p>
*
* @return The task actions in the order they are executed. Returns an empty list if this task has no actions.
*/
@Internal
List<Action<? super Task>> getActions();
/**
* <p>Sets the sequence of {@link Action} objects which will be executed by this task.</p>
*
* @param actions The actions.
*/
void setActions(List<Action<? super Task>> actions);
/**
* <p>Returns a {@link TaskDependency} which contains all the tasks that this task depends on.</p>
*
* @return The dependencies of this task. Never returns null.
*/
@Internal
TaskDependency getTaskDependencies();
/**
* <p>Returns the dependencies of this task.</p>
*
* @return The dependencies of this task. Returns an empty set if this task has no dependencies.
*/
@Internal
Set<Object> getDependsOn();
/**
* <p>Sets the dependencies of this task. See <a href="#dependencies">here</a> for a description of the types of
* objects which can be used as task dependencies.</p>
*
* @param dependsOnTasks The set of task paths.
*/
void setDependsOn(Iterable<?> dependsOnTasks);
/**
* <p>Adds the given dependencies to this task. See <a href="#dependencies">here</a> for a description of the types
* of objects which can be used as task dependencies.</p>
*
* @param paths The dependencies to add to this task. The path can be defined by:
* <li>A {@code String}, {@code CharSequence} or {@code groovy.lang.GString} task path or name. A relative path is interpreted relative to the task's {@link Project}. This
* allows you to refer to tasks in other projects.</li>
*
* <li>A {@link Task}.</li>
*
* <li>A closure. The closure may take a {@code Task} as parameter. It may return any of the types listed here. Its
* return value is recursively converted to tasks. A {@code null} return value is treated as an empty collection.</li>
*
* <li>A {@link TaskDependency} object.</li>
*
* <li>A {@link org.gradle.api.tasks.TaskReference} object.</li>
*
* <li>A {@link Buildable} object.</li>
*
* <li>A {@code Iterable}, {@code Collection}, {@code Map} or array. May contain any of the types listed here. The elements of the
* iterable/collection/map/array are recursively converted to tasks.</li>
*
* <li>A {@code Callable}. The {@code call()} method may return any of the types listed here. Its return value is
* recursively converted to tasks. A {@code null} return value is treated as an empty collection.</li>
*
* <li>Anything else is treated as a failure.</li>
*
* @return the task object this method is applied to
*/
Task dependsOn(Object... paths);
/**
* <p>Execute the task only if the given closure returns true. The closure will be evaluated at task execution
* time, not during configuration. The closure will be passed a single parameter, this task. If the closure returns
* false, the task will be skipped.</p>
*
* <p>You may add multiple such predicates. The task is skipped if any of the predicates return false.</p>
*
* <p>Typical usage:<code>myTask.onlyIf{ dependsOnTaskDidWork() } </code></p>
*
* @param onlyIfClosure code to execute to determine if task should be run
*/
void onlyIf(Closure onlyIfClosure);
/**
* <p>Execute the task only if the given spec is satisfied. The spec will be evaluated at task execution time, not
* during configuration. If the Spec is not satisfied, the task will be skipped.</p>
*
* <p>You may add multiple such predicates. The task is skipped if any of the predicates return false.</p>
*
* <p>Typical usage (from Java):</p>
* <pre>myTask.onlyIf(new Spec<Task>() {
* boolean isSatisfiedBy(Task task) {
* return task.dependsOnTaskDidWork();
* }
* });
* </pre>
*
* @param onlyIfSpec specifies if a task should be run
*/
void onlyIf(Spec<? super Task> onlyIfSpec);
/**
* <p>Execute the task only if the given closure returns true. The closure will be evaluated at task execution
* time, not during configuration. The closure will be passed a single parameter, this task. If the closure returns
* false, the task will be skipped.</p>
*
* <p>The given predicate replaces all such predicates for this task.</p>
*
* @param onlyIfClosure code to execute to determine if task should be run
*/
void setOnlyIf(Closure onlyIfClosure);
/**
* <p>Execute the task only if the given spec is satisfied. The spec will be evaluated at task execution time, not
* during configuration. If the Spec is not satisfied, the task will be skipped.</p>
*
* <p>The given predicate replaces all such predicates for this task.</p>
*
* @param onlyIfSpec specifies if a task should be run
*/
void setOnlyIf(Spec<? super Task> onlyIfSpec);
/**
* Returns the execution state of this task. This provides information about the execution of this task, such as
* whether it has executed, been skipped, has failed, etc.
*
* @return The execution state of this task. Never returns null.
*/
@Internal
TaskState getState();
/**
* Sets whether the task actually did any work. Most built-in tasks will set this automatically, but
* it may be useful to manually indicate this for custom user tasks.
* <p>This is useful when combined with onlyIf { dependsOnTaskDidWork() }.
* @param didWork indicates if the task did any work
*/
void setDidWork(boolean didWork);
/**
* <p>Checks if the task actually did any work. Even if a Task executes, it may determine that it has nothing to
* do. For example, a compilation task may determine that source files have not changed since the last time a the
* task was run.</p>
*
* @return true if this task did any work
*/
@Internal
boolean getDidWork();
/**
* <p>Returns the path of the task, which is a fully qualified name for the task. The path of a task is the path of
* its {@link Project} plus the name of the task, separated by <code>:</code>.</p>
*
* @return the path of the task, which is equal to the path of the project plus the name of the task.
*/
@Internal
String getPath();
/**
* <p>Adds the given {@link Action} to the beginning of this task's action list.</p>
*
* @param action The action to add
* @return the task object this method is applied to
*/
Task doFirst(Action<? super Task> action);
/**
* <p>Adds the given closure to the beginning of this task's action list. The closure is passed this task as a
* parameter when executed.</p>
*
* @param action The action closure to execute.
* @return This task.
*/
Task doFirst(Closure action);
/**
* <p>Adds the given {@link Action} to the end of this task's action list.</p>
*
* @param action The action to add.
* @return the task object this method is applied to
*/
Task doLast(Action<? super Task> action);
/**
* <p>Adds the given closure to the end of this task's action list. The closure is passed this task as a parameter
* when executed.</p>
*
* @param action The action closure to execute.
* @return This task.
*/
Task doLast(Closure action);
/**
* <p>Adds the given closure to the end of this task's action list. The closure is passed this task as a parameter
* when executed. You can call this method from your build script using the << left shift operator.</p>
*
* @param action The action closure to execute.
* @return This task.
*
* @deprecated Use {@link #doLast(Closure action)}
*/
@Deprecated
Task leftShift(Closure action);
/**
* <p>Removes all the actions of this task.</p>
*
* @return the task object this method is applied to
*/
Task deleteAllActions();
/**
* <p>Returns if this task is enabled or not.</p>
*
* @see #setEnabled(boolean)
*/
@Internal
boolean getEnabled();
/**
* <p>Set the enabled state of a task. If a task is disabled none of the its actions are executed. Note that
* disabling a task does not prevent the execution of the tasks which this task depends on.</p>
*
* @param enabled The enabled state of this task (true or false)
*/
void setEnabled(boolean enabled);
/**
* <p>Applies the statements of the closure against this task object. The delegate object for the closure is set to
* this task.</p>
*
* @param configureClosure The closure to be applied (can be null).
* @return This task
*/
Task configure(Closure configureClosure);
/**
* <p>Returns the <code>AntBuilder</code> for this task. You can use this in your build file to execute ant
* tasks.</p>
*
* @return The <code>AntBuilder</code>
*/
@Internal
AntBuilder getAnt();
/**
* <p>Returns the logger for this task. You can use this in your build file to write log messages.</p>
*
* @return The logger. Never returns null.
*/
@Internal
Logger getLogger();
/**
* Returns the {@link org.gradle.api.logging.LoggingManager} which can be used to receive logging and to control the
* standard output/error capture for this task. By default, System.out is redirected to the Gradle logging system at
* the QUIET log level, and System.err is redirected at the ERROR log level.
*
* @return the LoggingManager. Never returns null.
*/
@Internal
LoggingManager getLogging();
/**
* <p>Returns the value of the given property of this task. This method locates a property as follows:</p>
*
* <ol>
*
* <li>If this task object has a property with the given name, return the value of the property.</li>
*
* <li>If this task has an extension with the given name, return the extension. </li>
*
* <li>If this task's convention object has a property with the given name, return the value of the property.</li>
*
* <li>If this task has an extra property with the given name, return the value of the property.</li>
*
* <li>If not found, throw {@link MissingPropertyException}</li>
*
* </ol>
*
* @param propertyName The name of the property.
* @return The value of the property, possibly null.
* @throws MissingPropertyException When the given property is unknown.
*/
Object property(String propertyName) throws MissingPropertyException;
/**
* <p>Determines if this task has the given property. See <a href="#properties">here</a> for details of the
* properties which are available for a task.</p>
*
* @param propertyName The name of the property to locate.
* @return True if this project has the given property, false otherwise.
*/
boolean hasProperty(String propertyName);
/**
* <p>Sets a property of this task. This method searches for a property with the given name in the following
* locations, and sets the property on the first location where it finds the property.</p>
*
* <ol>
*
* <li>The task object itself. For example, the <code>enabled</code> project property.</li>
*
* <li>The task's convention object.</li>
*
* <li>The task's extra properties.</li>
*
* </ol>
*
* If the property is not found, a {@link groovy.lang.MissingPropertyException} is thrown.
*
* @param name The name of the property
* @param value The value of the property
*/
void setProperty(String name, Object value) throws MissingPropertyException;
/**
* <p>Returns the {@link Convention} object for this task. A {@link Plugin} can use the convention object to
* contribute properties and methods to this task.</p>
*
* @return The convention object. Never returns null.
*/
@Internal
Convention getConvention();
/**
* Returns the description of this task.
*
* @return the description. May return null.
*/
@Internal
String getDescription();
/**
* Sets a description for this task. This should describe what the task does to the user of the build. The
* description will be displayed when <code>gradle tasks</code> is called.
*
* @param description The description of the task. Might be null.
*/
void setDescription(String description);
/**
* Returns the task group which this task belongs to. The task group is used in reports and user interfaces to
* group related tasks together when presenting a list of tasks to the user.
*
* @return The task group for this task. Might be null.
*/
@Internal
String getGroup();
/**
* Sets the task group which this task belongs to. The task group is used in reports and user interfaces to
* group related tasks together when presenting a list of tasks to the user.
*
* @param group The task group for this task. Can be null.
*/
void setGroup(String group);
/**
* <p>Checks if any of the tasks that this task depends on {@link Task#getDidWork() didWork}.</p>
*
* @return true if any task this task depends on did work.
*/
boolean dependsOnTaskDidWork();
/**
* <p>Returns the inputs of this task.</p>
*
* @return The inputs. Never returns null.
*/
@Internal
TaskInputs getInputs();
/**
* <p>Returns the outputs of this task.</p>
*
* @return The outputs. Never returns null.
*/
@Internal
TaskOutputs getOutputs();
/**
* <p>Returns the destroyables of this task.</p>
* @return The destroyables. Never returns null.
*
* @since 4.0
*/
@Incubating
@Internal
TaskDestroyables getDestroyables();
/**
* <p>Returns a directory which this task can use to write temporary files to. Each task instance is provided with a
* separate temporary directory. There are no guarantees that the contents of this directory will be kept beyond the
* execution of the task.</p>
*
* @return The directory. Never returns null. The directory will already exist.
*/
@Internal
File getTemporaryDir();
/**
* <p>Specifies that this task must run after all of the supplied tasks.</p>
*
* <pre autoTested="true">
* task taskY {
* mustRunAfter "taskX"
* }
* </pre>
*
* <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
* As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* an ordering relationship.</p>
*
* @param paths The tasks this task must run after.
*
* @return the task object this method is applied to
*/
@Incubating
Task mustRunAfter(Object... paths);
/**
* <p>Specifies the set of tasks that this task must run after.</p>
*
* <pre autoTested="true">
* task taskY {
* mustRunAfter = ["taskX1", "taskX2"]
* }
* </pre>
*
* <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
* As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* an ordering relationship.</p>
*
* @param mustRunAfter The set of task paths this task must run after.
*/
@Incubating
void setMustRunAfter(Iterable<?> mustRunAfter);
/**
* <p>Returns tasks that this task must run after.</p>
*
* @return The tasks that this task must run after. Returns an empty set if this task has no tasks it must run after.
*/
@Incubating
@Internal
TaskDependency getMustRunAfter();
/**
* <p>Adds the given finalizer tasks for this task.</p>
*
* <pre autoTested="true">
* task taskY {
* finalizedBy "taskX"
* }
* </pre>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* a finalizer task.</p>
*
* @param paths The tasks that finalize this task.
*
* @return the task object this method is applied to
*/
@Incubating
Task finalizedBy(Object... paths);
/**
* <p>Specifies the set of finalizer tasks for this task.</p>
*
* <pre autoTested="true">
* task taskY {
* finalizedBy = ["taskX1", "taskX2"]
* }
* </pre>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* a finalizer task.</p>
*
* @param finalizedBy The tasks that finalize this task.
*/
@Incubating
void setFinalizedBy(Iterable<?> finalizedBy);
/**
* <p>Returns tasks that finalize this task.</p>
*
* @return The tasks that finalize this task. Returns an empty set if there are no finalising tasks for this task.
*/
@Incubating
@Internal
TaskDependency getFinalizedBy();
/**
* <p>Specifies that this task should run after all of the supplied tasks.</p>
*
* <pre autoTested="true">
* task taskY {
* shouldRunAfter "taskX"
* }
* </pre>
*
* <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
* As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* an ordering relationship.</p>
*
* @param paths The tasks this task should run after.
*
* @return the task object this method is applied to
*/
@Incubating
TaskDependency shouldRunAfter(Object... paths);
/**
* <p>Specifies the set of tasks that this task should run after.</p>
*
* <pre autoTested="true">
* task taskY {
* shouldRunAfter = ["taskX1", "taskX2"]
* }
* </pre>
*
* <p>For each supplied task, this action adds a task 'ordering', and does not specify a 'dependency' between the tasks.
* As such, it is still possible to execute 'taskY' without first executing the 'taskX' in the example.</p>
*
* <p>See <a href="#dependencies">here</a> for a description of the types of objects which can be used to specify
* an ordering relationship.</p>
*
* @param shouldRunAfter The set of task paths this task should run after.
*/
@Incubating
void setShouldRunAfter(Iterable<?> shouldRunAfter);
/**
* <p>Returns tasks that this task should run after.</p>
*
* @return The tasks that this task should run after. Returns an empty set if this task has no tasks it must run after.
*/
@Incubating
@Internal
TaskDependency getShouldRunAfter();
}