Using Ant Properties

In this Ant tutorial installment, we will use ant Properties to specify the work directory structure that will contain our .class and .jar files. The work directory structure tends to be a personal preference, and properties will allow us to centralize the structure definition so that any change will be relatively pain-free. We specify the directories with a location attribute, thereby binding the property to a file system location. This allows us to pass the property to another ant process without any local directory side effects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<project default="all">
<property name="obj-dir" location="obj" />
<property name="lib-dir" location="lib" />

<target name="init">
<mkdir dir="${obj-dir}" />
<mkdir dir="${lib-dir}" />
</target>
<target name="clean-init">
<delete dir="${obj-dir}" />
<delete dir="${lib-dir}" />
</target>

<target name="all" depends="init"/>
<target name="clean" depends="clean-init"/>
</project>

This build file features:

  • 4 targets:

    • init: to build the work directory structure.
    • clean-init: to remove the work directory structure.
    • all: the build roll-up target.
    • clean: to clean roll-up target. Note that my target naming convention is to pair a target with a clean-target. I reserve the all and the clean targets as roll-up targets for all build and clean targets respectively.
  • 2 properties:

    • obj-dir: the root directory for our .class files.
    • lib-dir: the root directory for our .jar files.

We can now execute the init target to create the work directories, and the clean-init target to remove the work directories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ ls
build.xml
$ ant
Buildfile: build.xml

init:
[mkdir] Created dir: /Tutorial/Ant/Properties/obj
[mkdir] Created dir: /Tutorial/Ant/Properties/lib

all:

BUILD SUCCESSFUL
Total time: 3 seconds
$ ls
build.xml obj/ lib/
$ ant clean
Buildfile: build.xml

clean-init:
[delete] Deleting directory /Tutorial/Ant/Properties/obj
[delete] Deleting directory /Tutorial/Ant/Properties/lib

clean:

BUILD SUCCESSFUL
Total time: 2 seconds
$ ls
build.xml

Now, let’s add targets to compile, jar and execute a java class. We’ll just copy over the hello.java class from our previous installment and place it in the src directory. The compile and jar targets from before remain largely the same; but we add the destdir attribute to the javac task to specify where the .class files are to be stored and we can remove the includes attribute from the jar task. Our new build.xml looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<project default="all">
<property name="obj-dir" location="obj" />
<property name="lib-dir" location="lib" />
<property name="src-dir" location="src" />

<target name="init">
<mkdir dir="${obj-dir}" />
<mkdir dir="${lib-dir}" />
</target>
<target name="clean-init">
<delete dir="${obj-dir}" />
<delete dir="${lib-dir}" />
</target>

<target name="compile" depends="init">
<javac srcdir="${src-dir}"
destdir="${obj-dir}"
/>

</target>
<target name="clean-compile">
<delete>
<fileset dir="${obj-dir}" includes="**/*.class" />
</delete>
</target>

<target name="jar" depends="compile">
<jar destfile="${lib-dir}/hello.jar"
basedir="${obj-dir}"
/>

</target>

<target name="clean-jar">
<delete file="${lib-dir}/hello.jar" />
</target>
<target name="run" depends="jar">
<java classname="hello"
classpath="${lib-dir}/hello.jar"
fork="true"
/>

</target>

<target name="all" depends="run"/>

<target name="clean" depends="clean-init"/>
</project>

And now we can execute our class and clean up our work directories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ ant run
Buildfile: build.xml

init:
[mkdir] Created dir: /Tutorial/Ant/Properties/obj
[mkdir] Created dir: /Tutorial/Ant/Properties/lib

compile:
[javac] Compiling 1 source file to /Tutorial/Ant/Properties/obj

jar:
[jar] Building jar: /Tutorial/Ant/Properties/lib/hello.jar

run:
[java] Hello World

BUILD SUCCESSFUL
Total time: 4 seconds
$ ant clean
Buildfile: build.xml

