lundi 29 juillet 2013

Utilisation de la balise <configuration> dans un plugin maven

Lorsque dans un pom, on active un plugin maven, il arrive de le configurer via une balise configuration.
Prenons l'exemple de maven war plugin :
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <webResources>
            <resource>
              <!-- this is relative to the pom.xml directory -->
              <directory>resource2</directory>
            </resource>
          </webResources>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Cette balise est très intéressante.
Imaginons que nous souhaitons créer un plugin qui exécute des commandes shell, et en plus dans un certain ordre, comment faire ?

Partons du postulat que notre plugin se configure comme suit :
<plugin>
 <groupId>org.test.plugins</groupId>
 <artifactId>maven-montest-plugin</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <executions>
  <execution>
   <phase>generate-sources</phase>
   <goals>
    <goal>shell-exec</goal>
   </goals>
   <configuration>
    <script name="toto">
     <run name="coucou1" exec="commande ${project.version}"></run>
     <run name="coucou2">nom du script ${project.version}</run>
    </script>
   </configuration>
  </execution>
 </executions>
</plugin> 

Pour pourvoir reproduire le comportement de la balise webResources. Il faut utiliser un objet du type org.codehaus.plexus.configuration.PlexusConfiguration.
Ici, nous aurons donc un attribut script :
/**
 * @goal shell-exec
 * @threadSafe true
 */
public class ShellExecutionMojo extends AbstractMojo {
    /**
     * The script to execute
     *
     * @parameter
     */
    private PlexusConfiguration script;
 
 ...
}

Il est important de noter, qu'il n'est pas possible d'avoir un tableau ou une liste à ce niveau.

La classe PlexusConfiguration contient une méthode getName() qui retourne le nom de la balise XML. Dans notre cas run.
Pour récupérer un attribut de la balise, il suffit d'appeler la méthode getAttribute(String). Cette méthode renvoit null si la balise n'est pas présente.
Pour récupérer le contenu de la balise (exemple coucou2), il faut utiliser la méthode getValue().
S'il y a des balises enfants, il faudra utiliser les méthodes getChild().
Si on souhaite récupérer la liste des enfants, il faudra utiliser la méthode getChildren(), qui renvoit un tableau et getChildCount() pour savoir le nombre d'enfants.

Voici l'exemple complet :
package org.test.plugins;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.configuration.PlexusConfiguration;

import org.test.plugin.util.PlexusConfigurationComparator;

/**
 * @goal shell-exec
 * @threadSafe true
 */
public class ShellExecutionMojo extends AbstractMojo {
    /**
     * The script to execute
     *
     * @parameter
     */
    private PlexusConfiguration script;
 
    /**
     * List of script to run
     */
    private List listScriptToRun ;
    
 @Override
 public void execute() throws MojoExecutionException, MojoFailureException {
  PlexusConfiguration[] children = script.getChildren() ;
  
  getLog().info("Running ShellExecutorMojo") ;
  
  listScriptToRun = new ArrayList(children.length) ;
  
  for (PlexusConfiguration currentNode : children) {
   if ("run".equals(currentNode.getName())) {
    listScriptToRun.add(currentNode) ;
   }
  }
  
  Collections.sort(listScriptToRun, new PlexusConfigurationComparator(getLog())) ;
  
  for (PlexusConfiguration currentNode : listScriptToRun) {
   getLog().info("> " + currentNode.getAttribute("name")) ;
   
   execScript(currentNode) ;
  }  
  
  getLog().info("Fin") ;
 }
 
 private void execScript(final PlexusConfiguration currentNode) {
  String cmd = currentNode.getAttribute("exec") ;
  
  if (StringUtils.trimToNull(cmd) == null) {   
   cmd = currentNode.getValue() ;
   
   getLog().info("Balise = " + cmd) ;
  } else {
   getLog().info("Balise exec = " + cmd) ;
  }
 }
}

La classe de tri :
/**
 * 
 */
package org.test.plugin.util;

import java.util.Comparator;

import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.logging.Log ;

/**
 * Sort PlexusConfiguration object
 * @author Emeric MARTINEAU
 */
public class PlexusConfigurationComparator implements Comparator {
 /**
  * Logger
  */
 private Log logger ;
 
 public PlexusConfigurationComparator(final Log log) {
  this.logger = log ;
 }
 
 @Override
 public int compare(PlexusConfiguration object1, PlexusConfiguration object2) {
  final String orderString1 = object1.getAttribute("order") ;
  final String orderString2 = object2.getAttribute("order") ;
  
  int order1 = convertOrder(orderString1) ;
  int order2 = convertOrder(orderString2) ;
  
  
  return order1 - order2 ;
 }
 
 /**
  * Converti l'order
  * @param orderString
  * @return
  */
 private int convertOrder(final String orderString) {
  int order = 0 ;
  
  // If string is null, no order attribut found
  if (StringUtils.trimToNull(orderString) != null) {  
   try {  
    order = Integer.valueOf(orderString) ; 
   } catch(final NumberFormatException e) { 
    logger.warn(String.format(
         "Invalide 'order' tag value = '%s'", orderString)) ;
   } 
  }
  
  return order ;
 }

}

Aucun commentaire:

Enregistrer un commentaire