<!--
  ~ 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'>
    <title>Gradle Plugins</title>
    <para>
        Gradle at its core intentionally provides very little for real world automation. All of the useful
        features, like the ability to compile Java code, are added by <emphasis>plugins</emphasis>.
        Plugins add new tasks (e.g. <apilink class='org.gradle.api.tasks.compile.JavaCompile'/>), domain objects (e.g.
        <apilink class="org.gradle.api.tasks.SourceSet"/>), conventions (e.g. Java source is located at
        <literal>src/main/java</literal>) as well as extending core objects and objects from other plugins.
    </para>
    <para>
        In this chapter we will discuss how to use plugins and the terminology and concepts surrounding plugins.
    </para>
    <section>
        <title>What plugins do</title>
        <para>
            Applying a plugin to a project allows the plugin to extend the project's capabilities. It can do things
            such as:
        </para>
        <itemizedlist>
            <listitem>Extend the Gradle model (e.g. add new DSL elements that can be configured)</listitem>
            <listitem>Configure the project according to conventions (e.g. add new tasks or configure sensible defaults)</listitem>
            <listitem>Apply specific configuration (e.g. add organizational repositories or enforce standards)</listitem>
        </itemizedlist>
        <para>
            By applying plugins, rather than adding logic to the project build script, we can reap a number of benefits.  Applying plugins:
        </para>
        <itemizedlist>
            <listitem>Promotes reuse and reduces the overhead of maintaining similar logic across multiple projects</listitem>
            <listitem>Allows a higher degree of modularization, enhancing comprehensibility and organization</listitem>
            <listitem>Encapsulates imperative logic and allows build scripts to be as declarative as possible</listitem>
        </itemizedlist>
    </section>
    <section id="sec:types_of_plugins">
        <title>Types of plugins</title>
        <para>
            There are two general types of plugins in Gradle, <emphasis>script</emphasis> plugins and <emphasis>binary</emphasis> plugins.
            Script plugins are additional build scripts that further configure the build and usually implement a declarative approach to
            manipulating the build.  They are typically used within a build although they can be externalized and accessed from a remote
            location.  Binary plugins are classes that implement the <apilink class='org.gradle.api.Plugin'/> interface and adopt a programmatic
            approach to manipulating the build.  Binary plugins can reside within a build script, within the project hierarchy or externally
            in a plugin jar.
        </para>
    </section>
    <section id='sec:using_plugins'>
        <title>Applying plugins</title>
        <para>
            Plugins are said to be <emphasis>applied</emphasis>, which is done via the <apilink class="org.gradle.api.Project" method="apply(java.util.Map)" /> method.
            The application of plugins is <emphasis>idempotent</emphasis>. That is, the same plugin can be applied multiple times. If the plugin
            has previously been applied, any further applications are safe and will have no effect.
        </para>
        <section>
            <title>Script plugins</title>
            <sample id="configureProjectUsingScript" dir="userguide/tutorial/configureProjectUsingScript" title="Applying a script plugin">
                <sourcefile file="build.gradle"/>
            </sample>
            <para>
                Script plugins can be applied from a script on the local filesystem or at a remote location.  Filesystem
                locations are relative to the project directory, while remote script locations are specified with an HTTP URL.
                Multiple script plugins (of either form) can be applied to a given build.
            </para>
        </section>
        <section id="sec:applying_binary_plugins">
            <title>Binary plugins</title>
            <sample id="useJavaPlugin" dir="java/quickstart" title="Applying a binary plugin">
                <sourcefile file="build.gradle" snippet="use-plugin"/>
            </sample>
            <para>
                Plugins can be applied using a <emphasis>plugin id</emphasis>.  The plugin id serves as a unique identifier
                for a given plugin.  Core plugins register a short name that can be used as the plugin id. In the above case, we are
                using the short name ‘<literal>java</literal>’ to apply the <apilink class="org.gradle.api.plugins.JavaPlugin" />.
                Community plugins, on the other hand, use a fully qualified form for the plugin id (e.g. <literal>com.github.foo.bar</literal>),
                although some legacy plugins may still utilize a short, unqualified form.
            </para>
            <para>
                Rather than using a plugin id, plugins can also be applied by simply specifying the class of the plugin:
            </para>
            <sample id="pluginIntro" dir="userguide/tutorial/pluginIntro" title="Applying a binary plugin by type">
                <sourcefile file="build.gradle" snippet="apply-by-type"/>
            </sample>
            <para>
                The <literal>JavaPlugin</literal> symbol in the above sample refers to the the <apilink class="org.gradle.api.plugins.JavaPlugin"/>.
                This class does not strictly need to be imported as the <literal>org.gradle.api.plugins</literal> package is automatically imported in all build scripts
                (see <xref linkend='script-default-imports'/>). Furthermore, it is not necessary to append <literal>.class</literal> to identify a class literal in Groovy as it is in Java.
            </para>
            <section>
                <title>Locations of binary plugins</title>
                <para>
                    A plugin is simply any class that implements the <apilink class="org.gradle.api.Plugin" /> interface. Gradle provides
                    the core plugins as part of its distribution so simply applying the plugin as above is all you need to do.
                    However, non-core binary plugins need to be available to the build classpath before they can be applied.  This can
                    be achieved in a number of ways, including:
                </para>
                <itemizedlist>
                    <listitem>Defining the plugin as an inline class declaration inside a build script.</listitem>
                    <listitem>Defining the plugin as a source file under the buildSrc directory in the project (see <xref linkend="sec:build_sources"/>).</listitem>
                    <listitem>Including the plugin from an external jar defined as a buildscript dependency (see <xref linkend="sec:applying_plugins_buildscript" />).</listitem>
                    <listitem>Including the plugin from the plugin portal using the plugins DSL (see <xref linkend="sec:plugins_block" />).</listitem>
                </itemizedlist>
                <para>
                    For more on defining your own plugins, see <xref linkend="custom_plugins" />.
                </para>
            </section>
        </section>
    </section>
    <section id="sec:applying_plugins_buildscript">
        <title>Applying plugins with the buildscript block</title>
        <para>
            Binary plugins that have been published as external jar files can be added to a project by adding the plugin to the
            build script classpath and then applying the plugin.  External jars can be added to the build script classpath
            using the <code>buildscript {}</code> block as described in <xref linkend="sec:external_dependencies" />.
        </para>
        <sample id="applyPluginBuildscript" dir="plugins/buildscript" title="Applying a plugin with the buildscript block">
            <sourcefile file="build.gradle" snippet="buildscript_block" />
        </sample>
    </section>
    <section id="sec:plugins_block">
        <title>Applying plugins with the plugins DSL</title>
        <note>
            <para>
                The plugins DSL is currently <link linkend="feature_lifecycle">incubating</link>.
                Please be aware that the DSL and other configuration may change in later Gradle versions.
            </para>
        </note>
        <para>
            The new plugins DSL provides a more succinct and convenient way to declare plugin dependencies.  It works with the
            new <ulink url="http://plugins.gradle.org">Gradle plugin portal</ulink> to provide easy access to both core and community
            plugins.  The plugins script block configures an instance of <apilink class="org.gradle.plugin.use.PluginDependenciesSpec" />.
        </para>
        <para>
            To apply a core plugin, the short name can be used:
        </para>
        <sample id="useJavaPluginDSL" dir="plugins/dsl" title="Applying a core plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
        <para>
            To apply a community plugin from the portal, the fully qualified plugin id must be used:
        </para>
        <sample id="useCommunityPluginDSL" dir="plugins/dsl" title="Applying a community plugin">
            <sourcefile file="build.gradle" snippet="use-community-plugin"/>
        </sample>
        <para>
            No further configuration is necessary.  Specifically, there is no need to configure the buildscript classpath.
            Gradle will resolve the plugin in the plugin portal, locate it, and make it available to the build.
        </para>
        <para>
            See <apilink class="org.gradle.plugin.use.PluginDependenciesSpec" /> for more information on using the Plugin DSL.
        </para>
        <section id="plugins_dsl_limitations">
            <title>Limitations of the plugins DSL</title>
            <para>
                The new way to add plugins to a project is much more than a more convenient syntax. The new DSL is processed very
                differently to the old one. The new mechanism allows Gradle to determine the plugins in use very early and very
                quickly. This allows Gradle to do smart things such as:
            </para>
            <itemizedlist>
                <listitem>Optimize the loading and reuse of plugin classes.</listitem>
                <listitem>Allow different plugins to use different versions of dependencies.</listitem>
                <listitem>Provide editors detailed information about the potential properties and values in the buildscript for
                editing assistance.</listitem>
            </itemizedlist>
            <para>
                This requires that plugins be specified in a way that Gradle can easily and quickly extract, before executing the
                rest of the build script. It also requires that the definition of plugins to use be somewhat static.
            </para>
            <para>
                There are some key differences between the new plugin mechanism and the “traditional” <code>apply()</code> method
                mechanism. There are also some constraints, some of which are temporary limitations while the mechanism is still
                being developed and some are inherent to the new approach.
            </para>
            <section>
                <title>Constrained Syntax</title>
                <para>
                    The new <code>plugins {}</code> block does not support arbitrary Groovy code. It is constrained, in order to be idempotent
                    (produce the same result every time) and side effect free (safe for Gradle to execute at any time).
                </para>
                <para>
                    The form is:
                </para>
                <programlisting>
