background image

Apache Ant

Ant jest narzędziem umożliwiającym automatyzację procesów związanych 

z budowaniem programów. Jego podstawowe cechy to:

konfiguracja zadań zapisana w formacie XML,

wieloplatformowość – m. in. Linux, Unix (np. Solaris and HP-UX), Windows 

9x i NT, OS/2 Warp, Novell Netware 6 oraz MacOS X.

rozszerzalność w oparciu o klasy napisane w Javie.

Ant jest rozwijany w ramach Apache Software Foundation. Strona domowa 

projektu

http://ant.apache.org

.

Wymagania:

parser XML'a zgodny z JAXP,

JDK w wersji 1.2 lub nowszej. W przypadku posiadania samego JRE część 

zadań nie będzie działać.

1

background image

Instalacja

Ant jest rozpowszechniany jako archiwum zip. Należy je rozpakować 

w wybranym katalogu. Następnie należy:

 dodać podkatalog 

bin

 do ścieżki poszukiwań,

 ustawić zmienną środowiska 

ANT_HOME

,

 ew. ustawić zmienną 

JAVA_HOME

,

np. (Windows).

set ANT_HOME=c:\ant
set JAVA_HOME=c:\jdk1.2.2
set PATH=%PATH%;%ANT_HOME%\bin

Zwykle należy też zwiększyć pamięć dla konsoli poleceniem:

shell=c:\command.com c:\ /p /e:32768

2

background image

Wykorzystanie – tag project

Informacje na temat zadań są zapisane w pliku XML. Taki plik zawiera jeden 

projekt (

project

) i co najmniej jeden cel (

target

). Cel składa się z zadań 

(

task

).

Projekt posiada trzy opcjonalne atrybuty:

 

name

 – nazwa projektu,

 

default

 – nazwa domyślnego celu wykonywanego przy budowaniu projektu,

 

basedir

 – katalog od którego będą ,,liczone” nazwy ścieżek.

Opcjonalnie projekt może posiadać opis umieszczeny w elemencie 

<description>

Przykład:

<project name="MyProject" default="dist" basedir=".">
    <description>
        simple example build file
    </description>

...

</project>

3

background image

Wykorzystanie – tag target

Cel (

target

) może być zależny od innych celów. Pozwala to na określenie 

kolejności wykonywania celów:

<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="B,C,A"/>

Ant wykonuje cele ,,zależne” w kolejności od lewej do prawej. 

W powyższym przykładzie, jeśli wywołać cel 

D

, zadania zostaną wykonane w 

kolejności 

A

B

C

D

.

Należy zwrócić uwagę na możliwość wywołania celu jeszcze wcześniej, jeśli był 

on zależny od innego wcześniej wykonanego celu.

4

background image

Wykorzystanie – tag target

Cel może być wywoływany warunkowo, korzystając z następującej składni:

<target name="A" if="property"/>

Jeśli wartość 

property

 jest ustawiona cel 

A

 jest aktywny. Wartość własności 

property jest bez znaczenia. 

<target name="A" unless="property"/>

Jeśli wartość 

property

 jest nieustawiona cel 

A

 jest aktywny.

Cel (

target

) posiada następujące atrybuty:

 

name

 - nazwa

 

depends

 – zależności,

 

if

 – jeśli

 

unless

 – ,,jeśli nie”,

 

description

 – dodatkowy, krótki opis zadania.

5

background image

Wykorzystanie – zadania

Zadanie określa konkretny kod, który ma zostać wykonany. Zadania zwykle 

definiuje się tagami w następującej postaci:

<taskname attribute1="value1" attribute2="value2" ... />

Wszystkie zadania posiadają nazwę – typ zadania. Liczba atrybutów zależy od 

rodzaju zadania. Zadania dzielimy na wbudowane, opcjonalne i własne. 

Zadanie może mieć także przyporządkowany identyfikator:

<taskname id="taskID" ... />

Dzięki temu można odwołać się do tego zadania z innych zadań. Przykład:

<script ... >
  task1.setAttr("bar");
</script>

ustawia atrybut 

attr

 konkretnej instancji zadania. Z poziomu programu w Javie 

dostęp do zadania uzyskujemy poprzez: 

project.getReference("task1")

.

6

background image

Wykorzystanie – własności

Z projektem może być związany zbiór własności. Aby je wykorzystać należy 

wpisać 

${nazwawlasosci}

. Ant umożliwia dostęp do wszystkich własności 

systemowych (

System.getProperties()

). Ponadto udostępnione są także:

 

basedir

 – bezwzględna ścieżka dla projektu (atrybut 

basedir

),

 

ant.file

 – bezwzględna scieżka do opisu XML (buildfile),

 

ant.version

 – wersja Ant'a

 

ant.project.name

 – nazwa wykonywanego projektu,

 