clean-init:
[delete] Deleting directory /Tutorial/Ant/Properties/obj
[delete] Deleting directory /Tutorial/Ant/Properties/lib

clean:

BUILD SUCCESSFUL
Total time: 2 seconds

Disclaimer: I don’t claim to be an expert on ant. Please send comments and corrections.

The Kickback Culture

Man to attractive Woman:
Would you sleep with me for $1 million?

Attractive Woman:
Yes.

Man:
How about for $100?

Attractive Woman:
No, what do you think I am?

Man:
I thought that we had already established what you are and that we could start to discuss the price.

Maybe I’m the one who just doesn’t get it.

Business Week has an article on Tech’s Kickback Culture this week. I just don’t understand how someone could accept Friends and Family stock in an IPO, flip it for a quick profit of $40,000, and not see a conflict of interest (the person in question said that $40,000 was not enough to sway his judgement). I don’t know about you, but I would want to know about that Friends and Family deal every time he recommended the company’s software.

High Flight

Growing up, building Revell models of the Gemini and Apollo spacecraft, it seemed as if our destiny was to go to space. And when we turned our backs on space exploration, it seemed like a betrayal.

The quest for knowledge claimed seven more yesterday. We are defined by what we attempt as surely as we are defined by what we achieve. We will be back.

Oh! I have slipped the surly bonds of Earth And danced the skies on laughter-silvered wings; Sunward I’ve climbed and joined the tumbling mirth of sun-split clouds,–and done a hundred things You have not dreamed of wheeled and soared and swung High in the sunlit silence. Hov’ring there, I’ve chased the shouting wind along, and flung My eager craft through footless falls of air… Up, up the long, delirious, burning blue I’ve topped the wind-swept heights with easy grace Where never lark, nor eer eagle flew– And, while with silent lifting mind I’ve trod The high, untrespassed sanctity of space, Put out my hand and touched the face of God.

I was wrong

Well, I was wrong. I thought that the Oakland OL would give Gannon time to pick the defense apart. I thought that the Tampa Bay offense would not be able to control time of possession. I was wrong on both counts.

Tampa Bay came up big on both sides of the ball. The defense held Oakland to 3 first downs in the first half. The offense put 20 points on the board in the first half and controlled time of possession.

Super Bowl XXXVII

OK, time to make a Super Bowl prediction. Many sports pundits consider this a classic matchup of a great offense and a great defense. I disagree. Greatness is judged by history, and I am confident that at least one of the two will be downgraded from great to very good by the end of the day. It’s like the collision of the unstoppable force and the immovable object. The one thing that you can be sure of is that at least one of them will come out of it with a new name.

Now, with free agency and salaries caps, I’m don’t think greatness is possible. In my mind, this is a meeting of a very good offense and a very good defense. In a meeting of very good, the questions to consider are:

  • Will the offense will be able to get good matchups?
  • Will the defense dictate the style of play?

I like the offense. I think Oakland can put more good receivers on the field than Tampa Bay has good cover men. And I think the Oakland offensive line will be able to give Gannon time to throw. The Tampa Bay rush may bother Gannon in the first half, but I expect it to tire in the second half.

The only way for Tampa Bay to win is for their offense to hold the ball and win the time of possession war. And that’s not going to happen.

Oakland 30, Tampa Bay 17

Ant Hello World Revisited

We’ll continue our Ant tutorials with “Hello World,” only now we’ll execute a Java class. Start by creating a simple hello class as shown below.

1
2
3
4
5
6
public class hello {
public static void main( String[] args )
{

System.out.println( "Hello World" );
}
}

From the command line, compiling, jarring and executing this class is as simple as:

1
$ javac hello.java
$ jar -cvf hello.jar hello.class
added manifest
adding: hello.class(in = 415) (out= 285)deflated 31%)
$ java -classpath hello.jar hello
Hello World

Now let’s write an Ant build file to compile. Naturally, you should start by reading the fine manual description of the javac task. We’ll just use the srcdir attribute to compile all java files in the directory tree rooted at srcdir.

