Classes d'un package
Par Cédric Tabin le mercredi 16.09.2009, 08:00 - Java - Lien permanent
Java possède une puissante API permettant de faire de la reflection. Toutefois, celle-ci ne permet pas tout : pour lister dynamiquement les classes d'un package il faut passer par un chemin quelque peu détourné...
A la base, je pensais pouvoir m'en sortir facilement grâce à la classe Package. Mais celle-ci ne dispose pas de méthode permettant de lister son contenu.
Du coup, on en revient à la bonne vieille méthode : celle qui consiste à aller parcourir bêtement le répertoire qui contient les fichiers class :
// ciblage du package voulu String targetPackage = "ch.capi.mypackage"; String targetPackagePath = targetPackage.replace('.', '/'); String targetPath = "/"+targetPackagePath; // récupération du chemin 'réel' du package URL resourceURL = MaClass.class.getResource(targetPath); String packageRealPath = resourceURL.getFile(); File packageFile = new File(packageRealPath);
Grâce à l'objet File ainsi trouvé, il ne reste plus qu'à récupérer le nom de la classe et obtenir une instance de Class :
//... for (File classFile : packageFile.listFiles()) { String fileName = classFile.getName(); if (fileName.endsWith(".class")) // ne traite que les fichiers '.class' { String className = fileName.substring(0, fileName.lastIndexOf(".")); // enlève le '.class' String fullClassName = targetPackage+"."+className; Class clazz = Class.forName(fullClassName); //... } }
Cela permet de résoudre quelques soucis, mais pas tous : cela ne marche pas si les classes sont dans un fichier jar ! Pour contourner ce problème, il faut utiliser une autre méthode pour parcourir les fichiers :
JarFile jf = new JarFile(packageRealPath); Enumeration<JarEntry> entries = jf.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); if (entryName.startsWith(targetPackagePath) && entryName.endsWith(".class")) { // récupération vie Class.forName(...) } }
Je suis tombé sur ce problème en Java EE puisque lorsqu'une application est déployée sous GlassFish, les classes se retrouvent dans un dossier, tandis que sous Weblogic tout est dans un jar.
J'ai mis en annexe la classe complète pour ceux qui en auraient l'utilité !
Commentaires
excellente "astuce". Ayant été confronté au problème aussi mais dans mon cas toutes les classes étaient nécessairement sous forme fichier (GlassFish / Tomcat) donc je n'ai pas eu à implémenter l'analyse JAR.
C'est un peu anormal que la classe package ne le permette pas ...