plugins {
    id «plugin id» version «plugin version»
}
                </programlisting>
                <para>
                    Where <literal>«plugin version»</literal> and <literal>«plugin id»</literal> must be constant, literal, strings.
                    No other statements are allowed; their presence will cause a compilation error.
                </para>
                <para>
                    The <code>plugins {}</code> block must also be a top level statement in the buildscript. It cannot be nested inside
                    another construct (e.g. an if-statement or for-loop).
                </para>
            </section>
            <section>
                <title>Can only be used in build scripts</title>
                <para>
                    The <code>plugins {}</code> block can currently only be used in a project's build script. It cannot be used in
                    script plugins, the settings.gradle file or init scripts.
                </para>
                <para>
                    <emphasis>Future versions of Gradle will remove this restriction.</emphasis>
                </para>
            </section>
            <section>
                <title>Cannot be used in conjunction with subprojects {}, allprojects {}, etc</title>
                <para>
                    It is not possible to use the familiar pattern of applying a plugin to multiple projects at once using <code>subprojects {}</code>,
                    etc at the moment. There is currently no mechanism for applying a plugin to multiple projects at once. At the moment, each
                    project that requires a plugin must declare so in the <code>plugins {}</code> block in its buildscript.
                </para>
                <para>
                    <emphasis>Future versions of Gradle will remove this restriction.</emphasis>
                </para>
            </section>
            <para>
                If the restrictions of the new syntax are prohibitive, the recommended approach is to apply plugins using the
                <link linkend="sec:applying_plugins_buildscript">buildscript {} block</link>.
            </para>
        </section>
    </section>
    <section id="sec:custom_plugin_repositories">
        <title>Custom Plugin Repositories</title>
        <note>
            <para>
                The <code>pluginRepositories {}</code> DSL is currently <link linkend="feature_lifecycle">incubating</link>.
                Please be aware that the DSL and other configuration may change in later Gradle versions.
            </para>
        </note>
        <para>
            By default, the <code>plugins {}</code> DSL resolves plugins from the public <ulink url="https://plugins.gradle.org">Gradle Plugin Portal.</ulink>
            Many build authors would also like to resolve plugins from private Maven or Ivy repositories because the plugins contain proprietary implementation
            details, or just to have more control over what plugins are available to their builds.
        </para>
        <para>
            To specify custom plugin repositories, add a <code>pluginRepositories {}</code> block to the <code>settings.gradle</code> file:
        </para>
        <sample id="customPluginRepositories" dir="plugins/consuming" title="Using plugins from custom plugin repositories.">
            <sourcefile file="settings.gradle" snippet="custom-plugin-repositories" />
        </sample>
        <para>
            This tells Gradle to first look in the Maven repository at <literal>maven-repo</literal> when resolving plugins and then to
            check the Gradle Plugin Portal if the plugins are not found in the Maven repository. If you don't want the Gradle Plugin Portal to be searched,
            omit the <code>gradlePluginPortal()</code> line. Finally, the Ivy repository at <literal>ivy-repo</literal> will be checked.
        </para>
        <para>
            The <code>pluginRepositories {}</code> block may only appear in the <code>settings.gradle</code> file, and must be the first block in the file.
            Custom Maven and Ivy plugin repositories must contain <link linkend="sec:plugin_markers">plugin marker artifacts</link> in addition to the artifacts
            which actually implement the plugin. For more information on publishing plugins to custom repositories read <xref linkend="javaGradle_plugin" />.
        </para>
        <para>
            See <apilink class="org.gradle.plugin.repository.PluginRepositoriesSpec" /> for complete documentation for using the
            <code>pluginRepositories {}</code> block.
        </para>
    </section>
    <section id="sec:plugin_markers">
        <title>Plugin Marker Artifacts</title>
        <para>
            Since the <code>plugins {}</code> DSL block only allows for declaring plugins by their globally unique plugin <literal>id</literal> and
            <literal>version</literal> properties, Gradle needs a way to look up the coordinates of the plugin implementation artifact. To do so,
            Gradle will look for a Plugin Marker Artifact with the coordinates <literal>plugin.id:plugin.id.gradle.plugin:plugin.version</literal>.
            This marker needs to have a dependency on the actual plugin implementation. Publishing these markers is automated by the
            <link linkend="javaGradle_plugin">java-gradle-plugin</link>.
        </para>
        <para>
            For example, the following complete sample from the <literal>sample-plugins</literal> project shows how to publish a
            <literal>org.gradle.sample.hello</literal> plugin and a <literal>org.gradle.sample.goodbye</literal> plugin to both an Ivy and Maven repository
            using the combination of the <link linkend="javaGradle_plugin">java-gradle-plugin</link>, the
            <link linkend="publishing_maven">maven-publish</link> plugin, and the <link linkend="publishing_ivy">ivy-publish</link> plugin.
        </para>
        <sample id="completePluginPublishing" title="Complete Plugin Publishing Sample" dir="plugins/publishing">
            <sourcefile file="build.gradle" snippet="complete-plugin-publishing" />
        </sample>
        <para>
            Running <literal>gradle publish</literal> in the sample directory causes the following repo layouts to exist:
        </para>
        <para>
            <imagedata fileref="img/pluginMarkers.png" />
        </para>
    </section>
    <section>
        <title>Finding community plugins</title>
        <para>
            Gradle has a vibrant community of plugin developers who contribute plugins for a wide variety of capabilities.
            The Gradle <ulink url="http://plugins.gradle.org">plugin portal</ulink> provides an interface for searching and
            exploring community plugins.
        </para>
    </section>
    <section>
        <title>More on plugins</title>
        <para>
            This chapter aims to serve as an introduction to plugins and Gradle and the role they play. For more information on the inner workings
            of plugins, see <xref linkend="custom_plugins" />.
        </para>
    </section>
</chapter>
