Can someone please tell me a reliable way to get the last modification time of a Java resource? The resource can be a file or an entry in a JAR.
If you with "resource" mean something reachable through Class#getResource or ClassLoader#getResource, you can get the last modified time stamp through the URLConnection:
URL url = Test.class.getResource("/org/jdom/Attribute.class");
System.out.println(new Date(url.openConnection().getLastModified()));
Be aware that getLastModified() returns 0 if last modified is unknown, which unfortunately is impossible to distinguish from a real timestamp reading "January 1st, 1970, 0:00 UTC".
1/1/1970
as birthdate on websites that I don't want to give my personal details, safely in the knowledge that in the DB there will be just the value 0
:) –
Faerie The problem with url.openConnection().getLastModified()
is that getLastModified()
on a FileURLConnection creates an InputStream to that file. So you have to call urlConnection.getInputStream().close()
after getting last modified date. In contrast JarURLConnection creates the input stream when calling getInputStream().
Apache Commons VFS provides a generic way of interacting with files from different sources. FileObject.getContent() returns a FileContent object which has a method for retreiving the last modified time.
Here is a modified example from the VFS website:
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileObject;
...
FileSystemManager fsManager = VFS.getManager();
FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );
System.out.println( jarFile.getName().getBaseName() + " " + jarFile.getContent().getLastModifiedTime() );
// List the children of the Jar file
FileObject[] children = jarFile.getChildren();
System.out.println( "Children of " + jarFile.getName().getURI() );
for ( int i = 0; i < children.length; i++ )
{
System.out.println( children[ i ].getName().getBaseName() + " " + children[ i ].getContent().getLastModifiedTime());
}
I am currently using the following solution. The solution is the same like most of the other solutions in its initial steps, namely some getResource() and then openConnection().
But when I have the connection I am using the following code:
/**
* <p>Retrieve the last modified date of the connection.</p>
*
* @param con The connection.
* @return The last modified date.
* @throws IOException Shit happens.
*/
private static long getLastModified(URLConnection con) throws IOException {
if (con instanceof JarURLConnection) {
return ((JarURLConnection)con).getJarEntry().getTime();
} else {
return con.getLastModified();
}
}
The above code works on android and non-android, it returns the last modified date of the entry inside the ZIP if the resources is found inside an archive, otherwise it returns what it gets from the connection.
Bye
P.S.: The code still needs some brushing, there are some border cases where getJarEntry() is null.
Here is my code for getting the last modification time of your JAR
file or compiled class (when using an IDE
).
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.attribute.FileTime;
import java.text.DateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
public class ProgramBuildTime
{
private static String getJarName()
{
Class<?> currentClass = getCurrentClass();
return new File(currentClass.getProtectionDomain()
.getCodeSource()
.getLocation()
.getPath())
.getName();
}
private static Class<?> getCurrentClass()
{
return new Object() {}.getClass().getEnclosingClass();
}
private static boolean runningFromJAR()
{
String jarName = getJarName();
return jarName.endsWith(".jar");
}
public static String getLastModifiedDate() throws IOException, URISyntaxException
{
Date date;
if (runningFromJAR())
{
String jarFilePath = getJarName();
try (JarFile jarFile = new JarFile(jarFilePath))
{
long lastModifiedDate = 0;
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); )
{
String element = entries.nextElement().toString();
ZipEntry entry = jarFile.getEntry(element);
FileTime fileTime = entry.getLastModifiedTime();
long time = fileTime.toMillis();
if (time > lastModifiedDate)
{
lastModifiedDate = time;
}
}
date = new Date(lastModifiedDate);
}
} else
{
Class<?> currentClass = getCurrentClass();
URL resource = currentClass.getResource(currentClass.getSimpleName() + ".class");
switch (resource.getProtocol())
{
case "file":
date = new Date(new File(resource.toURI()).lastModified());
break;
default:
throw new IllegalStateException("No matching protocol found!");
}
}
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
return dateFormat.format(date);
}
}
© 2022 - 2024 — McMap. All rights reserved.