读书人

特征与DataType

发布时间: 2012-09-10 22:20:13 作者: rapoo

特性与DataType
特性有两个特点,它们是不可变的,而且不论在哪里定义,总是属于全局作用域。
不可变说明一旦ant首次处理了键值对,那么这个特性值就不能变了。特性有优先顺序。在ant命令行通过参数传递进去的级别高于其他位置定义的特性。
随后,ant会根据其首次发现的特性声明,来作为第一级的特性。



<?xml version="1.0" encoding="utf-8"?>
<project name="测试" default="all" basedir=".">
<property name="one" value="${two}:one" />
<property name="two" value="two" />
<target name="all" description="所有操作,执行顺序是:clean, compile, jar">
<echo message="one=${one}" />
<echo message="${two}" />
</target>
</project>
运行结果:
D:\source\liyixing\ant>d:\soft\liyixing\ant\apache-ant-1.8.2\bin\ant
Buildfile: D:\source\liyixing\ant\build.xml

all:
[echo] one=${two}:one
[echo] two

BUILD SUCCESSFUL
Total time: 0 seconds
这里可以看到one的结果是${two}:one,而不是two:noe
这里有两个原因
因为ant的有加载顺序要确定特性的。它首先处理的是one,而one的时候two还不存在,ant对不存在的变量应用会输出${propertyname}。


DataType
argument,对于由一个ant构建文件调用的程序,向其传递参数
environment,对于一个ant构件文件调用的外部命令或程序,向其传递环境变量。
filelist,定义一个文件的命名列表,这些文件无需存在。
fileset,定义一个文件的命名列表,这些文件必须存在。
patternset(模式),将一组模式分组在一起。
filterset,将一组过滤器分组在一起。
path以某种在不同操作系统间可以移植的方式指定路径。
mapper定义一组输入文件和一组输出文件间的复杂关系。

ant的DataType实现在org.apache.tools.ant.types包中。由org.apache.tools.ant.types.DataType基类派生。EnumeratedAttribute和Commandline和Environment和Reference也被看做是DataType。但他们不是DataType派生。

org.apache.tools.ant.ProjectComponent提供了日志功能,还能访问Project对象。ProjectComponent是各个ant任务的基类。

属性类型:
boolean 完成不区分大小写的字符串比较,将on,true,yes转换成true。其他转换成false
Enum org.apache.tools.ant.types.EnumeratedAttribute实现,用于允许有固定的字符串值集合的情况
File java.io.File指定某个文件或目录的名字。除非另外做说明,否则文件和目录名都相对于项目基目录。
int,long java.lang.Integer和java.lang.Long包装类会处理
Path org.apahce.tools.ant.types.Path常用于classpath和sourcepath属性。用;或者:分隔路径列表。
Reference org.apache.tools.ant.types.Reference 常用于refid属性。对某个类型的id的应用。
String java.lang.String这是ant使用最多的。需要符合xml规范。如>符号需要写成$gt;

argument
<arg>元素由org.apache.tools.ant.types.Commandline.Argument类实现这个DataType
apply exec java任务都接受arg子元素。可以为他们传递参数。
具有的属性
file 作为一个参数的文件名。在构件文件中,此文件名相对于当前的工作目录。在传递过去前,会被转换成一个绝对路径。

line用空格分隔的多个参数的列表

path路径

value一个命令行参数。如果参数中有空格,需要使用这个属性传递。使用line,空格会被解析成多个参数。
每一个arg元素中,上面的属性有且只有一个。

测试
test类
/**
* test
* */
package test;

public class Test{
public static void main(String[] args) {
for(String arg : args) {
System.out.println("arg=" + arg);
}
}
}

<?xml version="1.0" encoding="utf-8"?>
<project name="arg元素测试" default="run" basedir=".">
<property name="run.dir" value="bin" />
<property name="result" value="Family Tree.html" />

<path id="project.class.path">
<pathelement location="${run.dir}" />
</path>

<target name="clean">
<delete file="${result}" />
</target>

<target name="run" description="运行">
<echo message="开始运行" />
<java fork="true" classname="test.Test" failonerror="true">
<arg line="-IN test" />
<arg file="build.xml" />
<arg value="to to to" />
<arg path="build.xml;/build.xml" />
<classpath refid="project.class.path" />
</java>
<echo message="运行结束" />
<tstamp />
<echo message="时间:${TSTAMP}" />
</target>
</project>
运行结果
D:\source\liyixing\ant>d:\soft\liyixing\ant\apache-ant-1.8.2\bin\ant
Buildfile: D:\source\liyixing\ant\build.xml

