プロパティは、Apache Antが実行時に${key}をvalueに展開しようとする、キーと値のペアです。
プロパティを設定できるタスクは多数ありますが、最も一般的なのはpropertyタスクです。さらに、プロパティはコマンドライン引数やAntの外部からの同様のメカニズムによって定義できます。
通常、プロパティの値は変更できません。プロパティが設定されると、ほとんどのタスクはその値の変更を許可しません。一般的に、プロパティはグローバルスコープを持ちます。つまり、一度定義されると、その後呼び出される任意のタスクまたはターゲットで使用できます。ただし、ant、antcall、subantタスクを使用して作成された子ビルドプロセスでプロパティを設定し、それを呼び出し元のビルドプロセスで使用できるようにすることはできません。
Ant 1.8.0以降、localタスクを使用して、ターゲットまたはsequential要素(macrodefタスクのものなど)にローカルスコープのプロパティを作成できます。
Antは、<property>タスクを使用して定義されたかのように、すべてのシステムプロパティへのアクセスを提供します。たとえば、${os.name}はオペレーティングシステムの名前に展開されます。
システムプロパティのリストについては、System.getPropertiesのJavadocを参照してください。
さらに、Antにはいくつかの組み込みプロパティがあります。
basedirant.fileant.versionant.project.name<project>のname属性で設定されます。ant.project.default-target<project>のdefault属性で設定されます。ant.project.invoked-targets<ant>タスクなど)のコンマ区切りのリスト。<project>タグの直下)で使用する場合、ターゲットが指定されていない場合はリストは空になり、ターゲット内にネストされたタスクの場合、プロジェクトのデフォルトターゲットが含まれます。ant.java.version9、
1.8、
1.7、
1.6、
1.5、
1.4、
1.3、
1.2の値を保持できます。
ant.core.libもう1つのプロパティもありますが、これはランチャースクリプトによって設定されるため、IDE内では設定されない場合があります。
ant.home次のプロパティは、ランチャー クラスを介して Ant が起動された場合にのみ設定されます(つまり、IDE 内でも設定されない場合があります)。
ant.library.dirAntのプロパティ処理は、現在のプロジェクトに関連付けられたorg.apache.tools.ant.PropertyHelperのインスタンスによって行われます。このクラスの詳細については、AntのJava APIを参照してください。Ant 1.8では、PropertyHelperクラスが大幅に改良され、プロパティの設定、取得、解析など、個別のタスクを処理するために、多くのヘルパークラス(実際にはorg.apache.tools.ant.PropertyHelper$Delegateマーカーインターフェースのインスタンス)を使用するようになりました。これにより、Antのプロパティ処理は非常に拡張性が高くなります。また、propertyhelperタスクは、AntビルドファイルのコンテキストからPropertyHelperとそのデリゲートを操作するために使用されるため、注目に値します。
Delegateには、実装に役立つ3つのサブインターフェースがあります。
org.apache.tools.ant.property.PropertyExpanderは、まず文字列内のプロパティ名を見つける役割を担います(デフォルトでは${foo}からfooを抽出します)。独自のプロパティ構文を作成する場合、またはデフォルトの実装では中括弧のバランスが取れていないため(例についてはprops AntlibのNestedPropertyExpanderを参照)、ネストされたプロパティ展開を許可する場合に、このインターフェースを実装します。
org.apache.tools.ant.PropertyHelper$PropertyEvaluatorは、${some-string}をObjectに展開するために使用されます。Antのプロジェクトインスタンスとは独立した独自のストレージを提供する場合、このインターフェースを実装します。このインターフェースは読み取り側を表します。これの例としては、ローカルプロパティのストレージを実装するorg.apache.tools.ant.property.LocalPropertiesがあります。
このインターフェースを実装するもう1つの理由は、プロジェクト参照fooを検索してtoString()を呼び出すことによってtoString:fooを展開するなど、独自の「プロパティプロトコル」を提供する場合です(これは既にAntに実装されています。以下を参照)。
org.apache.tools.ant.PropertyHelper$PropertySetterは、プロパティの設定を担当します。Antのプロジェクトインスタンスとは独立した独自のストレージを提供する場合、このインターフェースを実装します。このインターフェースは書き込み側を表します。これの例としては、ローカルプロパティのストレージを実装するorg.apache.tools.ant.property.LocalPropertiesがあります。
org.apache.tools.ant.PropertyHelper$PropertyEnumeratorは、プロパティ名の列挙を担当します。Antのプロジェクトインスタンスとは独立した独自のストレージを提供する場合、このインターフェースを実装します。このインターフェースは読み取り側の部分を表します。これの例としては、ローカルプロパティのストレージを実装するorg.apache.tools.ant.property.LocalPropertiesがあります。
このインターフェースは、Ant 1.10.9で追加されました。
デフォルトのPropertyExpanderは次のようになります。
public class DefaultExpander implements PropertyExpander {
public String parsePropertyName(String s, ParsePosition pos,
ParseNextProperty notUsed) {
int index = pos.getIndex();
if (s.indexOf("${", index) == index) {
int end = s.indexOf('}', index);
if (end < 0) {
throw new BuildException("Syntax error in property: " + s);
}
int start = index + 2;
pos.setIndex(end + 1);
return s.substring(start, end);
}
return null;
}
}
${toString:some-id}を現在のビルド内のidsome-idを持つオブジェクトの文字列表現に置き換えるロジックは、次のコードのようなPropertyEvaluatorに含まれています。
public class ToStringEvaluator implements PropertyHelper.PropertyEvaluator {
private static final String prefix = "toString:";
public Object evaluate(String property, PropertyHelper propertyHelper) {
Object o = null;
if (property.startsWith(prefix) && propertyHelper.getProject() != null) {
o = propertyHelper.getProject().getReference(
property.substring(prefix.length()));
}
return o == null ? null : o.toString();
}
}
Antが${some-text}という構成に出会うと、正確な解析セマンティクスは構成されたプロパティヘルパーデリゲートによって異なります。
$$展開デフォルトの構成では、Antはテキスト$$
を単一の$
に展開し、その直後のテキストの通常のプロパティ展開メカニズムを抑止します。つまり、$${key}は${key}に展開され、keyという名前のプロパティが定義されていて値がvalueであってもvalueには展開されません。これは、リテラル$
文字をエスケープするために使用でき、プロパティ展開のように見える構成や、次のような診断出力を作成する場合に役立ちます。
<echo>$${builddir}=${builddir}</echo>
これは、次のメッセージを出力します。
${builddir}=build/classes
プロパティbuilddirの値がbuild/classesの場合。
古いAntリリースとの下位互換性を維持するために、プロパティのような構成(フランス語の中括弧のマッチしたペアを含む)とは別に遭遇した単一の$
文字は、$
としてそのまま解釈されます。「正しい」指定方法は、エスケープメカニズムを無条件で使用することです。そのため、$$
は$$$$
を指定することで得られます。2つのアプローチを混在させると、$$$
が$$
になるなど、予測できない結果になります。
デフォルトの構成では、Antはプロパティ展開の中括弧のバランスを取ろうとしません。プロパティ名を作成する際、最初の中括弧までしかテキストを消費しません。つまり、${a${b}}のようなものを展開する場合、2つの部分に変換されます。
つまり、名前がプロパティに格納されているプロパティを簡単に展開することはできませんが、古いバージョンのAntにはいくつかの回避策があります。Ant 1.8.0以降、props Antlibを使用すると、このような機能が必要な場合は、そこに定義されているNestedPropertyExpanderを使用するようにAntを構成できます。
最も単純な形式では、${key}はkeyという名前のプロパティを検索し、プロパティの値に展開する必要があります。ただし、追加のPropertyEvaluatorによって、keyの解釈が異なる場合があります。
props Antlibはいくつかの興味深い評価器を提供しますが、いくつかの組み込み評価器もあります。
参照で宣言された任意のAntタイプのアイテムは、${toString:}操作を使用して文字列値を抽出することもでき、参照の名前がtoString:テキストの後にリストされます。参照されているJavaクラスインスタンスのtoString()メソッドが呼び出されます。すべての組み込みタイプは、このようなインスタンスで有用で関連性の高い出力を生成しようとします。
たとえば、fileset内のファイルのリストを取得する方法を次に示します。
<fileset id="sourcefiles" dir="src" includes="**/*.java"/>
<echo> sourcefiles = ${toString:sourcefiles} </echo>
外部タイプがそのような状況で意味のある情報を提供するという保証はありません。
参照で宣言された任意のAntタイプのアイテムは、${ant.refid:}操作を使用してプロパティとして使用することもでき、参照の名前がant.refid:テキストの後にリストされます。この操作と${toString:}の違いは、${ant.refid:}が参照されているオブジェクト自体に展開されることです。ほとんどの場合、toString()メソッドは呼び出されます。たとえば、${ant.refid:}が他のテキストで囲まれている場合などです。
この構文は、String以外のオブジェクトを受け入れる属性セッターを持つタスクを使用する場合に最も役立ちます。たとえば、セッターが次のようにResourceオブジェクトを受け入れる場合。
public void setAttr(Resource r) { ... }
構文を使用して、以前に参照として定義されたリソースサブクラスを渡すことができます。
<url url="https://ant.dokyumento.jp/" id="anturl"/>
<my:task attr="${ant.refid:anturl}"/>
<target> 要素と様々なタスク(<fail> など)およびタスク要素(<junit> 内の <test> など)は、if 属性と unless 属性をサポートしており、これらを使用してアイテムの実行または有効化の制御を行うことができます。
Ant 1.7.1以前では、これらの属性はプロパティ名のみを指定することができました。その名前のプロパティが定義されていれば(空文字列やfalse
であっても)、アイテムは有効になり、プロパティが定義されていなければ無効になります。例えば、以下は動作しますが、ファイルの存在チェックを否定的に(肯定的にのみならず)上書きする方法はありません。
<target name="-check-use-file">
<available property="file.exists" file="some-file"/>
</target>
<target name="use-file" depends="-check-use-file" if="file.exists">
<!-- do something requiring that file... -->
</target>
<target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/>
Ant 1.8.0以降、プロパティ展開を使用できるようになりました。true
(またはon
、yes
)の値はアイテムを有効にし、false
(またはoff
、no
)はアイテムを無効にします。それ以外の値は依然としてプロパティ名とみなされ、そのため、指定された名前のプロパティが定義されている場合のみ、アイテムは有効になります。
従来の方法と比較して、コマンドラインや親スクリプトから条件を上書きできるため、柔軟性が向上します。
<target name="-check-use-file" unless="file.exists">
<available property="file.exists" file="some-file"/>
</target>
<target name="use-file" depends="-check-use-file" if="${file.exists}">
<!-- do something requiring that file... -->
</target>
<target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/>
これで、ant -Dfile.exists=false lots-of-stuff を実行すると、予想通りother-unconditional-stuff
は実行されますが、use-file
は実行されません。他のスクリプトからも条件を無効化できます。
<antcall target="lots-of-stuff">
<param name="file.exists" value="false"/>
</antcall>
同様に、unless 属性は、定義されているプロパティの名前である場合、またはtrue
のような値に評価される場合に、アイテムを無効にします。例えば、以下のようにmy-prefs.propertiesでskip.printing.message=trueを定義すると、期待通りの結果が得られます。
<property file="my-prefs.properties"/>
<target name="print-message" unless="${skip.printing.message}">
<echo>hello!</echo>
</target>