<!--
  ~ 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="artifact_management" xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Artifact Management</title>
    <section>
        <title>Introduction</title>
        <para>This chapter is about how you declare what are the artifacts of your project and how to work with
            them (e.g. upload them). We define the artifacts of the projects as the files the project want to
            provide to the outside world. This can be a library or a distribution or any other file. Usually artifacts
            are archives, but not necessarily. In the Maven world a project can provide only one artifact. With Gradle
            a project can provide as many artifacts as needed.
        </para>
    </section>
    <section id="artifacts_and_configurations">
        <title>Artifacts and configurations</title>
        <para>Like dependencies, artifacts are grouped by configurations. In fact, a configuration can contain
            both, artifacts and dependencies, at the same time. To assign an artifact to a configuration, you can write:
        </para>
        <sample id="assignArtifact" dir="userguide/artifacts/uploading" title="Assignment of an artifact to a configuration">
            <sourcefile file="build.gradle" snippet="assign-artifact"/>
        </sample>
        <para>What do you gain by assigning an artifact to a configuration? For each configuration (also for the custom
        ones added by you) Gradle provides the tasks <code>upload[ConfigurationName]</code> and
        <code>build[ConfigurationName]</code>.
        <footnote><para>To be exact, the Base plugin provides those tasks. The BasePlugin is automatically applied, if you use
        the Java plugin.</para></footnote>
        Executing those tasks will build or upload the artifacts belonging to
        the respective configuration.
        </para>
        <para>Table <xref linkend="tab:configurations"/> shows the configurations added by the Java plugin. Two of the
        configurations are relevant for the usage with artifacts. The <code>archives</code> configuration is the standard
        configuration to assign your artifacts to. The Java plugin automatically assigns the default jar to this
        configuration. We will talk more about the <code>default</code> configuration in <xref linkend="project_libraries"/>.
            As with dependencies, you can declare as many custom configurations as you like and assign artifacts to them.
        </para>
        <para>It is important to note that the custom archives you are creating as part of your build are not
        automatically assigned to any configuration. You have to explicitly do this assignment.</para>
    </section>
    <section>
        <title>Uploading artifacts</title>
        <para>We have said that there is a specific upload task for each configuration. But before you can do an upload,
            you have to configure the upload task and define where to upload. The repositories you have defined as described
            in <xref linkend="sec:repositories"/> are not automatically used for uploading. In fact some of those repositories
            are not even capable of uploading, there are just capable of reading from a repository. Here is an example how
            you can configure the upload task of a configuration:
        </para>
        <sample id="uploading" dir="userguide/artifacts/uploading" title="Configuration of the upload task">
            <sourcefile file="build.gradle" snippet="uploading"/>
        </sample>
        <para>As you can see, you can either use a reference to an exisiting repository or create a new repository.
        As described in <xref linkend="sub:more_about_ivy_resolvers"/>, you can use all the Ivy resolvers suitable
        for the purpose of uploading.</para>
    </section>
    <section id="project_libraries">
        <title>More about project libraries</title>
        <para>If your project is supposed to be used as a library, you need to define what are the artifacts of this library
            and what are the dependencies of this artifacts. The Java plugin adds a <code>default</code> configuration for
            this purpose. This configuration extends both the <code>archives</code> and the <code>runtime</code> configuration,
            with the implicit assumption that the <code>runtime</code> dependencies are the dependencies of the <code>archives</code>
            configuration. Of course this is fully customizable. You can add your own custom configuration or let the the
            existing configurations extends from other configurations. You might have different group of artifacts which have
            a different set of dependencies. This mechanism is very powerful and flexible.
            </para>
        <para>If someone wants to use your project as a library, she simply needs to declare on which configuration of
            the dependency to depend on.
            A Gradle dependency offers the <code>configuration</code> property to declare this. If this
            is not specified, the <code>default</code> configuration is used (see <xref linkend="sec:dependency_configurations"/>).
            Using your project as a library
            can either happen from within a multi-project build or by retrieving your project from a repository. In
            the latter case, an ivy.xml descriptor in the repository is supposed to contain all the neccesary information. If you
            work with Maven repositories you don't have the flexibility as described above. For how to publish to a Maven
            repository, see the section <xref linkend="uploading_to_maven_repositories"/>.
        </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 some more work to do if you need support for other protocols than <literal>file</literal>. In
                this case the native Maven code we delegate to needs additional libraries. Which libraries depend on the
                protocol you need. The available protocols and the corresponding libraries are listed in <xref
                        linkend='wagonLibs'/> (those libraries have again 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 another 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:1.0-beta-2</td>
                </tr>
                <tr>
                    <td>ssh</td>
                    <td>org.apache.maven.wagon:wagon-ssh:1.0-beta-2</td>
                </tr>
                <tr>
                    <td>ssh-external</td>
                    <td>org.apache.maven.wagon:wagon-ssh-external:1.0-beta-2</td>
                </tr>
                <tr>
                    <td>scp</td>
                    <td>org.apache.maven.wagon:wagon-scp:1.0-beta-2</td>
                </tr>
                <tr>
                    <td>ftp</td>
                    <td>org.apache.maven.wagon:wagon-ftp:1.0-beta-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://maven.apache.org/ant-tasks/apidocs/org/apache/maven/artifact/ant/RemoteRepository.html'>
                            org.apache.maven.artifact.ant.RemoteRepository
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>authentication</td>
                    <td>
                        <ulink url='http://maven.apache.org/ant-tasks/apidocs/org/apache/maven/artifact/ant/Authentication.html'>
                            org.apache.maven.artifact.ant.Authentication
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>releases</td>
                    <td>
                        <ulink url='http://maven.apache.org/ant-tasks/apidocs/org/apache/maven/artifact/ant/RepositoryPolicy.html'>
                            org.apache.maven.artifact.ant.RepositoryPolicy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>snapshots</td>
                    <td>
                        <ulink url='http://maven.apache.org/ant-tasks/apidocs/org/apache/maven/artifact/ant/RepositoryPolicy.html'>
                            org.apache.maven.artifact.ant.RepositoryPolicy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>proxy</td>
                    <td>
                        <ulink url='http://maven.apache.org/ant-tasks/apidocs/org/apache/maven/artifact/ant/Proxy.html'>
                            org.apache.maven.artifact.ant.Proxy
                        </ulink>
                    </td>
                </tr>
                <tr>
                    <td>snapshotRepository</td>
                    <td>
                        <ulink url='http://maven.apache.org/ant-tasks/apidocs/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 add 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>The Maven Poms are automatically generated by Gradle. You can find the generated poms in the directory
                <literal>&lt;buildDir>/poms</literal>. In many scenarios it just works and you don't have to do anything.
                But there are situations were you want or have to customize the pom generation.
            </para>
            <section id='sub:changing_non_dependency_elements_of_the_pom'>
                <title>Changing non-dependency elements of the pom</title>
                <para>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 learn about all the customizable attributes of a pom have a look here: <apilink class="org.gradle.api.artifacts.maven.MavenPom"/>.
                    If you have more than one artifact to publish, things work 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>
            <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 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.GroovyPomFilterContainer"/>
                    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. One can assign also 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). Right now excludes-per-configuration are not converted to the Maven Pom.
                </para>
            </section>
            <section id='sub:planned_future_features'>
                <title>Planned future features</title>
                <para>We plan support for excludes-per-configuration. We also plan support for the new Ivy
                    <emphasis>override</emphasis>
                    element, which corresponds to the
                    <emphasis>dependencyManagement</emphasis>
                    element of a Maven pom. Last but not least we want to make the customization more powerful, by enabling
                    to add custom dependency elements to the pom and remove/modify auto-generated ones.
                </para>
            </section>
        </section>
    </section>
</chapter>
