Ivyxml Gradle Plugin

This plugin loads dependency definitions from an Ivy dependency file (aka ivy.xml) into Gradle. Besides encapsulating library dependencies to a single place, you use the simpler XML syntax specified in the Ivy documentation (instead of using Groovy syntax).

Purposefully does not do anything with any ivysettings.xml file. Purposefully ignores publishing-related ivy.xml elements and attributes.

The doc subdirectory contains an example. Take a look at the build.gradle and ivy.xml files there, and run gradle from that directory.

This work was motivated by discussion for issue GRADLE-197 at http://issues.gradle.org/browse/GRADLE-197, and started with code snippets from there. I have added much more complete support since then.

This plugin also bundles the Gradle utility method

    public void com.admc.gradle.VerifyResolve(Configuration)

This is a work-around for problems where Gradle silently fails to satisfy some dependencies.

Advanced features

With Gradle milestone-6, you will get warnings If you run ivyxml.load() after you apply Gradle's maven plugin. The warnings look like this:

    The MavenPluginConvention.getPomDirName() method is deprecated...

and

    The MavenPluginConvention.getPomDir() method is deprecated...

Ignore these messages, because the message text is wrong, and Ivyxml is doing nothing wrong. I have registered issue GRADLE-1967: http://issues.gradle.org/browse/GRADLE-1967

UNSUPPORTED ivy.xml features

Most ivy.xml elements and attributes are supported. Here we document those which are not.

The following ivy.xml elements and attributes are ignored. I did my best to detect and either, support, throw or warn, but the public Ivy API just does not allow for access to these settings.

        <conflicts> (and all attrs and sub-elements)
        <dependencies><dependency><conf>  (For conf-mapping)
        <dependencies><dependency><artifact conf="...">  attr.
        <dependencies><dependency><*><conf>

The following elements and attribute are purposefully prohibited. We don't support them, it would be misleading to silently ignore then, and we can detect their usage.

        <dependencies><dependency><exclude artifact="..." type="..."
            ext="..." matcher="..." cont="..."
            (i.e. only 'org' and 'module' attrs are supported).
        <dependencies><override>
        <dependencies><dependency branch="..." force="..."  attrs.
         (Branch and force have no support in Gradle).

As of Gradle 1.0-milestone-6, there is this difference in behavior between

        <dependencies><dependency><exclude...

in native Ivy and this plugin, for non-transitive dependencies. With native Ivy, the exclusion applies to the parent dependency item in addition to transitive dependencies of it. With Ivyxml, the exclusion applies to the transitive dependencies but not to the parent dependency item.

As of Gradle 1.0-milestone-6, there is this difference in behavior between

        <dependencies><exclude...

in native Ivy and this plugin, for non-transitive dependencies. With native Ivy, if an <exclude> at this level excludes a peer-level dependency element, the behavior is crazy with some but not all dependencies excluded. With Ivyxml, the exclusion applies consistently to peer-level dependencies as well as to transitive dependencies.

These elements and attributes are purposefully ignored, because the user may want to profitably process the same ivy.xml file with another tool the can make use of them.

        <info> (and all attrs and sub-elements)  (Element is required by Ivy)
        <publications>  (and all attrs and sub-elements)
        <dependencies><dependency revConstraint="...">
          (Will differ from "rev" only when publishing, which is not a use case
          for us).
        <dependencies><dependency revConstraint="..."  attr.

Usage

Pull plugin from Internet.

Couldn't be easier. This will pull the plugin from jCenter:

        buildscript {
            repositories { jcenter() }  // Before plugin v. 1.0.0 use mavenCentral()
            dependencies {
                classpath 'com.admc:gradle-ivyxml-plugin:latest.integration'
                // For strictly repeatable builds, replace 'latest.integration'
                // with the latest literal GA version label.
            }
        }
        apply plugin: 'com.admc.ivyxml'
        apply plugin: 'java'  // Load any plugins that define configurations
        ...
        ivyxml.load()
        // Note that the load() does not resolve or download anything.
        // What load()s are dependency records.

        // Here's an example that triggers a resolve and download:
        println configurations['confName'].asPath

Use plugin jar file locally.

Just use your browser to go to the Ivyxml directory at jCenter. http://jcenter.bintray.com/com/admc/gradle-ivyxml-plugin/. Click into the version that you want. Right-click and download the only file in that directory that ends in "-<VERSION_LABEL>.jar" (i.e. the only jar file which is neither for JavaDoc nor source code).

You can save the plugin jar with your project, thereby automatically sharing it with other project developers (assuming you use some SCM system). Or you can store it in a local directory, perhaps with other Gradle plugin jars. The procedure is the same either way:

        buildscript { dependencies {
            classpath fileTree(
                dir: 'directory/containing/the/plugin/jar/file',
                include: 'gradle-ivyxml-plugin-*.jar
            ),
            // Following not needed for Ivyxml before 1.0.0 / Gradle before 2.0
            classpath fileTree(
                dir: 'directory/containing/ivy/jar/file',
                include: 'apache-ivy-*.jar
            )
        } }
        apply plugin: 'com.admc.ivyxml'
        ...             // Define your custom configurations
        ivyxml.load()
        // Note that the load() does not resolve or download anything.
        // What load()s are dependency records.

        // Here's an example that triggers a resolve and download:
        println configurations['confName'].asPath

Settings

Java system properties are ALWAYS available in the dependency file as Ivy variables. This behavior is mandated by Ivy's own IvySettings constructor.

Utility Method verifyResolve

void com.admc.gradle.GradleUtil.verifyResolve(Configuration) Throws if all dependencies of the specified Configuration have not been satisfied by at least one artifact. This method is tenuously related to of Ivy XML functionality and is bundled here only because it was convenient for me to do so. Use it like so:

    buildscript {
        repositories { jcenter() }
        dependencies {
            classpath 'com.admc:gradle-ivyxml-plugin:latest.integration'
        }
    }

    apply plugin: 'com.admc.ivyxml'

    import com.admc.gradle.GradleUtil

    compileJava.doFirst { GradleUtil.verifyResolve(configurations.compile) }
    // And so forth for all tasks that elicit an Ivy resolve.

If you get a complaint like "ERRORS a required artifact is not listed by module descriptor: *!.*", just rerun the same Gradle command with the -s switch. You will get a clean report about the missing artifacts.

Classifiers

Beware that classifiers are incompatible with SNAPSHOT systems.

Just code your ivy.xml file like this to use classifiers:

    <ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
    ...
    <dependency org="org.hsqldb" name="hsqldb" rev="[2,)" m:classifier="jdk5"/>

You can't use the classifier attribute on artifact elements, because the current version of the Ivy API seems to be broken there. (Specifically, the classifier parameter for the DependencyArtifactDescriptor class has no effect).