2015-02-24 4 views
1

J'ai tâche assez difficile à écrire. J'ai dû faire des fichiers de build distincts et j'en ai laissé 1. Il y a 4 Fichiers:tâche ANT - plusieurs fichiers - boucle à travers

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

est buildpackage.bat juste un fichier de fourmi qui appelle buildpackage.xml "ant -f buildpackage.xml". C'est bon.

buildpackage.txt est simple et a obtenu des lignes séparées par des virgules:

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

Il y a toujours le nom du serveur et le nom du client:

  • Server name peut être seulement des lettres, des chiffres et des lettres, mais a une longueur variable.

  • Client name - lettres seulement.

J'ai besoin de diviser ces fichiers en 2 variables distinctes: server.name et client.name.

Ce que je l'ai fait est:

<loadfile property="buildpackage" srcFile="buildpackage.txt"/>  
<for list="${buildpackage}" param="depl.det" delimiter="${line.separator}"> 
<sequential> 
    <echo> 
    Input: @{deploy.details} 
    </echo> 
</sequential> 
</for> 

Les résultats que je reçois sont:

[echo] Input: server_01,Client_01 
[echo] Input: server_02,Client_02 
[echo] Input: server_03,Client_03 
[echo] Input: clientserver,client_04 

Je voudrais server_01 être paramètre1 et client_02 être paramètre2.

Je vais effectuer d'autres tâches dans une séquence. Je vais copier les fichiers du répertoire client [x] vers le serveur [x] (c'est simple mais comment diviser cette chaîne en 2 variables séparées?).

Et maintenant, la tâche très compliquée. J'ai également un fichier structure.xml. La structure est:

<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> 

J'ai beaucoup de clients, applications, marques, solutions. Chaque client peut avoir seulement 1 application et 1 branding mais plusieurs solutions.

Sur la base de tâche séquentielle précédente (get serveur et le nom) Je dois boucle à travers ce fichier xml et obtenir pour chaque client adapté (tâche précédente)

- branding 
- application 
- solutions (multiple or one) 

Je peux lire XML à l'aide <xmlproperty> mais je Je ne sais pas comment le faire séquentiellement (itérer) et obtenir des propriétés correspondantes.

Je sais que c'est compliqué. Le résumé est:

  1. script de compilation commence
  2. script de compilation
  3. extrait des données de buildpackage.txt comme client.name et server.name
  4. script build
  5. obtient ${client.name} de l'étape 2 en tant que paramètre et boucles à travers la structure. xml. Il trouve des marques/applications/solutions correspondantes et les affiche pour chaque client correspondant.

sortie:

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

Ant doit être traité pour chaque serveur/client. Je peux faire le reste de la construction et compiler si j'ai les propriétés. Je ne peux pas toucher structure.xml. Je peux faire tout ce dont j'ai besoin pour buildpackage.cml et buildpackge.txt. Buildpackage.txt peut être remplacé par un fichier .xml ou n'importe quel fichier (par exemple .properties). Il doit contenir ces 2 valeurs serveur et client.

Nous vous remercions de votre aide.

EDIT

Maintenant, j'ai un problème. Si je mets la même application 2x dans un fichier de construction, il ne construit que le premier. Voici mon fichier 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> 

Et si je tente yo construire fichier buildpackage.txt

client1=server1 
client2=server1 
client1=server2 

Je reçois client1-> server1, client2-> server1 mais ...... pas de client 1Pour server2

EDIT2

Toutes fixe. La solution pour tâche scp est:

 <!-- 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> 

Toutes les oeuvres. Merci pour votre aide

Répondre

1

Pour toute construction de xmldriven je recommande d'utiliser la fourmi addon xmltask, donc quelque chose comme:
(en supposant que clientnames sont similaires dans buildpackage.txt et structure.xml - votre extrait a plusieurs noms 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="\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> 

Si possible, vous devez créer buildpackage.txt comme propertyfile valide
avec le format => client [x] = serveur [x] tout de suite.
Ensuite, tout ce dont vous avez besoin est le xmltask. Mettez toutes vos étapes à faire dans la section de l'action imbriquée comme démontré avec echoxml/copy.

Sortie:

<?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 

- EDIT après question sur l'action conditionnelle, que si $ {@ {client}} est défini -

si propertyfile buildpackage.txt contient des propriétés mauvaises, des moyens serveur = client au lieu du client = serveur, fe :

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

vous avez besoin si la logique de isset. Le mieux est d'utiliser le new if/unless feature (introduit avec ant191) si vous êtes sur ant> = 1.9.3, 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> 

Note => l'appel xmltask a également si l'attribut, mais le nom_de_client ne sait pas lors du démarrage de la boucle, ne peut pas utiliser <call path="//client" if="@{client}">
sortie:

<?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 

Sinon, lorsque lié à la fourmi < = vous pouvez utiliser 1.9.3 antcontrib si la tâche, comme vous avez déjà taskdef dans votre extrait:

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

Attention, votre définition antcontrib de taskdef est erroné !!, les antcontrib.properties ne contient que taskdefs pour fourmi < 1.6, déclarer comme ça (en supposant antcontrib.jar déjà sur le chemin):

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

    <ac:if> 
    ... 

ou sans espaces de noms:

<project> 

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

EDIT. maintenant tout fonctionne parfaitement, mais il y a un problème. Si je veux construire application1 = serveur1 et application1 = serveur2 et appcation1 = serveur3 - il construit seulement 1 application. Si je mets applicaiton1 = server1, application2 = server1, applicaiton1 = server2 - les constructions stull s'appliquent une fois seulement. –

+0

@ES Su vous avez 3 propriétés nommées application1. Ce n'est pas possible. Dans Ant une propriété une fois définie est immuable. Lorsque le fichier de propriétés est chargé, la première définition, f.e. application1 = wins1, signifie que la propriété aura la valeur server1. – Rebse

+0

Que se passerait-il si 'buildpackage.txt' serait au format:' client1 = serveur1 = serveur2 = serveur3' 'client2 = serveur1'' client3 = serveur1 = serveur2 = serveur3 = serveur4 = serveur5' de 1 à 5 serveurs. C'est possible? –