27 janvier 2011

"Mavenizer" un projet

Lorsqu'on cherche à convertir un projet "old-school" sous Maven, l'une des premières tâches consiste à identifier la liste de dépendances du projet. On peut se baser sur le nom des JAR, éventuellement se rassurer en inspectant le fichier MANIFEST (lorsqu'il est renseigné), mais en général c'est :

  • long
  • barbant
  • peu fiable : j'ai déjà vu des JAR "patchés" ou "complétés" avec des classes annexes

Une solution plus propre consiste à se baser sur les empruntes MD5 et SHA1 que le repository Maven conservent pour chaque artefact. Une simple recherche Google sur cette clé retourne l'identification précise d'une bibliothèque (avec parfois des surprises !).

Il y a pourtant encore plus simple...

Le repository manager Nexus propose un moteur de recherche qui prend en entrée l'emprunte SHA1. Basé sur son index interne, il va nous retrouver la bibliothèque, et en plus nous indiquer les versions plus récentes (si on veut en profiter pour un petit lifting). L'avantage de Nexus, c'est qu'il propose une API REST qui permet d'automatiser tout ça. Allons-y donc gaillardement !

J'écrit donc mon tout premier script Ruby ! - et oui, tout fout le camp ma bonne dame - ce langage est génial pour écrire des scripts de ce type, avec des bibliothèques bien puissantes ;)

require 'find'
require 'digest/sha1'
require 'net/http'
require 'rexml/document'
include REXML

for file in Dir.glob("*.jar") do 
    sha = Digest::SHA1.file( file ).hexdigest
    url = "http://myNexus/service/local/lucene/search?sha1=" + sha 
    resp = Net::HTTP.get_response( URI.parse( url ) )
    puts File.basename( file ) + " (" + sha + ") = \n";
    doc = REXML::Document.new( resp.body )
    XPath.each( doc, "//artifact" ) do |r|
          puts "<dependency>"
          puts "   <groupId>#{r.elements["groupId"].text}</groupId>"
          puts "   <artifactId>#{r.elements["artifactId"].text}</artifactId>"
          puts "   <version>#{r.elements["version"].text}</version>"
          puts "</dependency>"
    end  
 
end
Rien de bien méchant, comme vous pouvez le constater, et ce script permet d'analyser rapidement une liste de jar en proposant les éléments à intégrer dans le POM. Il restera "juste" à identifier les bibliothèques qui seront passées entre les mailles du filet.

Maintenant que Maven Indexer est un projet Apache (depuis la version 3.1.0), ce serait bien d'intégrer cette fonctionnalité au plugin dependency [MDEP-269] ... ou ailleurs.

5 commentaires:

Sebastien Tanguy a dit…

Bienvenu dans le monde Ruby!

Par contre, Rexml, c'était bien en 2005, mais c'est pas forcément ce qui serait le plus conseillé de nos jours, en particulier si les fichiers traités peuvent être gros. De nos jours, je recommanderais de regarder Nokogiri et HPricot.

(sinon, y'a toujours moyen de se faire du mal et d'utiliser les libs java, via JRuby, évidemment)

Spawnrider a dit…

Encore un excellent article, merci à toi ;)

Cédric Vidal a dit…

Il existe aussi Mavenizer:
http://mavenizer.sourceforge.net/

(il serait intéressant de coupler ta technique à Mavenizer)

Disclaimer: je suis l'auteur ;)

Laurent a dit…

empreinte ;)

George Armhold a dit…

Bonjour, j'ai creé un projet qui fait à peu près la même chose, sauf c'est en Java:

https://github.com/armhold/Provenance

Forcement, c'est plus long, parce que ce n'est pas Ruby, mais peut etre pratique pour ceux qui ont besoin de qqc en Java pure.

Merci!