カスタムコンポーネントは、Apache Antコアの外で定義される条件、セレクタ、フィルタ、およびその他のオブジェクトです。
Ant 1.6では、カスタム条件、セレクタ、フィルタが改良されました。
Antコアコンポーネントのように動作するカスタム条件、セレクタ、フィルタを定義できるようになりました。これは、ビルドスクリプトで定義されたデータ型が、データ型のクラスが互換性がある場合、またはアダプタクラスによって適応されている場合、カスタムコンポーネントとして使用できるようにすることで実現されます。
カスタムコンポーネントを定義する従来の方法も引き続きサポートされています。
カスタムコンポーネントは、特定のインターフェースを実装するか、特定のクラスを拡張するか、またはインターフェースまたはクラスに適応された通常のJavaクラスです。
カスタムタスクを作成する場合と全く同じです。属性とネストされた要素は、setterメソッドとaddメソッドを記述することで定義します。
クラスを記述した後、<typedef>
を使用してAntシステムに追加します。
カスタム条件は、org.apache.tools.ant.taskdefs.condition.Condition
を実装するデータ型です。たとえば、文字列がすべて大文字の場合にtrueを返すカスタム条件は、次のように記述できます。
package com.mydomain; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.condition.Condition; public class AllUpperCaseCondition implements Condition { private String value; // The setter for the "value" attribute public void setValue(String value) { this.value = value; } // This method evaluates the condition public boolean eval() { if (value == null) { throw new BuildException("value attribute is not set"); } return value.toUpperCase().equals(value); } }
条件をシステムに追加する方法は次のとおりです。
<typedef name="alluppercase" classname="com.mydomain.AllUpperCaseCondition" classpath="${mydomain.classes}"/>
この条件は、コアAnt条件が使用されている場所であればどこでも使用できるようになりました。
<condition property="allupper"> <alluppercase value="THIS IS ALL UPPER CASE"/> </condition>
カスタムセレクタは、org.apache.tools.ant.types.selectors.FileSelector
を実装するデータ型です。
必要なメソッドはpublic boolean isSelected(File basedir, String filename, File file)
のみです。これは、指定されたファイルを選択するかどうかによってtrueまたはfalseを返します。
ファイル名が.javaで終わるファイルを選択するカスタム選択の例を以下に示します。
package com.mydomain; import java.io.File; import org.apache.tools.ant.types.selectors.FileSelector; public class JavaSelector implements FileSelector { public boolean isSelected(File b, String filename, File f) { return filename.toLowerCase().endsWith(".java"); } }
セレクタをシステムに追加する方法は次のとおりです。
<typedef name="javaselector" classname="com.mydomain.JavaSelector" classpath="${mydomain.classes}"/>
このセレクタは、コアAntセレクタが使用されている場所であればどこでも使用できます。たとえば、次のようになります。
<copy todir="to"> <fileset dir="src"> <javaselector/> </fileset> </copy>
org.apache.tools.ant.types.selectors.BaseSelector
は、妥当なデフォルトの動作を提供する便利なクラスです。利用できるいくつかの事前定義された動作があります。属性の設定またはタグの追加時に問題が発生した場合は、setError(String errmsg)
を呼び出すことができ、クラスは問題があることを認識します。その後、isSelected()
メソッドの先頭でvalidate()
を呼び出すと、エラーメッセージの内容を含むBuildException
がスローされます。validate()
メソッドは、verifySettings()
を呼び出すため、設定の一貫性をチェックするための最後の機会も提供します。このメソッドをオーバーライドし、セレクタの設定方法に問題を検出した場合はその中でsetError()
を呼び出してください。
カスタムセレクタコンテナを作成するには、org.apache.tools.ant.types.selectors.BaseSelectorContainer
を拡張する必要があります。public boolean isSelected(File baseDir, String filename, File file)
メソッドを実装して適切な処理を行います。おそらく、自分の下のセレクタを反復処理したいと思うでしょう。そのためには、selectorElements()
を使用してそれを行うイテレータを取得します。
たとえば、特定の数の含まれるセレクタが選択した場合にファイルを選択するセレクタコンテナを作成するには、次のようにセレクタを作成できます。
public class MatchNumberSelectors extends BaseSelectorContainer { private int number = -1; public void setNumber(int number) { this.number = number; } public void verifySettings() { if (number < 0) { throw new BuildException("Number attribute should be set"); } } public boolean isSelected(File baseDir, String filename, File file) { validate(); int numberSelected = 0; for (Enumeration e = selectorElements(); e.hasNextElement();) { FileSelector s = (FileSelector) e.nextElement(); if (s.isSelected(baseDir, filename, file)) { numberSelected++; } } return numberSelected == number; } }
このセレクタを定義して使用するには、次のことができます。
<typedef name="numberselected" classname="com.mydomain.MatchNumberSelectors"/> ... <fileset dir="${src.path}"> <numberselected number="2"> <contains text="script" casesensitive="no"/> <size value="4" units="Ki" when="more"/> <javaselector/> </numberselected> </fileset>
カスタムセレクタ
カスタムセレクタは、Ant 1.6以前のカスタムセレクタの定義方法でした。この方法は、下位互換性のために引き続きサポートされています。
独自のセレクタを作成し、<custom>
タグ内で指定することで、セレクタコンテナ内でそれらを使用できます。
新しいカスタムセレクタを作成するには、org.apache.tools.ant.types.selectors.ExtendFileSelector
を実装するクラスを作成する必要があります。最も簡単な方法は、<param>
タグのサポートに必要なすべてのメソッドを提供する便利な基本クラスorg.apache.tools.ant.types.selectors.BaseExtendSelector
を使用することです。まず、isSelected()
メソッドをオーバーライドし、必要に応じてverifySettings()
メソッドをオーバーライドします。カスタムセレクタでパラメータの設定が必要な場合は、setParameters()
メソッドをオーバーライドし、渡されたパラメータを好きなように解釈することもできます。コアセレクタのいくつかは、カスタムセレクタとしても使用できるため、その方法を示しています。
記述したら、<custom>
タグを使用してビルドファイルに含めます。
属性 | 説明 | 必須 |
---|---|---|
classname | org.apache.tools.ant.types.selectors.FileSelector を実装するクラスの名前。 |
はい |
classpath | カスタムセレクタクラスをロードするために使用するクラスパス。 classpathとclasspathrefのどちらも指定されていない場合、クラスはAntが使用するクラスパスからロードされます。 | いいえ |
classpathref | 以前に定義されたクラスパスへの参照。上記のclasspathrefとclasspathのどちらも指定されていない場合、クラスはAntが使用するクラスパスからロードされます。 | いいえ |
クラスをセレクタとして使用するのに<custom>
を使用する方法は次のとおりです。
<fileset dir="${mydir}" includes="**/*"> <custom classname="com.mydomain.MySelector"> <param name="myattribute" value="myvalue"/> </custom> </fileset>
カスタムセレクタとしても使用できるコアセレクタは次のとおりです。
org.apache.tools.ant.types.selectors.ContainsSelector
org.apache.tools.ant.types.selectors.DateSelector
org.apache.tools.ant.types.selectors.DepthSelector
org.apache.tools.ant.types.selectors.FilenameSelector
org.apache.tools.ant.types.selectors.SizeSelector
Depth Selectorセクションの例を<custom>
を使用してセレクタを使用するように書き直したものを次に示します。
<fileset dir="${doc.path}" includes="**/*"> <custom classname="org.apache.tools.ant.types.selectors.DepthSelector"> <param name="max" value="1"/> </custom> </fileset>
ベースディレクトリとその下の1つのディレクトリ内のすべてのファイルを選択します。
カスタムフィルタリーダーセレクタは、org.apache.tools.ant.types.filters.ChainableReader
を実装するデータ型です。
必要なメソッドはReader chain(Reader reader)
のみです。これは、指定されたリーダーからの入力をフィルタリングするリーダーを返します。
たとえば、2番目の文字を削除するfilterreaderは次のようになります。
public class RemoveOddCharacters implements ChainableReader { public Reader chain(Reader reader) { return new BaseFilterReader(reader) { int count = 0; public int read() throws IOException { while (true) { int c = in.read(); if (c == -1) { return c; } count++; if ((count % 2) == 1) { return c; } } } } } }
行指向のフィルタの場合、org.apache.tools.ant.filters.TokenFilter
の内部クラスであるChainableFilterReader
を拡張する方が簡単かもしれません。
たとえば、行番号を追加するフィルタは次のようになります。
public class AddLineNumber extends ChainableReaderFilter { private void lineNumber = 0; public String filter(String string) { lineNumber++; return "" + lineNumber + "\t" + string; } }