2010-09-23 9 views

Trả lời

31

đang Tiếp theo sẽ giúp:. Xử lý

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

ngoại lệ còn lại cho bạn :)

28

Bạn có thể sử dụng một cái gì đó như thế này:

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

Để có được các thuộc tính biểu hiện, bạn có thể lặp qua các biến "mainAttribs" hoặc trực tiếp lấy thuộc tính cần thiết của bạn nếu bạn biết chìa khóa.

Mã này lặp qua mỗi bình trên đường dẫn lớp và đọc MANIFEST của từng loại. Nếu bạn biết tên của jar bạn có thể muốn chỉ nhìn vào URL nếu nó có chứa() tên của jar bạn quan tâm đến

+1

Tuyệt vời là điều này trải qua tất cả các Tệp kê khai. – HankCa

3

bạn có thể sử dụng một lớp tiện ích Manifests từ jcabi-manifests:

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

lớp sẽ tìm thấy tất cả MANIFEST.MF tệp có sẵn trong classpath và đọc thuộc tính bạn đang tìm kiếm từ một trong số chúng. Ngoài ra, đọc: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

+0

Điều này thật tuyệt vời và hoạt động tốt. Tốt đẹp đó là một thư viện. Điều gì sẽ làm cho nó tốt hơn là nếu tất cả Manifests được đọc. Tôi nhận thấy Javadoc có một 'entry()', có thể là những gì tôi đã đề xuất, tuy nhiên phương thức đó không xuất hiện trong phiên bản tôi đang sử dụng (1.1 - phiên bản mới nhất tại ngày này trên MvnRepository). Câu trả lời http://stackoverflow.com/a/3777116/1019307 có giải pháp đã làm việc để truy xuất tất cả các tệp kê khai. – HankCa

7

tôi thực hiện một lớp AppVersion theo một số ý tưởng từ stackoverflow, ở đây tôi chỉ chia sẻ toàn bộ lớp:

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

Về cơ bản, lớp này có thể đọc thông tin phiên bản từ manifest của nó tệp JAR riêng hoặc tệp kê khai trong thư mục lớp của nó. Và hy vọng nó hoạt động trên các nền tảng khác nhau, nhưng tôi chỉ thử nghiệm nó trên Mac OS X cho đến nay.

Tôi hy vọng điều này sẽ hữu ích cho người khác.

+1

Vấn đề duy nhất với điều này là dòng chứa: String manifestPath = StringUtils.join [...] Sử dụng File.separatorChar dường như tạo ra một URL không hợp lệ trong Windows ... có lẽ tốt nhất để sử dụng "/" thay thế. –

+1

Cảm ơn bạn đã chỉ ra điều này. Sẽ có một thử và sửa đổi nó. –

+0

Waw, Nó hoạt động.Cảm ơn bạn! –

22

tôi sẽ đề nghị để làm như sau:

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

đâu MyClassName thể được bất kỳ lớp từ ứng dụng của bạn bằng văn bản của bạn.

+1

Đây là điều tôi cần (để đọc 'Phiên bản thực hiện'). Đáng buồn thay, điều này không làm việc cho tôi về các lớp được giải nén, mặc dù bản kê khai nằm trong 'META-INF/MANIFEST.MF'. –

+0

Điều này không hoạt động theo mặc định trừ khi bạn thêm addDefaultImplementationEntries thành true cho maven-jar-plugin để nó thực sự có thông tin phiên bản trong đó. Theo tệp kê khai mặc định không bao gồm bất kỳ thứ gì. Ngoài ra @Victor, hãy thử chạy gói mvn và xem bên trong nếu nó có thông tin thích hợp. Nói chung, cấu hình phiên bản này nằm trong maven-jar-plugin hoặc maven-war-plugin, vì vậy các lớp chưa được đóng gói không có. – wonhee

0

Giữ đơn giản. Một JAR cũng là một ZIP nên bất kỳ mã ZIP có thể được sử dụng để đọc các 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(); 
} 

Mặc dù sự linh hoạt, chỉ đọc dữ liệu this câu trả lời là tốt nhất.