自訂元件是 Apache Ant 核心外部定義的條件、選擇器、篩選器和其他物件。
在 Ant 1.6 中,自訂條件、選擇器和篩選器已進行大修。
現在可以定義表現得像 Ant Core 元件的自訂條件、選擇器和篩選器。這能透過允許在建置指令碼中定義的資料類型,在資料類別相容或已由轉接器類別轉接時,用作自訂元件來達成。
定義自訂元件的舊方法仍受支援。
自訂元件是實作特定介面或延伸特定類別,或已轉接至介面或類別的正常 Java 類別。
這完全就像撰寫 自訂工作。透過撰寫 設定器 方法和 新增 方法來定義屬性和巢狀元素。
在撰寫類別後,會使用 <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}"/>
現在可以在使用 Core 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}"/>
現在可以在使用 Core 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
的類別。最簡單的方法是透過便利基礎類別 org.apache.tools.ant.types.selectors.BaseExtendSelector
,它提供所有支援 <param>
標籤的方法。首先,覆寫 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>
選取基底目錄和其下一個目錄中的所有檔案。
自訂篩選器讀取器選擇器是實作 org.apache.tools.ant.types.filters.ChainableReader
的資料類型。
只有一個必要的方法,Reader chain(Reader reader)
。這會傳回一個篩選指定讀取器輸入的讀取器。
例如,移除每一個第二個字元的篩選器讀取器可以是
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; } } } } } }
對於以行為導向的篩選器,延伸 ChainableFilterReader
,也就是 org.apache.tools.ant.filters.TokenFilter
的內部類別,可能會比較容易。
例如,附加行號的篩選器可以是
public class AddLineNumber extends ChainableReaderFilter { private void lineNumber = 0; public String filter(String string) { lineNumber++; return "" + lineNumber + "\t" + string; } }