映射文件名称

某些任务需要源文件并创建目标文件。根据任务的不同,目标文件的名称可能非常明显(使用 javac,您知道将为您的 .java 文件创建 .class 文件)——在其他情况下,您可能希望指定目标文件,无论是为了帮助 Apache Ant 还是为了获得额外的功能。

虽然源文件通常指定为 fileset,但您不会直接指定目标文件——而是告诉 Ant 如何为一个源文件找到目标文件。一个 org.apache.tools.ant.util.FileNameMapper 实例负责此操作。它根据可以参数化的规则构建目标文件名,这些规则可以使用 fromto 属性参数化——其确切含义取决于实现。

这些实例在 <mapper> 元素中定义,具有以下属性

属性 描述 必需
type 指定内置实现之一。 这些属性中必须有一个
classname 通过类名指定实现。
classpath 查找 classname 时要使用的类路径。
classpathref 要使用的类路径,作为对在其他地方定义的路径的 引用 给出。
from 给定实现的 from 属性。 取决于实现
to 给定实现的 to 属性。 取决于实现
refid 使此 mapper 成为对在其他地方定义的 mapper引用。如果指定此属性,则不允许其他属性或嵌套元素。

请注意,Ant 不会自动将 /\ 字符从 tofrom 属性中的正确目录分隔符转换为当前平台的正确目录分隔符。如果您需要指定此分隔符,请使用 ${file.separator} 代替。对于 regexp 映射器,${file.separator} 将不起作用,因为在 Windows 上它是 \ 字符,它是正则表达式的转义字符,应该使用 handledirsep 属性代替。

作为嵌套元素指定的参数

类路径也可以通过嵌套的 <classpath> 指定——也就是说,一个类似于 路径 的结构。

从 Ant 1.7.0 开始,嵌套的文件映射器可以通过 <mapper> 元素或 <typedef> 定义的 org.apache.tools.ant.util.FileNameMapper 实现来提供。如果通过任一方式指定嵌套文件映射器,则映射器将隐式配置为 复合映射器

内置映射器类型

所有内置映射器都区分大小写。

从 Ant 1.7.0 开始,每个内置映射器实现类型都可以使用特定的标签名直接访问。这使得文件名映射器能够支持除普遍可用的 tofrom 之外的属性。
<mapper type|classname="..."> 使用形式出于向后兼容性的原因仍然有效。

identity

目标文件名与源文件名相同。 tofrom 都将被忽略。

示例
<mapper type="identity"/>
<identitymapper/>
源文件名 目标文件名
A.java A.java
foo/bar/B.java foo/bar/B.java
C.properties C.properties
Classes/dir/dir2/A.properties Classes/dir/dir2/A.properties

flatten

目标文件名与源文件名相同,所有前导目录信息都被剥离。 tofrom 都将被忽略。

示例
<mapper type="flatten"/>
<flattenmapper/>
源文件名 目标文件名
A.java A.java
foo/bar/B.java B.java
C.properties C.properties
Classes/dir/dir2/A.properties A.properties

merge

目标文件名将始终相同,如 to 所定义——from 将被忽略。

示例
<mapper type="merge" to="archive.tar"/>
<mergemapper to="archive.tar"/>
源文件名 目标文件名
A.java archive.tar
foo/bar/B.java archive.tar
C.properties archive.tar
Classes/dir/dir2/A.properties archive.tar

glob

tofrom 都需要,并定义可能包含最多一个 * 的模式。对于每个与 from 模式匹配的源文件,将从 to 模式构建目标文件名,方法是将 to 模式中的 * 替换为与 from 模式中的 * 匹配的文本。不匹配 from 模式的源文件名将被忽略。

