Skip to content

Commit 09d1236

Browse files
committed
Fix ZIP entries last modification time is rounded down
Zip archives store file modification times with a granularity of two seconds, so the times will either be rounded up or down. Plexus Archiver chooses to round up, but it assumes that Java 7 round the seconds down and Java 8 round them up. In reality that is not true. On Java 8 java.util.zip.ZipEntry.getTime() returns the same value set with java.util.zip.ZipEntry.setTime(), but that does not matter as the last modification time is again rounded down (if the seconds are odd value) when the entry is added to the archive. As a result Plexus Archiver rounds the seconds up or Java 7 and rounds them down on Java 8 or newer. Remove the Java version check so Plexus Archiver rounds up the last modification time on both Java 7 and Java 8+. Fixes #95
1 parent 818b01c commit 09d1236

File tree

2 files changed

+38
-37
lines changed

2 files changed

+38
-37
lines changed

src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java

+9-37
Original file line numberDiff line numberDiff line change
@@ -100,29 +100,6 @@ public abstract class AbstractZipArchiver
100100
*/
101101
protected boolean addingNewFiles = false;
102102

103-
/**
104-
* Whether the file modification times will be rounded up to the
105-
* next even number of seconds.
106-
* <p/>
107-
* <p>
108-
* Zip archives store file modification times with a
109-
* granularity of two seconds, so the times will either be rounded
110-
* up or down. If you round down, the archive will always seem
111-
* out-of-date when you rerun the task, so the default is to round
112-
* up. Rounding up may lead to a different type of problems like
113-
* JSPs inside a web archive that seem to be slightly more recent
114-
* than precompiled pages, rendering precompilation useless.</p>
115-
*
116-
* <p/>
117-
* plexus-archiver chooses to round up.
118-
* <p/>
119-
* Java versions up to java7 round timestamp down, which means we add a heuristic value (which is slightly
120-
* questionable)
121-
* Java versions from 8 and up round timestamp up.
122-
* s
123-
*/
124-
private static final boolean isJava7OrLower = getJavaVersion() <= 7;
125-
126103
// Renamed version of original file, if it exists
127104
private File renamedFile = null;
128105

@@ -134,19 +111,6 @@ public abstract class AbstractZipArchiver
134111

135112
protected ZipArchiveOutputStream zipArchiveOutputStream;
136113

137-
private static int getJavaVersion()
138-
{
139-
String javaSpecVersion = System.getProperty( "java.specification.version" );
140-
if ( javaSpecVersion.contains( "." ) )
141-
{//before jdk 9
142-
return Integer.parseInt( javaSpecVersion.split( "\\." )[1] );
143-
}
144-
else
145-
{
146-
return Integer.parseInt( javaSpecVersion );
147-
}
148-
}
149-
150114
public String getComment()
151115
{
152116
return comment;
@@ -569,7 +533,15 @@ public InputStream get()
569533

570534
private void setTime( java.util.zip.ZipEntry zipEntry, long lastModified )
571535
{
572-
zipEntry.setTime( lastModified + ( isJava7OrLower ? 1999 : 0 ) );
536+
// Zip archives store file modification times with a
537+
// granularity of two seconds, so the times will either be rounded
538+
// up or down. If you round down, the archive will always seem
539+
// out-of-date when you rerun the task, so the default is to round
540+
// up. Rounding up may lead to a different type of problems like
541+
// JSPs inside a web archive that seem to be slightly more recent
542+
// than precompiled pages, rendering precompilation useless.
543+
// plexus-archiver chooses to round up.
544+
zipEntry.setTime( lastModified + 1999 );
573545

574546
/* Consider adding extended file stamp support.....
575547

src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java

+29
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import java.io.FileWriter;
3131
import java.io.IOException;
3232
import java.io.InputStream;
33+
import java.nio.file.Files;
34+
import java.nio.file.attribute.FileTime;
3335
import java.util.Arrays;
3436
import java.util.Date;
3537
import java.util.Enumeration;
@@ -627,6 +629,33 @@ public void testSymlinkArchivedFileSet()
627629
ArchiveFileComparator.assertEquals( cmp1, cmp2, "" );
628630
}
629631

632+
/*
633+
* Zip archives store file modification times with a granularity of two seconds.
634+
* Verify that ZipArchiver rounds up the last modified time.
635+
*/
636+
public void testLastModifiedTimeRounding()
637+
throws Exception
638+
{
639+
File oddSecondsTimestampFile = File.createTempFile( "odd-seconds-timestamp", null );
640+
oddSecondsTimestampFile.deleteOnExit();
641+
// The milliseconds part is set to zero as not all filesystem support timestamp more granular than second.
642+
Files.setLastModifiedTime( oddSecondsTimestampFile.toPath(), FileTime.fromMillis( 1534189011_000L ) );
643+
File evenSecondsTimestampFile = File.createTempFile( "even-seconds-timestamp", null );
644+
evenSecondsTimestampFile.deleteOnExit();
645+
Files.setLastModifiedTime( evenSecondsTimestampFile.toPath(), FileTime.fromMillis( 1534189012_000L ) );
646+
647+
File destFile = getTestFile( "target/output/last-modified-time.zip" );
648+
ZipArchiver archiver = getZipArchiver( destFile );
649+
archiver.addFile( oddSecondsTimestampFile, "odd-seconds" );
650+
archiver.addFile( evenSecondsTimestampFile, "even-seconds" );
651+
archiver.createArchive();
652+
653+
// verify that the last modified time of the entry is equal or newer than the original file
654+
ZipFile resultingZipFile = new ZipFile( destFile );
655+
assertEquals( 1534189012_000L, resultingZipFile.getEntry( "odd-seconds" ).getTime() );
656+
assertEquals( 1534189012_000L, resultingZipFile.getEntry( "even-seconds" ).getTime() );
657+
}
658+
630659
/*
631660
*/
632661
public void testForced()

0 commit comments

Comments
 (0)