This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push: new 22a1d2d6a Drop reflection from ExtraFieldUtils static initialization (#480) 22a1d2d6a is described below commit 22a1d2d6a9c1310141426d1298f3caa57cf8529e Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Sat Feb 10 21:40:23 2024 +0100 Drop reflection from ExtraFieldUtils static initialization (#480) * Drop reflection from ExtraFieldUtils * [tests] fix IT (wrong assert usage) * [deprecation] deprecate ExtraFieldUtils#register which is not globally usable except in the single case you are in a flat leaf classloader case and you register the extra field support for the lifetime of the app [compress] is deployed into * [fixes] fix @since tags and javadoc build, plus ensure backward compat with extra fields implementation registration --- .../compress/archivers/zip/AsiExtraField.java | 2 +- .../compress/archivers/zip/ExtraFieldUtils.java | 65 +++++++---- .../commons/compress/archivers/zip/JarMarker.java | 2 +- .../archivers/zip/X0014_X509Certificates.java | 4 +- .../archivers/zip/X0015_CertificateIdForFile.java | 4 +- .../X0016_CertificateIdForCentralDirectory.java | 4 +- .../zip/X0017_StrongEncryptionHeader.java | 4 +- .../X0019_EncryptionRecipientCertificateList.java | 4 +- .../compress/archivers/zip/X7875_NewUnix.java | 2 +- .../compress/archivers/zip/ZipArchiveEntry.java | 119 +++++++++++++++++++-- .../archivers/zip/ZipArchiveInputStream.java | 16 +++ .../zip/ZipSplitReadOnlySeekableByteChannel.java | 1 + .../compress/archivers/tar/FileTimesIT.java | 38 +++---- 13 files changed, 209 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/AsiExtraField.java b/src/main/java/org/apache/commons/compress/archivers/zip/AsiExtraField.java index 856c4c918..57c7a7b8f 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/AsiExtraField.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/AsiExtraField.java @@ -61,7 +61,7 @@ import java.util.zip.ZipException; */ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable { - private static final ZipShort HEADER_ID = new ZipShort(0x756E); + static final ZipShort HEADER_ID = new ZipShort(0x756E); private static final int MIN_SIZE = WORD + SHORT + WORD + SHORT + SHORT; /** diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java b/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java index a90131b19..0a2c84260 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java @@ -16,11 +16,14 @@ */ package org.apache.commons.compress.archivers.zip; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import java.util.zip.ZipException; /** @@ -113,24 +116,25 @@ public class ExtraFieldUtils { /** * Static registry of known extra fields. */ - private static final Map<ZipShort, Class<?>> IMPLEMENTATIONS; + private static final Map<ZipShort, Supplier<ZipExtraField>> IMPLEMENTATIONS; static { - IMPLEMENTATIONS = new ConcurrentHashMap<>(); - register(AsiExtraField.class); - register(X5455_ExtendedTimestamp.class); - register(X7875_NewUnix.class); - register(JarMarker.class); - register(UnicodePathExtraField.class); - register(UnicodeCommentExtraField.class); - register(Zip64ExtendedInformationExtraField.class); - register(X000A_NTFS.class); - register(X0014_X509Certificates.class); - register(X0015_CertificateIdForFile.class); - register(X0016_CertificateIdForCentralDirectory.class); - register(X0017_StrongEncryptionHeader.class); - register(X0019_EncryptionRecipientCertificateList.class); - register(ResourceAlignmentExtraField.class); + IMPLEMENTATIONS = new ConcurrentHashMap<>(); // it can't be used at runtime by design so no need to be concurrent + // IMPLEMENTATIONS = new HashMap<>(); // see register() comment + IMPLEMENTATIONS.put(AsiExtraField.HEADER_ID, AsiExtraField::new); + IMPLEMENTATIONS.put(X5455_ExtendedTimestamp.HEADER_ID, X5455_ExtendedTimestamp::new); + IMPLEMENTATIONS.put(X7875_NewUnix.HEADER_ID, X7875_NewUnix::new); + IMPLEMENTATIONS.put(JarMarker.ID, JarMarker::new); + IMPLEMENTATIONS.put(UnicodePathExtraField.UPATH_ID, UnicodePathExtraField::new); + IMPLEMENTATIONS.put(UnicodeCommentExtraField.UCOM_ID, UnicodeCommentExtraField::new); + IMPLEMENTATIONS.put(Zip64ExtendedInformationExtraField.HEADER_ID, Zip64ExtendedInformationExtraField::new); + IMPLEMENTATIONS.put(X000A_NTFS.HEADER_ID, X000A_NTFS::new); + IMPLEMENTATIONS.put(X0014_X509Certificates.HEADER_ID, X0014_X509Certificates::new); + IMPLEMENTATIONS.put(X0015_CertificateIdForFile.HEADER_ID, X0015_CertificateIdForFile::new); + IMPLEMENTATIONS.put(X0016_CertificateIdForCentralDirectory.HEADER_ID, X0016_CertificateIdForCentralDirectory::new); + IMPLEMENTATIONS.put(X0017_StrongEncryptionHeader.HEADER_ID, X0017_StrongEncryptionHeader::new); + IMPLEMENTATIONS.put(X0019_EncryptionRecipientCertificateList.HEADER_ID, X0019_EncryptionRecipientCertificateList::new); + IMPLEMENTATIONS.put(ResourceAlignmentExtraField.ID, ResourceAlignmentExtraField::new); } static final ZipExtraField[] EMPTY_ZIP_EXTRA_FIELD_ARRAY = {}; @@ -163,9 +167,9 @@ public class ExtraFieldUtils { * @since 1.19 */ public static ZipExtraField createExtraFieldNoDefault(final ZipShort headerId) throws InstantiationException, IllegalAccessException { - final Class<?> c = IMPLEMENTATIONS.get(headerId); - if (c != null) { - return (ZipExtraField) c.newInstance(); + final Supplier<ZipExtraField> provider = IMPLEMENTATIONS.get(headerId); + if (provider != null) { + return provider.get(); } return null; } @@ -379,11 +383,30 @@ public class ExtraFieldUtils { * </p> * * @param c the class to register + * + * @deprecated use {@link ZipArchiveInputStream#setExtraFieldSupport} instead + * to not leak instances between archives and applications. */ + @Deprecated // note: when dropping update registration to move to a HashMap (static init) public static void register(final Class<?> c) { try { - final ZipExtraField ze = (ZipExtraField) c.getConstructor().newInstance(); - IMPLEMENTATIONS.put(ze.getHeaderId(), c); + final Constructor<? extends ZipExtraField> constructor = c + .asSubclass(ZipExtraField.class) + .getConstructor(); + final ZipExtraField ze = constructor.newInstance(); + IMPLEMENTATIONS.put(ze.getHeaderId(), () -> { + try { + return constructor.newInstance(); + } catch (final InstantiationException | IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (final InvocationTargetException e) { + final Throwable cause = e.getTargetException(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } + throw new IllegalStateException(cause); + } + }); } catch (final ClassCastException cc) { // NOSONAR throw new IllegalArgumentException(c + " doesn't implement ZipExtraField"); // NOSONAR } catch (final InstantiationException ie) { // NOSONAR diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/JarMarker.java b/src/main/java/org/apache/commons/compress/archivers/zip/JarMarker.java index 031dc00e1..093a940e9 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/JarMarker.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/JarMarker.java @@ -27,7 +27,7 @@ import org.apache.commons.compress.utils.ByteUtils; */ public final class JarMarker implements ZipExtraField { - private static final ZipShort ID = new ZipShort(0xCAFE); + static final ZipShort ID = new ZipShort(0xCAFE); private static final ZipShort NULL = new ZipShort(0); private static final JarMarker DEFAULT = new JarMarker(); diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X0014_X509Certificates.java b/src/main/java/org/apache/commons/compress/archivers/zip/X0014_X509Certificates.java index aa4b985d5..93a690d05 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X0014_X509Certificates.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X0014_X509Certificates.java @@ -44,8 +44,10 @@ package org.apache.commons.compress.archivers.zip; */ public class X0014_X509Certificates extends PKWareExtraHeader { + static final ZipShort HEADER_ID = new ZipShort(0x0014); + public X0014_X509Certificates() { - super(new ZipShort(0x0014)); + super(HEADER_ID); } } diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X0015_CertificateIdForFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/X0015_CertificateIdForFile.java index 79c51925e..bd01381aa 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X0015_CertificateIdForFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X0015_CertificateIdForFile.java @@ -47,12 +47,14 @@ import java.util.zip.ZipException; */ public class X0015_CertificateIdForFile extends PKWareExtraHeader { + static final ZipShort HEADER_ID = new ZipShort(0x0015); + private int rcount; private HashAlgorithm hashAlg; public X0015_CertificateIdForFile() { - super(new ZipShort(0x0015)); + super(HEADER_ID); } /** diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X0016_CertificateIdForCentralDirectory.java b/src/main/java/org/apache/commons/compress/archivers/zip/X0016_CertificateIdForCentralDirectory.java index 4af4bef54..43bd0da45 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X0016_CertificateIdForCentralDirectory.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X0016_CertificateIdForCentralDirectory.java @@ -48,12 +48,14 @@ import java.util.zip.ZipException; */ public class X0016_CertificateIdForCentralDirectory extends PKWareExtraHeader { + static final ZipShort HEADER_ID = new ZipShort(0x0016); + private int rcount; private HashAlgorithm hashAlg; public X0016_CertificateIdForCentralDirectory() { - super(new ZipShort(0x0016)); + super(HEADER_ID); } /** diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X0017_StrongEncryptionHeader.java b/src/main/java/org/apache/commons/compress/archivers/zip/X0017_StrongEncryptionHeader.java index fca05a6ac..d579949bd 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X0017_StrongEncryptionHeader.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X0017_StrongEncryptionHeader.java @@ -257,6 +257,8 @@ import java.util.zip.ZipException; */ public class X0017_StrongEncryptionHeader extends PKWareExtraHeader { + static final ZipShort HEADER_ID = new ZipShort(0x0017); + private int format; // TODO written but not read private EncryptionAlgorithm algId; @@ -279,7 +281,7 @@ public class X0017_StrongEncryptionHeader extends PKWareExtraHeader { private byte[] vCRC32; public X0017_StrongEncryptionHeader() { - super(new ZipShort(0x0017)); + super(HEADER_ID); } private void assertDynamicLengthFits(final String what, final int dynamicLength, final int prefixLength, final int length) throws ZipException { diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X0019_EncryptionRecipientCertificateList.java b/src/main/java/org/apache/commons/compress/archivers/zip/X0019_EncryptionRecipientCertificateList.java index a3e5af807..9922a5847 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X0019_EncryptionRecipientCertificateList.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X0019_EncryptionRecipientCertificateList.java @@ -50,8 +50,10 @@ package org.apache.commons.compress.archivers.zip; */ public class X0019_EncryptionRecipientCertificateList extends PKWareExtraHeader { + static final ZipShort HEADER_ID = new ZipShort(0x0019); + public X0019_EncryptionRecipientCertificateList() { - super(new ZipShort(0x0019)); + super(HEADER_ID); } } diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/X7875_NewUnix.java b/src/main/java/org/apache/commons/compress/archivers/zip/X7875_NewUnix.java index e36b187bc..fee17e57c 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/X7875_NewUnix.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/X7875_NewUnix.java @@ -57,7 +57,7 @@ import org.apache.commons.compress.utils.ByteUtils; * @since 1.5 */ public class X7875_NewUnix implements ZipExtraField, Cloneable, Serializable { - private static final ZipShort HEADER_ID = new ZipShort(0x7875); + static final ZipShort HEADER_ID = new ZipShort(0x7875); private static final ZipShort ZERO = new ZipShort(0); private static final BigInteger ONE_THOUSAND = BigInteger.valueOf(1000); private static final long serialVersionUID = 1L; diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java index 125437d04..8ddded61c 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java @@ -30,6 +30,7 @@ import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.function.Function; import java.util.zip.ZipEntry; import java.util.zip.ZipException; @@ -265,6 +266,7 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn private long dataOffset = OFFSET_UNKNOWN; private boolean isStreamContiguous; private NameSource nameSource = NameSource.NAME; + private final Function<ZipShort, ZipExtraField> extraFieldFactory; private CommentSource commentSource = CommentSource.COMMENT; @@ -288,11 +290,13 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn * will be stripped from the entry name. * </p> * + * @param extraFieldFactory custom lookup factory for extra fields or null * @param inputFile file to create the entry from * @param entryName name of the entry + * @since 1.26.0 */ - public ZipArchiveEntry(final File inputFile, final String entryName) { - this(inputFile.isDirectory() && !entryName.endsWith("/") ? entryName + "/" : entryName); + ZipArchiveEntry(final Function<ZipShort, ZipExtraField> extraFieldFactory, final File inputFile, final String entryName) { + this(extraFieldFactory, inputFile.isDirectory() && !entryName.endsWith("/") ? entryName + "/" : entryName); try { setAttributes(inputFile.toPath()); } catch (final IOException e) { // NOSONAR @@ -303,6 +307,21 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn } } + /** + * Creates a new ZIP entry taking some information from the given file and using the provided name. + * + * <p> + * The name will be adjusted to end with a forward slash "/" if the file is a directory. If the file is not a directory a potential trailing forward slash + * will be stripped from the entry name. + * </p> + * + * @param inputFile file to create the entry from + * @param entryName name of the entry + */ + public ZipArchiveEntry(final File inputFile, final String entryName) { + this(null, inputFile, entryName); + } + /** * Creates a new ZIP entry with fields taken from the specified ZIP entry. * @@ -314,11 +333,29 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn * @throws ZipException on error */ public ZipArchiveEntry(final java.util.zip.ZipEntry entry) throws ZipException { + this(null, entry); + } + + /** + * Creates a new ZIP entry with fields taken from the specified ZIP entry. + * + * <p> + * Assumes the entry represents a directory if and only if the name ends with a forward slash "/". + * </p> + * + * @param extraFieldFactory the extra field lookup factory. + * @param entry the entry to get fields from + * @throws ZipException on error + * @since 1.26.0 + */ + ZipArchiveEntry(final Function<ZipShort, ZipExtraField> extraFieldFactory, + final java.util.zip.ZipEntry entry) throws ZipException { super(entry); + this.extraFieldFactory = extraFieldFactory; setName(entry.getName()); final byte[] extra = entry.getExtra(); if (extra != null) { - setExtraFields(ExtraFieldUtils.parse(extra, true, ExtraFieldParsingMode.BEST_EFFORT)); + setExtraFields(parseExtraFields(extra, true, ExtraFieldParsingMode.BEST_EFFORT)); } else { // initializes extra data to an empty byte array setExtra(); @@ -342,7 +379,27 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn * @since 1.21 */ public ZipArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException { - this(Files.isDirectory(inputPath, options) && !entryName.endsWith("/") ? entryName + "/" : entryName); + this(null, inputPath, entryName, options); + } + + /** + * Creates a new ZIP entry taking some information from the given path and using the provided name. + * + * <p> + * The name will be adjusted to end with a forward slash "/" if the file is a directory. If the file is not a directory a potential trailing forward slash + * will be stripped from the entry name. + * </p> + * + * @param extraFieldFactory custom lookup factory for extra fields or null + * @param inputPath path to create the entry from. + * @param entryName name of the entry. + * @param options options indicating how symbolic links are handled. + * @throws IOException if an I/O error occurs. + * @since 1.26.0 + */ + ZipArchiveEntry(final Function<ZipShort, ZipExtraField> extraFieldFactory, + final Path inputPath, final String entryName, final LinkOption... options) throws IOException { + this(extraFieldFactory, Files.isDirectory(inputPath, options) && !entryName.endsWith("/") ? entryName + "/" : entryName); setAttributes(inputPath, options); } @@ -354,9 +411,27 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn * </p> * * @param name the name of the entry + * @since 1.26.0 */ public ZipArchiveEntry(final String name) { + this((Function<ZipShort, ZipExtraField>) null, name); + } + + /** + * Creates a new ZIP entry with the specified name. + * + * <p> + * Assumes the entry represents a directory if and only if the name ends with a forward slash "/". + * </p> + * + * @param extraFieldFactory custom lookup factory for extra fields or null + * @param name the name of the entry + * @since 1.26.0 + */ + ZipArchiveEntry(final Function<ZipShort, ZipExtraField> extraFieldFactory, + final String name) { super(name); + this.extraFieldFactory = extraFieldFactory; setName(name); } @@ -642,9 +717,9 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn return getExtraFields(false); } final byte[] local = getExtra(); - final List<ZipExtraField> localFields = new ArrayList<>(Arrays.asList(ExtraFieldUtils.parse(local, true, parsingBehavior))); + final List<ZipExtraField> localFields = new ArrayList<>(Arrays.asList(parseExtraFields(local, true, parsingBehavior))); final byte[] central = getCentralDirectoryExtra(); - final List<ZipExtraField> centralFields = new ArrayList<>(Arrays.asList(ExtraFieldUtils.parse(central, false, parsingBehavior))); + final List<ZipExtraField> centralFields = new ArrayList<>(Arrays.asList(parseExtraFields(central, false, parsingBehavior))); final List<ZipExtraField> merged = new ArrayList<>(); for (final ZipExtraField l : localFields) { ZipExtraField c; @@ -1079,7 +1154,7 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn */ public void setCentralDirectoryExtra(final byte[] b) { try { - mergeExtraFields(ExtraFieldUtils.parse(b, false, ExtraFieldParsingMode.BEST_EFFORT), false); + mergeExtraFields(parseExtraFields(b, false, ExtraFieldParsingMode.BEST_EFFORT), false); } catch (final ZipException e) { // actually this is not possible as of Commons Compress 1.19 throw new IllegalArgumentException(e.getMessage(), e); // NOSONAR @@ -1157,7 +1232,7 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn @Override public void setExtra(final byte[] extra) throws RuntimeException { try { - mergeExtraFields(ExtraFieldUtils.parse(extra, true, ExtraFieldParsingMode.BEST_EFFORT), true); + mergeExtraFields(parseExtraFields(extra, true, ExtraFieldParsingMode.BEST_EFFORT), true); } catch (final ZipException e) { // actually this is not possible as of Commons Compress 1.1 throw new IllegalArgumentException("Error parsing extra fields for entry: " // NOSONAR @@ -1456,4 +1531,32 @@ public class ZipArchiveEntry extends java.util.zip.ZipEntry implements ArchiveEn } } } + + private ZipExtraField[] parseExtraFields(final byte[] data, final boolean local, + final ExtraFieldParsingBehavior parsingBehavior) throws ZipException { + if (extraFieldFactory != null) { + return ExtraFieldUtils.parse(data, local, new ExtraFieldParsingBehavior() { + @Override + public ZipExtraField createExtraField(final ZipShort headerId) throws ZipException, InstantiationException, IllegalAccessException { + final ZipExtraField field = extraFieldFactory.apply(headerId); + return field == null ? parsingBehavior.createExtraField(headerId) : field; + } + + @Override + public ZipExtraField fill(final ZipExtraField field, + final byte[] data, final int off, final int len, + final boolean local) throws ZipException { + return parsingBehavior.fill(field, data, off, len, local); + } + + @Override + public ZipExtraField onUnparseableExtraField( + final byte[] data, final int off, final int len, + final boolean local, final int claimedLength) throws ZipException { + return parsingBehavior.onUnparseableExtraField(data, off, len, local, claimedLength); + } + }); + } + return ExtraFieldUtils.parse(data, local, parsingBehavior); + } } diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java index 7b017bdee..d3b493fd6 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java @@ -33,6 +33,7 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Objects; +import java.util.function.Function; import java.util.zip.CRC32; import java.util.zip.DataFormatException; import java.util.zip.Inflater; @@ -292,6 +293,11 @@ public class ZipArchiveInputStream extends ArchiveInputStream<ZipArchiveEntry> i private int entriesRead; + /** + * The factory for extra fields or null. + */ + private Function<ZipShort, ZipExtraField> extraFieldSupport; + /** * Constructs an instance using UTF-8 encoding * @@ -360,6 +366,16 @@ public class ZipArchiveInputStream extends ArchiveInputStream<ZipArchiveEntry> i buf.limit(0); } + /** + * Enable custom extra fields factory. + * @param extraFieldSupport the lookup function based on extra field header id. + * @return the archive. + */ + public ZipArchiveInputStream setExtraFieldSupport(final Function<ZipShort, ZipExtraField> extraFieldSupport) { + this.extraFieldSupport = extraFieldSupport; + return this; + } + /** * Checks whether the current buffer contains the signature of a "data descriptor", "local file header" or "central directory * entry". diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java index 29815d25a..43ea678d8 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java @@ -197,6 +197,7 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy * * @param paths the file paths to concatenate, note that the LAST FILE of files should be the LAST SEGMENT(.zip) and these files should be added in correct * order (e.g.: .z01, .z02... .z99, .zip) + * @param openOptions the options to open paths (shared by all paths). * @return SeekableByteChannel that concatenates all provided files * @throws NullPointerException if files is null * @throws IOException if opening a channel for one of the files fails diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/FileTimesIT.java b/src/test/java/org/apache/commons/compress/archivers/tar/FileTimesIT.java index ed8d6c0ea..d5414a62a 100644 --- a/src/test/java/org/apache/commons/compress/archivers/tar/FileTimesIT.java +++ b/src/test/java/org/apache/commons/compress/archivers/tar/FileTimesIT.java @@ -52,7 +52,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime"); @@ -62,7 +62,7 @@ public class FileTimesIT extends AbstractTest { e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime"); @@ -81,7 +81,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveInputStream tin = new TarArchiveInputStream(in)) { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime"); @@ -90,7 +90,7 @@ public class FileTimesIT extends AbstractTest { assertNull(e.getCreationTime(), "birthtime"); assertGlobalHeaders(e); e = tin.getNextTarEntry(); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime"); @@ -130,7 +130,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test-times.txt", e.getName()); + assertEquals("test-times.txt", e.getName()); assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime"); assertNull(e.getLastAccessTime(), "atime"); assertNull(e.getStatusChangeTime(), "ctime"); @@ -138,7 +138,7 @@ public class FileTimesIT extends AbstractTest { e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test-times.txt", e.getName()); + assertEquals("test-times.txt", e.getName()); assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getLastModifiedTime(), "mtime"); assertEquals(toFileTime("2022-03-14T03:17:10Z"), e.getLastAccessTime(), "atime"); assertEquals(toFileTime("2022-03-14T03:17:10Z"), e.getStatusChangeTime(), "ctime"); @@ -210,7 +210,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test-times.txt", e.getName()); + assertEquals("test-times.txt", e.getName()); assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime"); assertNull(e.getLastAccessTime(), "atime"); assertNull(e.getStatusChangeTime(), "ctime"); @@ -218,7 +218,7 @@ public class FileTimesIT extends AbstractTest { e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test-times.txt", e.getName()); + assertEquals("test-times.txt", e.getName()); assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getLastModifiedTime(), "mtime"); assertEquals(toFileTime("2022-03-14T03:17:06Z"), e.getLastAccessTime(), "atime"); assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getStatusChangeTime(), "ctime"); @@ -237,7 +237,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime"); @@ -247,7 +247,7 @@ public class FileTimesIT extends AbstractTest { e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime"); @@ -286,7 +286,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-16T10:19:43.382883700Z"), e.getLastModifiedTime(), "mtime"); @@ -296,7 +296,7 @@ public class FileTimesIT extends AbstractTest { e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-16T10:21:00.249238500Z"), e.getLastModifiedTime(), "mtime"); @@ -334,7 +334,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getLastModifiedTime(), "mtime"); @@ -343,7 +343,7 @@ public class FileTimesIT extends AbstractTest { assertNull(e.getCreationTime(), "birthtime"); e = tin.getNextTarEntry(); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-17T00:38:20Z"), e.getLastModifiedTime(), "mtime"); @@ -414,7 +414,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getLastModifiedTime(), "mtime"); @@ -422,7 +422,7 @@ public class FileTimesIT extends AbstractTest { assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getStatusChangeTime(), "ctime"); assertNull(e.getCreationTime(), "birthtime"); e = tin.getNextTarEntry(); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertTrue(e.getExtraPaxHeaders().isEmpty()); @@ -443,7 +443,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test-times.txt", e.getName()); + assertEquals("test-times.txt", e.getName()); assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getLastModifiedTime(), "mtime"); assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getLastAccessTime(), "atime"); assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getStatusChangeTime(), "ctime"); @@ -486,7 +486,7 @@ public class FileTimesIT extends AbstractTest { TarArchiveEntry e = tin.getNextTarEntry(); assertNotNull(e); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/", e.getName()); + assertEquals("test/", e.getName()); assertEquals(TarConstants.LF_DIR, e.getLinkFlag()); assertTrue(e.isDirectory()); assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime"); @@ -495,7 +495,7 @@ public class FileTimesIT extends AbstractTest { assertNull(e.getCreationTime(), "birthtime"); e = tin.getNextTarEntry(); assertTrue(e.getExtraPaxHeaders().isEmpty()); - assertEquals("name", "test/test-times.txt", e.getName()); + assertEquals("test/test-times.txt", e.getName()); assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag()); assertTrue(e.isFile()); assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");