示例
<mapper type="glob" from="*.java" to="*.java.bak"/>
<globmapper from="*.java" to="*.java.bak"/>
源文件名 目标文件名
A.java A.java.bak
foo/bar/B.java foo/bar/B.java.bak
C.properties 忽略
Classes/dir/dir2/A.properties 忽略
<mapper type="glob" from="C*ies" to="Q*y"/>
<globmapper from="C*ies" to="Q*y"/>
源文件名 目标文件名
A.java 忽略
foo/bar/B.java 忽略
C.properties Q.property
Classes/dir/dir2/A.properties Qlasses/dir/dir2/A.property

globmapper 映射器可以接受以下额外属性。

属性 描述 必需
casesensitive 此属性可以是 truefalse。如果为 false,则映射器在匹配 glob 模式时将忽略大小写。从 Ant 1.6.3 开始 否;默认值为 true
handledirsep 此属性可以是 truefalse。如果指定此属性,则映射器将忽略普通目录分隔符字符(\/)之间的差异。此属性对于跨平台构建文件很有用。从 Ant 1.6.3 开始否;默认值为 false

一个例子

<pathconvert property="x" targetos="unix">
  <path path="Aj.Java"/>
  <mapper>
  <chainedmapper>
    <flattenmapper/>
    <globmapper from="a*.java" to="*.java.bak" casesensitive="no"/>
  </chainedmapper>
  </mapper>
</pathconvert>
<echo>x is ${x}</echo>

将输出 x is j.java.bak,并且

<pathconvert property="x" targetos="unix">
  <path path="d/e/f/j.java"/>
  <mapper>
    <globmapper from="${basedir}\d/e\*" to="*" handledirsep="yes"/>
  </mapper>
</pathconvert>
<echo>x is ${x}</echo>

将输出 x is f/j.java

regexp

tofrom 都需要,并定义正则表达式。如果源文件名(全部或部分)与 from 模式匹配,则将从 to 模式构建目标文件名,使用 \0\9 作为对完整匹配(\0)或圆括号中子表达式的匹配的回溯引用。 to 模式确定整个文件名,因此如果您想替换文件的扩展名,则不应使用 from="\.old$" to=".new",而应使用 from="(.*)\.old$" to="\1.new"(或者在这种情况下使用 glob 映射器)。

不匹配 from 模式的源文件将被忽略。

请注意,您需要在 Ant 中使用另一个美元符号 ($) 来转义美元符号。

有关在 Ant 中使用 gnu.regexpgnu.rex 的信息,请参阅 本文。请记住,您的里程可能会有所不同,具体取决于不同的正则表达式引擎。

如果您想使用除 java.util.regex 之外的 正则表达式库 之一,您还需要使用您正在使用的 Ant 版本中的相应 ant-[apache-oro, apache-regexp].jar。确保两者都从同一个类路径加载,也就是说,要么将它们放在您的 CLASSPATHANT_HOME/lib 目录或映射器的嵌套 <classpath> 元素中——您不能将 ant-[apache-oro, apache-regexp].jar 放在 ANT_HOME/lib 中,并将库放在嵌套的 <classpath> 中。

Ant 将根据以下算法选择正则表达式库

示例
<mapper type="regexp" from="^(.*)\.java$$" to="\1.java.bak"/>
<regexpmapper from="^(.*)\.java$$" to="\1.java.bak"/>
源文件名 目标文件名
A.java A.java.bak
foo/bar/B.java foo/bar/B.java.bak
C.properties 忽略
Classes/dir/dir2/A.properties 忽略
<mapper type="regexp" from="^(.*)/([^/]+)/([^/]*)$$" to="\1/\2/\2-\3"/>
<regexpmapper from="^(.*)/([^/]+)/([^/]*)$$" to="\1/\2/\2-\3"/>
源文件名 目标文件名
A.java 忽略
foo/bar/B.java foo/bar/bar-B.java
C.properties 忽略
Classes/dir/dir2/A.properties Classes/dir/dir2/dir2-A.properties
<mapper type="regexp" from="^(.*)\.(.*)$$" to="\2.\1"/>
<regexpmapper from="^(.*)\.(.*)$$" to="\2.\1"/>
源文件名 目标文件名
A.java java.A
foo/bar/B.java java.foo/bar/B
C.properties properties.C
Classes/dir/dir2/A.properties properties.Classes/dir/dir2/A
<mapper type="regexp" from="^(.*?)(\$$[^/\\\.]*)?\.class$$" to="\1.java"/>
<regexpmapper from="^(.*?)(\$$[^/\\\.]*)?\.class$$" to="\1.java"/>
源文件名 目标文件名
ClassLoader.class ClassLoader.java
java/lang/ClassLoader.class java/lang/ClassLoader.java
java\lang\ClassLoader$1.class java\lang\ClassLoader.java
java/lang/ClassLoader$foo$1.class java/lang/ClassLoader.java

