ANT 任务 - 多个文件 - 循环
ANT task - multiple files - loop through
我有相当复杂的蚂蚁任务要写。我不得不制作单独的构建文件,剩下 1 个。
有 4 个文件:
buildpackage.bat, buildpackage.xml, buildpackage.txt, structure.xml
buildpackage.bat只是一个调用buildpackage.xml "ant -f buildpackage.xml"
的ant文件。那也行。
buildpackage.txt 很简单并且有逗号分隔的行:
server1,client1
server2,client2
genericserver,client[x]
server[x],client[x]
总是有服务器名称和客户端名称:
Server name
只能是字母、数字和字母,但长度可变。
Client name
- 仅限字母。
我需要将这些文件拆分为 2 个单独的变量:server.name
和 client.name
。
我所做的是:
<loadfile property="buildpackage" srcFile="buildpackage.txt"/>
<for list="${buildpackage}" param="depl.det" delimiter="${line.separator}">
<sequential>
<echo>
Input: @{deploy.details}
</echo>
</sequential>
</for>
我得到的结果是:
[echo] Input: server_01,Client_01
[echo] Input: server_02,Client_02
[echo] Input: server_03,Client_03
[echo] Input: clientserver,client_04
我希望 server_01 成为参数 1,client_02 成为参数 2。
我会按顺序执行其他任务。我会将文件从 client[x] 目录复制到 server[x](这很简单,但我如何将该字符串拆分为 2 个单独的变量?)。
现在是非常复杂的任务。
我还有 structure.xml 文件。结构是:
<core>
<clients>
<client>
<name>Client_01</name>
<branding>brand_01</branding>
<applications>
<application>application_01</application>
</applications>
<solutions>
<solution>solution01</solution>
</solutions>
</client>
<client>
<name>Client_07</name>
<branding>brand_09</branding>
<applications>
<application>application_03</application>
</applications>
<solutions>
<solution>solution01</solution>
<solution>solution07</solution>
<solution>solution08</solution>
</solutions>
</client>
<clients>
<core>
我有很多客户、应用程序、品牌和解决方案。每个客户只能有 1 个应用程序和 1 个品牌,但可以有多个解决方案。
基于之前的顺序任务(获取服务器和名称),我必须遍历 xml 文件并为每个匹配的客户端获取(来自之前的任务)
- branding
- application
- solutions (multiple or one)
我可以使用 <xmlproperty>
读取 XML,但我不知道如何按顺序读取(迭代)并获得匹配的属性。
我知道这很复杂。摘要是:
- 构建脚本开始
- 构建脚本从 buildpackage.txt 提取数据作为 client.name 和 server.name
- 构建脚本从步骤 2 中获取
${client.name}
作为参数并循环遍历 structure.xml。它找到匹配的 branding/application/solutions 并为每个匹配的客户端输出它。
输出:
server.name
client.name
branding.name
application name
solution [X]
solution [y]
每个 server/client 都必须处理 Ant。如果我有属性,我可以完成其余的构建和编译。我不能碰 structure.xml。我可以尽我所能 need/want 到 buildpackage.cml 和 buildpackge.txt。 Buildpackage.txt 可以替换为 .xml 文件或任何文件(例如 .properties)。它必须包含这 2 个值服务器和客户端。
感谢您的帮助。
编辑
现在我有一个问题。
如果我将相同的应用程序 2x 放入构建文件中,它只会构建第一个。
这是我的 build.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<project name="DoTheJob" basedir="." xmlns:ac="antlib:net.sf.antcontrib" xmlns:if="ant:if" xmlns:unless="ant:unless">
<!-- Define classpath and default locations-->
<property name="root.dir" location="../.."/>
<property name="dest.dir" location="packages"/>
<property name="ant.lib.dir" location="../lib"/>
<property name="repository_url" value="http://repository-url"/>
<path id="project.classpath">
<fileset dir="${ant.lib.dir}">
<include name="*.jar"/>
</fileset>
<fileset dir="${root.dir}/IIT/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="../savedjar/compiled.jar"/>
</path>
<path id="svnant.path">
<fileset dir="../lib/">
<include name="svnant.jar"/>
<include name="svnClientAdapter.jar"/>
</fileset>
</path>
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.path" />
<tstamp>
<format property="build_time" pattern="YYYY MMMM dd HH:mm:ss"/>
</tstamp>
<!-- Change characters to lowercase -->
<scriptdef language="javascript" name="lowercase">
<attribute name="string" />
<attribute name="to" />
project.setProperty(attributes.get("to"),attributes.get("string").toLowerCase());
</scriptdef>
<!-- Import XMLTask for XML transformations-->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask" classpathref="project.classpath"/>
<!-- Define buildfiles locations-->
<property name="structure.file" location="../structure.xml"/>
<property name="buildpackage.file" location="buildpackage.txt"/>
<!-- load client/server file-->
<property file="${buildpackage.file}"/>
<!-- loop over all clients -->
<xmltask source="${structure.file}">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<actions>
<!-- loop through all XML properties only when @{client} condition is matched -->
<ac:if>
<isset property="@{client}"/>
<then>
<echo>=====================================================</echo>
<echo>Building package for @{client} on ${@{client}} </echo>
<echo>=====================================================</echo>
<!-- creating destination directories -->
<delete dir="${build.dir}/@{client}"/>
<mkdir dir="${dest.dir}/@{client}"/>
<echo>=====================================================</echo>
<echo>Copy application files code/temaplates to destination</echo>
<echo>=====================================================</echo>
<!-- creating code build directory -->
<mkdir dir="${dest.dir}/@{client}/code"/>
<!-- copy application code -->
<echo>copy application code</echo>
<copy todir="${dest.dir}/@{client}/code/application/@{application}" overwrite="yes">
<fileset dir="${root.dir}/client-source/application/@{application}" includes="**/*.*"/>
</copy>
<!-- copy application templates -->
<mkdir dir="${dest.dir}/@{client}/app/@{client}"/>
<echo>copy application templates</echo>
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/apps/@{application}" includes="**/*.*"/>
</copy>
<echo>===================================================</echo>
<echo>copy Solutions files code/temaplates to destination</echo>
<echo>===================================================</echo>
<!-- nested xmltask for loop over solutions -->
<xmltask source="${structure.file}">
<call path="/core/clients/client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<!-- making sure that solution is lowercase -->
<lowercase string="@{solution}" to="solution.lowercase" />
<echo>copy solutions code</echo>
<!-- copy solutions code -->
<copy todir="${dest.dir}/@{client}/code/solutions/${solution.lowercase}" overwrite="yes">
<fileset dir="${root.dir}/client-source/solutions/${solution.lowercase}" includes="**/*.*"/>
</copy>
<!-- copy solutions templates -->
<echo>copy Solutions templates</echo>
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/solutions/${solution.lowercase}" includes="**/*.*"/>
</copy>
</actions>
</call>
</xmltask>
<echo>==============================================</echo>
<echo>copy Client files code/temaplates to destination</echo>
<echo>==============================================</echo>
<!-- copy branding directory -->
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/brandings/@{branding}" includes="**/*.*"/>
</copy>
<!-- copy client code -->
<copy todir="${dest.dir}/@{client}/code/client/@{client}" overwrite="yes">
<fileset dir="${root.dir}/client-source/client/@{client}" includes="**/*.*"/>
</copy>
<!-- set templates directory -->
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/clients/@{client}" includes="**/*.*"/>
</copy>
<echo>==============================================</echo>
<echo>compiling code </echo>
<echo>==============================================</echo>
<!-- making classes directory -->
<mkdir dir="${dest.dir}/@{client}/classes"/>
<javac destdir="${dest.dir}/@{client}/classes" classpathref="project.classpath" debug="on" fork="true" includeantruntime="false" memoryinitialsize="256m" memorymaximumsize="1024m">
<src path="${dest.dir}/@{client}/code/"/>
</javac>
<echo>==============================================</echo>
<echo>creating Client.jar </echo>
<echo>==============================================</echo>
<!-- jar classes directory -->
<jar jarfile="${dest.dir}/@{client}/app/Client.jar" basedir="${dest.dir}/@{client}/classes"/>
<!-- reaplce text in files -->
<replaceregexp byline="true">
<regexp pattern="@ReleaseDate@"/>
<substitution expression="${build_time}"/>
<fileset dir="${dest.dir}/@{client}/app/@{client}/templates/">
<include name="*.htm"/>
<include name="*.html"/>
<include name="*.ini"/>
</fileset>
</replaceregexp>
<!-- get svn info -->
<svn username="********" password="************" javahl="false" svnkit="false">
<info target="${repository_url}" />
</svn>
<!-- creating Client.ini file -->
<touch file="${dest.dir}/@{client}/app/Client.ini"/>
<concat destfile="${dest.dir}/@{client}/app/Client.ini" append="true">releaseDate=${build_time}${line.separator}</concat>
<concat destfile="${dest.dir}/@{client}/app/Client.ini" append="true">svnrevision=${svn.info.lastRev}${line.separator}</concat>
<!-- ziping package -->
<zip destfile="${dest.dir}/@{client}/@{client}.zip" basedir="${dest.dir}/@{client}/app/" />
<echo>==============================================</echo>
<echo>sending @{client}.zip to the server via scp </echo>
<echo>==============================================</echo>
<!-- scp file to remote server -->
<property name="scp_username" value="**********"/>
<property name="scp_password" value="**********"/>
<property name="scp_server" value="${@{client}}"/>
<property name="scp_remote_directory" value="*********"/>
<scp trust="true" verbose="true" localFile="${dest.dir}/@{client}/@{client}.zip" remoteTodir="${scp_username}:${scp_password}@${scp_server}:${scp_remote_directory}"/>
<echo>${line.separator}${line.separator}${line.separator}</echo>
</then>
</ac:if>
</actions>
</call>
</xmltask>
</project>
如果我尝试构建 buildpackage.txt
文件
client1=server1
client2=server1
client1=server2
我明白了
client1->server1, client2->server1 但是......没有client 1to server2
编辑2
全部修复。
scp任务的解决方案是:
<!-- scp file to remote server -->
<property name="scp_username" value="XXX"/>
<property name="scp_password" value="YYY"/>
<property name="scp_remote_directory" value="path"/>
<for list="${@{client}}" delimiter="=" param = "val">
<sequential>
<property name="token" value="@"/>
<scp trust="true" verbose="true" localFile="${dest.dir}/@{client}/@{client}.zip" remoteTodir="${scp_username}:${scp_password}${token}@@{val}:${scp_remote_directory}"/>
</sequential>
</for>
一切正常。
感谢您的帮助
对于任何 xmldriven 构建,我建议使用 ant 插件 xmltask,例如:
(假设客户端名称在 buildpackage.txt 和 structure.xml 中相似 - 您的片段有几个名字 Client_01, client1 .. !?)
<project>
<!-- Import XMLTask -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<!-- make buildpackage.txt a valid propertyfile to get the job done
f.e. server1,client1 will get client1=server1 etc. ..
to make server easily accessible within xml loop
-->
<replaceregexp
file="buildpackage.txt"
match="(.+),(.+)"
replace="="
byline="true" />
<!-- now load that file -->
<property file="buildpackage.txt"/>
<!-- loop over all clients -->
<xmltask source="structure.xml">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<!-- inside action adress params with @{..} syntax ! -->
<actions>
<!-- the copy (or whatever) action
here demonstrated with echoxml -->
<echoxml>
<!-- access the corresponding server (set via buildpackage.txt)
with nested ${@{..}} syntax ! -->
<copy todir="//${@{client}}/share">
<fileset dir="@{client}/somedir"/>
</copy>
</echoxml>
<echo>${@{client}}${line.separator}@{client}${line.separator}@{application}${line.separator}@{branding}</echo>
<!-- another nested xmltask for loop over solutions -->
<xmltask source="structure.xml">
<call path="//client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<echo>@{solution}${line.separator}</echo>
</actions>
</call>
</xmltask>
</actions>
</call>
</xmltask>
</project>
如果可能,您应该创建 buildpackage.txt 作为有效的属性文件
使用格式 => Client[x]=Server[x] right away.
然后您只需要 xmltask。将所有要完成的步骤放入嵌套操作部分,如 echoxml/copy 所示。
输出:
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//server1/share">
<fileset dir="client1/somedir" />
</copy>
[echo] server1
[echo] client1
[echo] application_03
[echo] brand_01
[echo] solution01
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//server4/share">
<fileset dir="client4/somedir" />
</copy>
[echo] server4
[echo] client4
[echo] application_03
[echo] brand_09
[echo] solution01
[echo] solution07
[echo] solution08
BUILD SUCCESSFUL
-- 在关于条件操作的问题后编辑,仅当 ${@{client}} 被设置时 --
如果 propertyfile buildpackage.txt 包含错误的属性,意味着 server=client 而不是 client=server,f.e。 :
Sol-e-45-D=PRODUCTION1
CONNECTION=PRODUCTION3
PRODUCTION4=DFHH
PRODUCTION5=MEGA-5
你需要一些 if isset 逻辑。如果你使用的是 ant >= 1.9.3,最好是使用 new if/unless feature(随 ant191 一起引入),f.e。 :
<!-- you need to activate that feature via namespaces -->
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<!-- Import XMLTask -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<!-- load propertyfile with client=server mappings -->
<property file="buildpackage.txt"/>
<!-- loop over all clients -->
<xmltask source="structure.xml">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<!-- inside action adress params with @{..} syntax ! -->
<actions>
<!-- the copy (or whatever) action
here demonstrated with echoxml -->
<echoxml if:set="@{client}">
<!-- access the corresponding server (set via buildpackage.txt)
with nested ${@{..}} syntax ! -->
<copy todir="//${@{client}}/share">
<fileset dir="@{client}/somedir"/>
</copy>
</echoxml>
<echo if:set="@{client}">${@{client}}${line.separator}@{client}${line.separator}@{application}${line.separator}@{branding}</echo>
<!-- another nested xmltask for loop over solutions -->
<xmltask source="structure.xml">
<call path="//client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<echo if:set="@{client}">@{solution}${line.separator}</echo>
</actions>
</call>
</xmltask>
</actions>
</call>
</xmltask>
</project>
注意 => xmltask 调用也有一个 if 属性,但是在开始循环时不知道 clientname,不能使用 <call path="//client" if="@{client}">
输出:
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//PRODUCTION1/share">
<fileset dir="Sol-e-45-D/somedir" />
</copy>
[echo] PRODUCTION1
[echo] Sol-e-45-D
[echo] Sol-e-45-D
[echo] Branding-BLUE
[echo] Sol-e-45-D
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//PRODUCTION3/share">
<fileset dir="CONNECTION/somedir" />
</copy>
[echo] PRODUCTION3
[echo] CONNECTION
[echo] Sol-e-45-D
[echo] Branding-BLUE
[echo] Sol-e-45-D
否则,当绑定到 ant <= 1.9.3 时,您可以使用 antcontrib if task,因为您的代码段中已经有了该 taskdef :
<if>
<isset property="@{client}"/>
<then>
<!-- ... -->
</then>
</if>
当心,你的 antcontrib taskdef 定义是错误的 !!,antcontrib.properties 只包含 ant < 1.6 的 taskdefs,这样声明它(假设 antcontrib.jar 已经在路径上):
<project xmlns:ac="antlib:net.sf.antcontrib">
<ac:if>
...
或没有命名空间:
<project>
<!-- Import AntContrib -->
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
...
我有相当复杂的蚂蚁任务要写。我不得不制作单独的构建文件,剩下 1 个。 有 4 个文件:
buildpackage.bat, buildpackage.xml, buildpackage.txt, structure.xml
buildpackage.bat只是一个调用buildpackage.xml "ant -f buildpackage.xml"
的ant文件。那也行。
buildpackage.txt 很简单并且有逗号分隔的行:
server1,client1
server2,client2
genericserver,client[x]
server[x],client[x]
总是有服务器名称和客户端名称:
Server name
只能是字母、数字和字母,但长度可变。Client name
- 仅限字母。
我需要将这些文件拆分为 2 个单独的变量:server.name
和 client.name
。
我所做的是:
<loadfile property="buildpackage" srcFile="buildpackage.txt"/>
<for list="${buildpackage}" param="depl.det" delimiter="${line.separator}">
<sequential>
<echo>
Input: @{deploy.details}
</echo>
</sequential>
</for>
我得到的结果是:
[echo] Input: server_01,Client_01
[echo] Input: server_02,Client_02
[echo] Input: server_03,Client_03
[echo] Input: clientserver,client_04
我希望 server_01 成为参数 1,client_02 成为参数 2。
我会按顺序执行其他任务。我会将文件从 client[x] 目录复制到 server[x](这很简单,但我如何将该字符串拆分为 2 个单独的变量?)。
现在是非常复杂的任务。
我还有 structure.xml 文件。结构是:
<core>
<clients>
<client>
<name>Client_01</name>
<branding>brand_01</branding>
<applications>
<application>application_01</application>
</applications>
<solutions>
<solution>solution01</solution>
</solutions>
</client>
<client>
<name>Client_07</name>
<branding>brand_09</branding>
<applications>
<application>application_03</application>
</applications>
<solutions>
<solution>solution01</solution>
<solution>solution07</solution>
<solution>solution08</solution>
</solutions>
</client>
<clients>
<core>
我有很多客户、应用程序、品牌和解决方案。每个客户只能有 1 个应用程序和 1 个品牌,但可以有多个解决方案。
基于之前的顺序任务(获取服务器和名称),我必须遍历 xml 文件并为每个匹配的客户端获取(来自之前的任务)
- branding
- application
- solutions (multiple or one)
我可以使用 <xmlproperty>
读取 XML,但我不知道如何按顺序读取(迭代)并获得匹配的属性。
我知道这很复杂。摘要是:
- 构建脚本开始
- 构建脚本从 buildpackage.txt 提取数据作为 client.name 和 server.name
- 构建脚本从步骤 2 中获取
${client.name}
作为参数并循环遍历 structure.xml。它找到匹配的 branding/application/solutions 并为每个匹配的客户端输出它。
输出:
server.name
client.name
branding.name
application name
solution [X]
solution [y]
每个 server/client 都必须处理 Ant。如果我有属性,我可以完成其余的构建和编译。我不能碰 structure.xml。我可以尽我所能 need/want 到 buildpackage.cml 和 buildpackge.txt。 Buildpackage.txt 可以替换为 .xml 文件或任何文件(例如 .properties)。它必须包含这 2 个值服务器和客户端。
感谢您的帮助。
编辑
现在我有一个问题。
如果我将相同的应用程序 2x 放入构建文件中,它只会构建第一个。
这是我的 build.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<project name="DoTheJob" basedir="." xmlns:ac="antlib:net.sf.antcontrib" xmlns:if="ant:if" xmlns:unless="ant:unless">
<!-- Define classpath and default locations-->
<property name="root.dir" location="../.."/>
<property name="dest.dir" location="packages"/>
<property name="ant.lib.dir" location="../lib"/>
<property name="repository_url" value="http://repository-url"/>
<path id="project.classpath">
<fileset dir="${ant.lib.dir}">
<include name="*.jar"/>
</fileset>
<fileset dir="${root.dir}/IIT/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="../savedjar/compiled.jar"/>
</path>
<path id="svnant.path">
<fileset dir="../lib/">
<include name="svnant.jar"/>
<include name="svnClientAdapter.jar"/>
</fileset>
</path>
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.path" />
<tstamp>
<format property="build_time" pattern="YYYY MMMM dd HH:mm:ss"/>
</tstamp>
<!-- Change characters to lowercase -->
<scriptdef language="javascript" name="lowercase">
<attribute name="string" />
<attribute name="to" />
project.setProperty(attributes.get("to"),attributes.get("string").toLowerCase());
</scriptdef>
<!-- Import XMLTask for XML transformations-->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask" classpathref="project.classpath"/>
<!-- Define buildfiles locations-->
<property name="structure.file" location="../structure.xml"/>
<property name="buildpackage.file" location="buildpackage.txt"/>
<!-- load client/server file-->
<property file="${buildpackage.file}"/>
<!-- loop over all clients -->
<xmltask source="${structure.file}">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<actions>
<!-- loop through all XML properties only when @{client} condition is matched -->
<ac:if>
<isset property="@{client}"/>
<then>
<echo>=====================================================</echo>
<echo>Building package for @{client} on ${@{client}} </echo>
<echo>=====================================================</echo>
<!-- creating destination directories -->
<delete dir="${build.dir}/@{client}"/>
<mkdir dir="${dest.dir}/@{client}"/>
<echo>=====================================================</echo>
<echo>Copy application files code/temaplates to destination</echo>
<echo>=====================================================</echo>
<!-- creating code build directory -->
<mkdir dir="${dest.dir}/@{client}/code"/>
<!-- copy application code -->
<echo>copy application code</echo>
<copy todir="${dest.dir}/@{client}/code/application/@{application}" overwrite="yes">
<fileset dir="${root.dir}/client-source/application/@{application}" includes="**/*.*"/>
</copy>
<!-- copy application templates -->
<mkdir dir="${dest.dir}/@{client}/app/@{client}"/>
<echo>copy application templates</echo>
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/apps/@{application}" includes="**/*.*"/>
</copy>
<echo>===================================================</echo>
<echo>copy Solutions files code/temaplates to destination</echo>
<echo>===================================================</echo>
<!-- nested xmltask for loop over solutions -->
<xmltask source="${structure.file}">
<call path="/core/clients/client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<!-- making sure that solution is lowercase -->
<lowercase string="@{solution}" to="solution.lowercase" />
<echo>copy solutions code</echo>
<!-- copy solutions code -->
<copy todir="${dest.dir}/@{client}/code/solutions/${solution.lowercase}" overwrite="yes">
<fileset dir="${root.dir}/client-source/solutions/${solution.lowercase}" includes="**/*.*"/>
</copy>
<!-- copy solutions templates -->
<echo>copy Solutions templates</echo>
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/solutions/${solution.lowercase}" includes="**/*.*"/>
</copy>
</actions>
</call>
</xmltask>
<echo>==============================================</echo>
<echo>copy Client files code/temaplates to destination</echo>
<echo>==============================================</echo>
<!-- copy branding directory -->
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/brandings/@{branding}" includes="**/*.*"/>
</copy>
<!-- copy client code -->
<copy todir="${dest.dir}/@{client}/code/client/@{client}" overwrite="yes">
<fileset dir="${root.dir}/client-source/client/@{client}" includes="**/*.*"/>
</copy>
<!-- set templates directory -->
<copy todir="${dest.dir}/@{client}/app/@{client}" overwrite="yes">
<fileset dir="${root.dir}/applications/clients/@{client}" includes="**/*.*"/>
</copy>
<echo>==============================================</echo>
<echo>compiling code </echo>
<echo>==============================================</echo>
<!-- making classes directory -->
<mkdir dir="${dest.dir}/@{client}/classes"/>
<javac destdir="${dest.dir}/@{client}/classes" classpathref="project.classpath" debug="on" fork="true" includeantruntime="false" memoryinitialsize="256m" memorymaximumsize="1024m">
<src path="${dest.dir}/@{client}/code/"/>
</javac>
<echo>==============================================</echo>
<echo>creating Client.jar </echo>
<echo>==============================================</echo>
<!-- jar classes directory -->
<jar jarfile="${dest.dir}/@{client}/app/Client.jar" basedir="${dest.dir}/@{client}/classes"/>
<!-- reaplce text in files -->
<replaceregexp byline="true">
<regexp pattern="@ReleaseDate@"/>
<substitution expression="${build_time}"/>
<fileset dir="${dest.dir}/@{client}/app/@{client}/templates/">
<include name="*.htm"/>
<include name="*.html"/>
<include name="*.ini"/>
</fileset>
</replaceregexp>
<!-- get svn info -->
<svn username="********" password="************" javahl="false" svnkit="false">
<info target="${repository_url}" />
</svn>
<!-- creating Client.ini file -->
<touch file="${dest.dir}/@{client}/app/Client.ini"/>
<concat destfile="${dest.dir}/@{client}/app/Client.ini" append="true">releaseDate=${build_time}${line.separator}</concat>
<concat destfile="${dest.dir}/@{client}/app/Client.ini" append="true">svnrevision=${svn.info.lastRev}${line.separator}</concat>
<!-- ziping package -->
<zip destfile="${dest.dir}/@{client}/@{client}.zip" basedir="${dest.dir}/@{client}/app/" />
<echo>==============================================</echo>
<echo>sending @{client}.zip to the server via scp </echo>
<echo>==============================================</echo>
<!-- scp file to remote server -->
<property name="scp_username" value="**********"/>
<property name="scp_password" value="**********"/>
<property name="scp_server" value="${@{client}}"/>
<property name="scp_remote_directory" value="*********"/>
<scp trust="true" verbose="true" localFile="${dest.dir}/@{client}/@{client}.zip" remoteTodir="${scp_username}:${scp_password}@${scp_server}:${scp_remote_directory}"/>
<echo>${line.separator}${line.separator}${line.separator}</echo>
</then>
</ac:if>
</actions>
</call>
</xmltask>
</project>
如果我尝试构建 buildpackage.txt
文件
client1=server1
client2=server1
client1=server2
我明白了 client1->server1, client2->server1 但是......没有client 1to server2
编辑2
全部修复。 scp任务的解决方案是:
<!-- scp file to remote server -->
<property name="scp_username" value="XXX"/>
<property name="scp_password" value="YYY"/>
<property name="scp_remote_directory" value="path"/>
<for list="${@{client}}" delimiter="=" param = "val">
<sequential>
<property name="token" value="@"/>
<scp trust="true" verbose="true" localFile="${dest.dir}/@{client}/@{client}.zip" remoteTodir="${scp_username}:${scp_password}${token}@@{val}:${scp_remote_directory}"/>
</sequential>
</for>
一切正常。 感谢您的帮助
对于任何 xmldriven 构建,我建议使用 ant 插件 xmltask,例如:
(假设客户端名称在 buildpackage.txt 和 structure.xml 中相似 - 您的片段有几个名字 Client_01, client1 .. !?)
<project>
<!-- Import XMLTask -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<!-- make buildpackage.txt a valid propertyfile to get the job done
f.e. server1,client1 will get client1=server1 etc. ..
to make server easily accessible within xml loop
-->
<replaceregexp
file="buildpackage.txt"
match="(.+),(.+)"
replace="="
byline="true" />
<!-- now load that file -->
<property file="buildpackage.txt"/>
<!-- loop over all clients -->
<xmltask source="structure.xml">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<!-- inside action adress params with @{..} syntax ! -->
<actions>
<!-- the copy (or whatever) action
here demonstrated with echoxml -->
<echoxml>
<!-- access the corresponding server (set via buildpackage.txt)
with nested ${@{..}} syntax ! -->
<copy todir="//${@{client}}/share">
<fileset dir="@{client}/somedir"/>
</copy>
</echoxml>
<echo>${@{client}}${line.separator}@{client}${line.separator}@{application}${line.separator}@{branding}</echo>
<!-- another nested xmltask for loop over solutions -->
<xmltask source="structure.xml">
<call path="//client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<echo>@{solution}${line.separator}</echo>
</actions>
</call>
</xmltask>
</actions>
</call>
</xmltask>
</project>
如果可能,您应该创建 buildpackage.txt 作为有效的属性文件
使用格式 => Client[x]=Server[x] right away.
然后您只需要 xmltask。将所有要完成的步骤放入嵌套操作部分,如 echoxml/copy 所示。
输出:
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//server1/share">
<fileset dir="client1/somedir" />
</copy>
[echo] server1
[echo] client1
[echo] application_03
[echo] brand_01
[echo] solution01
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//server4/share">
<fileset dir="client4/somedir" />
</copy>
[echo] server4
[echo] client4
[echo] application_03
[echo] brand_09
[echo] solution01
[echo] solution07
[echo] solution08
BUILD SUCCESSFUL
-- 在关于条件操作的问题后编辑,仅当 ${@{client}} 被设置时 --
如果 propertyfile buildpackage.txt 包含错误的属性,意味着 server=client 而不是 client=server,f.e。 :
Sol-e-45-D=PRODUCTION1
CONNECTION=PRODUCTION3
PRODUCTION4=DFHH
PRODUCTION5=MEGA-5
你需要一些 if isset 逻辑。如果你使用的是 ant >= 1.9.3,最好是使用 new if/unless feature(随 ant191 一起引入),f.e。 :
<!-- you need to activate that feature via namespaces -->
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<!-- Import XMLTask -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<!-- load propertyfile with client=server mappings -->
<property file="buildpackage.txt"/>
<!-- loop over all clients -->
<xmltask source="structure.xml">
<call path="//client">
<param path="name/text()" name="client"/>
<param path="branding/text()" name="branding"/>
<param path="applications/application/text()" name="application"/>
<!-- inside action adress params with @{..} syntax ! -->
<actions>
<!-- the copy (or whatever) action
here demonstrated with echoxml -->
<echoxml if:set="@{client}">
<!-- access the corresponding server (set via buildpackage.txt)
with nested ${@{..}} syntax ! -->
<copy todir="//${@{client}}/share">
<fileset dir="@{client}/somedir"/>
</copy>
</echoxml>
<echo if:set="@{client}">${@{client}}${line.separator}@{client}${line.separator}@{application}${line.separator}@{branding}</echo>
<!-- another nested xmltask for loop over solutions -->
<xmltask source="structure.xml">
<call path="//client[name/text()='@{client}']/*/solution">
<param path="text()" name="solution"/>
<actions>
<echo if:set="@{client}">@{solution}${line.separator}</echo>
</actions>
</call>
</xmltask>
</actions>
</call>
</xmltask>
</project>
注意 => xmltask 调用也有一个 if 属性,但是在开始循环时不知道 clientname,不能使用 <call path="//client" if="@{client}">
输出:
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//PRODUCTION1/share">
<fileset dir="Sol-e-45-D/somedir" />
</copy>
[echo] PRODUCTION1
[echo] Sol-e-45-D
[echo] Sol-e-45-D
[echo] Branding-BLUE
[echo] Sol-e-45-D
<?xml version="1.0" encoding="UTF-8"?>
<copy todir="//PRODUCTION3/share">
<fileset dir="CONNECTION/somedir" />
</copy>
[echo] PRODUCTION3
[echo] CONNECTION
[echo] Sol-e-45-D
[echo] Branding-BLUE
[echo] Sol-e-45-D
否则,当绑定到 ant <= 1.9.3 时,您可以使用 antcontrib if task,因为您的代码段中已经有了该 taskdef :
<if>
<isset property="@{client}"/>
<then>
<!-- ... -->
</then>
</if>
当心,你的 antcontrib taskdef 定义是错误的 !!,antcontrib.properties 只包含 ant < 1.6 的 taskdefs,这样声明它(假设 antcontrib.jar 已经在路径上):
<project xmlns:ac="antlib:net.sf.antcontrib">
<ac:if>
...
或没有命名空间:
<project>
<!-- Import AntContrib -->
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
...