ant.java.version

 – wersja Wirtualnej Maszyny Javy (obecnie 

dopuszczalne wartości to "1.1", "1.2", "1.3", "1.4"  oraz "1.5").

7

background image

Wykorzystanie – przykład

<project name="MyProject" default="dist" basedir=".">

<description>

przykładowy buildfile

</description>
<!-- ustawienie właściwości globalnych -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist"  location="dist"/>

<target name="init">

<!-- timestamp -->
<tstamp/>
<!-- Przygotowanie katalogów dla kompilacji -->
<mkdir dir="${build}"/>

</target>

<target name="compile" depends="init" 

description="compilation" >
<!-- Kompilacja źródeł z ${src} do ${build} -->
<javac srcdir="${src}" destdir="${build}"/>

</target>

8

background image

Wykorzystanie – przykład

<target name="dist" depends="compile"

description="generowanie dystrybucji" >
<!-- Przygotowanie katalogu -->
<mkdir dir="${dist}/lib"/>
<!-- Stworzenie archiwum MyProject-${DSTAMP}.jar -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar"

basedir="${build}"/>

</target>

<target name="clean" description="porzadki" >

<!-- Kasowanie katalogów ${build} i ${dist} -->
<delete dir="${build}"/>
<delete dir="${dist}"/>

</target>

</project>

9

background image

Ścieżki

Często wymagane jest podanie zbioru plików (np. Zmienna 

CLASPATH

). Można 

tu skorzystać z elementów 

pathelement

fileset

 i 

dirset

.

Przykład:

<classpath>

<pathelement path="${classpath}"/>
<fileset dir="lib">

<include name="**/*.jar"/>

</fileset>
<pathelement location="classes"/>
<dirset dir="${build.dir}">

<include name="apps/**/classes"/>
<exclude name="apps/**/*Test*"/>

</dirset>
<filelist refid="third-party_jars"/>

</classpath>

10

background image

Referencje

<project ... >
  <target ... >
    <rmic ...>
      <classpath>
        <pathelement location="lib/"/>
        <pathelement path="${java.class.path}/"/>
        <pathelement path="${additional.path}"/>
      </classpath>
    </rmic>
  </target>

  <target ... >
    <javac ...>
      <classpath>
        <pathelement location="lib/"/>
        <pathelement path="${java.class.path}/"/>
        <pathelement path="${additional.path}"/>
      </classpath>
    </javac>
  </target>
</project>

11

background image

Referencje

<project ... >
  <path id="project.class.path">
    <pathelement location="lib/"/>
    <pathelement path="${java.class.path}/"/>
    <pathelement path="${additional.path}"/>
  </path>

  <target ... >
    <rmic ...>
      <classpath refid="project.class.path"/>
    </rmic>
  </target>

  <target ... >
    <javac ...>
      <classpath refid="project.class.path"/>
    </javac>
  </target>
</project>

12

background image

Uruchamianie Ant'a

Aby uruchomić projekt należy wcześniej dodać do 

CLASSPATH

 katalog 

ANT_HOME/lib

. Przykładowe uruchomienie programu:

ant

uruchamia domyslny cel ze skryptu 

build.xml

 z bierzącego katalogu,

ant -buildfile plik.xml

uruchamia domyslny cel ze skryptu 

plik.xml

 z bierzącego katalogu,

Można też uruchomić Ant'a poprzez wirtualną maszynę Javy:

java -Dant.home=c:\ant org.apache.tools.ant.Main [options] 

[target]

lub

java -Dant.home=c:\ant org.apache.tools.ant.launch.Launcher 

[options] [target]

13

background image

Podstawowe zadania - javac

javac

 – służy do kompilacji programów. Przykład zastosowania:

<javac 

srcdir

="${src}"

// katalog z plikami 

.java

destdir="${build}"

// katalog na pliki 

.class

   includes="d1/**,d2/**"

// dodatkowe źródła do kompilacji

   excludes="${src}/test/**"

// pliki wykluczone z kompilacji

fork="true"

// do kompilacji użyty zostanie program 

javac

source="1.2"

// źródla zgodne z wersją 1.2 javy

target="1.2"

// klasy zgodne z wersją 1.2 javy

   classpath="xyz.jar"

// zbiór klas i bibliotek z których korzysta program

/>

14

background image

Podstawowe zadania – jar, signjar

jar

 – pozwala  przykotować archiwum jar. Przykład zastosowania:

<jar 

destfile

="${dist}/lib/mylib.jar">

//tworzymy bibliotekę

<fileset dir="${build}/classes"

excludes="**/Test.class"

/>
<fileset dir="${src}/resources"/>

</jar>

<jar 

destfile

="${dist}/lib/mylibtest.jar"> 

// tworzymy test

<fileset dir="${build}/classes"/>
<fileset dir="${src}/resources"/>
<manifest>

