Nuts & Gum: Together At Last

Article Scope

This article is aimed at two seemingly distinct sets of developers: application developers who spend the bulk of their time churning out Java classes, and profesisonals who use AppleScript to automate their work flow. While there is overlap between the two communities, each serves a distinct need: Java developers are building applications designed to run on any platform that supports a Java Runtime Environment (JRE), while AppleScripters are writing scripts to act as the glue between applications on the Macintosh. However, we'll see that tools from each community can aid the other in the development process: Ant to aid in the development of AppleScripts, and AppleScript to aid in the development of Java applications.

This article contains an introduction to Ant for those who haven't worked with it before. If you already use Ant on a regular basis, most of the material in the first part of this article will be will be familiar to you, in which case you can skip ahead to the section "Installing Antfarm". For those readers who are new to Ant, the beginning of this article will serve as an introduction.

Introduction to Ant

In recent years, the Apache Software Foundation's Ant (an abbreviation for Another Neat Tool) has become the de facto standard for automating the build process of Java projects. Like the rest of Apache's offerings, Ant is open source software. So if you're looking for a task that isn't included in the default distribution, there's a strong chance that someone else has written the code and is willing to share their work with you.

There are several reasons why Ant is so popular among software developers (see the list of rewards that it has received here), the most important being the fact that it has made building Java projects, both big and small, easy. Other reasons include:

Installing Ant

Since Java is included in Mac OS X, installing Ant is a straight-forward process. Version 1.5.4, which is the latest version at the time of this writing (September 2003), can be downloaded from here. Because the project's codebase is constantly being updated and revised, it's a good idea to keep an eye out for new releases, as they will add new features and fix bugs afflicting older versions; by joining the mailing list, such notifications will automatically be delivered to your inbox.

Once you've downloaded the latest release to your desktop, open up a Terminal window and execute the following commands:

d@localhost> cd ~/Desktop
d@localhost> sudo sh  
root@localhost> mv /usr/local/
root@localhost> cd /usr/local/
root@localhost> unzip
root@localhost> chown d:staff apache-ant-1.5.4
root@localhost> ln -s apache-ant-1.5.4 ant

For those not familiar with the command line, here is a brief explanation of what the above commands accomplish (if the above commands are still completely foreign, you might want to invest in a UNIX book to brush up on the underbelly of OS X):

Now that everything is in place, we can invoke Ant with the command /usr/local/ant/bin/ant. Which, is a little long-winded and a pain to type; what we'll do now is set up our account so that we can simply type the command ant, instead. In order to do this, we'll have to edit our tcsh initialization file: open up a Terminal and type emacs ~/.tcshrc, and ensure that it contains the following three lines:

setenv JAVA_HOME /Library/Java/Home
setenv ANT_HOME /usr/local/ant
setenv PATH /usr/local/ant/bin:$PATH

To save our file and exit emacs, type ctrl-x ctrl-s ctrl-x ctrl-c. Once that's done, quit the Terminal application and open it again to allow our new settings to take effect. We will now be able to invoke Ant by simply typing the command ant in a Terminal window; if you receive an error, review the steps listed above and ensure that they were successfully completed.

Unfortunately, a comprehensive introduction to tcsh is beyond the scope of this article; if you're interested in learning more about it, see the tcsh man page online, or pick up Using csh & tcsh by Paul Dubois (O'Reilly & Associates, 1995).

How Ant Works

