web-dev-qa-db-fra.com

Exécuter la tâche Ant juste si une condition est remplie

J'ai besoin d'exécuter une tâche Ant au sein d'une cible spécifique uniquement si une condition est remplie.

J'ai trouvé un moyen de définir la condition au niveau cible, mais pas au niveau de la tâche. J'ai également trouvé une contribution qui implémente une tâche IF .

Ma question est la suivante: connaissez-vous un moyen d'atteindre cet objectif avec des tâches Ant standard?

Explication plus longue: j'essaie de démarrer Tomcat Server au cas où il serait arrêté. Pour détecter s'il est arrêté, j'utilise le code suivant:

<echo message="Checking whether Tomcat is running"/>
<condition property="Tomcat.running">
  <socket server="${Tomcat.Host}" port="${Tomcat.port}"/> 
</condition>

Donc, ma prochaine tâche dans cette cible est une tâche exec qui ne doit être exécutée que si ${Tomcat.running} c'est faux. Et comme je l'ai dit, je ne veux pas ajouter une seule tâche dans une cible pour utiliser la propriété à moins.

33
Jose Miguel Ordax

Une cible Ant peut avoir une clause if ou unless facultative. Cela signifie d'exécuter la tâche uniquement si la propriété est définie, avec une clause if, ou n'est pas définie avec la clause unless1. Fait intéressant, cette clause if ou unless est vérifiée après toute tâche dépendante est d'abord exécuté.

Cela signifie que vous pouvez le faire dans Ant standard comme moyen d'exécuter une tâche Ant uniquement si une condition particulière est remplie:

 <target name="test.if.Tomcat.is.running">
      <condition property="Tomcat.running">
          <socket server="${Tomcat.Host}" port="${Tomcat.port}"/> 
      </condition>
</target>

<target name="my.target"
    if="Tomcat.running"
    depends="test.if.Tomcat.is.running">
    <yaddah/>
    <yaddah/>
    <yaddah/>
</target>

Vous spécifiez que vous souhaitez que Ant exécute Target my.target. Ant remarque que my.target dépend du test.if.Tomcat.is.running cible, et l'exécutera en premier. Le test.if.Tomcat.is.running la tâche définira le Tomcat.running propriété si Tomcat est en cours d'exécution. Sinon, cette propriété n'est pas définie.

Enfin, Ant retournera au my.target ciblez et voyez si la propriété Tomcat.running est défini et exécutera uniquement la cible my.target s'il est défini.

Ou, vous pouvez utiliser les tâches Ant-contrib qui peuvent rendre votre processus de construction plus facile à comprendre.

Si vous souhaitez suivre la route Ant-Contrib, il existe un moyen simple de configurer Ant-Contrib, de sorte que le pot Ant-contrib fait réellement partie de votre projet. Si quelqu'un extrait votre projet à partir du système de contrôle de version, il obtiendra également le pot Ant-contrib et n'aura donc pas à installer Ant-Contrib lui-même.

Téléchargez le pot Ant-Contrib et placez-le dans un répertoire à la racine de votre projet appelé antlib/ac. antlib peut être utilisé pour toutes sortes de fichiers de tâches facultatifs tels que Findbugs ou PMD. Il suffit de placer chaque bocal Ant optionnel dans son propre répertoire sous antlib (comme j'ai mis Ant-Contrib sous le répertoire ac).

Ensuite, dans votre build.xml, vous spécifiez les tâches Ant-Contrib de cette façon:

<taskdef resource="net/sf/antcontrib/antlib.xml">
   <classpath>
       <fileset dir="${basedir}/antlib/ac"/>
   </classpath>
</taskdef>

Maintenant, vous pouvez utiliser les tâches Ant-Contrib sans vous soucier de savoir si elles sont installées ou non sur une machine particulière. Vous extrayez votre projet et vous avez accès à ces tâches automatiquement.


1. C'est vrai, le if/unless clause vérifie si une propriété est définie et non true/false ce qui peut provoquer beaucoup de confusion. J'ai vu des développeurs définir une propriété sur false ou no, puis je me demande pourquoi la cible s'exécute réellement puisque la clause if est définie sur false.

46
David W.

Depuis la version 1.9.1 (*) ant prend en charge d'avoir si- et à moins-conditions d'une manière plus fine - sur n'importe quelle tâche, si vous déclarez les espaces de noms nécessaires à l'intérieur de l'élément de projet.

(*) Veuillez utiliser la dernière version de ant (1.9.6 à ce jour), car la version 1.9.1 contient des défauts WRT cette nouvelle fonctionnalité, comme l'utilisateur @Rebse l'a gentiment souligné.

Dans l'exemple ci-dessous, vous pouvez jouer en commentant/décommentant les propriétés ...

<project name="test"
         xmlns:if="ant:if"
         xmlns:unless="ant:unless">

  <property name="is.good" value="hohoho"/>
  <!--property name="hide.base" value="boo"/-->

  <target name="foo">
     <echo unless:set="hide.base">${basedir}</echo>
     <echo if:set="is.good">GOOD</echo>
  </target>
</project>

... et observez des sorties comme celle-ci:

Buildfile: D:\test\ant\taskcondition\build.xml
foo:
     [echo] D:\test\ant\taskcondition
     [echo] GOOD
BUILD SUCCESSFUL
Total time: 191 milliseconds
10
Jörg

Si vous voulez une implémentation de type "sinon":

<target name="test.if.Tomcat.is.running">
      <condition property="Tomcat.running" value="true" else="false">
          <socket server="${Tomcat.Host}" port="${Tomcat.port}"/> 
      </condition>
</target>

<target name="my.target.running"
    if="${Tomcat.running}"
    depends="test.if.Tomcat.is.running">
...
</target>

<target name="my.target.ifnotrunning"
    unless="${Tomcat.running}"
    depends="test.if.Tomcat.is.running">
   .....
</target>
5
Agilan Palani

Il y a des situations où vous ne pouvez pas faire dépendre votre cible Ant d'une autre cible Ant parce que le si doit être évalué sur la base d'une valeur initialisée juste avant exec (je peux fournir un exemple clair mais pour des raisons de simplicité Je ne le ferai pas).

Sur les systèmes de type Unix, une alternative (préférable dans certaines situations) est la suivante:

<!-- the property that contains the value to be checked agains IF -->
<property name="myprop" value="true"/>

<!-- the Ant's exec combined with OS-IF command -->
<exec executable="bash">
        <arg value="-c" />
        <arg value="if [ &quot;${myprop}&quot; != &quot;$${myprop}&quot;] || [&quot;${tag_exists}&quot; != &quot;true&quot; ]; then my-bash-command _arguments_; fi" />
</exec>

Dans ce qui précède, le my-bash-command illustre la commande/programme que vous souhaitez exécuter et les arguments illustre les arguments de cette commande.

Notez que lorsque myprop n'est pas défini, $ {myprop} sera simplement évalué dans la chaîne "$" + "{" + "myprop" + "}" (c.-à-d. "$ {Myprop } "), nous devons donc comparer la valeur de myprop avec cette chaîne.

D'un autre côté, lorsque myprop est défini, sa valeur est probablement la chaîne true/false afin de vérifier SI notre condition est remplie, nous devons comparer le myprop avec la chaîne true (ou quelle que soit la valeur que vous puissiez avoir).

Conclusion: en utilisant la fourmi exec combinée avec la commande OS SI nous pouvons exécuter des commandes OS arbitraires/programmes sans avoir besoin d'une autre cible Ant. En utilisant la même logique que ci-dessus, l'instruction SI peut être modifiée pour fonctionner même sous Windows.

1
Eugen Mihailescu