2010-09-23 19 views

Répondre

31

Code suivant devrait aider.

JarInputStream jarStream = new JarInputStream(stream); 
Manifest mf = jarStream.getManifest(); 

Gestion des exceptions est laissé pour vous :)

28

Vous pouvez utiliser quelque chose comme ceci:

public static String getManifestInfo() { 
    Enumeration resEnum; 
    try { 
     resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME); 
     while (resEnum.hasMoreElements()) { 
      try { 
       URL url = (URL)resEnum.nextElement(); 
       InputStream is = url.openStream(); 
       if (is != null) { 
        Manifest manifest = new Manifest(is); 
        Attributes mainAttribs = manifest.getMainAttributes(); 
        String version = mainAttribs.getValue("Implementation-Version"); 
        if(version != null) { 
         return version; 
        } 
       } 
      } 
      catch (Exception e) { 
       // Silently ignore wrong manifests on classpath? 
      } 
     } 
    } catch (IOException e1) { 
     // Silently ignore wrong manifests on classpath? 
    } 
    return null; 
} 

Pour obtenir les attributs manifestes, vous pouvez itérer sur la variable « mainAttribs » ou directement récupérer votre attribut nécessaire si vous connaissez la clé.

Ce code parcourt chaque fichier jar sur le chemin de classe et lit le MANIFEST de chacun. Si vous connaissez le nom du pot, vous voudrez peut-être à ne regarder que l'URL si elle contient() le nom du pot que vous êtes intéressé par

+1

Excellent que cela passe par tous Manifests. – HankCa

3

vous pouvez utiliser une classe utilitaire Manifests de jcabi-manifests:

final String value = Manifests.read("My-Version"); 

La classe trouvera tous MANIFEST.MF fichiers disponibles dans classpath et lire l'attribut que vous recherchez dans l'un d'entre eux. De plus, lisez ceci: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

+0

C'est génial et ça marche bien. Sympa que c'est une bibliothèque. Ce qui le rendrait meilleur, c'est que tous les Manifestes étaient lus. Je remarque que le Javadoc a un 'entry()', ce qui est peut-être ce que j'ai suggéré, mais cette méthode n'apparaît pas dans la version que j'utilise (1.1 - la dernière date à ce jour sur MvnRepository). La réponse http://stackoverflow.com/a/3777116/1019307 a la solution qui a fonctionné pour récupérer tous les Manifestes. – HankCa

7

Je mis en place une classe appversion selon quelques idées de stackoverflow, ici je viens de partager toute la classe:

import java.io.File; 
import java.net.URL; 
import java.util.jar.Attributes; 
import java.util.jar.Manifest; 

import org.apache.commons.lang.StringUtils; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class AppVersion { 
    private static final Logger log = LoggerFactory.getLogger(AppVersion.class); 

    private static String version; 

    public static String get() { 
    if (StringUtils.isBlank(version)) { 
     Class<?> clazz = AppVersion.class; 
     String className = clazz.getSimpleName() + ".class"; 
     String classPath = clazz.getResource(className).toString(); 
     if (!classPath.startsWith("jar")) { 
     // Class not from JAR 
     String relativePath = clazz.getName().replace('.', File.separatorChar) + ".class"; 
     String classFolder = classPath.substring(0, classPath.length() - relativePath.length() - 1); 
     String manifestPath = classFolder + "/META-INF/MANIFEST.MF"; 
     log.debug("manifestPath={}", manifestPath); 
     version = readVersionFrom(manifestPath); 
     } else { 
     String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF"; 
     log.debug("manifestPath={}", manifestPath); 
     version = readVersionFrom(manifestPath); 
     } 
    } 
    return version; 
    } 

    private static String readVersionFrom(String manifestPath) { 
    Manifest manifest = null; 
    try { 
     manifest = new Manifest(new URL(manifestPath).openStream()); 
     Attributes attrs = manifest.getMainAttributes(); 

     String implementationVersion = attrs.getValue("Implementation-Version"); 
     implementationVersion = StringUtils.replace(implementationVersion, "-SNAPSHOT", ""); 
     log.debug("Read Implementation-Version: {}", implementationVersion); 

     String implementationBuild = attrs.getValue("Implementation-Build"); 
     log.debug("Read Implementation-Build: {}", implementationBuild); 

     String version = implementationVersion; 
     if (StringUtils.isNotBlank(implementationBuild)) { 
     version = StringUtils.join(new String[] { implementationVersion, implementationBuild }, '.'); 
     } 
     return version; 
    } catch (Exception e) { 
     log.error(e.getMessage(), e); 
    } 
    return StringUtils.EMPTY; 
    } 
} 

Fondamentalement, cette classe peut lire les informations de version du manifeste de son propre fichier JAR, ou le manifeste dans son dossier de classes. Et j'espère que cela fonctionne sur différentes plates-formes, mais je l'ai seulement testé sur Mac OS X jusqu'à présent. J'espère que ce serait utile pour quelqu'un d'autre.

+1

Le seul problème avec ceci est la ligne contenant: String manifestPath = StringUtils.join [...] Utiliser File.separatorChar semble générer une URL invalide sous Windows ... probablement préférable d'utiliser "/" à la place. –

+1

Merci d'avoir signalé cela. Je vais essayer et le modifier. –

+0

Waw, ça marche.Je vous remercie! –

22

Je suggère de faire ce qui suit:

Package aPackage = MyClassName.class.getPackage(); 
String implementationVersion = aPackage.getImplementationVersion(); 
String implementationVendor = aPackage.getImplementationVendor(); 

Où MyClassName peut être une classe de votre demande écrite par vous.

+1

C'est ce dont j'ai besoin (pour lire 'Implementation-Version'). Malheureusement, cela n'a pas fonctionné pour moi sur les classes décompressées, bien que le manifeste se trouve dans 'META-INF/MANIFEST.MF'. –

+0

Cela ne fonctionne pas par défaut à moins que vous ajoutiez addDefaultImplementationEntries à true pour maven-jar-plugin afin qu'il y ait des informations de version. Par défaut, le fichier manifeste n'inclut rien. Aussi @Victor, essayez d'exécuter mvn package et voir l'intérieur s'il a des informations correctes. Généralement, cette configuration de version se trouve dans maven-jar-plugin ou maven-war-plugin, donc les classes non compressées ne l'ont pas. – wonhee

0

Restez simple. Un JAR est aussi un ZIP donc un code ZIP peut être utilisé pour lire le MAINFEST.MF:

public static String readManifest(String sourceJARFile) throws IOException 
{ 
    ZipFile zipFile = new ZipFile(sourceJARFile); 
    Enumeration entries = zipFile.entries(); 

    while (entries.hasMoreElements()) 
    { 
     ZipEntry zipEntry = (ZipEntry) entries.nextElement(); 
     if (zipEntry.getName().equals("META-INF/MANIFEST.MF")) 
     { 
      return toString(zipFile.getInputStream(zipEntry)); 
     } 
    } 

    throw new IllegalStateException("Manifest not found"); 
} 

private static String toString(InputStream inputStream) throws IOException 
{ 
    StringBuilder stringBuilder = new StringBuilder(); 
    try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) 
    { 
     String line; 
     while ((line = bufferedReader.readLine()) != null) 
     { 
      stringBuilder.append(line); 
      stringBuilder.append(System.lineSeparator()); 
     } 
    } 

    return stringBuilder.toString().trim() + System.lineSeparator(); 
} 

Malgré la flexibilité, pour la simple lecture des données this réponse est le meilleur.