2010-09-23 6 views

risposta

31

codice seguente dovrebbe aiutare:. Maneggevolezza

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

Eccezione è a sinistra per voi :)

28

Si potrebbe usare qualcosa di simile:

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; 
} 

Per ottenere gli attributi si manifestano, si potrebbe iterare la variabile "mainAttribs" o direttamente recuperare l'attributo richiesto se si conosce la chiave.

Questo codice scorre in ogni jar del classpath e legge il MANIFEST di ciascuno. Se si conosce il nome del vaso si consiglia di guardare solo l'URL se contiene() il nome del vaso che ti interessa

+1

Eccellente che questo passa attraverso tutti i Manifesti. – HankCa

3

È possibile utilizzare una classe di utilità Manifests da jcabi-manifests:

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

La classe troverà tutti MANIFEST.MF file disponibili in classpath e leggi l'attributo che stai cercando da uno di essi. Inoltre, leggere questo: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

+0

Questo è ottimo e funziona bene. Bello che è una biblioteca. Ciò che farebbe meglio se tutti i Manifesti venissero letti. Ho notato che Javadoc ha un 'entry()', che potrebbe essere quello che ho suggerito, tuttavia quel metodo non appare nella versione che sto usando (1.1 - l'ultima a questa data su MvnRepository). La risposta http://stackoverflow.com/a/3777116/1019307 ha la soluzione che ha funzionato per recuperare tutti i Manifests. – HankCa

7

ho implementato una classe appVersion secondo alcune idee da StackOverflow, qui ho solo condivido l'intera 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; 
    } 
} 

In sostanza, questa classe in grado di leggere le informazioni sulla versione dal manifesto della sua proprio file JAR o manifest nella propria cartella delle classi. E speriamo che funzioni su piattaforme diverse, ma l'ho testato su Mac OS X finora.

Spero che questo possa essere utile per qualcun altro.

+1

L'unico problema con questa è la riga contenente: String manifestPath = StringUtils.join [...] L'uso di File.separatorChar sembra generare un URL non valido in Windows ... probabilmente meglio usare "/". –

+1

Grazie per aver segnalato questo. Avrà una prova e la modificherà. –

+0

Waw, funziona.Grazie! –

22

vorrei suggerire di fare seguente:

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

Dove MyClassName può essere qualsiasi classe dall'applicazione scritto da te.

+1

Questa è la cosa di cui ho bisogno (per leggere 'Implementation-Version'). Purtroppo, questo non ha funzionato per me sulle classi decompresse, sebbene il manifest sia in "META-INF/MANIFEST.MF". –

+0

Questo non funziona per impostazione predefinita a meno che non si aggiunga addDefaultImplementationEntries su true per maven-jar-plugin in modo che contenga effettivamente le informazioni sulla versione. Di default il file manifest non include nulla. Anche @Victor, prova ad eseguire il pacchetto mvn e vedere l'interno se ha informazioni corrette. Generalmente la configurazione di questa versione è in maven-jar-plugin o maven-war-plugin, quindi le classi non compresse non ce l'hanno. – wonhee

0

Semplicità. Un JAR è anche un ZIP in modo che qualsiasi codice ZIP può essere utilizzato per leggere il 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(); 
} 

Nonostante la flessibilità, solo per la lettura dei dati this risposta è il migliore.