run:
[echo] 开始运行
[java] arg=-IN
[java] arg=test
[java] arg=D:\source\liyixing\ant\build.xml
[java] arg=to to to
[java] arg=D:\source\liyixing\ant\build.xml;D:\build.xml
[echo] 运行结束
[echo] 时间:1605

BUILD SUCCESSFUL
Total time: 0 seconds
可以看出来
属性
line="-IN test"被解析成了两个参数
file="build.xml"传递进去的结果是D:\source\liyixing\ant\build.xml,绝对路径。
value="to to to"被当做一个参数传递
path="build.xml;/build.xml"被解析成了D:\source\liyixing\ant\build.xml;D:\build.xml,在unix中会被解析成
/source/liyixing/ant/(这部分是当前目录)build.xml:/build.xml


environment DataType
对于系统命令的
apply和exec任务,需要0或多个env元素。这个元素指定哪些系统环境要传递给正在执行的系统命令。由 org.apache.tools.ant.types.Environment.Variable类实现。
属性:
file,文件,会被转换成绝对路径
key,必须,环境变量名
path,ant会把它转换成一个本地约定。
value,环境变量的一个直接量值
file,path,value只取其一

测试
编写test.bat
echo off
echo JAVA_HOME = %JAVA_HOME%

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<property name="run.dir" value="bin" />
<property name="result" value="Family Tree.html" />
<property name="JAVA_HOME" value="java-home" />

<path id="project.class.path">
<pathelement location="${run.dir}" />
</path>

<target name="clean">
<delete file="${result}" />
</target>

<target name="run" description="运行">
<echo message="开始运行" />
<java fork="true" classname="test.Test" failonerror="true">
<arg line="-IN test" />
<arg file="build.xml" />
<arg value="to to to" />
<arg path="build.xml;/build.xml" />
<classpath refid="project.class.path" />
</java>

<exec executable="test.bat">
<env key="JAVA_HOME" value="${JAVA_HOME}" />
</exec>

<echo message="运行结束" />
<tstamp />
<echo message="时间:${TSTAMP}" />
</target>
</project>
<!--
<target name="prepare">
<mkdir dir="${build.dir}" />
<mkdir dir="${build.classes}" />
</target>

<target name="clean" description="删除build目录">
<delete dir="${build.dir}" />
</target>

<target name="compile" description="编译" depends="prepare">
<javac srcdir="${src.dir}" destdir="${build.classes}" />
</target>

<target name="jar" description="打包" depends="prepare">
<echo message="${debug.flag}" />
</target>

<target name="all" description="所有操作,执行顺序是:clean, compile, jar" depends="clean, compile, jar">
<javac srcdir="${src.dir}" destdir="${build.classes}" />
</target>-->
运行结果
D:\source\liyixing\ant>d:\soft\liyixing\ant\apache-ant-1.8.2\bin\ant
Buildfile: D:\source\liyixing\ant\build.xml

run:
[echo] 开始运行
[java] arg=-IN
[java] arg=test
[java] arg=D:\source\liyixing\ant\build.xml
[java] arg=to to to
[java] arg=D:\source\liyixing\ant\build.xml;D:\build.xml
[exec]
[exec] D:\source\liyixing\ant>echo off
[exec] JAVA_HOME = java-home
[echo] 运行结束
[echo] 时间:1619

BUILD SUCCESSFUL
Total time: 1 second
上面是自己设置的环境值,可以访问系统环境

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<property name="run.dir" value="bin" />
<property name="result" value="Family Tree.html" />
<property environment="env" />
<property name="JAVA_HOME" value="${env.JAVA_HOME}" />

<path id="project.class.path">
<pathelement location="${run.dir}" />
</path>

<target name="clean">
<delete file="${result}" />
</target>

<target name="run" description="运行">
<echo message="开始运行" />
<java fork="true" classname="test.Test" failonerror="true">
<arg line="-IN test" />
<arg file="build.xml" />
<arg value="to to to" />
<arg path="build.xml;/build.xml" />
<classpath refid="project.class.path" />
</java>

<exec executable="test.bat">
<env key="JAVA_HOME" value="${JAVA_HOME}" />
</exec>

<echo message="运行结束" />
<tstamp />
<echo message="时间:${TSTAMP}" />
</target>
</project>
这里的
<property environment="env" />
将系统环境变量定义在env中。
通过env.xxx访问,结果
D:\source\liyixing\ant>d:\soft\liyixing\ant\apache-ant-1.8.2\bin\ant
Buildfile: D:\source\liyixing\ant\build.xml

