2010-09-23 72 views

回答

31

接下來的代碼應幫助:

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

異常處理是留給你:)

28

你可以使用這樣的事情:

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

要獲得清單屬性,你可以在變量迭代「mainAttribs」或直接檢索您需要的屬性,如果你知道的關鍵。

此代碼遍歷類路徑上的每個jar並讀取每個jar的清單。如果你知道罐子裏的名字,你可能只想看看它是否包含()你有興趣在罐子的名稱對應的URL

+1

非常好,這通過所有清單。 – HankCa 2016-05-18 01:36:44

3

您可以使用一個工具類Manifestsjcabi-manifests

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

類會發現所有在classpath中可用的個文件,並從其中一個文件中讀取要查找的屬性。此外,閱讀這樣的:http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

+0

這很棒,效果很好。很高興它是一個圖書館。如果所有的清單都被讀過,那麼更好的辦法是什麼。我注意到Javadoc有一個'entry()',這可能是我的建議,但是這個方法並沒有出現在我使用的版本中(1.1 - 這是MvnRepository上的最新版本)。答案http://stackoverflow.com/a/3777116/1019307有找到所有清單的解決方案。 – HankCa 2016-05-18 01:35:37

7

我根據從計算器一些想法實現的AppVersion類,在這裏我只是共享整個類:

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

基本上,這個類可以從清單讀版本信息的自己的JAR文件或其classes文件夾中的清單。希望它可以在不同的平臺上工作,但我只在Mac OS X上測試過。

我希望這對其他人有用。

+1

唯一的問題是這個行包含:String manifestPath = StringUtils.join [...]使用File.separatorChar似乎在Windows下生成一個無效的URL ...可能最好使用「/」代替。 – 2013-07-24 11:38:19

+1

感謝您指出這一點。將嘗試並修改它。 – 2013-07-24 13:38:25

+0

Waw,它的工作。謝謝! – 2016-12-05 18:04:13

22

我建議做以下幾點:

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

哪裏MyClassName可以從你寫你的應用程序的任何類。

+1

這是我需要的東西(閱讀'Implementation-Version')。可悲的是,這對解開的類沒有幫助,儘管這個清單是在'META-INF/MANIFEST.MF'中。 – 2016-03-02 10:27:41

+0

默認情況下這不起作用,除非您爲maven-jar-plugin添加addDefaultImplementationEntries爲true,以便它實際上包含版本信息。默認情況下,Manifest文件不包含任何內容。另外@Victor,嘗試運行mvn包並查看裏面是否有適當的信息。通常這些版本配置在maven-jar-plugin或maven-war-plugin中,所以未打包的類沒有它。 – wonhee 2016-04-06 00:46:45

0

保持簡單。一個JAR也是ZIP所以任何ZIP代碼可用於讀取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(); 
} 

儘管靈活性,只是讀取數據this答案是最好的。