build.xml上に「${ }」でプロパティーを指定すると、属性(セッターメソッド)には、プロパティーが展開された値が入ってくる。
ただし、そのタスク実行時点でそのプロパティーに値が入っていない場合は、展開されずにそのまま入ってくる。
ボディー部にはプロパティーが展開されずに入ってくるので、必要であれば自分で展開する。
プロパティーの展開(置換)は、Project#replaceProperties()を使用する。
String str = getProject().replaceProperties("置換元:${property}");
ただし、該当のプロパティーが無かった場合は変換されずにそのまま(${ }形式)で返ってくる。
プロパティーに値をセットするには、setNewProperty()を使用する。(Ant1.5以降)
このメソッドでは、既にプロパティーに値が入っている場合は(verboseレベルでメッセージ出力のみ行い、)値をセットしない。
(通常、Antでは、プロパティーの上書きや削除は行わない)
また、値がnullの場合も値は設定されない。(以前の値がそのまま残る)
getProject().setNewProperty(name, value);
setProperty()を使うと、既に値が入っている場合でも値がセットされる。
(こちらも、値がnullの場合は何もしない)
getProject().setProperty(name, value);
属性のプロパティーを扱う例。
事前にプロパティーがセットされている場合 | 事前にプロパティーがセットされていない場合 | |
---|---|---|
概要 |
独自タスク実行前にプロパティーがセットされている場合、 セッターメソッド呼び出し時点で展開されている。 |
独自タスク実行前にプロパティーがセットされていない場合、 セッターメソッドには展開前の形でそのまま入ってくる。 |
build.xml |
<target name="〜"> <property name="test" value="abc" /> <sample attr="${test}" /> </target> |
<target name="〜"> <sample attr="${test}" /> </target> |
SampleTask |
public class SampleTask extends Task { protected String attr; public void setAttr(String s) { attr = s; } public void execute() throws BuildException { log(attr); log(getProject().replaceProperties(attr)); } } |
public class SampleTask extends Task { protected String attr; public void setAttr(String s) { attr = s; } public void execute() throws BuildException { log(attr); getProject().setProperty("test", "def"); log(getProject().replaceProperties(attr)); } } |
出力例 | abc |
${test} |
ボディー部のテキストにはプロパティーが展開されずに入ってくるので、必要であれば自分で展開する。[2009-01-26]
public class SampleTask extends Task { protected String text; public void addText(String s) { text = s; } public void execute() throws BuildException { log(text); log(getProject().replaceProperties(text)); } }
<target name="text"> <sample>Antパスは${ant.library.dir}です。</sample> </target>
Buildfile: C:\workspace\sample\bin\build.xml text: [sample] Antパスは${ant.library.dir}です。 [sample] AntパスはC:\eclipse\plugins\org.apache.ant_1.7.0.v200803061910\libです。 BUILD SUCCESSFUL Total time: 203 milliseconds
Ant1.6からPropertyHelperというクラスが導入され、Projectクラスを使ったプロパティーの取得/設定はPropertyHelperに委譲されるようになった。
ProjectのsetProperty()・getProperty()の値はStringしか受け付けないが、PropertyHelperではObjectを使用できる。
ただしProject#getProperty()はPropertyHelper#getProperty()の戻り値を問答無用でStringにキャストしているので注意。
Ant1.6〜1.7のプロパティーにはフックという仕組みがある。(Ant1.8でフックの機能は使えなくなった。Delegateを使用する。[2015-12-28])
つまり、getProperty()が呼ばれた際に、自分で作ったメソッドを経由させることが出来る。
ここで独自の判定を行って値を返すようにすれば、setProperty()を呼んで値をセットしておかなくてもプロパティーの値が返せることになる。
使うかどうか分からない値を軒並み事前にセットしておくよりは、使うものだけを使う際に算出することで、効率が良くなると考えられる。
このフックの機能を実現しているのがPropertyHelper。
import org.apache.tools.ant.PropertyHelper;
public class MyPropertyHelper extends PropertyHelper { static final String PREFIX = "sample."; static Map<String, String> MAP = new HashMap<String, String>(); static { MAP.put(PREFIX + "prop1", "値1"); MAP.put(PREFIX + "prop2", "値2"); } /** * getProperty()の際に呼ばれるフック. * * @param ns * @param name プロパティー名 * @param user */ @Override public Object getPropertyHook(String ns, String name, boolean user) { if (name != null && name.startsWith(PREFIX)) { return MAP.get(name); } return super.getPropertyHook(ns, name, user); } }
getProperty()で独自の値を返すには、PropertyHelperを継承したクラスを作り、getPropertyHook()をオーバーライドする。
上記の例では「sample.
」で始まるプロパティー名を対象とし、「sample.prop1
」の時は「値1」、「sample.prop2
」の時は「値2」を返している。
super.getPropertyHook()を呼ぶと、後続のフック処理が実行される。つまり、通常のプロパティー取得処理が行われる。
独自タスクの開始時に、自分のPropertyHelperを登録してやる。
import org.apache.tools.ant.Project; import org.apache.tools.ant.PropertyHelper;
public class SampleTask extends Task { protected String attr; public void setAttr(String s) { attr = s; } @Override public void init() throws BuildException { initMyPropertyHelper(); } @Override public void execute() throws BuildException { // initMyPropertyHelper(); log("attr = " + attr); log("attr[rep]= " + getProject().replaceProperties(attr)); } void initMyPropertyHelper() { Project project = getProject(); PropertyHelper rootHelper = PropertyHelper.getPropertyHelper(project); MyPropertyHelper helper = new MyPropertyHelper(); helper.setProject(project); helper.setNext(rootHelper.getNext()); //自分の次のヘルパーに、今までのヘルパーを指定 rootHelper.setNext(helper); //自分のヘルパーを指定 } }
※setNext()によってヘルパーを追加する。したがって、何度もこのタスクが実行されると、どんどん同じヘルパーが追加されることになる…。
別の箇所でヘルパーを追加しているクラスがあるかもしれないので、単純に自分の前のヘルパーを保持しておいて戻せばいいわけでもない。
<target name="sample"> <taskdef name="sample" classname="jp.hishidama.sample.ant.SampleTask" classpath="classes" /> <sample attr="${sample.prop1}" /> ←SampleTaskの実行(ここで独自のプロパティーヘルパーを設定) <echo message="${sample.prop1}" /> <property name="sample.prop2" value="zzz" /> <echo message="${sample.prop2}" /> ←proprtyタスクで設定した値よりも、PropertyHelperで返す値の方が優先される </target>
ヘルパーをinit()で登録 | ヘルパーをexecute()で登録 |
---|---|
Buildfile: C:\workspace\sample\bin\build.xml sample: [sample] attr = 値1 [sample] attr[rep]= 値1 [echo] 値1 [echo] 値2 BUILD SUCCESSFUL Total time: 282 milliseconds |
Buildfile: C:\workspace\sample\bin\build.xml
sample:
[sample] attr = ${sample.prop1}
[sample] attr[rep]= 値1
[echo] 値1
[echo] 値2
BUILD SUCCESSFUL
Total time: 282 milliseconds
|
init()は属性の設定が行われる前(セッターメソッドが呼ばれる前)に実行されるので、
自分の属性にPropertyHelperで返すプロパティーをセットしておいてもその値が渡される。
自分のタスクより後のタスクでプロパティーを使うことを考えるならsetProperty()を呼んでおく方が素直だと思うが、
自分のタスクの属性でプロパティー名を指定して それを自分で使うような場合にはPropertyHelperを使うのが便利かも。
Ant1.8でPropertyHelperの仕様が変わり、Ant1.6のgetPropertyHook()やsetNext()/getNext()が使えなくなった。[2015-12-28]
PropertyHelperから独自のプロパティー値を返したい場合は、PropertyEvaluatorというクラスを作り、それをPropertyHelperに登録する。
(PropertyEvaluatorに限らず、PropertyHelperにDelegateを登録する形になった。PropertyEvaluatorもDelegateのひとつである)
import org.apache.tools.ant.Project; import org.apache.tools.ant.PropertyHelper;
public class Example18Task extends Task { protected String attr; public void setAttr(String s) { attr = s; } @Override public void init() throws BuildException { initMyPropertyHelper(); } @Override public void execute() throws BuildException { log("attr = " + attr); log("attr[rep]= " + getProject().replaceProperties(attr)); } void initMyPropertyHelper() { Project project = getProject(); PropertyHelper helper = PropertyHelper.getPropertyHelper(project); MyPropertyEvaluator evaluator = new MyPropertyEvaluator(); helper.add(evaluator); // 自分のdelegateをヘルパーに登録 } }
import org.apache.tools.ant.PropertyHelper.PropertyEvaluator; import org.apache.tools.ant.property.NullReturn;
public class MyPropertyEvaluator implaments PropertyEvaluator { static final String PREFIX = "example."; static Map<String, String> MAP = new HashMap<String, String>(); static { MAP.put(PREFIX + "prop1", "値1"); MAP.put(PREFIX + "prop2", "値2"); } /** * getProperty()の際に呼ばれるフック. * * @param name プロパティー名 * @param propertyHelper */ @Override public Object evaluate(String name, PropertyHelper propertyHelper) { if (name != null && name.startsWith(PREFIX)) { String value = MAP.get(name); return (value != null) ? value : NullReturn.NULL; } return null; } }
PropertyEvaluatorではevaluateメソッドを実装する。
このメソッドはPropetyHelperのgetPropertyメソッドの中から呼ばれるので、自分が処理する対象のプロパティーであれば、その値を返すようにする。
PropetyHelperには複数のDelegateが登録されるので、evaluateメソッドでnullを返すと、次のDelegateが呼ばれる。
自分の値としてのnullを返したい場合は、NullReturn.NULL
を返せばよい。