regexp 映射器可以接受以下额外属性。

属性 描述 必需
casesensitive 此属性可以是 truefalse。如果为 false,则映射器在匹配模式时将忽略大小写。从 Ant 1.6.3 开始 否;默认值为 true
handledirsep 此属性可以是 truefalse。如果指定此属性,则映射器将把文件名中的 \ 字符视为匹配目的的 /。此属性对于跨平台构建文件很有用。从 Ant 1.6.3 开始否;默认值为 false

一个例子

<pathconvert property="x" targetos="unix">
  <path path="Aj.Java"/>
  <chainedmapper>
    <flattenmapper/>
    <regexpmapper from="a(.*)\.java" to="\1.java.bak" casesensitive="no"/>
  </chainedmapper>
</pathconvert>
<echo>x is ${x}</echo>

将输出 x is j.java.bak,并且

<pathconvert property="hd.prop" targetos="windows">
  <path path="d\e/f\j.java"/>
  <chainedmapper>
    <regexpmapper from="${basedir}/d/e/(.*)" to="\1" handledirsep="yes"/>
  </chainedmapper>
</pathconvert>

hd.prop 设置为 f\j.java

package

glob 映射器 共享相同的语法,包映射器用匹配的源模式中找到的点替换目标模式占位符中的目录分隔符。此映射器与 <uptodate><junit> 输出结合使用特别有用。

tofrom 属性都是必需的。

示例
<mapper type="package" from="*Test.java" to="TEST-*Test.xml"/>
<packagemapper from="*Test.java" to="TEST-*Test.xml"/>
源文件名 目标文件名
org/apache/tools/ant/util/PackageMapperTest.java TEST-org.apache.tools.ant.util.PackageMapperTest.xml
org/apache/tools/ant/util/Helper.java 忽略

unpackage

从 Ant 1.6.0 开始

此映射器是 package 映射器的逆映射器。它用目录分隔符替换包名称中的点。这对于将 XML 格式化程序结果与它们的 JUnit 测试测试用例进行匹配很有用。映射器与 glob 映射器 共享示例语法。

tofrom 属性都是必需的。

示例
<mapper type="unpackage" from="TEST-*Test.xml" to="${test.src.dir}/*Test.java">
<unpackagemapper from="TEST-*Test.xml" to="${test.src.dir}/*Test.java">
源文件名 目标文件名
TEST-org.acme.AcmeTest.xml ${test.src.dir}/org/acme/AcmeTest.java

composite

从 Ant 1.7.0 开始

此映射器实现可以包含多个嵌套映射器。文件映射是通过依次将源文件名传递给每个嵌套的 <mapper> 来执行的,并返回所有结果。 tofrom 属性将被忽略。

从 Ant 1.8.0 开始,映射结果的顺序与嵌套映射器的顺序相同;在 Ant 1.8.0 之前,顺序是未定义的。

示例
<compositemapper>
  <identitymapper/>
  <packagemapper from="*.java" to="*"/>
</compositemapper>
源文件名 目标文件名
foo/bar/A.java foo/bar/A.java
foo.bar.A

复合映射器没有相应的 <mapper> type 属性。

chained

从 Ant 1.7.0 开始

