How to read meta data from Manifest file

Chad Estes picture Chad Estes · Nov 5, 2015 · Viewed 7.9k times · Source

I'm trying to extract information from my manifest file to display in one of the methods in my jar file, but seem to be having some issues. Any help is appreciated.

Manifest file:

Manifest-Version: 1.0
Created-By: 1.8.0_60 (Oracle Corporation)
Main-Class: com.example.package1.myClass

Name: com/example/package1
Specification-Title: MyPackage
Specification-Version: v1.1
Specification-Vendor: MyCompanyName
Implementation-Title: MP
Implementation-Version: 2015-11-05-C
Implementation-Vendor: MyName

Name: com/example/package2
Specification-Title: MySecondaryPackage
Specification-Version: v2.0
Specification-Vendor: MyCompanyName
Implementation-Title: M2ndP
Implementation-Version: 2015-11-05-C
Implementation-Vendor: MyName

myClass.java:

package com.example.package1;
import com.example.package2;

class myClass {
  public static void main(String[] args) {
    try {
      myClass clz = new myClass();
      Thread.sleep(10000); //pause 10 seconnds so we can see what's spit out
    } catch (Exception e) {
    //excluded in example
    }
  }

  public myClass() {
    Package pkg = getClass().getPackage();
    if (pkg == null)
      System.out.println("No Package Found");
    else {
      System.out.println("specs: " + pkg.getSpecificationTitle() + " - " + pkg.getSpecificationVersion());
      System.out.println("imps:  " + pkg.getImplementationTitle() + " - " + pkg.getImplementationVersion());
      System.out.println("name:  " + pkg.getName());
    }
    //other code here excluded from example
  }
}

Output:

specs: null - null
imps:  null - null
name:  com.example.package1

So what gives? It looks like the pkg object is being defined correctly, but it doesn't read any of the Specification or Implementation properties.

Answer

Chad Estes picture Chad Estes · Nov 6, 2015

So I finally figured it out and thought I'd share incase anyone else was banging their head against the proverbial brick wall as much as I was. I never could get the methods in the Package class to return anything other than null. See revised code below for how I managed to pull it off.

package com.example.package1;
import java.util.*;
import java.util.jar.*;
import java.net.*;

class myClass {
  public static void main(String[] args) {
    try {
    new myClass();
    } catch (Exception e) {
    System.out.println(e.getMessage());
    } finally {
    System.out.println("Done");
    try{Thread.sleep(40000);}catch(Exception ee){}
    }
  }

public myClass() throws Exception {
  String clz = getClass().getSimpleName() + ".class";
  String pth = getClass().getResource(clz).toString();
  String mnf = pth.substring(0, pth.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
  String pkg = getClass().getPackage().getName().replaceAll("\\.","/");
  URL url = new URL(mnf);
  Manifest manifest = new Manifest(url.openStream());

  Attributes attr = manifest.getAttributes(pkg);
  String value = attr.getValue("Specification-Title") + " - " + 
  attr.getValue("Implementation-Title") + " " + 
  attr.getValue("Specification-Version") + " build # " + 
  attr.getValue("Implementation-Version");
  System.out.println(value);
  }
}

Output:

MyPackage - MP v1.1 build # 2015-11-05-C
Done

Which is a lot of code to extract four pieces of Metadata.

So if you like a few less lines here's what I used instead:

public myClass() throws Exception {
  Attributes attr = new Manifest(new URL(getClass().getResource(getClass().getSimpleName() + ".class").toString().substring(0, getClass().getResource(getClass().getSimpleName() + ".class").toString().lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF").openStream()).getAttributes(getClass().getPackage().getName().replaceAll("\\.","/"));
  String value = attr.getValue("Specification-Title") + " - " + attr.getValue("Implementation-Title") + " " + attr.getValue("Specification-Version") + " build # " + attr.getValue("Implementation-Version");
  System.out.println(value);
}