About This Demo

This is a quick demo that shows how to use attributes together with Ant. Don't worry about 90% here seemingly being pure unexplainable magic - the purpose of this part of the tutorial is to show you what steps you must do to make the Commons Attributes package work. In the walkthrough we'll focus more on just what happens, and how the all features work.

Download and Installation

Download the following files and put them in your $ANT_HOME/lib directory:

Getting the Demo Files

Download these files and put them in a directory of your choice:

Running the Demo

The buildfile is already set up, so you should only have to do the following:

# cd directory-where-i-put-demo-files
# ant
Buildfile: build.xml

compile-attributes:
[attribute-compiler] Generated attribute information for 1 classes.

compile:
    [javac] Compiling 2 source files to /home/leosutic/demo

run:
     [java] [[MyAttribute  constructor argument: "This string is passed to the c
onstructor." named argument: "This argument will be passed to the setNamedArgume
nt method"]]

BUILD SUCCESSFUL
Total time: 7 seconds

If you have JDK 1.4 or later, you can also generate Javadocs for the demo with attribute information in the docs:

# ant javadoc
Buildfile: build.xml

javadoc:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] Loading source file /home/leosutic/demo/AttributeDemo.java...
  [javadoc] Constructing Javadoc information...
  [javadoc] /home/leosutic/demo/AttributeDemo.java:18: 
            package org.apache.commons.attributes does not exist
  [javadoc] import org.apache.commons.attributes.Attributes;
  [javadoc]                                      ^
  [javadoc] Registered Taglet org.apache.commons.attributes.javadoc.CATaglet ...

  [javadoc] Standard Doclet version 1.4.0

  [javadoc] Building tree for all the packages and classes...
  [javadoc] Building index for all the packages and classes...
  [javadoc] Building index for all classes...
  [javadoc] Generating /home/leosutic/demo/javadoc/stylesheet.css...
  [javadoc] 1 warning

BUILD SUCCESSFUL
Total time: 7 seconds

Look in the javadoc/ subdirectory for the results.

Demo Walkthrough

The demo consists of two files. We will first look at the Java source file, and then the build.xml file.

Java Sources

class MyAttribute {
    private final String ctorArg;
    private String namedArg = null;
    
    public MyAttribute (String ctorArg) {
        this.ctorArg = ctorArg;
    }
    
    public void setNamedArgument (String namedArg) {
        this.namedArg = namedArg;
    }
    
    public String toString () {
        return "[MyAttribute  constructor argument: \"" + 
            ctorArg + "\" named argument: \"" + namedArg + "\"]";
    }
}

This is simply the definition of an attribute class. It takes one constructor argument, and has one named argument.

/**
 * @@MyAttribute ("This string is passed to the constructor.", 
 *                namedArgument="This argument will be passed to the setNamedArgument method")
 */
public class AttributeDemo {

OK, now it is getting interesting! This is where we add one instance of the MyAttribute class to the AttributeDemo class. The two @-signs indicate that this is an attribute, and will cause the attribute compiler to pick up the attribute. The first string will be passed to the constructor. The second parameter, however, is on the form name = expression, and will result in the setNamedArgument method being called.

public class AttributeDemo {
    public static void main (String args[]) {
        System.out.println (Attributes.getAttributes (AttributeDemo.class));
    }
}

This is where we access the attributes. The Attributes.getAttributes method returns a Collection of all attributes attached to the AttributeDemo class.

build.xml

The build.xml file is pretty much what you'd expect - a target to compile the Java sources, and a target to run the demo. But in addition you'll find a target to preprocess the Java sources.

The attribute compiler works by first generating a bunch of extra Java sources (one extra file per class with attributes). These extra java sources are then compiled along with the original Java sources. Here's some art to illustrate the process:

+------------+                              +--------------------+
|Java Sources|----> Attribute Compiler ---->|Generated Java Files|   
+------------+                              +--------------------+
      |                                                 |
      |                                                 |
      |               +-------------+                   |
      +-------------->|Java Compiler|<------------------+
                      +-------------+
                             |
                             v
                    +-----------------+
                    |Java .class files|
                    +-----------------+

We must therefore invoke the Attribute Compiler before compiling the sources.

<project default="run" name="commons-attributes ant demo" basedir=".">
    
    <taskdef resource="org/apache/commons/attributes/anttasks.properties"/>

Nothing special here. We define the Ant tasks provided by the commons-attributes compiler.

    <target name="clean" description="o Clean up the generated files">
        <delete>
            <fileset dir="${basedir}" includes="*.class,*$*"/>
        </delete>
    </target>

Again nothing special. Just a convenience target to clean up all generated files. But after that comes:

    <target name="compile-attributes" description="o Run the commons-attributes precompiler">
        <attribute-compiler destdir=".">
            <fileset dir="." includes="*.java"/>
        </attribute-compiler>
    </target>

This is where we do all the preprocessing. The Attribute Compiler generates a set of Java sources with attribute information in them. This is where we tell the compiler to generate attribute repositories (autogenerated .java files) for all existing .java files. When those files are generated, we go on to compile everything:

    <target name="compile" depends="compile-attributes" description="o Compile the code">
        <javac 
            srcdir="." 
            destdir="${basedir}" 
            deprecation="true" 
            debug="true" 
            classpath="${ant.home}/lib/commons-attributes-api-2.2.jar;."
            optimize="false">
        </javac>
    </target>

Since we use attributes, we have to include the commons-attributes-api-2.2.jar file in the classpath.

    <target name="run" description="o Compile and run the demo" depends="compile">
        <java 
            classpath="${ant.home}/lib/commons-attributes-api-2.2.jar;."
            classname="AttributeDemo"/>
    </target>

This target simply runs the compiled demo class. JDK 1.4 users can in addition to this generate Javadocs:

    <target name="javadoc" description="o Create Javadocs for the demo">
        <mkdir dir="${basedir}/javadoc/"/>
        <javadoc 
            destdir="${basedir}/javadoc/"
            additionalparam="-J-Dorg.apache.commons.attributes.javadoc.CATaglet.sources=${basedir}">
            <taglet
                name="org.apache.commons.attributes.javadoc.CATaglet"
                path="${ant.home}/lib/commons-attributes-compiler-2.2.jar"
             />
            <fileset dir="${basedir}/" includes="**/*.java" />
        </javadoc>
    </target>

See Documenting for a walkthrough of the Javadoc Taglet.

</project>