2010-11-06 22 views
1

J'ai créé une bibliothèque simple AppInfo fournissant un moyen facile d'afficher des informations mises à jour automatiquement et toujours valides sur une version de logiciel en cours d'exécution dans les applications Java, particulièrement utile avec les versions automatiques du serveur CI.Comment obtenir le nom de JAR qui est une application de bureau à partir?

Dans ma bibliothèque, il est nécessaire de lire MANIFEST.MF à partir de JAR (dans le cas d'une application de bureau) qui est l'exécution de l'application finale (pas d'une autre sur un chemin de classe). Actuellement, j'utilise une solution basée sur une idée prise sous forme forum Sun (quel lien ne fonctionne plus):

String classContainer = classFromRightJar.getProtectionDomain().getCodeSource().getLocation().toString(); 
URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF"); 

et il fonctionne en général, mais elle oblige les développeurs d'une application de bureau pour créer haricot supplémentaire configuré avec nom d'une classe qui se trouve dans un fichier JAR spécifique.

Existe-t-il une meilleure solution générique qui donne un nom/emplacement/MANIFEST.MF de/à partir de JAR, une application de bureau à partir de laquelle?

Merci pour votre aide
Marcin

Répondre

0

Par « développeur de forces d'une application de bureau pour créer haricots supplémentaires ... » faites ce que vous vous entendez ne voulez pas qu'ils aient jamais faire référence à une de leur application de noms de classe du tout? Si c'est le cas, alors il n'y a probablement pas de manière 100% fiable de le faire, mais une approche pourrait être d'appeler java.awt.Frame.getFrames() et de vérifier les sous-classes non-java * de JFrame. .: par exemple

for (Frame frame in Frame.getFrames()) { 
    if (frame.getClass().getPackage().getName().startsWith("java")) 
     continue; 
    URL manifestURL = frame.getClass().getResource("/META-INF/MANIFEST.MF"); 
    // do something with the manifest 
} 

Cela se décomposera si l'application ne sous-classe pas le JFrame/se cadre, de sorte que vous pouvez également marcher à travers les enfants du cadre pour vérifier les sous-classes des enfants. Une autre approche pourrait consister à récupérer Thread.getAllStackTraces() et à les parcourir tous (en particulier le thread "principal") à la recherche de la classe principale qui a démarré l'application, puis récupérer le manifeste de cette classe. Comme je l'ai dit, cependant, il n'y a probablement aucun moyen fiable à 100% de le faire, car l'application ne peut utiliser aucune sous-classe personnalisée et les piles des threads peuvent avoir un mélange d'applications différentes.

+0

L'idée était de créer une bibliothèque qui est attachée et fonctionne. J'avais peur s'il y avait un moyen de le faire de manière fiable. Je vais probablement forcer le développeur de l'application finale à créer un bean String avec un nom (+ package) de classe à partir de l'archive principale. C'est toujours facile à faire et beaucoup plus sûr. Merci pour votre réponse. Btw, joli hack avec traces de pile. –

2

Il existe une propriété système "sun.java.command" qui contient le nom du jar ou le nom de la classe plus tous les arguments de la méthode main(). Donc, pour l'invocation

java -jar test.jar arg1 arg2 

vous obtiendrez "test.jar arg1 arg2" et

java test.Test arg1 arg2 

la valeur de la propriété serait "test.Test arg1 arg2". Comme le suggère le nom de la propriété, il n'est pas "officiel" (il n'est pas nécessaire de travailler sur des implémentations non Sun/Oracle). Je l'ai vérifié sur Java 7, je ne sais pas quand il a été introduit.