此映射器实现可以包含多个嵌套映射器。文件映射是通过将源文件名传递给第一个嵌套映射器、将结果传递给第二个映射器,依此类推来执行的。最后一个嵌套映射器生成的 target 文件名构成了映射操作的最终结果。 tofrom 属性将被忽略。

示例
<chainedmapper>
  <flattenmapper/>
  <globmapper from="*" to="new/path/*"/>
  <mapper>
    <globmapper from="*" to="*1"/>
    <globmapper from="*" to="*2"/>
  </mapper>
</chainedmapper>
源文件名 目标文件名
foo/bar/A.java new/path/A.java1
new/path/A.java2
boo/far/B.java new/path/B.java1
new/path/B.java2

链式映射器没有相应的 <mapper> type 属性。

filtermapper

从 Ant 1.6.3 开始

此映射器实现将 filterchain 应用于源文件名。

示例
<filtermapper>
  <replacestring from="\" to="/"/>
</filtermapper>
源文件名 目标文件名
foo\bar\A.java foo/bar/A.java
<filtermapper>
  <scriptfilter language="beanshell">
    self.setToken(self.getToken().toUpperCase());
  </scriptfilter>
</filtermapper>
源文件名 目标文件名
foo\bar\A.java FOO\BAR\A.JAVA

filtermapper 没有相应的 <mapper> type 属性。

scriptmapper

从 Ant 1.7 开始

此映射器执行用 Apache BSFJSR 223 支持的语言编写的脚本,每个文件映射一次。

脚本可以在内联或在指定的文件中声明。

有关脚本和依赖项的说明,请参阅 脚本 任务。

属性 描述 必需
language 脚本语言
manager 要使用的脚本引擎管理器。有关使用此属性的信息,请参阅 script 任务。 否;默认值为 auto
src 包含脚本的文件
encoding 脚本作为文件的编码。自 Ant 1.10.2 起 否;默认为默认 JVM 字符编码
setbeans 是否将所有属性、引用和目标作为脚本中的全局变量。自 Ant 1.8.0 起 否;默认值为 true
classpath 传递到脚本的类路径。
classpathref 要使用的类路径,作为对在其他地方定义的路径的 引用 给出。

此文件名映射器可以接受嵌套的 <classpath> 元素。有关如何使用此元素,请参阅 script 任务。

示例
<scriptmapper language="javascript">
  self.addMappedName(source.toUpperCase());
  self.addMappedName(source.toLowerCase());
</scriptmapper>
源文件名 目标文件名
foo\bar\A.java FOO\BAR\A.JAVA
foo\bar\a.java

要使用此映射器,脚本需要访问源文件,并且能够返回多个映射。以下是相关的 bean 及其方法。脚本针对每个源文件调用一次,每次调用后映射名称列表都会重置。

脚本 bean 描述
source: String 要映射的文件/路径
self 脚本映射器本身
self.addMappedName(String name) 添加新的映射
self.clear() 重置文件列表

脚本映射器没有相应的 <mapper> type 属性。

firstmatchmapper

自 Ant 1.8.0 起

此映射器支持任意数量的嵌套映射器,并返回第一个匹配的映射器的结果。这与 复合映射器 不同,后者收集所有匹配子级的结果。

示例
<firstmatchmapper>
  <globmapper from="*.txt" to="*.bak"/>
  <globmapper from="*A.*" to="*B.*"/>
</firstmatchmapper>
源文件名 目标文件名
foo/bar/A.txt foo/bar/A.bak
foo/bar/A.java foo/bar/B.java

firstmatchmapper 没有相应的 <mapper> type 属性。

cutdirsmapper

自 Ant 1.8.2 起

此映射器从源文件名中剥离配置数量的前导目录。

示例
<cutdirsmapper dirs="1"/>
源文件名 目标文件名
foo/bar/A.txt bar/A.txt

cutdirsmapper 没有相应的 <mapper> type 属性。

属性 描述 必需
dirs 要剥离的目录数量(必须为正数)。