Once invoked, Ant looks for a build file, which is simply an XML file that contains instructions on what has to be done to build this project (by default, this file is named build.xml, and is stored in your project's root directory). Each project is comprised of targets, which, in turn, are made up of one or more tasks. Typical tasks include compiling classes, copying or deleting files/directories, in addition to creating documentation, compressing files into zip archives, composing and sending an email message, and countless other actions. To see which tasks are included with Ant, view the list from the online documentation.

Targets are created by specifying a list of tasks that are to be executed. For example, a typical build file for Java projects may contain these targets:

Take a look at this sample project to see what a very basic Ant build file looks like. Unfortunately, a thorough tutorial on using Ant is beyond the scope of this article; to gain a deeper understanding of how to use Ant, refer to the manual that is included in the distribution.

Installing Antfarm

Once Ant is installed, you'll need Antfarm, which is available here. De-compress the zip file, and place the jar file in Ant's library directory (ex: if Ant is installed in /usr/local/ant, the library can be found at /usr/local/ant/lib). The Antfarm classes are now available to Ant, which allows us to use them in our build files. This last step is crucial; if antfarm.jar is placed in the wrong location, Ant won't know where to find the tasks, and we'll be stuck with error messages instead of AppleScripts.

Using Antfarm

The com.fivevoltlogic.antfarm package (Antfarm) contains two classes that allow us to bridge the gap between AppleScript and Java; osacompile will compile source files into scripts, while osascript will execute files/scripts (similar to Apple's Script Editor application or Script Menu extension).

Using the two OSA tasks in your own build files is much like using any other Ant task; simply include the task's XML tag (and optional attributes to control how the task operates) in your project's targets. However, because the tasks are not included in the standard distribution of Ant, we'll have to tell it which class is used to implement which task. This can be accomplished by including the following tags in each build file that uses Antfarm:

<taskdef task="osacompile" class="com.fivevoltlogic.antfarm.OSACompile" />
<taskdef task="osascript" class="com.fivevoltlogic.antfarm.OSAScript" />


The osacompile task will compile plain-text files into AppleScripts. There are several flags, specified via the tag's attributes, that can be optionally set to control how the resulting script will be created:

In addition to the above options, the osacompile task can operate in two modes: file-based, or directory-based. In file-based operation, the task will attempt to compile only one input file into a script. In directory-based operation, the task will attempt to compile all files within a directory (not including sub-directories) into individual scripts; this option allows the compilation of multiple scripts in one step.

Let's take a look at several examples of using the osacompile task:

Example Uses of osacompile

By integrating the compilation of our scripts into Ant, we can now create an automated build and distribution process for AppleScripts. And by storing the source of our AppleScripts in plain-text files, we can now take advantage of other resources, such as BBEdit for editing, and CVS for revision control (see this series of articles on MacDevCenter for an introduction to CVS).


Like its cousin osacompile, osascript has several flags that can be included as attributes to control how the task operates:

Now let's take a look at some examples of using osascript:

Example Uses of osascript

Using AppleScripts within Ant gives the developer access to a whole new level of functionality that was previously impossible with Ant's tasks composed of Java classes. For example, using osascript we can now:

Antfarm Issues

Atleast one recent version of OS X has had its AppleScript support somewhat broken when updated (see the comments on this article for a description). If Antfarm seems to be misbehaving on your version of OS X, please report the problems in the comments section and we'll see if we can't iron them out.

How Antfarm Works

The last section of this article is targetted towards Java developers, and provides a brief overview of how the tasks wrap around the osacompile and osascript applications; Below is a code sample that illustrates how the osascript task works; the osacompile task is nearly identical, apart from handling the optional parameters of the task.

(1) Instantiate an ArrayList object that will hold the arguments to be passed to the Runtime.exec(String[]) method, which is how we'll execute the script. We also need a counter variable to keep track of how many arguments are being passed to the command, and the index of the next empty "slot" in the list:

ArrayList cmd = new ArrayList(); 
int i = 0;

(2) The first thing we'll need to construct the command is the name of the program that we want to run:

cmd.add(i, "/usr/bin/osascript");

(3) If the language attribute of the tag has been included, we'll add the necessary command-line arguments to the array:

if (language != null) {
  cmd.add(i, "-l"); i++;
  cmd.add(i, language); i++;

(4) Finally, add the location of the file (which is kept track of using the script object, which is an instance of to the list of arguments, and copy the results of the ArrayList into a static array:

cmd.add(i, script.getPath());

String[] cmdArray = new String[cmd.size()];
for (i = 0; i < cmdArray.length; i++) {
  cmdArray[i] = (String) cmd.get(i);

(5) Execute the command using our array of arguments and wait until it has finished running until we move on to the next steps in our code:

Process r = Runtime.getRuntime().exec(cmdArray);

(6) If something bad happened while trying to run the script, throw a BuildException and let the user know what the problem is:

if (r.exitValue() != 0) {

  BufferedReader err =
    new BufferedReader(
      new InputStreamReader(
  String line, error = "";
  while ((line = err.readLine()) != null) {
    error = line + "\n";
  throw new BuildException(error);		

Garbage Collection

In this article we've seen how to use Ant and AppleScript, two seemingly distinct tools, as stepping stones for developers in OS X. One is open-source, and targetted towards high-level application developers on just about every platform in the market today, and the other is a niche tool targetted towards professionals who use Macs to do anything but use the command-line. Who would've thought that they would have so much fun in the sandbox?