<!--
  ~ 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 <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 and project dependencies are considered.</para>

    <para>The Eclipse plugin will create different files depending on the other plugins used. If used together with
        the <link linkend="java_plugin">Java plugin</link>, <filename>.project</filename> and <filename>.classpath</filename>
        files will be generated. If used with the <link linkend="war_plugin">War plugin</link>, additional wtp files
        will be generated.</para>
<section>
        <title>Usage</title>
    <para>To use the Eclipse plugin, include in your build script:</para>
    <sample id="useEclipsePlugin" dir="eclipse" title="Using the Eclipse plugin">
        <sourcefile file="build.gradle" snippet="use-plugin"/>
    </sample>
    <para>There are several tasks (presented in <xref linkend='eclipsetasks'/>) that the Eclipse plugin provides. Some tasks
        are preconfigured to use the <literal>GRADLE_CACHE</literal> eclipse classpath variable. To make use of this variable
        you need to define it in Eclipse pointing to <literal>&lt;USER_HOME&gt;/.gradle/cache</literal>.
        In a future release of Gradle this will be automated (<ulink url="http://jira.codehaus.org/browse/GRADLE-1074">Issue GRADLE-1074</ulink>).
</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>eclipseWtp</literal></td>
                <td><literal>-</literal></td>
                <td>Generates all the eclipse configuration files</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipse</literal>
                </td>
                <td>
                    <literal>cleanEclipseProject</literal>, <literal>cleanEclipseClasspath</literal>, <literal>cleanEclipseWtp</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>Removes the eclipse project file</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the eclipse classpath file</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseWtp</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the eclipse .settings directory</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseProject</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.eclipse.EclipseProject" lang="groovy"/></td>
                <td>Generates the eclipse project file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.eclipse.EclipseClasspath" lang="groovy"/></td>
                <td>Generates the Eclipse classpath file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseWtp</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.eclipse.EclipseWtp" lang="groovy"/></td>
                <td>Generates the <filename>org.eclipse.wst.common.component</filename> and 
                    <filename>org.eclipse.wst.common.project.facet.core</filename> files.</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>String</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>String</td>
                <td>null</td>
                <td>A comment for the eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>referencedProjects</literal>
                </td>
                <td>Set&lt;String&gt;</td>
                <td>empty set</td>
                <td>The referenced projects of the Eclipse project.</td>
            </tr>
            <tr>
                <td>
                    <literal>natures</literal>
                </td>
                <td>List&lt;String&gt;</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>List&lt;BuildCommand&gt;</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>Set&lt;Link&gt;</td>
                <td>empty set</td>
                <td>The links for this 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>DomainObjectContainer</td>
                <td>
                    <literal>sourceSets</literal>
                </td>
                <td>The source sets which source directories should be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>containers</literal>
                </td>
                <td>Set&lt;String&gt;</td>
                <td>empty set</td>
                <td>The containers to be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>plusConfigurations</literal>
                </td>
                <td>Set&lt;Configuration&gt;</td>
                <td><literal>[configurations.testRuntime]</literal></td>
                <td>The configurations, which files are to be transformed into classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>minusConfigurations</literal>
                </td>
                <td>Set&lt;Configuration&gt;</td>
                <td><literal>empty set</literal></td>
                <td>The configurations which files are to be excluded from the classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>downloadSources</literal>
                </td>
                <td>boolean</td>
                <td>true</td>
                <td>Whether to download sources for the external dependencies.</td>
            </tr>
            <tr>
                <td>
                    <literal>downloadJavadoc</literal>
                </td>
                <td>boolean</td>
                <td>false</td>
                <td>Whether to download javadoc for the external dependencies.</td>
            </tr>
            <tr>
                <td>
                    <literal>variables</literal>
                </td>
                <td>Map&lt;String,String&gt;</td>
                <td><literal>[GRADLE_CACHE: &lt;path to gradle cache&gt;]</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'>
            <title>EclipseWtp 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>DomainObjectContainer</td>
                <td>
                    <literal>sourceSets</literal>
                </td>
                <td>The source sets which source directories should be added to the Eclipse classpath.</td>
            </tr>
            <tr>
                <td>
                    <literal>deployName</literal>
                </td>
                <td>String</td>
                <td><literal>project.name</literal></td>
                <td>The deploy name to be used in the org.eclipse.wst.common.component file.</td>
            </tr>
            <tr>
                <td>
                    <literal>plusConfigurations</literal>
                </td>
                <td>Set&lt;Configuration&gt;</td>
                <td><literal>[configurations.testRuntime]</literal></td>
                <td>The configurations, which files are to be transformed into classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>minusConfigurations</literal>
                </td>
                <td>Set&lt;Configuration&gt;</td>
                <td><literal>[configurations.providedRuntime]</literal></td>
                <td>The configurations which files are to be excluded from the classpath entries.</td>
            </tr>
            <tr>
                <td>
                    <literal>variables</literal>
                </td>
                <td>Map&lt;String,String&gt;</td>
                <td><literal>[GRADLE_CACHE: &lt;path to gradle cache&gt;]</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>
            <tr>
                <td>
                    <literal>facets</literal>
                </td>
                <td>List&lt;Facet&gt;</td>
                <td><literal>jst.java</literal> and <literal>jst.web</literal> facet</td>
                <td>The facets to be added as installed elements to the org.eclipse.wst.common.project.facet.core file.</td>
            </tr>
        </table>


        <table id='eclipse-task-hooks'>
            <title>Task Hooks</title>
            <thead>
                <tr>
                    <td>Method</td>
                    <td>EclipseProject Task Argument</td>
                    <td>EclipseClasspath Task Argument</td>
                    <td>EclipseWtp Task Argument</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal><code>beforeConfigured { arg -> }</code></literal>
                </td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Project" lang="groovy"/></td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Classpath" lang="groovy"/></td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Wtp" lang="groovy"/></td>
                <td>Gets called directly after the domain objects have been populated with the content of the
                    existing XML file (if there is one).</td>
            </tr>
            <tr>
                <td>
                    <literal><code>whenConfigured { arg -> }</code></literal>
                </td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Project" lang="groovy"/></td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Classpath" lang="groovy"/></td>
                <td><apilink class="org.gradle.plugins.eclipse.model.Wtp" lang="groovy"/></td>
                <td>Gets called after the domain objects have been populated with the content of the
                    existing XML file and the content from the build script.</td>
            </tr>
            <tr>
                <td>
                    <literal><code>withXml { arg -> }</code></literal>
                </td>
                <td><code>groovy.util.Node</code></td>
                <td><code>groovy.util.Node</code></td>
                <td><code>['org.eclipse.wst.common.component': groovy.util.Node, 'org.eclipse.wst.common.project.facet.core': groovy.util.Node]</code></td>
                <td>The root node of the XML just before the XML is written to disk.</td>
            </tr>
        </table>
    </section>
    <section>
        <title>Customizing the generated files</title>
        <para>All the tasks of the eclipse plugin provide the same hooks and behavior for customizing the generated content.</para>
        <para>The tasks recognize existing eclipse files. If an eclipse project, classpath or wtp file does not exists,
        default values are used. Otherwise the existing ones are merged.</para>
        <section>
            <title>Merging</title>
            <para>The first option to customize the Eclipse files is to have an existing Eclipse file before the tasks are run.
            Existing files will be merged together with the generated content.
            Any section of the existing Eclipse files that are not the target of generated content will neither be changed nor removed.</para>
            <section id="sec:complete-overwrite">
                <title>Disabling merging with a complete overwrite</title>
                <para>If you want Gradle to completely overwrite existing Eclipse files you can specify this on the command line by
                    executing something like <userinput>gradle cleanEclipse eclipse</userinput> or <userinput>gradle cleanEclipseClasspath eclipseClasspath</userinput>.
                    You can specify this also in the build script. Just make the generating tasks depending on the deleting tasks. You can tailor this
                    to your needs. You could make the <literal>eclipse</literal> task dependent on the <literal>cleanEclipse</literal> task. If you only want
                    to overwrite for example the classpath files you simply make the <literal>eclipseClasspath</literal> task dependent on the
                    <literal>cleanEclipseClasspath</literal> task.
                </para>
            </section>
        </section>
        <section>
            <title>Hooking into the generation lifecycle</title>
            <para>The Eclipse plugin provides a couple of domain classes that model the Eclipse files.
                But only the sections that are autogenerated by Gradle. The generation lifecycle is the following.
                If there is an existing Eclipse file, its whole XML is parsed and stored in memory. Then the domain
                objects are populated with the relevant content of the the existing XML. After that the build script information
                is used to further populate those objects (e.g. add additional dependencies).
                Then all sections modelled by the domain objects are removed from the XML in memory. After that the domain objects are used to inject
                their content into the XML. Finally the XML is written to disk. The lifecycle provides hooks to modify the result according to your needs.
            </para>
            <section id="sec:partial-overwrite">
                <title>Partial Overwrite</title>
                <para>Doing a <link linkend="sec:complete-overwrite">complete overwrite</link> removes all your manual customizations.
                    This might be not what you want.
                    Therefore Gradle provides the option for a partial overwrite. You can hook into the phase just after the existing
                    Eclipse files have populated the domain objects. You could then for example remove all the dependencies
                    from the <literal>classpath</literal> object.
                    <sample id="partialOverwrites" dir="eclipse"
                            title="Partial Overwrite for Module">
                        <sourcefile file="build.gradle" snippet="module-before-configured"/>
                    </sample>
                    The generated XML will have all sections of the existing Eclipse classpath file,
                    except for the dependencies, where only the information of the build script is used. You could do something
                    similar for the project 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>You can also hook into the phase after the existing Eclipse files and the build script metadata have
                    populated the domain objects. You could then for example disable export of all the dependencies
                    of the <literal>module</literal> object.
                    <sample id="exportDependencies" dir="eclipse"
                            title="Export Dependencies">
                        <sourcefile file="build.gradle" snippet="module-when-configured"/>
                    </sample>

                </para>
            </section>
            <section>
                <title>Modifying the XML</title>
                <para>You can also hook into the phase after the XML DOM is fully populated but not written to disk.
                    That hook provides total control over what is generated.
                    <sample id="file-dependencies" dir="eclipse"
                            title="Customizing the XML">
                        <sourcefile file="build.gradle" snippet="wtp-with-xml"/>
                    </sample>
                </para>
            </section>
        </section>
    </section>
</chapter>