本Tipsは、Javaのクラスとして実装したAntの新規タスクにネストした要素を渡す方法を説明します。Antで使用するタスクを作成する方法の基本については、「Antで使う新規タスクを作成する」を、Antで使用するタスクにパラメータを渡す方法については、「Antで使う新規タスクにパラメータを渡す」を参照してください。
Antでは、ビルドファイル中のタスク要素の子要素としてデータ構造をネストすることで、ネストしたデータ構造を当該タスクのパラメータとして渡すことができます。例えば<javac>タスクはネストした要素として<fileset>データ構造を取ることができ、ネストした<fileset>によって示されるJavaソースファイルをコンパイルします。
Antで扱えるデータ構造はそれぞれJavaのクラスとして実装されています。Antでは任意のクラスをデータ構造として使用することができます。Antのデータ構造ではXMLの属性としてパラメータを渡すことができます。あるデータ構造でXxx(Xxxは任意の英数字かアンダーライン)というパラメータを使用したい場合は、対応するJavaクラスにsetXxxメソッドを実装します。このsetXxxメソッドの詳細については、「Antで使う新規タスクにパラメータを渡す」のTipsで説明したsetXxxメソッドと同様ですので、そちらを参照してください。
Antではデフォルトでいくつかのデータ構造が使用可能になっています。これらのうち主要なものについて、データ構造とJavaクラスの対応表を以下に示します。
|
Antでのデータ構造 |
Javaのクラス |
|
fileset |
org.apache.tools.ant.types.FileSet |
|
filelist |
org.apache.tools.ant.types.FileList |
|
dirset |
org.apache.tools.ant.types.DirSet |
|
新規タスクでネストした要素を取れるようにする方法はいくつかありますが、ここではcreateYyyメソッド(Yyyはネスト可能な要素の要素名で、大文字・小文字同一視)を使用する方法について説明します。createYyyメソッドは引数なしで、ネストする要素に対応するJavaクラスのインスタンスを戻り値とします。createYyyメソッド内には以下のような処理を実装します。
- ネストする要素に対応するJavaクラスのインスタンスを新規作成する。
- 同一要素を複数ネスト可能にする場合は、新規作成したインスタンスへの参照をコレクション等に保存しておく
- 新規作成したインスタンスをメソッドの戻り値とする
Antは、ビルドファイルの処理中に、タスクの要素にネストしたYyy要素があると、当該タスクの処理を行うJavaクラスのcreateYyyメソッドを呼びます。複数のYyy要素がネストされていたときは、ネストされている数だけcreateYyyメソッドが呼ばれます。
ここでは、タスクにネスト可能なデータ構造として、Antのデフォルトで使用可能な<fileset>と、このタスクでのみ使用可能な独自データ構造<mymessage>を取るタスクをSampleTask3というクラスとして作成します。<mymessage>はMyOwnNestedElementクラスとして実装されており、属性textを取るものとします。
MyOwnNestedElement.java
// <mymessage>要素として使用するデータ構造
public class MyOwnNestedElement {
private String text;
//属性textの属性値がセットされる
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
} |
SampleTask3.java
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
public class SampleTask3 extends Task {
private ArrayList filesets = new ArrayList();
private ArrayList mymessages = new ArrayList();
public FileSet createFileSet() {//ネストしたfileset要素
FileSet fs = new FileSet();
//複数個のfilesetがネストした場合を考えてArrayListに追加
filesets.add(fs);
return fs;
}
//ネストしたmymessage要素
public MyOwnNestedElement createMyMessage() {
MyOwnNestedElement element = new MyOwnNestedElement();
//複数個のMyMessageがネストした場合を考えてArrayListに追加
mymessages.add(element);
return element;
}
public void execute() throws BuildException {//タスクの実行処理
//ネストしたFileSetにセットされた全ファイル名を表示
for (Iterator i = filesets.iterator(); i.hasNext();) {
FileSet fs = (FileSet)i.next();
DirectoryScanner ds
= fs.getDirectoryScanner(getProject());
//ディレクトリ内の全ファイル名
String[] files = ds.getIncludedFiles();
for (int j = 0; j < files.length; j++) {
System.out.println("File=" + files[j]);
}
}
//ネストした全てのMyMessageのtext属性値を表示
for (Iterator i = mymessages.iterator(); i.hasNext();) {
MyOwnNestedElement element
= (MyOwnNestedElement)i.next();
System.out.println("MyMessage=" + element.getText());
}
}
} |
sampletask3.jar内にSampleTask3.classとMyOwnNestedElement.classが入っており、ディレクトリ構造が以下のようになっている場合に、上記タスクを実行するビルドファイルbuild.xmlの記述例と、このビルドファイルの実行結果を以下に示します。
ディレクトリ構造
D:\work\sampletask3\build.xml
D:\work\sampletask3\sampletask3.jar |
build.xml
<?xml version="1.0" encoding="Shift_JIS"?>
<project name="taskdef_sample3" default="execute_sample3">
<taskdef name="sampletask3" classname="SampleTask3"
classpath="./sampletask3.jar"/>
<target name="execute_sample3">
<sampletask3>
<fileset dir="." includes="*"/>
<mymessage text="foo"/>
<mymessage text="bar"/>
<mymessage text="baz"/>
</sampletask3>
</target>
</project> |
実行結果
Buildfile: D:\work\sampletask3\build.xml
execute_sample3:
[sampletask3] File=build.xml
[sampletask3] File=sampletask3.jar
[sampletask3] MyMessage=foo
[sampletask3] MyMessage=bar
[sampletask3] MyMessage=baz
BUILD SUCCESSFUL
Total time: 1 second |