<!--
  ~ Copyright 2012 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="publishing_maven">
    <title>Maven Publishing (new)</title>
    <note>
        <para>
            This chapter describes the new <link linkend="feature_lifecycle">incubating</link> Maven publishing support provided by the “<literal>maven-publish</literal>”
            plugin. Eventually this new publishing support will replace publishing via the <literal>Upload</literal> task.
        </para>
        <para>
            If you are looking for documentation on the original Maven publishing support using the <literal>Upload</literal> task please see
            <xref linkend="artifact_management"/>.
        </para>
    </note>
    <para>
        This chapter describes how to publish build artifacts to an <ulink url="http://maven.apache.org/">Apache Maven</ulink> Repository.
        A module published to a Maven repository can be consumed by Maven, Gradle (see <xref linkend="dependency_management" />) and other tools that understand the Maven repository format.
    </para>
    <section>
        <title>The “<literal>maven-publish</literal>” Plugin</title>
        <para>
            The ability to publish in the Maven format is provided by the “<literal>maven-publish</literal>” plugin.
        </para>
        <para>
            The “<literal>publishing</literal>” plugin creates an extension on the project named “<literal>publishing</literal>” of type <apilink class="org.gradle.api.publish.PublishingExtension"/>.
            This extension provides a container of named publications and a container of named repositories. The “<literal>maven-publish</literal>” plugin works with
            <apilink class="org.gradle.api.publish.maven.MavenPublication"/> publications and <apilink class="org.gradle.api.artifacts.repositories.MavenArtifactRepository" /> repositories.
        </para>
        <sample id="publishing_maven:apply_plugin" dir="maven-publish/quickstart" title="Applying the 'maven-publish' plugin">
            <sourcefile file="build.gradle" snippet="use-plugin" />
        </sample>
        <para>
            Applying the “<literal>maven-publish</literal>” plugin does the following:
        </para>
        <itemizedlist>
            <listitem>Applies the “<literal>publishing</literal>” plugin
            </listitem>
            <listitem>
                Establishes a rule to automatically create a <apilink class="org.gradle.api.publish.maven.tasks.GenerateMavenPom"/>
                task for each <apilink class="org.gradle.api.publish.maven.MavenPublication"/> added (see <xref linkend="publishing_maven:publications"/>).
            </listitem>
            <listitem>
                Establishes a rule to automatically create a <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenRepository"/> task
                for the combination of each <apilink class="org.gradle.api.publish.maven.MavenPublication"/> added (see <xref linkend="publishing_maven:publications"/>),
                with each <apilink class="org.gradle.api.artifacts.repositories.MavenArtifactRepository"/> added (see <xref linkend="publishing_maven:repositories"/>).
            </listitem>
            <listitem>
                Establishes a rule to automatically create a <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenLocal"/> task
                for each <apilink class="org.gradle.api.publish.maven.MavenPublication"/> added (see<xref linkend="publishing_maven:publications"/>).
            </listitem>
        </itemizedlist>
    </section>
    <section id="publishing_maven:publications">
        <title>Publications</title>
        <note>
            <para>
                If you are not familiar with project artifacts and configurations, you should read the <xref linkend="artifact_management" />
                that introduces these concepts. This chapter also describes “publishing artifacts” using a different mechanism than what is
                described in this chapter. The publishing functionality described here will eventually supersede that functionality.
            </para>
        </note>
        <para>
            Publication objects describe the structure/configuration of a publication to be created. Publications are published to repositories via tasks, and the
            configuration of the publication object determines exactly what is published. All of the publications of a project are defined in the
            <apilink class="org.gradle.api.publish.PublishingExtension" method="getPublications()" /> container. Each publication has a unique name within the project.
        </para>
        <para>
            For the “<literal>maven-publish</literal>” plugin to have any effect, a <apilink class="org.gradle.api.publish.maven.MavenPublication" /> must be added to the set of publications.
            This publication determines which artifacts are actually published as well as the details included in the associated POM file.
            A publication can be configured by adding components, customizing artifacts, and by modifying the generated POM file directly.
        </para>
        <section>
            <title>Publishing a Software Component</title>
            <para>
                The simplest way to publish a Gradle project to a Maven repository is to specify a <apilink class="org.gradle.api.component.SoftwareComponent"/> to publish.
                The components presently available for publication are:
            </para>
            <table>
                <title>Software Components</title>
                <thead>
                    <tr>
                        <td>Name</td>
                        <td>Provided By</td>
                        <td>Artifacts</td>
                        <td>Dependencies</td>
                    </tr>
                </thead>
                <tr>
                    <td><literal>java</literal></td>
                    <td><xref linkend="java_plugin"/></td>
                    <td>Generated jar file</td>
                    <td>Dependencies from 'runtime' configuration</td>
                </tr>
                <tr>
                    <td><literal>web</literal></td>
                    <td><xref linkend="war_plugin"/></td>
                    <td>Generated war file</td>
                    <td>No dependencies</td>
                </tr>
            </table>
            <para>
                 In the following example, artifacts and runtime dependencies are taken from the `java` component, which is added by the <literal>Java Plugin</literal>.
             </para>
            <sample dir="maven-publish/quickstart" id="publishing_maven:publish-component" title="Adding a MavenPublication for a java component">
                <sourcefile file="build.gradle" snippet="publish-component" />
            </sample>
        </section>
        <section>
            <title>Publishing custom artifacts</title>
            <para>
                It is also possible to explicitly configure artifacts to be included in the publication. Artifacts are commonly supplied as raw files, or as instances of
                <apilink class="org.gradle.api.tasks.bundling.AbstractArchiveTask"/> (e.g. Jar, Zip).
            </para>
            <para>
                For each custom artifact, it is possible to specify the <literal>extension</literal> and <literal>classifier</literal> values to use for publication. Note that
                only one of the published artifacts can have an empty classifier, and all other artifacts must have a unique classifier/extension combination.
            </para>
            <para>
                Configure custom artifacts as follows:
            </para>
            <sample dir="maven-publish/javaProject" id="publishing_maven:publish-custom-artifact" title="Adding additional artifact to a MavenPublication">
                <sourcefile file="build.gradle" snippet="publish-custom-artifact" />
            </sample>
            <para>
                See <apilink class="org.gradle.api.publish.maven.MavenPublication" /> for more detailed documentation on how artifacts can be customized.
            </para>
        </section>

        <section>
            <title>Identity values in the generated POM</title>
            <para>
                The attributes of the generated <literal>POM</literal> file will contain identity values derived from the following project properties:
            </para>
            <itemizedlist>
                <listitem><literal>groupId</literal> - <apilink class="org.gradle.api.Project" method="getGroup()" /></listitem>
                <listitem><literal>artifactId</literal> - <apilink class="org.gradle.api.Project" method="getName()" /></listitem>
                <listitem><literal>version</literal> - <apilink class="org.gradle.api.Project" method="getVersion()" /></listitem>
            </itemizedlist>

            <para>
                Overriding the default identity values is easy: simply specify the <literal>groupId</literal>, <literal>artifactId</literal>
                or <literal>version</literal> attributes when configuring the <literal>MavenPublication</literal>.
            </para>
            <sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-customize-identity" title="customizing the publication identity">
                <sourcefile file="build.gradle" snippet="customize-identity" />
            </sample>
            <tip>
                Certain repositories will not be able to handle all supported characters.
                For example, the ':' character cannot be used as an identifier when publishing to a filesystem-backed repository on Windows.
            </tip>
            <para>
                Maven restricts 'groupId' and 'artifactId' to a limited character set (<literal>[A-Za-z0-9_\\-.]+</literal>) and Gradle enforces this restriction.
                For 'version' (as well as artifact 'extension' and 'classifier'), Gradle will handle any valid Unicode character.
            </para>
            <para>
                The only Unicode values that are explicitly prohibited are '<literal>\</literal>', '<literal>/</literal>' and any ISO control character.
                Supplied values are validated early in publication.
            </para>
        </section>
        <section>
            <title>Modifying the generated POM</title>
            <para>
                At times, the POM file generated from the project information will need to be tweaked before publishing. The “<literal>maven-publish</literal>”
                plugin provides a hook to allow such modification.
            </para>
            <sample dir="maven-publish/pomCustomization" id="publishing_maven:pom_modification" title="Modifying the POM file">
                <sourcefile file="build.gradle" snippet="pom-modification" />
            </sample>
            <para>
                In this example we are adding a 'description' element for the generated POM. With this hook, you can modify any aspect of the POM.
                For example, you could replace the version range for a dependency with the actual version used to produce the build.
            </para>
            <para>
                See <apilink class="org.gradle.api.publish.maven.MavenPom" method="withXml(org.gradle.api.Action)" /> for the relevant API reference documentation.
            </para>
            <para>
                It is possible to modify virtually any aspect of the created POM should you need to.
                This means that it is also possible to modify the POM in such a way that it is no longer a valid
                Maven Pom, so care must be taken when using this feature.
            </para>
            <para>
                The identifier (groupId, artifactId, version) of the published module is an exception; these values cannot be modified in the POM using the `withXML` hook.
            </para>
        </section>
        <section>
             <title>Publishing multiple modules</title>
             <para>
                 Sometimes it's useful to publish multiple modules from your Gradle build, without creating a separate Gradle subproject.
                 An example is publishing a separate API and implementation jar for your library. With Gradle this is simple:
             </para>
             <sample dir="maven-publish/multiple-publications" id="publishing_maven:publish-multiple-publications" title="Publishing multiple modules from a single project">
                 <sourcefile file="build.gradle" snippet="multiple-publications" />
             </sample>
             <para>
                 If a project defines multiple publications then Gradle will publish each of these to the defined repositories. Each publication
                 must be given a unique identity as described above.
             </para>
         </section>
    </section>

    <section id="publishing_maven:repositories">
        <title>Repositories</title>
        <para>
            Publications are published to repositories. The repositories to publish to are defined by the <apilink class="org.gradle.api.publish.PublishingExtension" method="getRepositories()" />
            container.
        </para>
        <sample dir="maven-publish/quickstart" id="publishing_maven:repositories" title="Declaring repositories to publish to">
            <sourcefile file="build.gradle" snippet="repositories" />
        </sample>
        <para>
            The DSL used to declare repositories for publication is the same DSL that is used to declare repositories to consume dependencies from,
            <apilink class="org.gradle.api.artifacts.dsl.RepositoryHandler" />. However, in the context of Maven publication only
            <apilink class="org.gradle.api.artifacts.repositories.MavenArtifactRepository" /> repositories can be used for publication.
        </para>
    </section>
    <section id="publishing_maven:publishing">
        <title>Performing a publish</title>
        <para>
            The “<literal>maven-publish</literal>” plugin automatically creates a <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenRepository" />
            task for each <apilink class="org.gradle.api.publish.maven.MavenPublication" /> and <apilink class="org.gradle.api.artifacts.repositories.MavenArtifactRepository" />
            combination in the <literal>publishing.publications</literal> and <literal>publishing.repositories</literal> containers respectively.
        </para>
        <para>
            The created task is named using the pattern "<literal>publish«<emphasis>NAME OF PUBLICATION</emphasis>»PublicationTo«<emphasis>NAME OF REPOSITORY</emphasis>»Repository</literal>".
        </para>
        <sample dir="maven-publish/quickstart" id="publishingMavenPublishMinimal" title="Publishing a project to a Maven repository">
            <sourcefile file="build.gradle"/>
            <output args="publish"/>
        </sample>
        <para>
            So in this example a single <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenRepository" /> task is be added, named '<literal>publishMavenJavaPublicationToMavenRepository</literal>'.
            This task is wired into the <literal>publish</literal> lifecycle task.
            Executing <literal>gradle publish</literal> builds the POM file and all of the artifacts to be published, and transfers them to the repository.
        </para>
    </section>
    <section id="publishing_maven:install">
        <title>Publishing to Maven Local</title>
        <para>
            For integration with a local Maven installation, it is sometimes useful to publish the module into the local .m2 repository. In Maven parlance, this is
            referred to as 'installing' the module. The “<literal>maven-publish</literal>” plugin makes this easy to do by automatically creating a
            <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenLocal" /> task for each <apilink class="org.gradle.api.publish.maven.MavenPublication" />
            in the <literal>publishing.publications</literal> container. Each of these tasks is wired into the <literal>publishToMavenLocal</literal> lifecycle task.
            You do not need to have `mavenLocal` in your `publishing.repositories` section.
        </para>
        <para>
            The created task is named using the pattern "<literal>publish«<emphasis>NAME OF PUBLICATION</emphasis>»PublicationToMavenLocal</literal>".
        </para>
        <sample dir="maven-publish/quickstart" id="publishingMavenPublishLocal" title="Publish a project to the Maven local repository">
            <output args="publishToMavenLocal"/>
        </sample>
        <para>
            So in this example you can see that a single <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenLocal" /> task is be added,
            named '<literal>publishMavenJavaPublicationToMavenLocal</literal>'. This task is wired into the <literal>publishToMavenLocal</literal> lifecycle task.
            Executing <literal>gradle publishToMavenLocal</literal> builds the POM file and all of the artifacts to be published, and 'installs' them into the local Maven repository.
        </para>
    </section>
    <section id="publishing_maven:generate-pom">
        <title>Generating the POM file without publishing</title>
        <para>
            At times it is useful to generate a Maven POM file for a module without actually publishing. Since POM generation is performed by a separate task, it is very easy
            to do so.
        </para>
        <para>
            The task for generating the POM file is of type <apilink class="org.gradle.api.publish.maven.tasks.GenerateMavenPom"/>, and it is given a name based on the name
            of the publication: "<literal>generatePomFileFor«<emphasis>NAME OF PUBLICATION</emphasis>»Publication</literal>". So in the below example where the publication is named
            "<literal>mavenCustom</literal>",
            the task will be named "<literal>generatePomFileForMavenCustomPublication</literal>".
        </para>
        <sample dir="maven-publish/pomCustomization" id="publishingMavenGeneratePom" title="Generate a POM file without publishing">
            <sourcefile file="build.gradle" snippet="generate" />
            <output args="generatePomFileForMavenCustomPublication"/>
        </sample>
        <para>
            All details of the publishing model are still considered in POM generation, including <literal>components</literal>`, custom <literal>artifacts</literal>,
            and any modifications made via <literal>pom.withXml</literal>.
        </para>
        <note>
            <para>
                The “<literal>maven-publish</literal>” plugin leverages some experimental support for late plugin configuration,
                and any <literal>GenerateMavenPom</literal> tasks will not be constructed until the publishing extension is configured.
                The simplest way to ensure that the publishing plugin is configured when you attempt to access the <literal>GenerateMavenPom</literal> task
                is to place the access inside a <literal>publishing</literal> block, as the above example demonstrates.
            </para>
            <para>
                The same applies to any attempt to access publication-specific tasks like <apilink class="org.gradle.api.publish.maven.tasks.PublishToMavenRepository"/>.
                These tasks should be referenced from within a <literal>publishing</literal> block.
            </para>
        </note>
    </section>
</chapter>
