Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support a pass through mode for modification time of DataEntries in ZipWriter #121

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/ClassPathDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return -1;
}


@Override
public boolean isDirectory()
{
Expand Down
5 changes: 5 additions & 0 deletions base/src/main/java/proguard/io/DataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public interface DataEntry
*/
public long getSize();

/**
* Returns the modification time of this data entry in milliseconds,
* since the epoch (1970-01-01T00:00:00Z), or -1 if unknown.
*/
public long getModificationTime();
netomi marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns whether the data entry represents a directory.
Expand Down
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/DummyDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return -1;
}


@Override
public boolean isDirectory()
{
Expand Down
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/FileDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return file.lastModified();
}


@Override
public boolean isDirectory()
{
Expand Down
8 changes: 8 additions & 0 deletions base/src/main/java/proguard/io/NamedDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;

/**
* This <code>DataEntry</code> represents a named output entry with a parent.
Expand Down Expand Up @@ -68,6 +69,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return -1;
}


@Override
public boolean isDirectory()
{
Expand Down
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/StreamingDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return -1;
}


@Override
public boolean isDirectory()
{
Expand Down
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/WrappedDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return wrappedEntry.getModificationTime();
}


@Override
public boolean isDirectory()
{
Expand Down
6 changes: 6 additions & 0 deletions base/src/main/java/proguard/io/ZipDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return zipEntry.getLastModifiedTime().toMillis();
}

@Override
public boolean isDirectory()
{
Expand Down
7 changes: 7 additions & 0 deletions base/src/main/java/proguard/io/ZipFileDataEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ public long getSize()
}


@Override
public long getModificationTime()
{
return zipEntry.getLastModifiedTime().toMillis();
}


@Override
public boolean isDirectory()
{
Expand Down
77 changes: 68 additions & 9 deletions base/src/main/java/proguard/io/ZipWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
*/
package proguard.io;

import java.time.Instant;
import java.time.LocalDateTime;

import proguard.classfile.TypeConstants;
import proguard.util.StringMatcher;

import java.io.*;
import java.time.ZoneId;

/**
* This {@link DataEntryWriter} sends data entries to the zip files specified by
Expand Down Expand Up @@ -53,7 +57,7 @@ public ZipWriter(DataEntryWriter dataEntryWriter)
this(null,
1,
false,
0,
-1,
dataEntryWriter);
}

Expand All @@ -66,7 +70,8 @@ public ZipWriter(DataEntryWriter dataEntryWriter)
* uncompressed entries.
* @param useZip64 Whether to write out the archive in zip64 format.
* @param modificationTime the modification date and time of the zip
* entries, in DOS format.
* entries, in DOS format. If {@code -1}, the modification time
* of each {@link DataEntry} will be passed through.
* @param dataEntryWriter the data entry writer that can provide
* output streams for the zip archives.
*/
Expand Down Expand Up @@ -98,7 +103,8 @@ public ZipWriter(StringMatcher uncompressedFilter,
* @param extraUncompressedAlignment the desired alignment for the data of
* entries matching extraAlignmentFilter.
* @param modificationTime the modification date and time of the zip
* entries, in DOS format.
* entries, in DOS format. If {@code -1}, the modification time
* of each {@link DataEntry} will be passed through.
* @param dataEntryWriter the data entry writer that can provide
* output streams for the zip archives.
*/
Expand Down Expand Up @@ -129,7 +135,8 @@ public ZipWriter(StringMatcher uncompressedFilter,
* uncompressed entries.
* @param useZip64 Whether to write out the archive in zip64 format.
* @param modificationTime the modification date and time of the zip
* entries, in DOS format.
* entries, in DOS format. If {@code -1}, the modification time
* of each {@link DataEntry} will be passed through.
* @param dataEntryWriter the data entry writer that can provide
* output streams for the zip archives.
*/
Expand Down Expand Up @@ -161,7 +168,8 @@ public ZipWriter(StringMatcher uncompressedFilter,
* @param extraUncompressedAlignment the desired alignment for the data of
* entries matching extraAlignmentFilter.
* @param modificationTime the modification date and time of the zip
* entries, in DOS format.
* entries, in DOS format. If {@code -1}, the modification time
* of each {@link DataEntry} will be passed through.
* @param dataEntryWriter the data entry writer that can provide
* output streams for the zip archives.
*/
Expand Down Expand Up @@ -195,7 +203,8 @@ public ZipWriter(StringMatcher uncompressedFilter,
* @param extraUncompressedAlignment the desired alignment for the data of
* entries matching extraAlignmentFilter.
* @param modificationTime the modification date and time of the zip
* entries, in DOS format.
* entries, in DOS format. If {@code -1}, the modification time
* of each {@link DataEntry} will be passed through.
* @param dataEntryWriter the data entry writer that can provide
* output streams for the zip archives.
*/
Expand Down Expand Up @@ -240,13 +249,12 @@ public boolean createDirectory(DataEntry dataEntry) throws IOException
OutputStream outputStream =
currentZipOutput.createOutputStream(name,
false,
modificationTime);
getDosModificationTime(dataEntry));
outputStream.close();

return true;
}


@Override
public boolean sameOutputStream(DataEntry dataEntry1,
DataEntry dataEntry2)
Expand Down Expand Up @@ -290,7 +298,31 @@ public OutputStream createOutputStream(DataEntry dataEntry) throws IOException
currentZipOutput.createOutputStream(name,
compress1 && compress2,
uncompressedAlignment,
modificationTime);
getDosModificationTime(dataEntry));
}


/**
* Returns the modification time of a {@link DataEntry} in dos format.
* <p>
* If {@link ZipWriter#modificationTime} is -1, the modification time of the
* {@link DataEntry} will be used, otherwise {@link ZipWriter#modificationTime}
* will be used for all encountered {@link DataEntry}s.
* <p>
* If a {@link DataEntry} has no valid modification time, the {@link Instant#now()}
* will be assumed.
*/
private int getDosModificationTime(DataEntry dataEntry)
{
int dosModificationTime = modificationTime;
if (dosModificationTime == -1) {
long dataEntryModificationTime = dataEntry.getModificationTime();
if (dataEntryModificationTime == -1) {
dataEntryModificationTime = Instant.now().toEpochMilli();
}
dosModificationTime = (int) javaToDosTime(dataEntryModificationTime);
}
return dosModificationTime;
}


Expand Down Expand Up @@ -378,4 +410,31 @@ private void finish() throws IOException
currentZipOutput = null;
}
}

/*
* Utility method for conversion of a java time to dos time.
* Copied from
* https://github.com/apache/commons-compress/blob/master/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java
*
* Licenced under Apache Licence v2.
*/
private static final long DOSTIME_BEFORE_1980 = 1 << 21 | 1 << 16; // 0x210000

// version with integer overflow fixed - see https://bugs.openjdk.org/browse/JDK-8130914
private static long javaToDosTime(final long t)
{
final LocalDateTime ldt =
LocalDateTime.ofInstant(Instant.ofEpochMilli(t), ZoneId.systemDefault());

if (ldt.getYear() < 1980) {
return DOSTIME_BEFORE_1980;
}

return (ldt.getYear() - 1980 << 25
| ldt.getMonthValue() << 21
| ldt.getDayOfMonth() << 16
| ldt.getHour() << 11
| ldt.getMinute() << 5
| ldt.getSecond() >> 1) & 0xffffffffL;
}
}
Loading
Loading