Get JAR compilation time
Asked Answered
A

2

8

I am trying to get the compilation time of the runnable JAR file I am exporting from Eclipse. One way to do this would probably be to get the modification time of the META-INF/MANIFEST.MF file. Unfortunately I can't seem to find a way to get this information (I know how to read the manifest itself using getResourceAsStream("/META-INF/MANIFEST.MF"), but I can't seem to be able to read its modification time).

Has anybody some insight on how to do it?

Adjuvant answered 29/3, 2012 at 14:39 Comment(0)
A
5

In the end, based on Aleks G's answer and others found elsewhere, I came up with a more robust solution (that e.g. works also on network shares):

public static Long getTime(Class<?> cl) {
    try {
        String rn = cl.getName().replace('.', '/') + ".class";
        JarURLConnection j = (JarURLConnection) cl.getClassLoader().getResource(rn).openConnection();
        return j.getJarFile().getEntry("META-INF/MANIFEST.MF").getTime();
    } catch (Exception e) {
        return null;
    }
}

I was hoping for a better way to go from the Class object to the resource name but I guess this will have to do.

Adjuvant answered 30/3, 2012 at 10:26 Comment(1)
You might want to replace ClassLoader.getSystemResource(rn) with cl.getClassLoader().getResource(rn) in case the class was not loaded using the system classloaderDaugavpils
S
7

If you have access to the jar file itself, you should be able to read the jar file using java.util.jar package, then get ZipEntry for the Manifest file and use getTime() on it to get its last update time.

JarFile jf = new JarFile("myfile.jar");
ZipEntry manifest = jf.getEntry("META-INF/MANIFEST.MF");
long manifestTime = manifest.getTime();  //in standard millis

If you need to deal with the specific class, then you may find this code also useful;

String rn = this.getClass().getName().replace('.', '/') + ".class";
String path = getClass().getClassLoader().getResource(rn).getPath();
String jarFile = path.substring(0, path.indexOf("!"));

Then jarFile will contain the path name of your jar. Note that if the class is not loaded from the jar file, then the third line will fail, as path.indexOf will return -1.

Suki answered 29/3, 2012 at 14:47 Comment(6)
Sure, but this breaks horribly if the jar is renamed. Can I get a reference to the actual JarFile my main class is being loaded from?Adjuvant
Yes, you should be able to get that through the classloader object.Suki
@Adjuvant I updated my answer to show how to get the name of the jar file having the class.Suki
Almost there. The problem is that the path variable won't contain an absolute path (when run from a jar file), but only the relative path inside the jar itself (i.e. something like com/strayorange/test/test.class). This means the following line will inevitably fail.Adjuvant
@Adjuvant That would be rather strange. As you're requesting the load path of the resource straight from the classloader, it should know the full path of the jar file.Suki
jarFile is prefixed with "file:". You need something like jarFile = jarFile.replace("file:", "") to get rid of it else the new JarFile() will fail.Aikoail
A
5

In the end, based on Aleks G's answer and others found elsewhere, I came up with a more robust solution (that e.g. works also on network shares):

public static Long getTime(Class<?> cl) {
    try {
        String rn = cl.getName().replace('.', '/') + ".class";
        JarURLConnection j = (JarURLConnection) cl.getClassLoader().getResource(rn).openConnection();
        return j.getJarFile().getEntry("META-INF/MANIFEST.MF").getTime();
    } catch (Exception e) {
        return null;
    }
}

I was hoping for a better way to go from the Class object to the resource name but I guess this will have to do.

Adjuvant answered 30/3, 2012 at 10:26 Comment(1)
You might want to replace ClassLoader.getSystemResource(rn) with cl.getClassLoader().getResource(rn) in case the class was not loaded using the system classloaderDaugavpils

© 2022 - 2024 — McMap. All rights reserved.