ivy

Java is a very mature and popular software development platform. Many of the available java software packages have being placed in external repositories. These repositories can be accessed tools such as:

  • apache ivy
  • maven
  • gradle
The apache ivy system interfaces easily with ant.

apache ivy simplifies the construction of software that depends on external packages by automating the package retrival. Any other packages that are necessary for the required package are also retrieved.

The main service provided by apache ivy is to retrieve all of a project's external dependencies. The the ivy file (ivy.xml) explicitly states the dependencies required by the project. ivy ensures that any dependencies required by the listed ones are also fetched.

http://mvnrepository.com/ and http://search.maven.org/#browse are two searchable external package repositories.

Example: Linear.java

To compile and run Linear classes from ejml-0.25.jaropencsv-2.3.jar are required. Linear.java source is:

lin/src/Linear.java

import org.ejml.data.DenseMatrix64F;
import org.ejml.ops.CommonOps;

import au.com.bytecode.opencsv.*;

import java.io.*;
import java.util.List;


/**
 * A linear equation solver using csv input.
 * 
 * @author rod
 *
 */
public class Linear {
    
    public static void main(String args[] ){

        try {
            CSVReader reader = new CSVReader(
                new FileReader(args[0]));
            List rows = reader.readAll();
            String[] first = (String [])rows.get(0);
            int cols = first.length;
            int sz = cols - 1;
            
            DenseMatrix64F A = new DenseMatrix64F(sz,sz);
            DenseMatrix64F x = new DenseMatrix64F(sz,1);
            DenseMatrix64F b = new DenseMatrix64F(sz,1);
            
            for( int i = 0; i < sz; i++ ){
                double[] row = new double[sz+1];
                String[] r = (String [])rows.get(i);
                for( int j = 0; j < row.length; j++ ){
                    row[j] = Double.parseDouble( r[j]);
                }
                for( int j = 0; j < sz; j++ ){
                    A.set(i,j, row[j]);
                }
                b.set(i, row[sz]);
            }
            A.print();
            b.print();
            x.print();

            // A * x = b
            // x = invert(A) * b 
            if( !CommonOps.solve(A,b,x) ) {
                System.out.println("failed");
            }
            System.out.println("Solution");
            x.print();
            
        } catch (FileNotFoundException e) {
            System.err.println("File not found");
        } catch (IOException e) {
            System.err.println("Error reading csv");
        }
    }
}

The following import statements reference classes from ejml-0.25.jar and opencsv-2.3.jar.

import org.ejml.data.DenseMatrix64F;
import org.ejml.ops.CommonOps;

import au.com.bytecode.opencsv.*;

Some Java programs only use classes that are either defined by the programmer or use the standard Java API.

But many programs require external classes, which are usually packaged in jar files and imported just like this.

Ant file with ivy task

lin/build.xml

<?xml version="1.0"?>
<project name="lin" default="compile" basedir="."
     xmlns:ivy="antlib:org.apache.ivy.ant" >

    <property name="src.dir" value="src"/>
    <property name="dest.dir" value="classes"/>
    <property name="lib.dir" value="lib"/>

    <path id="lib-jars">
        <fileset dir="${lib.dir}/default" />
    </path>

    <target name="help">
        <echo message="ant help -- print this message"/>
        <echo message="ant compile -- compiles the source"/>
        <echo message="ant resolve -- fetches dependencies"/>
        <echo message="ant clean -- removes classes"/>
    </target>

    <target name="init">
        <mkdir dir="${dest.dir}"/>
    </target>

    <target
        name="resolve" depends="init"
        description="retreive dependencies with ivy">

        <mkdir dir="${lib.dir}"/>
        <ivy:retrieve
            pattern="${lib.dir}/[conf]/[artifact]-[revision].[ext]"
            conf="default" log="quiet"/>
    </target>

    <target name="compile" depends="resolve">
        <javac includeantruntime="false"
            debug="on"
            srcdir="${src.dir}"
            destdir="${dest.dir}">
            <include name="**/*.java"/>
            <classpath>
                <path refid="lib-jars"/>
            </classpath>
        </javac>
    </target>

    <target name="jar" depends="compile">
        <jar jarfile="lin.jar" basedir="classes"
            includes="**/*.class">
            <manifest>
                <attribute name="Main-Class"
                    value="Linear" />
                <attribute name="Class-Path"
                    value="lib/ejml.jar lib/opencsv.jar" />
            </manifest>
        </jar>
    </target>

    <target name="run-data" depends="compile">
        <java classname="Linear" fork="true">
            <arg value="data.csv"/>
            <classpath>
                <pathelement path="${dest.dir}"/>
                <path refid="lib-jars"/>
            </classpath>
        </java>
    </target>

    <target name="clean">
        <delete includeemptydirs="true">
            <fileset dir="classes" includes="**/*"/>
        </delete>
        <delete file="lin.jar" />
    </target>

</project>

To use ivy tasks, the package start tag must include the attribute:

xmlns:ivy="antlib:org.apache.ivy.ant"

The following ant task from ivy, specifies that the dependencies should be downloaded and stored in the ${lib.dir} directory.

<target
    name="resolve" depends="init"
    description="retreive dependencies with ivy">

    <mkdir dir="${lib.dir}"/>
    <ivy:retrieve
        pattern="${lib.dir}/[conf]/[artifact]-[revision].[ext]"
        conf="default" log="quiet"/>
</target>

The download directory is added to the class path with:

<path id="lib-jars">
    <fileset dir="${lib.dir}/default" />
</path>

and

<classpath>
    <path refid="lib-jars"/>
</classpath>

Ivy file

The ivy.xml file specifies the configurations and dependencies. The file for this project is:

lin/ivy.xml

<ivy-module version="2.0">
    <info organisation="ca.mun.cs" module="lin-demo"/>
    <configurations>
        <conf name="default" description="the defaults"/>
    </configurations>
    <dependencies>
        <dependency org="com.googlecode.efficient-java-matrix-library"
            name="ejml" rev="0.25" conf="default"/>
        <dependency org="net.sf.opencsv" name="opencsv" rev="2.3"
            conf="default"/>
    </dependencies>
</ivy-module>

Since most software has many revisions, the rev attribute is used to specify the particular revisions that is required.

While the default configuration is one of the most common, the other standard configurations are: master, compile, provided, runtime, test, system, sources, javadoc, and optional.

Software Licences

If an external software package is used, then most packages provide a licence that restrict/allows how the package can be used. Some of the common licences are:

  • BSD
  • Apache
  • GPL
  • LGPL
  • Public Domain