<!--
  ~ Copyright 2009 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.
  -->
<chapter id='plugins' xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Using Plugins</title>
    <para>Now we look at <emphasis>how</emphasis> Gradle provides build-by-convention and out of the box functionality.
        These features are decoupled from the core of Gradle, and are provided via plugins. Although the plugins are
        decoupled, we would like to point out that the Gradle core plugins are NEVER updated or changed for a
        particular Gradle distribution. If there is a bug in the compile functionality of Gradle, we will release a new
        version of Gradle. There is no change of behavior for the lifetime of a given distribution of Gradle.
    </para>
    <section id='sec:using_plugins'>
        <title>Declaring plugins</title>
        <para>If you want to use the plugin for building a Java project, simply include
        </para>
        <sample id="useJavaPlugin" dir="java/quickstart" title="Using a plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
        <para>in your script. That's all. From a technological point of view plugins use just the same
            operations as you can use from your build scripts. That is, they use the Project and Task API.
            The Gradle plugins generally use this API to:
        </para>
        <itemizedlist>
            <listitem>
                <para>Add tasks to the project (e.g. compile, test)
                </para>
            </listitem>
            <listitem>
                <para>Create dependencies between those tasks to let them execute in the appropriate order.
                </para>
            </listitem>
            <listitem>
                <para>Add dependency configurations to the project.</para>
            </listitem>
            <listitem>
                <para>Add a so called <firstterm>convention object</firstterm> to the project.
                </para>
            </listitem>
        </itemizedlist>
        <para>Let's check this out:
        </para>
        <sample id="pluginIntro" dir="userguide/tutorial/pluginIntro" title="Applying a plugin by id">
            <sourcefile file="build.gradle" snippet="apply-by-id"/>
            <output args="-q show"/>
        </sample>
        <para>The Java plugin adds a <literal>compileJava</literal> task and a <literal>processResources</literal> task
            to the project object which can be accessed by a build script. It has configured the <literal>destinationDir</literal>
            property of both of these tasks.
        </para>
        <para>The <literal>apply()</literal> method either takes a string or a class as an argument. You can write
        </para>
        <sample id="pluginIntro" dir="userguide/tutorial/pluginIntro" title="Applying a plugin by type">
            <sourcefile file="build.gradle" snippet="apply-by-type"/>
        </sample>
        <para>Thanks to Gradle's default imports (see <xref linkend='ide_support'/>) you can also write in this case.
        </para>
        <sample id="pluginIntro" dir="userguide/tutorial/pluginIntro" title="Applying a plugin by type">
            <sourcefile file="build.gradle" snippet="apply-by-type-with-import"/>
        </sample>
        <para>Any class, which implements the <apilink class="org.gradle.api.Plugin"/> interface, can be used as a
            plugin. Just pass the class as an argument. You don't need to configure anything else for this.</para>
        <para>If you want to use your own plugins, you must make sure that they are accessible via the build script
            classpath (see <xref linkend='organizing_build_logic'/> for more information). To learn more about how
            to write custom plugins, see <xref linkend='custom_plugins'/>.
        </para>
    </section>
    <section id='sub:more_about_convention_objects'>
        <title>Using the convention object</title>
        <para>If you use the Java plugin
            for example, there are a <literal>compileJava</literal> and a <literal>processResources</literal> task for
            your production code (the same is true for your test
            code). The default location for the output of those tasks is the directory <literal>build/classes/main</literal>.
            What if you want to change this? Let's try:
        </para>
        <sample id="pluginConfig" dir="userguide/tutorial/pluginConfig" title="Configuring a plugin task">
            <sourcefile file="build.gradle"/>
            <output args="-q show"/>
        </sample>
        <para>Setting the <literal>destinationDir</literal>
            of the <literal>processResources</literal> task had only an effect on the <literal>processResources</literal>
            task. Maybe this was what you wanted. But what if
            you want to change the output directory for all tasks? It would be unfortunate if you had to do this for
            each task separately.
        </para>
        <para>Gradle's tasks are usually <firstterm>convention aware</firstterm>. A plugin can add a convention object to
            your project, and map certain values of this convention object to task properties.
        </para>
        <sample id="pluginConvention" dir="userguide/tutorial/pluginConvention" title="Plugin convention object">
            <sourcefile file="build.gradle"/>
            <output args="-q show"/>
        </sample>
        <para>The Java plugin has added a convention object with a <literal>sourceSets</literal>
            property, which we use to set the classes directory. Notice that setting this has changed the <literal>destinationDir</literal>
            property of both the <literal>processResources</literal> and
            <literal>compileJava</literal> tasks.</para>
        <para>By setting a task attribute explicitly (as we have done in the first example) you overwrite the convention
            value for this particular task.
        </para>
        <para>Not all of the tasks attributes are mapped to convention object values. It is the decision of the plugin
            to decide what are the shared properties and then bundle them in a convention object and map them to the
            tasks.
        </para>
        <para>
            The properties of a convention object can be accessed as project properties. As shown in the following
            example, you can also access the convention object explicitly.
        </para>
        <sample id="pluginAccessConvention" dir="userguide/tutorial/pluginAccessConvention" title="Using the plugin convention object">
            <sourcefile file="build.gradle"/>
            <output args="-q show"/>
        </sample>
        <para>Every project object has a <apilink class="org.gradle.api.plugins.Convention"/> object which is a
            container for convention objects contributed
            by the plugins declared for your project. If you simply access or set a property or access a method in
            your build script, the project object first looks if this is a property of itself. If not, it delegates
            the request to its convention object. The convention object checks if any of the plugin convention
            objects can fulfill the request (first wins and the order is not defined). The plugin convention objects
            also introduce a namespace.
        </para>
        <section id='sub:declaring_plugins_multiple_times'>
            <title>Declaring plugins multiple times</title>
            <para>A plugin is only called once for a given project, even if you have multiple
                <literal>apply()</literal>
                statements. An additional call after the first call has no effect but doesn't hurt either. This can be
                important if you use plugins which extend other plugins. For example
                the Groovy plugin automatically applies the Java plugin. We say the Groovy plugin extends the Java plugin. But you might as well
                write:
            </para>
            <sample id="pluginIntro" dir="userguide/tutorial/pluginIntro" title="Explicit application of an implied plugin">
                <sourcefile file="build.gradle" snippet="explicit-apply"/>
            </sample>
            <para>If you use cross-project configuration in multi-project builds this is a useful feature.
            </para>
        </section>
    </section>
</chapter>
