MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


Ant and AppleScript

by David Miller
10/03/2003

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 professionals who use AppleScript to automate their workflow.

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 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 straightforward process. Version 1.5.4, which is the latest version at the time of this writing (September 2003), can be downloaded 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  
Password:
root@localhost> mv apache-ant-1.5.4-bin.zip /usr/local/
root@localhost> cd /usr/local/
root@localhost> unzip apache-ant-1.5.4-bin.zip
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 these commands are still completely foreign, you might want to invest in a UNIX book to brush up on the innards of OS X.

Related Reading

Ant: The Definitive Guide
By Jesse E. Tilly, Eric M. Burke

Now that everything is in place, we can invoke Ant with the command /usr/local/ant/bin/ant. This 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 composed of targets, which, in turn, are made up of one or more tasks. Typical tasks include compiling classes, copying or deleting files/directories, creating documentation, compressing files into .zip archives, composing and sending email messages, 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 (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" />

osacompile

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

Mac OSX Conference

Session by Matt Neuburg:
AppleScript Everywhere

AppleScript is Apple's built-in scripting language for letting you automate the Mac. You can relieve drudgery, reduce many steps to one, and communicate between applications. But this session isn't about WHAT you can do with AppleScript; it's about WHERE you can do it. In this session, drawn from the upcoming new book, AppleScript: The Definitive Guide, you'll learn about all the many ways you can access AppleScript in Mac OS X: in a dedicated script editor, in a scripting environment, in an internally scriptable application, in a script runner, in an application you write, and even from a Unix script.

O'Reilly Mac OS X Conference
October 27-30, 2003
Santa Clara, CA


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 Mac DevCenter for an introduction to CVS).

And because our development is now done entirely via the command line, we can log into our Mac remotely using SSH and work on our scripts from anywhere in the world using any computer that has an SSH client installed, since Antfarm frees us from using Script Editor.

osascript

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

At least one recent version of OS X has had its AppleScript support somewhat broken due to an update (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 targeted 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");
i++;

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 java.io.File) 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 before we move on to the next steps in our code:


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

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(
        result.getErrorStream()));
        
  String line, error = "";
  while ((line = err.readLine()) != null) {
    error = line + "\n";
  }
  
  throw new BuildException(error);		
}

As you can see, the code isn't very complex, and given the foundation that Ant gives you to start from, writing your own Ant task is pretty simple.

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 targeted towards high-level application developers on just about every platform in the market today, and the other is a niche tool targeted 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?

David Miller is combining his passions of photography and working on the web at iStockphoto; when not hacking away with a text editor and a few web browsers in hand, he can be seen huddled over his laptop tweaking levels and curves for his freelance photography. Keep track of David's latest projects over at his home on the web.


Return to the Mac DevCenter

Copyright © 2009 O'Reilly Media, Inc.