<!--
  ~ 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="maven_plugin">
    <title>The Maven Plugin</title>
    <note>
        <para>This chapter is a work in progress</para>
    </note>
    <para>The Maven plugin adds support for deploying artifacts to Maven repositories.</para>

    <section>
        <title>Usage</title>
        <para>To use the Maven plugin, include the following in your build script:</para>
        <sample id="useMavenPlugin" dir="maven/quickstart" title="Using the Maven plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
    </section>

    <section>
        <title>Tasks</title>
        <para>The Maven plugin defines the following tasks:</para>
        <table>
            <title>Maven plugin - tasks</title>
            <thead>
                <tr>
                    <td>Task name</td>
                    <td>Depends on</td>
                    <td>Type</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>install</literal>
                </td>
                <td>
                    All tasks that build the associated archives.
                </td>
                <td><apilink class="org.gradle.api.tasks.Upload"/></td>
                <td>Installs the associated artifacts to the local Maven cache, including Maven metadata generation.
                By default the install task is associated with the <literal>archives</literal> configuration. This
                configuration has by default only the default jar as an element. To learn more about installing to the
                local repository, see: <xref linkend="sub:installing_to_the_local_repository"/></td>
            </tr>
        </table>
    </section>

    <section>
        <title>Dependency management</title>
        <para>The Maven plugin does not define any dependency configurations.</para>
    </section>

    <section>
        <title>Convention properties</title>
        <para>The Maven plugin defines the following convention properties:</para>
        <table>
            <title>Maven plugin - properties</title>
            <thead>
                <tr>
                    <td>Property name</td>
                    <td>Type</td>
                    <td>Default value</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>mavenPomDir</literal>
                </td>
                <td>
                    <classname>File</classname>
                </td>
                <td>
                    <literal><replaceable>${project.buildDir}</replaceable>/poms</literal>
                </td>
                <td>
                    The directory where the generated POMs are written to.
                </td>
            </tr>
            <tr>
                <td>
                    <literal>conf2ScopeMappings</literal>
                </td>
                <td>
                    <classname><apilink class="org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer"/></classname>
                </td>
                <td>
                    <literal>n/a</literal>
                </td>
                <td>
                    Instructions for mapping Gradle configurations to Maven scopes. See <xref linkend="sub:dependency_mapping"/>.
                </td>
            </tr>
        </table>
        <para>These properties are provided by a <apilink class="org.gradle.api.plugins.MavenPluginConvention"/>
            convention object.</para>
    </section>

    <section>
        <title>Convention methods</title>
        <para>The maven plugin provides a factory method for creating a POM. This is useful if you need a POM
        without the context of uploading to a Maven repo.</para>
        <sample id="newPom" dir="maven/pomGeneration" title="Creating a stand alone pom.">
            <sourcefile file="build.gradle" snippet="new-pom"/>
        </sample>
        <para>Amongst other things, Gradle supports the same builder syntax as polyglot Maven. To learn more about the Gradle Maven POM object, see
            <apilink class="org.gradle.api.artifacts.maven.MavenPom"/>. See also: <apilink class="org.gradle.api.plugins.MavenPluginConvention"/>
        </para>
    </section>

    <section id='uploading_to_maven_repositories'>
        <title>Interacting with Maven repositories</title>
        <section id='sec:introduction'>
            <title>Introduction</title>
            <para>With Gradle you can deploy to remote Maven repositories or install to your local Maven repository. This
                includes all Maven metadata manipulation and works also for Maven snapshots. In fact, Gradle's deployment is
                100 percent Maven compatible as we use the native Maven Ant tasks under the hood.
            </para>
            <para>Deploying to a Maven repository is only half the fun if you don't have a POM. Fortunately Gradle can
                generate this POM for you using the dependency information it has.
            </para>
        </section>
        <section id='sec:deploying_to_a_maven_repository'>
            <title>Deploying to a Maven repository</title>
            <para>Let's assume your project produces just the default jar file. Now you want to deploy this jar file to
                a remote Maven repository.
            </para>
            <sample id="uploadFile" dir="userguide/artifacts/maven" title="Upload of file to remote Maven repository">
                <sourcefile file="build.gradle" snippet="upload-file"/>
            </sample>
            <para>That is all. Calling the
                <literal>uploadArchives</literal>
                task will generate the POM and deploys the artifact and the POM to the specified repository.
            </para>
            <para>There is more work to do if you need support for protocols other than <literal>file</literal>. In
                this case the native Maven code we delegate to needs additional libraries. Which libraries are needed depends on what
                protocol you plan to use. The available protocols and the corresponding libraries are listed in <xref
                        linkend='wagonLibs'/> (those libraries have transitive dependencies which have transitive
                dependencies).
                <footnote>
                    <para>It is planned for a future release to provide out-of-the-box support for this
                    </para>
                </footnote>
                For example, to use the ssh protocol you can do:
            </para>
            <sample id="uploadWithSsh" dir="userguide/artifacts/maven" title="Upload of file via SSH">
                <sourcefile file="build.gradle" snippet="upload-with-ssh"/>
            </sample>
            <para>There are many configuration options for the Maven deployer. The configuration is done via a Groovy builder.
                All the elements of this tree are Java beans. To configure the simple attributes you pass a map to the bean
                elements. To add bean elements to its parent, you use a closure. In the example above <emphasis>repository</emphasis>
                and <emphasis>authentication</emphasis> are such bean elements. <xref linkend='deployerConfig'/>
                lists the available bean elements and a link to the Javadoc of the corresponding class. In the Javadoc you
                can see the possible attributes you can set for a particular element.
            </para>
            <para>In Maven you can define repositories and optionally snapshot repositories. If no snapshot repository
                is defined, releases and snapshots are both deployed to the
                <literal>repository</literal>
                element. Otherwise snapshots are deployed to the
                <literal>snapshotRepository</literal>
                element.
            </para>
            <table id='wagonLibs'>
                <title>Protocol jars for Maven deployment</title>
                <thead>
                    <tr>
                        <td>Protocol</td>
                        <td>Library</td>
                    </tr>
                </thead>
                <tr>
                    <td>http</td>
                    <td>org.apache.maven.wagon:wagon-http:2.2</td>
                </tr>
                <tr>
                    <td>ssh</td>
                    <td>org.apache.maven.wagon:wagon-ssh:2.2</td>
                </tr>
                <tr>
                    <td>ssh-external</td>
                    <td>org.apache.maven.wagon:wagon-ssh-external:2.2</td>
                </tr>
                <tr>
                    <td>ftp</td>
                    <td>org.apache.maven.wagon:wagon-ftp:2.2</td>
                </tr>
                <tr>
                    <td>webdav</td>
                    <td>org.apache.maven.wagon:wagon-webdav:1.0-beta-2</td>
                </tr>
                <tr>
                    <td>file</td>
                    <td>-</td>
                </tr>
            </table>
            <table id='deployerConfig'>
                <title>Configuration elements of the MavenDeployer</title>
                <thead>
                    <tr>
                        <td>Element</td>
                        <td>Javadoc</td>
                    </tr>
                </thead>
                <tr>
                    <td>root</td>
                    <td>
                        <apilink class="org.gradle.api.artifacts.maven.MavenDeployer"/>
                    </td>
                </tr>
                <tr>
                    <td>repository</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/RemoteRepository.html'>
                            org.apache.maven.artifact.ant.RemoteRepository
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>authentication</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/Authentication.html'>
                            org.apache.maven.artifact.ant.Authentication
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>releases</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/RepositoryPolicy.html'>
                            org.apache.maven.artifact.ant.RepositoryPolicy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>snapshots</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/RepositoryPolicy.html'>
                            org.apache.maven.artifact.ant.RepositoryPolicy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>proxy</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/Proxy.html'>
                            org.apache.maven.artifact.ant.Proxy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>snapshotRepository</td>
                    <td>
                        <ulink url='http://www.docjar.com/docs/api/org/apache/maven/artifact/ant/RemoteRepository.html'>
                            org.apache.maven.artifact.ant.RemoteRepository
                        </ulink>
                    </td>
                </tr>

            </table>
        </section>
        <section id='sub:installing_to_the_local_repository'>
            <title>Installing to the local repository</title>
            <para>The Maven plugin adds an <literal>install</literal> task to your project. This task depends on all the archives
                task of the <literal>archives</literal> configuration. It installs those archives to your local Maven repository.
                If the default location for the local repository is redefined in a Maven <literal>settings.xml</literal>, this is
                considered by this task.
            </para>
        </section>
        <section id='sec:maven_pom_generation'>
            <title>Maven POM generation</title>
            <para>When deploying an artifact to a Maven repository, Gradle automatically generates a POM for it. The
                <literal>groupId</literal>, <literal>artifactId</literal>, <literal>version</literal> and <literal>packaging</literal>
                elements used for the POM default to the values shown in the table below. The <literal>dependency</literal>
                elements are created from the project's dependency declarations.
            </para>
            <table>
                <title>Default Values for Maven POM generation</title>
                <thead>
                    <tr>
                        <td>Maven Element</td>
                        <td>Default Value</td>
                    </tr>
                </thead>
                <tr>
                    <td>groupId</td>
                    <td>project.group</td>
                </tr>
                <tr>
                    <td>artifactId</td>
                    <td>uploadTask.repositories.mavenDeployer.pom.artifactId (if set) or archiveTask.baseName.</td>
                </tr>
                <tr>
                    <td>version</td>
                    <td>project.version</td>
                </tr>
                <tr>
                    <td>packaging</td>
                    <td>archiveTask.extension</td>
                </tr>
            </table>
            <para>
                Here, <literal>uploadTask</literal> and <literal>archiveTask</literal> refer to the tasks used for uploading and generating the archive,
                respectively (for example <literal>uploadArchives</literal> and <literal>jar</literal>). <literal>archiveTask.baseName</literal> defaults
                to <literal>project.archivesBaseName</literal> which in turn defaults to <literal>project.name</literal>.
            </para>
            <note>
                <para>
                    When you set the “<literal>archiveTask.baseName</literal>” property to a value other than the default, you'll also have to set
                    <literal>uploadTask.repositories.mavenDeployer.pom.artifactId</literal> to the same value. Otherwise, the project at hand may
                    be referenced with the wrong artifact ID from generated POMs for other projects in the same build.
                </para>
            </note>
            <para>
                Generated POMs can be found in <literal>&lt;buildDir>/poms</literal>. They can be further customized via the
                <apilink class="org.gradle.api.artifacts.maven.MavenPom"/> API. For example, you might want the artifact deployed
                to the Maven repository to have a different version or name than the artifact generated by Gradle. To customize these you can do:
            </para>
            <sample id="customizePom" dir="userguide/artifacts/maven" title="Customization of pom">
                <sourcefile file="build.gradle" snippet="customize-pom"/>
            </sample>
            <para>To add additional content to the POM, the <literal>pom.project</literal> builder can be used. With this builder,
                any element listed in the <ulink url="http://maven.apache.org/pom.html">Maven POM reference</ulink> can be added.
            </para>
            <sample id="pomBuilder" dir="userguide/artifacts/maven" title="Builder style customization of pom">
                <sourcefile file="build.gradle" snippet="builder"/>
            </sample>
            <para>Note: <literal>groupId</literal>, <literal>artifactId</literal>, <literal>version</literal>, and <literal>packaging</literal>
                should always be set directly on the <literal>pom</literal> object.
            </para>
            <sample id="pomBuilder" dir="maven/pomGeneration" title="Modifying auto-generated content">
                <sourcefile file="build.gradle" snippet="when-configured"/>
            </sample>
            <para>If you have more than one artifact to publish, things work a little bit differently. See <xref
                        linkend="sub:multiple_artifacts_per_project"/>.
            </para>
            <para>To customize the settings for the Maven installer (see <xref
                    linkend='sub:installing_to_the_local_repository'/>), you can do:
            </para>
            <sample id="customizeInstaller" dir="userguide/artifacts/maven" title="Customization of Maven installer">
                <sourcefile file="build.gradle" snippet="customize-installer"/>
            </sample>
            <section id='sub:multiple_artifacts_per_project'>
                <title>Multiple artifacts per project</title>
                <para>Maven can only deal with one artifact per project. This is reflected in the structure of the
                    Maven POM. We think there are many situations where it makes sense to have more than one artifact per
                    project. In such a case you need to generate multiple POMs. In such a case you have to explicitly declare each artifact
                    you want to publish to a Maven repository. The <apilink class="org.gradle.api.artifacts.maven.MavenDeployer"/> and the MavenInstaller
                    both provide an API for this:
                </para>
                <sample id="multiplePoms" dir="userguide/artifacts/maven" title="Generation of multiple poms">
                    <sourcefile file="build.gradle" snippet="multiple-poms"/>
                </sample>
                <para>You need to declare a filter for each artifact you want to publish. This filter defines a boolean expression for
                    which Gradle artifact it accepts. Each filter has a POM associated with it which you can configure.
                    To learn more about this have a look at <apilink class="org.gradle.api.artifacts.maven.PomFilterContainer"/>
                    and its associated classes.
                </para>
            </section>
            <section id='sub:dependency_mapping'>
                <title>Dependency mapping</title>
                <para>The Maven plugin configures the default mapping between the Gradle configurations added by the
                    Java and War plugin and the Maven scopes. Most
                    of the time you don't need to touch this and you can safely skip this section. The mapping
                    works like the following. You can map a configuration to one and only one scope. Different
                    configurations can be mapped to one or different scopes. You can also assign a priority to a particular
                    configuration-to-scope mapping. Have a look at
                    <apilink class="org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer"/>
                    to learn more. To access the mapping configuration you can say:
                </para>
                <sample id="mappings" dir="userguide/artifacts/maven" title="Accessing a mapping configuration">
                    <sourcefile file="build.gradle" snippet="mappings"/>
                </sample>
                <para>Gradle exclude rules are converted to Maven excludes if possible. Such a conversion is possible if in
                    the Gradle exclude rule the group as well as the module name is specified (as Maven needs both in
                    contrast to Ivy). Per-configuration excludes are also included in the Maven POM, if they are convertible.
                </para>
            </section>
        </section>
    </section>
    
</chapter>