run:
[echo] 开始运行
[java] arg=-IN
[java] arg=test
[java] arg=D:\source\liyixing\ant\build.xml
[java] arg=to to to
[java] arg=D:\source\liyixing\ant\build.xml;D:\build.xml
[exec]
[exec] D:\source\liyixing\ant>echo off
[exec] JAVA_HOME = C:\Program Files\Java\jdk1.6.0_22
[echo] 运行结束
[echo] 时间:1624

BUILD SUCCESSFUL
Total time: 1 second

filelist DataType
org.apache.tools.ant.types.FileList,文件无需真正存在。
属性:
dir用于计算绝对文件名的路径
files用逗号分隔的文件名列表
refid对某处定义的filelist的应用。
在没有指定refid的情况下,dir和files是必须的。而指定了的话,files和dir就不能使用。

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />
<target name="run">
<dependset>
<srcfilelist refid="needFiles" />
<srcfilelist refid="moreFiles" />
<targetfilelist dir="." files="d.txt" />
</dependset>
<tstamp />
<echo message="时间:${TSTAMP}" />
</target>
</project>
<targetfilelist dir="." files="d.txt" />这里也可以使用refid。只是因为一个文件,使用files属性更方便。


fileset DataType
文件必须存在。fileset还可能指定为目标级构建文件元素(<project>的子元素)并由其id引用(refid)。
属性
dir,必须,fileset的基目录
casesensitive如果是false,那么文件不区分大小写。默认值是true
defaultexcludes是否使用默认的排除模式。默认是true。默认的排除模式会排除文件:**/*~ **/#*# **/%*% **/CVS **/CVS/** **/.cvsignore **/SCCS **/SCCS/** **/vssver.scc
excludes用逗号分隔,需要排除的文件模式劣币哦啊。
excludesfile每行包括一个排除模式的文件的文件名。
includes用逗号分隔的需要包含的文件模式列表
includesfile每行包括一个包含模式的文件的文件名
另外它也可以包含
0-n个<patternset>元素,patternset元素可以包含。<exclude>元素,<include>元素,<excludesfile>元素,<includesfile>元素。或者直接写<exclude>元素,<include>元素,<excludesfile>元素,<includesfile>元素
<fileset id="source1" dir="src" include="**/*.java" excludes="**/test/**/*.java">
</fileset>

<fileset id="source2" dir="src">
<include name="**/*.java" />
<exclude name="*/test/**/*.java" />
</fileset>

fileset id="source3" dir="src">
<patternset>
<include name="**/*.java" />
<exclude name="*/test/**/*.java" />
</patternset>
</fileset>

<patternset id="patternset.source1">
<include name="**/*.java" />
<exclude name="*/test/**/*.java" />
</patternset>
fileset id="source4" dir="src">
<patternset refid="patternset.source1" />
</fileset>

包含和排除的模式语法
*与0个或多个字符匹配。*.java可以与任何以java结尾的文件

?与1个字符相匹配。File?.Java,可以和FileA.java匹配,但是不和FileTest.java,因为?字匹配一个字符。

**与0个或多个目录相匹配(包括子目录)。/xml/**与/xml/下的所有目录和文件都匹配。

匹配模式可以结合
com/oreilly/**/*Test.java可以匹配
com/oreilly/antbook/AccountTest.java
com/oreilly/BTest.java
com/oreilly/service/CTest.java

patternset DataType
fileset是对文件的分组。而patternset是对模式的分组。fileset依赖于选择文件的模式。它可以作为目标级(project子元素)构建文件元素出现。也可以作为fileset的一个嵌套元素出现。
属性
includes,excludes,includesfile,excludesfile和fileset的属性类似。

另外它还可以包含
include元素
exclude元素
他们都支持如下属性
name 匹配的模式
if特性名。只在设置了该特性时,ant才使用此模式。
unless特性名。只在未设置该特性时ant才使用此模式。

包含includesfile和excludesfile
他们支持属性
name类似,每行一个模式
if类似
unless类似

实例
<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />
<target name="run">
<echo message="开始" />
<copy todir="copy">
<fileset dir="." includes="1.txt, 2.txt"/>
</copy>
<tstamp />
<echo message="时间:${TSTAMP}" />
<echo message="结束" />
</target>
</project>
会把1.txt和2.txt拷贝到copy目录

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />

<patternset id="copyFiles">
<include name="**/*.txt" />
</patternset>
<target name="run">
<echo message="开始" />
<copy todir="copy">
<fileset dir=".">
<patternset refid="copyFiles" />
</fileset>
</copy>
<tstamp />
<echo message="时间:${TSTAMP}" />
<echo message="结束" />
</target>
</project>
拷贝所有txt文件到copy目录

有选择的

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />

