<!--
  ~ 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.
  -->

<chapter id="eclipse_plugin">
    <title>The Eclipse Plugin</title>
    
    <para>The Eclipse plugin generates files that are used by the <ulink url="http://eclipse.org">Eclipse IDE</ulink>, thus
        making it possible to import the project into Eclipse (<guimenuitem>File</guimenuitem> - <guimenuitem>Import...</guimenuitem> - <guimenuitem>Existing Projects into Workspace</guimenuitem>).
        Both external dependencies (including associated source and javadoc files) and project dependencies are considered.</para>

    <para>What exactly the Eclipse plugin generates depends on which other plugins are used:</para>
    <table>
        <title>Eclipse plugin behavior</title>
        <thead>
            <tr><td>Plugin</td><td>Description</td></tr>
        </thead>
        <tr>
            <td>None</td><td>Generates minimal <filename>.project</filename> file.</td>
        </tr>
        <tr>
            <td><link linkend="java_plugin">Java</link></td><td>Adds Java configuration to <filename>.project</filename>.
            Generates <filename>.classpath</filename> and JDT settings file.</td>
        </tr>
        <tr>
            <td><link linkend="groovy_plugin">Groovy</link></td><td>Adds Groovy configuration to <filename>.project</filename> file.</td>
        </tr>
        <tr>
                <td><link linkend="scala_plugin">Scala</link></td><td>Adds Scala support to <filename>.project</filename> file.</td>
        </tr>
        <tr>
            <td><link linkend="war_plugin">War</link></td><td>Adds web application support to <filename>.project</filename> file.
            Generates WTP settings files.</td>
        </tr>
    </table>

    <para>One focus of the Eclipse plugin is to be open to customization. Each task provides a standardized set of hooks
        for adding and removing content from the generated files.
    </para>

    <section>
        <title>Usage</title>
        <para>To use the Eclipse plugin, include this in your build script:</para>
        <sample id="useEclipsePlugin" dir="eclipse" title="Using the Eclipse plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
        <para>The Eclipse plugin adds a number of tasks to your projects. The main tasks that you will use
            are the <literal>eclipse</literal> and<literal>cleanEclipse</literal> tasks.
        </para>
    </section>
    <section>
        <title>Tasks</title>

        <para>The Eclipse plugin adds the tasks shown below to a project.</para>

        <table id='eclipsetasks'>
            <title>Eclipse plugin - tasks</title>
            <thead>
                <tr>
                    <td>Task name</td>
                    <td>Depends on</td>
                    <td>Type</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>eclipse</literal>
                </td>
                <td><literal>eclipseProject</literal>, <literal>eclipseClasspath</literal>, <literal>eclipseJdt</literal>,
                    <literal>eclipseWtpComponent</literal>, <literal>cleanEclipseWtpFacet</literal></td>
                <td><apilink class="org.gradle.api.Task"/></td>
                <td>Generates all Eclipse configuration files</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipse</literal>
                </td>
                <td>
                    <literal>cleanEclipseProject</literal>, <literal>cleanEclipseClasspath</literal>, <literal>cleanEclipseJdt</literal>,
                    <literal>cleanEclipseWtpComponent</literal>, <literal>cleanEclipseWtpFacet</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes all Eclipse configuration files</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseProject</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Generates the <filename>.project</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Generates the <filename>.classpath</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseJdt</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.settings/org.eclipse.jdt.core.prefs</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseWtpComponent</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.settings/org.eclipse.wst.common.component</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseWtpFacet</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td>
                    <apilink class="org.gradle.api.tasks.Delete"/>
                </td>
                <td>Removes the <filename>.settings/org.eclipse.wst.common.component</filename> file.
                </td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseProject</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseProject"/></td>
                <td>Generates the <filename>.project</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseClasspath"/></td>
                <td>Generates the <filename>.classpath</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseJdt</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseJdt"/></td>
                <td>Generates the <filename>.settings/org.eclipse.jdt.core.prefs</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseWtpComponent</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseWtpComponent"/></td>
                <td>Generates the <filename>.settings/org.eclipse.wst.common.component</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseWtpFacet</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.EclipseWtpFacet"/>
                </td>
                <td>Generates the <filename>.settings/org.eclipse.wst.common.project.facet.core.xml</filename> file.</td>
            </tr>
        </table>

        <table id='eclipse-project'>
            <title>EclipseProject task</title>
            <thead>
                <tr>
                    <td>Property</td>
                    <td>Type</td>
                    <td>Default Value</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>projectName</literal>
                </td>
                <td>
                    <classname>String</classname>
                </td>
                <td><literal>project.name</literal></td>
                <td>The name of the Eclipse project. Must not be null.</td>
            </tr>
            <tr>
                <td>
                    <literal>comment</literal>
                </td>
                <td>
                    <classname>String</classname>
                </td>
                <td><literal>project.description</literal></td>
                <td>A comment for the Eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>referencedProjects</literal>
                </td>
                <td>
                    <classname>Set&lt;String&gt;</classname>
                </td>
                <td>empty set</td>
                <td>The referenced projects of the Eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>natures</literal>
                </td>
                <td>
                    <classname>List&lt;String&gt;</classname>
                </td>
                <td>The default is an empty set. Applying Java, Groovy, Scala or War plugin
                will add additional natures.</td>
                <td>The natures of the Eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>buildCommands</literal>
                </td>
                <td>
                    <classname>List&lt;BuildCommand&gt;</classname>
                </td>
                <td>The default is an empty set. Applying Java, Groovy, Scala or War plugin
                will add additional build commands.</td>
                <td>The build commands of the Eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>links</literal>
                </td>
                <td>
                    <classname>Set&lt;Link&gt;</classname>
                </td>
                <td>empty set</td>
                <td>The links for the Eclipse project.</td>
            </tr>
        </table>

        <table id='eclipse-classpath'>
            <title>EclipseClasspath task</title>
            <thead>
                <tr>
                    <td>Property</td>
                    <td>Type</td>
                    <td>Default Value</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>sourceSets</literal>
                </td>
                <td><classname>Iterable&lt;SourceSet></classname></td>
                <td>
                    <literal>project.sourceSets</literal>
                </td>
                <td>The source sets whose source directories are to be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>containers</literal>
                </td>
                <td>
                    <classname>Set&lt;String&gt;</classname>
                </td>
                <td>empty set</td>
                <td>The containers to be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>plusConfigurations</literal>
                </td>
                <td>
                    <classname>Set&lt;Configuration&gt;</classname>
                </td>
                <td><literal>[configurations.testRuntime]</literal></td>
                <td>The configurations whose files are to be transformed into classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>minusConfigurations</literal>
                </td>
                <td>
                    <classname>Set&lt;Configuration&gt;</classname>
                </td>
                <td>empty set</td>
                <td>The configurations whose files are to be excluded from the classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>downloadSources</literal>
                </td>
                <td>
                    <classname>boolean</classname>
                </td>
                <td>
                    <literal>true</literal>
                </td>
                <td>Whether to download sources for external dependencies.</td>
            </tr>
            <tr>
                <td>
                    <literal>downloadJavadoc</literal>
                </td>
                <td>
                    <classname>boolean</classname>
                </td>
                <td>
                    <literal>false</literal>
                </td>
                <td>Whether to download javadoc for external dependencies.</td>
            </tr>
            <tr>
                <td>
                    <literal>variables</literal>
                </td>
                <td>
                    <classname>Map&lt;String,File&gt;</classname>
                </td>
                <td><literal>[:]</literal></td>
                <td>If the beginning of the absolute path of a library matches a value of a variable,
                a variable entry is created. The matching part of the library path is replaced with the variable name.</td>
            </tr>
        </table>

        <table id='eclipse-wtp-component'>
            <title>EclipseWtpComponent task</title>
            <thead>
                <tr>
                    <td>Property</td>
                    <td>Type</td>
                    <td>Default Value</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>sourceDirs</literal>
                </td>
                <td><classname>Set&lt;File&gt;</classname></td>
                <td>
                    The source directories of <literal>sourceSets.main</literal>
                </td>
                <td>The source sets whose source directories are to be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>deployName</literal>
                </td>
                <td>
                    <classname>String</classname>
                </td>
                <td><literal>project.name</literal></td>
                <td>The deploy name to be used.</td>
            </tr>
            <tr>
                <td>
                    <literal>plusConfigurations</literal>
                </td>
                <td>
                    <classname>Set&lt;Configuration&gt;</classname>
                </td>
                <td><literal>[configurations.testRuntime]</literal></td>
                <td>The configurations whose files are to be transformed into classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>minusConfigurations</literal>
                </td>
                <td>
                    <classname>Set&lt;Configuration&gt;</classname>
                </td>
                <td><literal>[configurations.providedRuntime]</literal></td>
                <td>The configurations whose files are to be excluded from the classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>variables</literal>
                </td>
                <td>
                    <classname>Map&lt;String,File&gt;</classname>
                </td>
                <td><literal>[:]</literal></td>
                <td>If the beginning of the absolute path of a library matches a value of a variable,
                a variable entry is created. The matching part of the library path is replaced with the variable name.</td>
            </tr>
        </table>

        <table id='eclipse-wtp-facet'>
            <title>EclipseWtpFacet task</title>
            <thead>
                <tr>
                    <td>Property</td>
                    <td>Type</td>
                    <td>Default Value</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>facets</literal>
                </td>
                <td>
                    <classname>List&lt;Facet&gt;</classname>
                </td>
                <td>
                    <literal>jst.java</literal>
                    and
                    <literal>jst.web</literal>
                    facet
                </td>
                <td>The facets to be added as installed elements.</td>
            </tr>
        </table>
    </section>
    <section>
        <title>Customizing the generated files</title>
        <para>All Eclipse tasks provide the same hooks and behavior for customizing the generated content.</para>
        <para>The tasks recognize existing Eclipse files, and merge them with the generated content.</para>
        <section>
            <title>Merging</title>
            <para>Sections of existing Eclipse files that are also the target of generated content will be amended or overwritten,
                 depending on the particular section. The remaining sections will be left as-is.</para>
            <section id="sec:complete-overwrite">
                <title>Disabling merging with a complete overwrite</title>
                <para>To completely overwrite existing Eclipse files, execute a clean task together with its corresponding generation task,
                    for example <userinput>gradle cleanEclipse eclipse</userinput> (in that order). If you want to make this
                    the default behavior, add <code>eclipse.dependsOn(cleanEclipse)</code> to your build script. This makes it
                    unnecessary to execute the clean task explicitly.
                </para>
                <para>Complete overwrite works equally well for individual files, for example by executing<userinput>gradle cleanEclipseClasspath eclipseClasspath</userinput>.
                </para>
            </section>
        </section>
        <section>
            <title>Hooking into the generation lifecycle</title>
            <para>The Eclipse plugin provides domain classes modeling the sections of the Eclipse files
                that are autogenerated by Gradle. The generation lifecycle is as follows:
                <orderedlist>
                    <listitem>If there is an existing file, its whole XML content is parsed and stored in memory; otherwise, a default file is used in its place</listitem>
                    <listitem>The domain objects are populated with the relevant content of the existing file</listitem>
                    <listitem>The <code>beforeConfigured</code> hook is executed</listitem>
                    <listitem>The domain objects are populated with content from Gradle's build model, which may require merging with content from the existing file</listitem>
                    <listitem>The <code>whenConfigured</code> hook is executed</listitem>
                    <listitem>All sections modeled by the domain objects are removed from the in-memory XML representation</listitem>
                    <listitem>The domain objects inject their content into the in-memory XML representation</listitem>
                    <listitem>The <code>withXml</code> hook is executed</listitem>
                    <listitem>The in-memory XML representation is written to disk</listitem>
                </orderedlist>
                The following table lists the domain object used for each of the Eclipse task types:
            </para>
            <table id='eclipse-task-hooks'>
                <title>Task Hooks</title>
                <thead>
                    <tr>
                        <td>Task type</td>
                        <td><literal>beforeConfigured { arg -> }</literal> argument type</td>
                        <td><literal>whenConfigured { arg -> }</literal> argument type</td>
                        <td><literal>withXml { arg -> }</literal> argument type</td>
                    </tr>
                </thead>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseProject"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Project"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Project"/></td>
                    <td><apilink class="org.gradle.api.artifacts.maven.XmlProvider"/></td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseClasspath"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Classpath"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Classpath"/></td>
                    <td><apilink class="org.gradle.api.artifacts.maven.XmlProvider"/></td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseJdt"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Jdt"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Jdt"/></td>
                    <td><apilink class="org.gradle.api.artifacts.maven.XmlProvider"/></td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseWtpComponent"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpComponent"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpComponent"/></td>
                    <td><apilink class="org.gradle.api.artifacts.maven.XmlProvider"/></td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.EclipseWtpFacet"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpFacet"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpFacet"/></td>
                    <td><apilink class="org.gradle.api.artifacts.maven.XmlProvider"/></td>
                </tr>
            </table>
            <section id="sec:partial-overwrite">
                <title>Partial overwrite of existing content</title>
                <para>A <link linkend="sec:complete-overwrite">complete overwrite</link> causes all existing content to be discarded,
                    thereby losing any changes made directly in the IDE. The <code>beforeConfigured</code> hook makes it possible
                    to overwrite just certain parts of the existing content. The following example removes all existing dependencies
                    from the <literal>Classpath</literal> domain object:
                    <sample id="partialOverwrites" dir="eclipse"
                            title="Partial Overwrite for Classpath">
                        <sourcefile file="build.gradle" snippet="module-before-configured"/>
                    </sample>
                    The resulting <literal>.classpath</literal> file will only contain Gradle-generated dependency entries, but
                    not any other dependency entries that may have been present in the original file. (In the case of dependency entries,
                    this is also the default behavior.) Other sections of the <literal>.classpath</literal> file will be either left as-is or merged.
                    The same could be done for the natures in the <literal>.project</literal> file:
                    <sample id="partialOverwritesProject" dir="eclipse"
                            title="Partial Overwrite for Project">
                        <sourcefile file="build.gradle" snippet="project-before-configured"/>
                    </sample>
                </para>
            </section>
            <section>
                <title>Modifying the fully populated domain objects</title>
                <para>The <code>whenConfigured</code> hook allows to manipulate the fully populated domain objects. Often this is the
                    preferred way to customize Eclipse files. Here is how you would export all the dependencies of an Eclipse project:
                    <sample id="exportDependencies" dir="eclipse"
                            title="Export Dependencies">
                        <sourcefile file="build.gradle" snippet="module-when-configured"/>
                    </sample>
                </para>
            </section>
            <section>
                <title>Modifying the XML representation</title>
                <para>The <code>withXml</code>hook allows to manipulate the in-memory XML representation just before the file gets written to disk.
                    Although Groovy's XML support makes up for a lot, this approach is less convenient than manipulating the domain objects.
                    In return, you get total control over the generated file, including sections not modeled by the domain objects.
                    <sample id="wtpWithXml" dir="eclipse"
                            title="Customizing the XML">
                        <sourcefile file="build.gradle" snippet="wtp-with-xml"/>
                        <test args="cleanEclipse eclipse"/>
                    </sample>
                </para>
            </section>
        </section>
    </section>
</chapter>