2015-02-24 70 views
1

我有相當複雜的螞蟻任務寫。我必須做出單獨的構建文件,剩下1個。 有4個文件:ANT任務 - 多個文件 - 循環通過

buildpackage.bat, buildpackage.xml, buildpackage.txt, structure.xml 

buildpackage.bat僅僅是一個Ant文件調用buildpackage.xml "ant -f buildpackage.xml"。沒事兒。

buildpackage.txt是簡單的,並已獲得逗號隔開:

server1,client1 
server2,client2 
genericserver,client[x] 
server[x],client[x] 

總是有服務器名稱和客戶端名稱:

  • Server name可以是字母只,數字和字母,但具有可變長度。

  • Client name - 僅限字母。

我需要將這些文件分割成2個獨立的變量:server.nameclient.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。

我會按順序執行其他任務。我會將文件從客戶端[x]目錄複製到服務器[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,但我做的不知道如何順序執行(迭代)並獲得匹配的屬性。

我知道這很複雜。該摘要是:

  1. 構建腳本開始
  2. 構建腳本從buildpackage.txt如client.name和server.name提取數據
  3. 構建腳本從步驟2作爲參數得到${client.name}和遍歷結構。 XML。它找到匹配的品牌/應用/解決方案並將其輸出給每個匹配的客戶端。

輸出:

server.name 
client.name 
branding.name 
application name 
solution [X] 
solution [y] 

螞蟻具有用於每個服務器/客戶端以進行處理。如果我有屬性,我可以完成構建的其餘部分並進行編譯。我無法觸摸structure.xml。我可以做所有我需要/想要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="@[email protected]"/> 
          <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的,但是......沒有客戶端1to服務器2

EDIT2

所有固定。 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> 

所有的作品。 感謝您的幫助

回答

1

對於任何xmldriven構建我建議使用ant插件xmltask,所以像:
(假設clientnames在buildpackage.txt和structure.xml相似 - 你的片斷有幾個名字Client_01,客戶端1 ..!?)

<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="\2=\1" 
    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爲有效propertyfile
與格式=>客戶端[X] =服務器[X]的時候了。
然後,你需要的是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 

- 有關條件操作的問題後編輯,僅當$ {@ {客戶}}設置 -

如果propertyfile buildpackage.txt包含錯誤的性質,手段服務器=客戶端而不是客戶端=服務器,fe :

Sol-e-45-D=PRODUCTION1 
CONNECTION=PRODUCTION3 
PRODUCTION4=DFHH 
PRODUCTION5=MEGA-5 

如果isset邏輯需要一些。如果你使用ant> = 1.9.3,f.e.最好使用new if/unless feature(與ant191一起引入)。:

<!-- 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呼叫也是如果屬性,但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 

否則,當綁定到螞蟻< = 1.9.3你可以使用antcontrib如果任務,因爲你的代碼段中已經有了taskdef:

<if> 
<isset property="@{client}"/> 
    <then> 
    <!-- ... --> 
    </then> 
</if> 

當心,你的antcontrib的taskdef定義是錯誤 !!時,antcontrib.properties僅包含螞蟻< 1.6任務定義,聲明這樣說,這(假設antcontrib.jar已經在路徑):

<project xmlns:ac="antlib:net.sf.antcontrib"> 

    <ac:if> 
    ... 

或沒有命名空間:

<project> 

    <!-- Import AntContrib --> 
    <taskdef resource="net/sf/antcontrib/antlib.xml"/> 
    ... 
+0

編輯。現在都完美運作,但有一個問題。如果我想構建application1 = server1和application1 = server2和appcation1 = server3 - 它只構建1個應用程序。如果我把applicaiton1 = server1,application2 = server1,applicationaiton1 = server2 - stull只建立一次應用程序。 – 2015-03-18 08:39:55

+0

@ES蘇你有3個屬性命名爲application1。這是不可能的。在螞蟻中,曾經設置的屬性是不變的。當propertyfile被加載時,第一個定義f.e. application1 = server1獲勝,意味着該屬性將具有值server1。 – Rebse 2015-03-18 13:14:24

+0

如果'buildpackage.txt'的格式是:client1 = server1 = server2 = server3'' client2 = server1'' client3 = server1 = server2 = server3 = server4 = server5'從一個到5個服務器。可能嗎? – 2015-03-19 08:28:45