<patternset id="copyFiles">
<include name="**/*.txt" />
<exclude name="**/*t.txt" unless="includetests" />
</patternset>
<target name="run">
<echo message="开始" />
<copy todir="copy">
<fileset dir=".">
<patternset refid="copyFiles" />
</fileset>
</copy>
<tstamp />
<echo message="时间:${TSTAMP}" />
<echo message="结束" />
</target>
</project>
在没有定义属性includetests的时候可以看到结果没有把*t.java拷贝过去。
而当我定义了includetests,
<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />

<patternset id="copyFiles">
<include name="**/*.txt" />
<exclude name="**/*t.txt" unless="includetests" />
</patternset>
<target name="run">
<echo message="开始" />
<copy todir="copy">
<fileset dir=".">
<patternset refid="copyFiles" />
</fileset>
</copy>
<tstamp />
<echo message="时间:${TSTAMP}" />
<echo message="结束" />
</target>
</project>
会把*t.java也拷贝过去了。

filterset DataType
ant1.4支持。定义一组过滤器。这些过滤器由filter任务实现。将在文件移动或者复制的时候完成文件中的文本替换。
由filterset元素表示。可以作为copy或者move任务中的内容出现或者作为目标级构建文件出现(作为project元素的子元素出现)
属性
beginoken,对于嵌套过滤器所搜索的记号。这是标识其开始的字符串。默认@
endtoken,对于嵌套过滤器所搜索的记号。这是标识其结束的字符串。默认@
id,此过滤器的唯一标识符。
refid,对构建文件中某处定义的一个过滤器的引用。

filterset还可以包含以下子元素
0-N个filter
token必须,指定要替换的记号,不包括定界符。如果此过滤器要替换@VERSION@,则将VERSION作为此属性值。

value必须,指定遇到记号时的替换文本。
0-N个<filtersfile>
每个元素指定一个java特性文件,由此可加载另外的过滤器。此文件格式是每一行一个记号,其后面为一个冒号(;)或者等于号(=)。再后面是一个值。
属性
file必须,包含过滤器的特性文件的文件名。


<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<patternset id="copyFiles">
<include name="**/*.txt" />
<exclude name="build/*.*" unless="includetests" />
</patternset>

<target name="run">
<echo message="开始" />
<tstamp>
<format property="starttime" pattern="yyyy-MM-dd hh:mm:ss" />
</tstamp>
<echo message="时间:${starttime}" />

<copy todir="build" filtering="true">
<fileset dir=".">
<patternset refid="copyFiles" />
</fileset>

<filterset begintoken="%" endtoken="!">
<filter token="BUILD_DATE" value="${starttime}" />
<filter token="COPYRIGHT" value="李义星" />
</filterset>
</copy>

<echo message="结束" />
<tstamp>
<format property="endtime" pattern="yyyy-MM-dd hh:mm:ss" />
</tstamp>
<echo message="时间:${endtime}" />
</target>
</project>
<!--
<filelist id="needFiles" dir="." files="1.txt, 2.txt, 3.txt" />
<filelist id="moreFiles" dir="." files="4.txt" />

<patternset id="copyFiles">
<include name="**/*.txt" />
<exclude name="**/*t.txt" unless="includetests" />
</patternset>
<target name="run">
<echo message="开始" />
<copy todir="copy">
<fileset dir=".">
<patternset refid="copyFiles" />
</fileset>
</copy>
<tstamp />
<echo message="时间:${TSTAMP}" />
<echo message="结束" />
</target>
-->
<!--
<property name="run.dir" value="bin" />
<property name="result" value="Family Tree.html" />
<property environment="env" />
<property name="JAVA_HOME" value="${env.JAVA_HOME}" />

<path id="project.class.path">
<pathelement location="${run.dir}" />
</path>

<target name="clean">
<delete file="${result}" />
</target>

<target name="run" description="运行">
<echo message="开始运行" />
<java fork="true" classname="test.Test" failonerror="true">
<arg line="-IN test" />
<arg file="build.xml" />
<arg value="to to to" />
<arg path="build.xml;/build.xml" />
<classpath refid="project.class.path" />
</java>

<exec executable="test.bat">
<env key="JAVA_HOME" value="${JAVA_HOME}" />
</exec>

<echo message="运行结束" />
<tstamp />
<echo message="时间:${TSTAMP}" />
</target>
-->
<!--
<target name="prepare">
<mkdir dir="${build.dir}" />
<mkdir dir="${build.classes}" />
</target>

<target name="clean" description="删除build目录">
<delete dir="${build.dir}" />
</target>

