Ein Vergleich mit dem Make-System
Simon Lembke (WI4139)
Der Erweiterung von Make sind keine Grenzen gesetzt. Jedes eigene Programm, das in der zugrunde liegenden Shell lauffähig ist, kann von Make aus aufgerufen werden. Daher ist es egal, ob es sich bei der Erweiterung um ein Shell-Skript, ein Perl-Programm oder irgendeine andere ausführbare Datei handelt. Man muss allerdings beachten, das die eigenen Erweiterungen auf den Systemen laufen, auf denen das Makefile verwendet wird und man das entsprechende Programm zusammen mit dem Makefile ausliefern muss.
Ant lässt sich auf zwei Wegen erweitern. Zum einen können, wie schon
im vorigen Abschnitt kurz angesprochen, externe Programme ausgeführt werden.
Damit schränkt man Ant jedoch gleichzeitig ein, denn die Plattformunabhängigkeit
bleibt natürlich nur bestehen, wenn diese Programme auf allen Systemen
vorhanden sind. Die zweite und deutlich elegantere Methode ist, einen eigenen
Task zu entwickeln.
Jeder Task in Ant entspricht einer Klasse. Um nun selber einen solchen Task
zu schreiben, muss man zunächst eine Klasse erstellen, die die Klasse org.apache.tools.ant.Task
erweitert.
Für jedes Attribut, über das der Task verfügen soll, muss eine
setter-Methode geschrieben werden. Die Namen dieser Methoden beginnen
mit set, gefolgt vom Namen des Attributs, wobei der erste Buchstabe
groß geschrieben wird. Alle setter-Methoden sind dabei public
void und haben genau ein Argument, dessen Typ der Entwickler festlegen
kann. Diese Methode wäre also zuständig für ein Attribut namens
version:
public void setVersion(int version)
Ant führt diverse Konvertierungen durch, bevor die Methoden aufgerufen
werden. boolean-Typen erhalten den Wert true, wenn im Build-File
yes, true oder on angegeben wurde, char-Typen
erhalten den ersten Buchstaben, die anderen primitiven Datentypen den Zahlenwert
des angegebenen Wertes. Bei den Typen java.io.File und org.apache.tools.ant.types.Path
wird zunächst geprüft, ob es sich um absolute oder relative Pfade
handelt und letztere danach, ausgehend vom basedir, umgesetzt. Wenn
es sich bei dem Typen um java.lang.Class handelt, wird der angegebene
Wert als Name einer Klasse angesehen. Ant versucht dann eine Instanz dieser
Klasse zu erstellen. Bei allen anderen Typen, die einen Konstruktor mit einem
Parameter vom Typ String besitzen, wird Ant ebenfalls versuchen eine
Instanz dieser Klasse zu erstellen.
Ein spezieller Fall sind Nachkommen der abstrakten Klasse EnumeratedAttribute.
Dieser Typ repräsentiert eine Liste von gültigen Werten, wobei bereits
beim Parsen des Build-Files entschieden wird, ob es sich um einen gültigen
Wert für dieses Attribut handelt. Jede Klasse, die EnumeratedAttribute
erweitert, muss dazu nur folgende Methode implementieren:
public String[] getValues();
Diese Methode gibt ein Array mit allen gültigen Werten immer in der gleichen
Reihenfolge zurück.
Wenn der Task ausgeführt werden soll, ruft Ant indirekt die Methode execute
auf. Diese muss ebenfalls public sein, darf keinen Rückgabewert
und keine Parameter haben und muss eine BuildException im Fehlerfall
werfen.
package de.fh-wedel;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task;
public class MessageTask extends Task { private String msg; public void execute() throws BuildException { System.out.println(msg); }
public void setMessage(String msg) { this.msg = msg; } }
Dieses Beispiel ist der Hilfe von Ant entnommen und schreibt die Nachricht, die im Build-File als Attribut message (Methode setMessage) angegeben wurde, auf die Standard-Ausgabe.
Um einen eigenen Task im Build-File verfügbar zu machen, muss man mit Hilfe des taskdef-Elements der Klasse einen Namen geben, unter dem sie in Ant referenziert werden kann.
<taskdef classname=“de.fh-wedel.MessageTask“ name=“printmessage“>
Danach kann man seinen Task wie jeden anderen Task auch verwenden:
<printmessage message=“Hallo Welt!“>