1
2
3
4
5
6
<project default="compile">
<target name="compile">
<javac srcdir="." />
</target>

</project>

Executing ant from the command line:

1
$ rm *.class
$ ant -f hello.xml compile
Buildfile: hello.xml

compile:
    [javac] Compiling 1 source file

BUILD SUCCESSFUL
Total time: 4 seconds

Now, let’s add a target to create the jar. The destfile attribute is required and both the basedir and the includes attributes are necessary in this case. The jar file will only contain the manifest file without the basedir attribute and the includes attribute is required to exclude all the non-class files (in particular, the jar file cannot contain itself). The regular expression used in the includes attribute will match all class files in the directory tree rooted at basedir.

1
2
3
4
5
6
7
8
9
10
11
12
<project default="compile">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">
<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
/>

</target>
</project>

Executing ant from the command line:

1
$ rm *.jar
$ ant -f hello.xml jar
Buildfile: hello.xml

compile:

jar:
      [jar] Building jar: /Tutorial/Ant/Jar/hello.jar

BUILD SUCCESSFUL
Total time: 2 seconds
$ jar -tvf hello.jar
jar -tvf hello.jar
     0 Wed Jan 22 17:06:32 EST 2003 META-INF/
    55 Wed Jan 22 17:06:32 EST 2003 META-INF/MANIFEST.MF
   335 Wed Jan 22 16:36:16 EST 2003 hello.class

Finally, let’s add a target to execute our class. We insure that the jar is always built first by having the execution target run depend upon the jar target. In this example, both the classname and the classpath attributes of the java task are used to completely specify the class to execute – eliminating a dependence upon the CLASSPATH environment variable. And we request a new JVM by setting fork=”true”; providing the class full access to the java runtime and preventing a call to System.exit() from terminating the ant process.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<project default="compile">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">
<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
/>

</target>

<target name="run" depends="jar">
<java classname="hello"
classpath="hello.jar"
fork="true"
/>

</target>
</project>

And execute:

1
$ant -f hello.xml run
Buildfile: hello.xml

compile:

jar:

run:
     [java] Hello World

BUILD SUCCESSFUL
Total time: 2 seconds

25 June: Made the run target depend upon the jar target.
5 Oct 08: Building an executable jar with Ant.

Disclaimer: I don’t claim to be an expert on ant. Please send comments and corrections.

A "technical" Violation

USOC CEO Lloyd Ward just doesn’t get it. He somehow thought that membership in a major organization discriminating against women (Augusta National Golf Club) wasn’t relevant to his position at the USOC. Now he feels that trying to steer business towards a company employing his brother is a technical ethics violation.

This is the same thinking that got Corporate America into it’s current ethical crisis. It’s thinking that ethics is about rules, and that acts not expressly forbidden are permissable. The reality is that ethics is about motives and intent and all sorts of grey areas.

Ward should have realized that his actions were leading him into a grey area. His description of his actions as a technical violation indicates that he thought he was following the rules, but that he just didn’t understand the rules in depth at the time.

He should realize that handling his punishment during his yearly review would appear to many as if they’re sweeping the problem under a rug and hoping that all would be forgotten.

USOC Imploding

Well, it looks like the USOC really is imploding. Between the new independent investigation of CEO Lloyd Ward and the investigation of President Marty Mankamyer, I’m not sure which end is up. I still think that Ward committed an ethics violation. And I still think that only way out for the USOC is for some heads to roll. But it’s no longer clear that Ward’s head should be the one, although I still think that his is the leading contender.

My initial speculation was that Ward politicked the ethics committee into it’s initial conclusion. I still think that is the leading contender. But, the new conspiracy theory is that Mankamyer orchestrated the ethics committee verdict in order to produce a firestorm that would force Ward’s ouster. That strikes me as a bit far-fetched, but I’ll just have to wait and see.