<target name="compile" description="编译" depends="prepare">
<javac srcdir="${src.dir}" destdir="${build.classes}" />
</target>

<target name="jar" description="打包" depends="prepare">
<echo message="${debug.flag}" />
</target>

<target name="all" description="所有操作,执行顺序是:clean, compile, jar" depends="clean, compile, jar">
<javac srcdir="${src.dir}" destdir="${build.classes}" />
</target>-->

1.txt
%BUILD_DATE!
%COPYRIGHT!

拷贝后
2011-05-14 08:51:32
李义星
上面的copy任务的filtering设置为true,以确保filter开启。

path DataType
它既可以作为一个属性存在,也可以作为一个嵌套的元素存在。用作属性的时候,应该使用分号;或者冒号:分隔多个路径。这个路径会被代替为平台所用的路径分隔符,windows是分号;,而linux则是冒号:,这个是ant自动判断的。

属性
location 表示一个文件或者目录。ant会自动生成为绝对路径
path一个文件的路径名列表,使用;或者:分隔
refid引用当前构建文件中某处定义的path
如果指定了refid属性,location和path就不能使用。切其内部就不能出现嵌套元素。而不使用refid,location和path需要选择一个。

它还支持嵌套元素:
pathelement
包含一个或多个的path中的文件。每个pathelement也有location和path属性。

fileset元素
提供将文件包含在path中的另一种方法。
<path>
<pathelement location="xxx.jar" />
<pathelement path="aaa.jar" />
</path>

<path>
<pathelement location="xxx.jar" />
<pathelement path="aaa.jar;bbb.jar;ccc.jar" />
</path>

还支持一种简写方法
<classpath>
<pathelement path="${builddir}\aaa.jar;bbb.jar;ccc.jar" />
</classpath>

<classpath path="${builddir}\aaa.jar;bbb.jar;ccc.jar">
</classpath>
嵌套fileset的情况
<classpath>
<pathelement path="${builddir}\aaa.jar;bbb.jar;ccc.jar" />
<fileset dir="${lib}" includes="**\*.jar" />
</classpath>

mapper DataType
ant 1.3
定义了一组源文件和一组目标文件如何关联。
属性:
classname,实现mapper类的类名。可以用来定义自己的mapper实现。
classpath,查找定制的mapper实现的类路径
classpathref,对某处定义的一个类路径的引用。
from,此属性含义取决与mapper的实现。
refid,对另一个mapper的引用。如果指定了refid,则不能出现其他属性。
to,取决与mapper的实现
type,可选值为identity,flatten,glob,merge,或者regexp中的一个。要使用的内置mapper的类型。
type和classname必须选择一个。其他的像form和to由mapper的实现决定。

<?xml version="1.0" encoding="utf-8"?>
<project name="DataType 测试" default="run" basedir=".">
<tstamp>
<format property="now" pattern="yyyy-MM-dd-hh-mm-ss" />
</tstamp>
<mapper id="backupMapper" type="glob" from="*.java" to="*-${now}.java.bak" />

<target name="clean">
<delete dir="backup" />
</target>

<target name="prepare">
<mkdir dir="bak" />
</target>

<target name="run" depends="clean,prepare">
<echo message="开始" />
<tstamp>
<format property="starttime" pattern="yyyy-MM-dd hh:mm:ss" />
</tstamp>
<echo message="时间:${starttime}" />

<copy todir="backup" filtering="true">
<fileset dir="src" includes="**/*.java" />
<mapper refid="backupMapper" />
</copy>

<echo message="结束" />
<tstamp>
<format property="endtime" pattern="yyyy-MM-dd hh:mm:ss" />
</tstamp>
<echo message="时间:${endtime}" />
</target>
</project>
我在src目录下面有一个Test.java
运行后的结果是在backup目录有一个新的文件生成
Test-2011-05-14-09-26-04.java.bak

当文件被删除或者复制的时候,会被按照mapper指定的模式命名。
这里使用的是glob mapper

identity mapper
将源文件与目标文件匹配。这是copy任务所使用的默认mapper。
这个mapper复制的同时,会把目录结构也复制进去。

flatten mapper
从文件名中删除所有的路径信息。
像glob,identity mapper都会把目录结构也复制进去。而flatten则不会

glob mapper基于简单的通配符模式。to和from都最多可以出现一个*符号。当源文件名与from模式匹配时,即生成目标文件。to的*会被from的*所匹配的字符替换。

merge mapper
这个不知。

regexp mapper
类似glob的mapper。支持正则。正则的语法由底层使用的正则表达式库决定。

ant包含了实现一下正则库的类
jse
jakarta-regexp
jakarta-ORO

读书人网 >软件开发

热点推荐