<attribute name="Main-Class" value="com.myapp.Test" />

</manifest>

</jar>

<signjar 

jar

="${dist}/lib/mylibtest.jar" 

// podpisujemy aplikacje

alias

="myalias" 

storepass

="mypass" 

/>

15

background image

Inne zadania – izpack

izpack

 – jest zadaniem zdefiniowanym w pakiecie izpack i służy do 

przygotowania wersji instalacyjnej programu. Przykład zastosowania:

<taskdef name="izpack" 

classpath="${lib}/standalone-compiler.jar"
classname="com.izforge.izpack.ant.IzPackTask"

/>

...

<echo message="Makes the installer using IzPack"/>
<izpack 

input="${basedir}/install.xml"
output="${basedir}/myapp-install.jar"
installerType="standard"
basedir="${basedir}"

/>

16

background image

Tworzenie nowych własnych zadań

1. Utworzenie klasy rozszerzającej 

org.apache.tools.ant.Task

.

2. Stworzenie publicznego setter'a dla każdego argumentu. Przykład – dla 

argumentu 

file

 tworzymy metodę 

setFile()

.

3. Jeśli zadanie może zawierać podzadania (jako elementy) klasa musi 

implementować interfejs 

org.apache.tools.ant.TaskContainer

. Takie 

zadanie nie może zawierać innych elementów.

4. Jeśli zadanie może posiadać dane tekstowe pomiędzy tagiem otwierającym i 

zamykającym należy zaimplementowac metodę 

public void setText(String)

. Własności nie są wypełniane.

5. Dla każdego elementu (np. 

field

)   należy zaimplementowac odpowiednią 

metodę:

 createField()

addField()

 lub 

addConfiguredField()

.

6. Zaimplementowac metodę 

public void execute() throws 

BuildException

, która realizuje zadanie.

17

background image

Prosty przykład

package pl.domena;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class MyVeryOwnTask extends Task {

private String msg;
public void execute() throws BuildException {

System.out.println(msg);

}
public void setMessage(String msg) {

this.msg = msg;

}

}

<?xml version="1.0"?>
<project name="OwnTaskExample" default="main" basedir=".">
  <taskdef name="mytask" classname="pl.domena.MyVeryOwnTask"/>
  <target name="main">
    <mytask message="Hello World! MyVeryOwnTask works!"/>
  </target>
</project>

18

background image

Cykl życia zadania

1. 

Zadanie jest tworzone w momencie parsowania dokumentu. Oznacza to, że 

zadanie istnieje nawet jeśli nie zostanie wywołane.

2. Zadanie otrzymuje referencje do projektu, pozycji i celu poprzez dziedziczone 

pola: 

projectlocation 

i

 target

 (w trakcie parsowania).

3. 

Jeśli użytkownik użyje atrybutu 

id

 projekt zapisuje referencje do zadania.

4. Wywoływana jest metoda 

init()

 (w trakcie parsowania).

5. Za pomocą metod 

createXXX()

 lub 

addXXX()

 tworzone są wszystkie 

elementy zadania (w trakcie parsowania).

6. Za pomocą metod 

setXXX()

  is ew. 

setText()

 są ustawiane atrybuty 

(w trakcie uruchomienia).

7. Ustawiane są atrybuty podzadań lub innych elementów (w trakcie 

uruchomienia).

8.  Wywoływana jest metoda 

execute()

. Metoda może być wywołana więcej 

niż raz (w trakcie uruchomienia).

19

background image

Konwersje typów

Typowo metody 

setXXX()

 używają argumentu java.lang.String. Wtedy wartość 

jest przekazywana do programu (po ew. wypełnieniu własności). Jednak istnieje 

możliwość użycia innych typów:

 

boolean

 -  zostanie przekazane 

true

 jeśli w pliku konfiguracyjnym było 

wpisane 

true

 lub 

yes

. W przeciwnym przypadku zostanie przekazane 

false

.

 

char

 lub 

java.lang.Character

 – pierwsza litera wyrażenia określonego w 

pliku konfiguracyjnym,

 jakikolwiek inny typ podstawowy (

int

short

, ...) - zostanie wykonana 

odpowiednia konwersja,

 

java.io.File

 – najpierw zostanie ustalone czy podana ścieżka jest 

bezwzględna, jeśli nie zostanie zinterpretowana jako względna w odniesieniu do 

podanej w projekcie jako 

basedir

,

20

background image

Konwersje typów

 

org.apache.tools.ant.types.Path

 - dane zostaną rozdzielone z 

wykorzystaniem 

:

 i 

;

 jako separatorów. Względne ścieżki zostaną uzupełnione o 

basedir

 

java.lang.Class

 - klasa o podanej nazwie zostanie załadowana i 

przekazana do metody,

 jakikolwiek inny typ posiadający konstruktor, którego jedynym argumentem 

