IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Lecture du manifest d'un jar dépendant.


Sujet :

Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut Lecture du manifest d'un jar dépendant.
    Bonjour à tous.
    Je suis actuellement confronté à un problème que je ne parviens pas à résoudre et j'espère que vous pourrez m'aider.
    J'explique :
    J'ai un jar "outils" qui contient un certain nombre de classes utilitaires me permettant de créer des "bundles" de données à injecter dans un système d'information.
    Afin de d'assurer la compatibilité de ces bundles, je veux stocker à l'intérieur la version du jar ayant servi à les créer.
    J'ai donc tout naturellement, dans la méthode permettant la création de bundle, écrit un code de ce style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            final InputStream stream = this.getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF"); //$NON-NLS-1$
            final Manifest man = new Manifest(stream);
    Mon gros problème c'est qu'en faisant cela, je ne récupère pas le manifest du jar dans lequel je suis, mais celui du jar principal (exécutable) ayant appelé ma classe.

    Quelqu'un a-t'il une idée pour forcer la lecture du manifest du jar qui contient la classe dans laquelle j'écris le code ?

  2. #2
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Bonjour,

    Pourquoi passer par le ClassLoader ?
    J'irai plutôt chercher la ressource directement dans le jar.

  3. #3
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    j'ai jamais essayé mais je me retournerai vers la classe Package en ayant des informations de version dans le manifeste du jar cible.
    On devrait pouvoir utiliser ce mécanisme pour récupérer des infos de version.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut
    Merci à vous pour vos réponses.
    Citation Envoyé par Jimmy_ Voir le message
    Bonjour,

    Pourquoi passer par le ClassLoader ?
    J'irai plutôt chercher la ressource directement dans le jar.
    C'est justement ce que je n'arrive pas à faire.
    Typiquement, mon jar peut être utilisé dans plusieurs applications différentes, je ne peux donc pas y accéder par un chemin absolu sur le disque vu que le path du ficher "*.jar" sera différent selon les applis.

    Citation Envoyé par professeur shadoko Voir le message
    j'ai jamais essayé mais je me retournerai vers la classe Package en ayant des informations de version dans le manifeste du jar cible.
    On devrait pouvoir utiliser ce mécanisme pour récupérer des infos de version.
    C'était une bonne idée, malheureusement, bien que mon jar possède un manifest, ces informations ne sont pas contenues dans les objets Package du jar.

    Voici le Manifest du jar en question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Manifest-Version: 1.0
    Ant-Version: Apache Ant 1.8.0
    Created-By: 1.5.0_22-b03 (Sun Microsystems Inc.)
     
    Name: DataLoad
    Specification-Title: DataLoad
    Specification-Version: 2.2.3.2
    Implementation-Date: 09/29/2010 03:50 PM
    C'est l'attribut "Specification-Version" que je veux récupérer.

    un bout de code pour tester la solution proposée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for (Package p :Package.getPackages()) {
        if (p.getName().startsWith("com.xxx.dataload")) {
            System.out.println(p.getName()+" impl :" + p.getImplementationVersion() + " spec :" +p.getSpecificationVersion());
        }
    }
    et la sortie correspondante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    com.xxx.dataload impl :null spec :null
    com.xxx.dataload.log.listeneretl impl :null spec :null
    com.xxx.dataload.log impl :null spec :null
    com.xxx.dataload.exception impl :null spec :null
    com.xxx.dataload.utils impl :null spec :null
    com.xxx.dataload.job impl :null spec :null
    com.xxx.dataload.threads impl :null spec :null
    com.xxx.dataload.model.excel.headers impl :null spec :null
    com.xxx.dataload.model.bundle impl :null spec :null
    com.xxx.dataload.model.excel.impl impl :null spec :null
    com.xxx.dataload.model.excel impl :null spec :null
    A moins que certaines options de compilation soient nécessaires dans mon jar pour écrire ces informations dans les packages à la compil ...

  5. #5
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 766
    Par défaut
    Dans ce cas le manifest ne convient pas. Il te faut nom unique ou une classe particulière qui porte ta version. Il suffirait alors de la chercher dans le classpath.

  6. #6
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    je ne comprends pas pourquoi dans ton cas: name=Dataload et ensuite tu cherches les packages com.xxx.dataload .... C'est quoi l'idée derrière?

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    je ne comprends pas pourquoi dans ton cas: name=Dataload et ensuite tu cherches les packages com.xxx.dataload .... C'est quoi l'idée derrière?
    Dataload, c'est le nom du jar, com.xxx.dataload.zzz sont le nom des packages contenus dans le jar.

    Citation Envoyé par Jimmy_ Voir le message
    Dans ce cas le manifest ne convient pas. Il te faut nom unique ou une classe particulière qui porte ta version. Il suffirait alors de la chercher dans le classpath.
    Ben, en fait, j'ai fini par trouver comment faire pour aller lire le manifest, mais c'est un peu tiré par les cheveux.

    Je vous mets ma solution si quelqu'un d'autre est confronté au même problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
           final Class< ? > clazz = this.getClass();
     
            final String className = clazz.getSimpleName();
            final String classFileName = className + ".class"; //$NON-NLS-1$
            final String pathToThisClass = clazz.getResource(classFileName).toString();
     
            final int mark = pathToThisClass.indexOf("/com/xxx/dataload"); //$NON-NLS-1$
     
            String pathToManifest = pathToThisClass.toString().substring(0, mark + 1);
            pathToManifest += "/META-INF/MANIFEST.MF"; //$NON-NLS-1$
            final Manifest manifest = new Manifest(new URL(pathToManifest).openStream());
     
            final String version = manifest.getAttributes("DataLoad").getValue(Attributes.Name.SPECIFICATION_VERSION); //$NON-NLS-1$

  8. #8
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par professeur shadoko Voir le message
    je ne comprends pas pourquoi dans ton cas: name=Dataload et ensuite tu cherches les packages com.xxx.dataload .... C'est quoi l'idée derrière?
    +1

    Dans le manifest les blocs indiquant les versions doivent être associé à un nom de package. En clair Name: doit indiqué le nom du package...



    Sinon, pour en revenir à ton problème : le classloader principal de l'application utilise plusieurs jar, et donc la méthode getResource() retourne le premier élément trouvée. Pour des classes c'est généralement parfait, mais pour d'autres ressources qui pourrait faire doublons c'est plus délicat.

    Il faut utiliser getResources() et parcourir la liste des éléments retournées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Enumeration<URL> en = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
    for (URL url : Collections.list(en)) {
        System.out.println(url);
    }


    Une autre solution serait d'utiliser l'emplacement de base du code, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
    Ceci te retourne le jar ou le répertoire de base contenant le fichier *.class courant.


    a++

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Dans le manifest les blocs indiquant les versions doivent être associé à un nom de package. En clair Name: doit indiqué le nom du package...
    ??
    Ça voudrait dire que, dans un même jar, on pourrait avoir plusieurs packages ayant des versions différentes ?
    Dans mon cas, c'est impossible car la compil est automatique via ant et du coup, tous les packages du même jar auront toujours la même version...

    Citation Envoyé par adiGuba Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Enumeration<URL> en = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
    for (URL url : Collections.list(en)) {
        System.out.println(url);
    }
    Une autre solution serait d'utiliser l'emplacement de base du code, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
    Ceci te retourne le jar ou le répertoire de base contenant le fichier *.class courant.
    Merci pour ces solutions qui me semblent largement plus robustes que la mienne. Je vais sans doute utiliser la première mais la deuxième me servira sans doute un jour.

  10. #10
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par targol Voir le message
    ??
    Ça voudrait dire que, dans un même jar, on pourrait avoir plusieurs packages ayant des versions différentes ?
    Dans mon cas, c'est impossible car la compil est automatique via ant et du coup, tous les packages du même jar auront toujours la même version...
    et bien alors c'est parfait tu documentes juste la version du package com.xxx.dataload et le tour est joué!

    (maintenant, entre nous soit dit, il y a là quelque chose d'étrange: que tu compiles tout d'un coup soit mais que les packages aient tous les mêmes numéros de version là j'ai des doutes ou alors votre gestion de version est zarbi; il n'empêche que tu peux avoir un package de référence qui serve de support à ta numérotation du jar)

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    (maintenant, entre nous soit dit, il y a là quelque chose d'étrange: que tu compiles tout d'un coup soit mais que les packages aient tous les mêmes numéros de version là j'ai des doutes ou alors votre gestion de version est zarbi; il n'empêche que tu peux avoir un package de référence qui serve de support à ta numérotation du jar)
    Pour être plus clair :
    "Dataload" est le nom d'un projet sous Eclipse qui contient un certain nombres de packages qui commencent tous par "com.xxx.dataload".
    Lors de la compilation Ant, le projet est compilé d'un block ce qui fait que tous les packages du projet ont forcement la même version.
    Je ne comprends pas en quoi c'est zarbi... mais je ne suis pas un spécialiste de ces questions

  12. #12
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par targol Voir le message
    Je ne comprends pas en quoi c'est zarbi... mais je ne suis pas un spécialiste de ces questions
    tout peux se discuter mais en principe:

    - quand on corrige le code d'une classe d'un package elle change de numéro de version

    - en java: quand une classe d'un package change de numero de version tout le package change de numero de version (il s'agit bien entendu d'un numero différent puisque si classe A passe en 1.1 et ensuite classe B passe en 1.1, leur package sera en 1.2 -ou autre-). On voit bien ici que si classe A passe en 1.1 les autres classes non modifiées restent en 1.0.

    - de la même manière: si le package X passe en 1.2 il n'y pas de raison pour que le package Y passe en 1.2 (il n'y a pas eu de modification dans ce package!)

    - ensuite si tu veux gérer ton numero de version de ta librairie pourquoi pas

    effectivement ça peut devenir pénible de dire que la version 1.3 de ta librairie est composée du package X en 1.2 et du package Y en 1.1 et alors on est tenté de dire que tous les numéros de version sont changés en même temps. Dans ce cas: les packages ne constituent plus des unités indépendantes (ça peut se concevoir) et on admet qu'ils changent de numéro de version sans modification d'une de leur classe.... C'est un choix .... on pourrait même continuer en disant que les classes changent de numero de version sans modification tant qu'on y est.
    On a alors une gestion très monolithique.... Dans votre cas c'est volontaire et issu d'un choix stratégique ou c'est un hasard?

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 33
    Par défaut
    Merci pour tes clarifications.
    Citation Envoyé par professeur shadoko Voir le message
    Dans votre cas c'est volontaire et issu d'un choix stratégique ou c'est un hasard?
    Bien que n'étant pas responsable de cette décision, je pense que c'est volontaire.
    Nous avons en effet une plateforme logicielle assez balaise composée de plus de 30 projets différents sur laquelle viennent se connecter de nombreuses applications, elle-mêmes composées de plusieurs projets Eclipse.
    Pour donner un exemple, l'application d'administration de la plateforme sur laquelle je travaille comporte à ce jour (elle est loin d'être finie) 15 projets différents et elle référence pas moins de 38jars.
    Étant donné que l'on gère les alignements de versions entre les différents projets, il deviendrait impossible de faire un simple build si on devait descendre les version à une granulométrie de niveau package.

    Merci néanmoins d'avoir éclairé ma lanterne à ce sujet.

  14. #14
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par targol Voir le message
    Étant donné que l'on gère les alignements de versions entre les différents projets, il deviendrait impossible de faire un simple build si on devait descendre les version à une granulométrie de niveau package.
    c'est un point de vue .... mais de là à dire que c'est impossible ....

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 12/10/2010, 11h58
  2. manifest d'un jar
    Par feridferid dans le forum Général Java
    Réponses: 1
    Dernier message: 30/01/2009, 09h23
  3. [débutant] Edition du manifest dans le .jar
    Par onzeaout dans le forum Langage
    Réponses: 9
    Dernier message: 09/10/2007, 17h23
  4. Réponses: 7
    Dernier message: 31/07/2007, 15h29
  5. [JAR]Fichier manifest dans un jar
    Par nicoo dans le forum Général Java
    Réponses: 2
    Dernier message: 10/03/2005, 08h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo