1

I have to scan EARs to determine the version of one of its JARs, by reading the manifest...

I happen to have something like this to read: MyApplication.ear/MyLibrary.jar/META-INF/Manifest.MF

I can't figure how to do this the simplest way... i've been struggling with JarFile, JarInputStream, JarURLConnection, so far no luck.

Here's what i have at the time:

JarFile myEAR = new JarFile(urlOfMyEAR);
JarEntry myJAR = myEAR.getJarEntry(libname);
Attributes m = myJAR.getAttributes();
System.out.println(m.getValue("Implementation-Version"));

but the getAttributes() returns null...

I assume there's surely a complicated/thourough way to do it (by extracting the file or else), but I was hoping there's a simpler...

Thanks for your help.

EDIT: my own answer below...

pataluc
  • 569
  • 4
  • 19
  • Is the jar under your control? Do you use Maven? You could use maven "filtering" to inject your version number to any file you need it... – spi Jun 06 '16 at 09:44
  • it's not really in my control, I want to read versions of the application on multiple environments that I manage to integrate in a dashboard... the designated JAR is our framework, and I need to show my users along with the application version number the framework version number it's based on... – pataluc Jun 06 '16 at 09:48
  • 1
    If you were using Maven (or any sofisticated build tool) you could for example inject the various version number you are using directly into an html template at build time... Thus not needing to read a jar, thus not limitating your scope to the embedded dependencies - you could inject the (expected) JDBC driver version number for example, which should not be shipped in your ear.. Without Maven, you should try locating the jar, open it as a ZipFile, loop to find the right entry, then unzipping it in memory and finally parsing the manifest... but it is tricky – spi Jun 06 '16 at 10:00
  • thx spi, unfortunately my possibilities of changing existing processes is thin (big application in a big company), so i have to solve it on my own if i want a quick result (not very devops so far ^^). In the end using maven is a viable option that has been taken into consideration... – pataluc Jun 06 '16 at 13:49

2 Answers2

2

I manage to solve my problem by using this code:

JarFile myEAR = new JarFile(urlOfMyEAR);

File f = File.createTempFile("jar", null);
FileOutputStream resourceOS = new FileOutputStream(f);
byte[] byteArray = new byte[1024];
int i;

InputStream jarIS = myEAR.getInputStream(myEAR.getEntry(libname));
while ((i = jarIS.read(byteArray)) > 0) {
    //Write the bytes to the output stream
    resourceOS.write(byteArray, 0, i);
}
//Close streams to prevent errors
jarIS.close();
resourceOS.close();

JarFile myJAR = new JarFile(f);

Attributes m = myJAR.getManifest().getMainAttributes();

System.out.println(m.getValue("Implementation-Version"));

(thanks to this post https://stackoverflow.com/a/17902842/2454970)

the whole uncompressing takes only 7 seconds for a 7MB jar in a nearly 200MB ear...

thanks for your thoughts, guys.

Community
  • 1
  • 1
pataluc
  • 569
  • 4
  • 19
0

If your scanner runs in the same JVM with your application, you can get the manifest files like below:

Enumeration<URL> resources = this.getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
while(resources.hasMoreElements()){
    URL u = resources.nextElement();
    try(InputStream is = u.openStream()){
        if(is!=null){
            Manifest manifest = new Manifest(is);
            //do something blabla
        }
    }
}

If not, I think adding a simple jar to your application to collect these data then upload the results to you dashboard would be a better solution.

PaniniGelato
  • 565
  • 1
  • 5
  • 13
  • it is not on the same JVM, sadly... I'm not sure to understand by "adding a simple jar..." – pataluc Jun 06 '16 at 10:05
  • 1
    @Pataluc As you mentioned, the JAR is your framework. You can add the scanner in your framework, run on startup and upload the results. – PaniniGelato Jun 06 '16 at 10:26
  • I'm in a big company, I do not have access to the framework to modify it... ;( – pataluc Jun 06 '16 at 12:22
  • @pataluc if maven was used in all of your project, your can consider to develop a maven plugin to get the results by scanning the pom files. And you can integrate the plugin into the CI tools without any change of your application. or frameworks. – PaniniGelato Jun 07 '16 at 06:31