jest typ 

java.lang.String

 -  zostanie utworzona nawa instancja obiektu i 

przekazana metodzie.

 podklasa 

org.apache.tools.ant.types.EnumeratedAttribute

 – 

zostanie wywołana metoda 

setValue()

 .

21

background image

Elementy

Chcąc umożliwić używanie nowego elementu w zadaniu o nazwie 

field

 typu 

FieldElement

 należy zdefiniować jedną z metod:

1. 

public FieldElement createField()

 - tworzona jest nowa instancje 

FieldElement

.

2. 

public void addField(FieldElement value)

 – przekazywany jest 

argument utworzony po wywołaniu odpowiedniego konstruktora.

3. 

public void addConfiguredField(FieldElement value)

 – 

dodatkowo tworzone są wszystkie elementy wewnętrzne za pomocą 

odpowiednich konstruktorów. 

W drugim i trzecim przypadku klasa 

FieldElement

 musi posiadć publiczny 

bezargumentowy konstruktor lub publiczny jednoargumentowy konstruktor 

korzystający z parametru typu oklreślającego projekt.

22

background image

Typy

Aby umożliwić używanie nowego typu 

Type

 w zadaniu należy zdefiniować 

jedną z metod:

1. 

public void add(Type type)

 - przekazywany jest argument utworzony 

po wywołaniu odpowiedniego konstruktora.

2. 

public void addConfigured(Type type)

 – dodatkowo tworzone są 

wszystkie elementy wewnętrzne za pomocą odpowiednich konstruktorów. 

23

background image

Typy – przykład

Zadanie 

MyTask

 zawiera elementy typu 

Condition

:

public class MyTask extends Task {

private List conditions = new ArrayList();
public void add(Condition c) {

conditions.add(c); // dodanie zadania do listy

}
public void execute() {

// wykonanie zadania

}

}

Użycie zadania 

MyTask

:

<taskdef name="mytask" classname="MyTask" classpath="classes"/>
<typedef name="condition.equals"         
classname="org.apache.tools.ant.taskdefs.conditions.Equals"/>
<mytask>
    <condition.equals arg1="${debug}" arg2="true"/>
</mytask>

24

background image

Typy i elementy – przykład

public class Sample {

public static class MyFileSelector implements FileSelector {

public void setAttrA(int a) {}
public void setAttrB(int b) {}
public void add(Path path) {}
public boolean isSelected(File basedir, 

String filename, File file) {
return true;

}

}
interface MyInterface {

void setVerbose(boolean val);

}

public static class BuildPath extends Path {

public BuildPath(Project project) {

super(project);

}

public void add(MyInterface inter) {}
public void setUrl(String url) {}

}

25

background image

Typy i elementy – przykład

public static class XInterface implements MyInterface {

public void setVerbose(boolean x) {...}
public void setCount(int c) {...}

}

}

<typedef name="myfileselector" classname="Sample$MyFileSelector"
         classpath="classes" loaderref="classes"/>
<typedef name="buildpath" classname="Sample$BuildPath"
         classpath="classes" loaderref="classes"/>
<typedef name="xinterface" classname="Sample$XInterface"
         classpath="classes" loaderref="classes"/>

<copy todir="copy-classes">
   <fileset dir="classes">
      <myfileselector attrA="10" attrB="-10">
         <buildpath path="." url="abc">
            <xinterface count="4"/>
         </buildpath>
      </myfileselector>
   </fileset>
</copy>

26

background image

Podzadania i zdarzenia

Zadanie posiadające podzadania posiada metodę 

addTask()

, która powinna 

uruchomić podzadanie za pomocą metody 

perform()

 z pakietu 

org.apache.tools.ant. Metoda perform wywołuje odpowiednie zdarzenie 

BuildEvent

 i wykonuje metodę 

execute()

.

Zdarzenia można przechwycić w obiekcie typu Project używając odpowienich 

BuildListener'ow (

org.apache.tools.antBuildListener

). Listener 

przechwytuje zdarzenia: rozpoczęcie i zakończenie dla projektu, celu oraz 

logowanie komunikatów. Od wersji 1.6.2 pojawił się 

SubBuildListener

 

pozwalający obsłużyć zadania 

<ant>

 i 

<subant>

.

UWAGA: listener nie może korzystać bezpośrednio ze strumieni systemowych 

ponieważ Ant przekierowuje te strumienie do systemu obsługi zdarzeń 

BuildEvent

.

27

background image

Podsumowanie

Wykorzystanie Ant'a umożliwia automatyzaję wielu procesów związanych 

z tworzeniem oprogramowania. Narzędzie to jest powszechnie używane 

szczególnie przez programistów urzywających Javy. Uniwersalność 

i elastyczność Anta istotnie wpłynęła na popularnośc tego rozwiązania.

28