diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fd65a807276..c1712dd0bb1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -125,6 +125,7 @@ The type attribute can be add,update,fix,remove. Introduce builders for all ArchiveInputStream implementations and deprecate some constructors. TarFile now implements IOIterable<TarArchiveEntry>. Add a builder for the TarFile class and deprecate some constructors. + SevenZFile, TarFile, and ZipFile now always close underlying resources when builder or constructor fails. Bump org.apache.commons:commons-parent from 85 to 88 #707. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. diff --git a/src/main/java/org/apache/commons/compress/archivers/AbstractArchiveBuilder.java b/src/main/java/org/apache/commons/compress/archivers/AbstractArchiveBuilder.java new file mode 100644 index 00000000000..0bfa688b66c --- /dev/null +++ b/src/main/java/org/apache/commons/compress/archivers/AbstractArchiveBuilder.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.commons.compress.archivers; + +import org.apache.commons.io.build.AbstractStreamBuilder; + +/** + * Base class for builder pattern implementations of all archive readers. + * + *

Ensures that all {@code ArchiveInputStream} implementations and other + * archive handlers expose a consistent set of configuration options.

+ * + * @param The type of archive stream or file to build. + * @param The type of the concrete builder subclass. + * @since 1.29.0 + */ +public abstract class AbstractArchiveBuilder> + extends AbstractStreamBuilder { + + /** + * Constructs a new instance. + */ + protected AbstractArchiveBuilder() { + // empty + } +} diff --git a/src/main/java/org/apache/commons/compress/archivers/ArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/ArchiveInputStream.java index 73c4dbefd3a..66b795fb7f1 100644 --- a/src/main/java/org/apache/commons/compress/archivers/ArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/ArchiveInputStream.java @@ -26,7 +26,6 @@ import java.util.Objects; import org.apache.commons.io.Charsets; -import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.function.IOIterator; import org.apache.commons.io.input.NullInputStream; @@ -52,24 +51,6 @@ */ public abstract class ArchiveInputStream extends FilterInputStream { - /** - * Generic builder for ArchiveInputStream instances. - * - * @param The type of {@link ArchiveInputStream} to build. - * @param The type of the concrete AbstractBuilder. - * @since 1.29.0 - */ - public abstract static class AbstractBuilder, B extends AbstractBuilder> - extends AbstractStreamBuilder { - - /** - * Constructs a new instance. - */ - protected AbstractBuilder() { - // empty - } - } - /** * An iterator over a collection of a specific {@link ArchiveEntry} type. */ @@ -121,30 +102,45 @@ public Iterator unwrap() { */ @SuppressWarnings("resource") public ArchiveInputStream() { - this(new NullInputStream(), Charset.defaultCharset()); + this(new NullInputStream(), Charset.defaultCharset().name()); } /** * Constructs a new instance. * * @param inputStream the underlying input stream, or {@code null} if this instance is to be created without an underlying stream. - * @param charset charset. + * @param charsetName charset name. + * @since 1.26.0 + */ + protected ArchiveInputStream(final InputStream inputStream, final String charsetName) { + super(inputStream == null ? new NullInputStream() : inputStream); + this.charset = Charsets.toCharset(charsetName); + } + + /** + * Constructs a new instance from a builder. + * + * @param builder The builder. * @since 1.29.0 */ - protected ArchiveInputStream(final InputStream inputStream, final Charset charset) { - super(inputStream); - this.charset = Charsets.toCharset(charset); + protected ArchiveInputStream(AbstractArchiveBuilder builder) throws IOException { + this(builder.getInputStream(), builder); } /** - * Constructs a new instance. + * Constructs a new instance from a builder and an input stream. * - * @param inputStream the underlying input stream, or {@code null} if this instance is to be created without an underlying stream. - * @param charsetName charset name. - * @since 1.26.0 + *

Note: This overload exists to support legacy constructors that did not declare + * {@link IOException}. For new constructors, prefer + * {@link #ArchiveInputStream(AbstractArchiveBuilder)} and propagate I/O errors to callers.

+ * + * @param inputStream The underlying input stream, or {@code null} if this instance is to be created without an underlying stream. + * @param builder The builder. + * @since 1.29.0 */ - protected ArchiveInputStream(final InputStream inputStream, final String charsetName) { - this(inputStream, Charsets.toCharset(charsetName)); + protected ArchiveInputStream(final InputStream inputStream, final AbstractArchiveBuilder builder) { + super(inputStream); + this.charset = builder.getCharset(); } /** diff --git a/src/main/java/org/apache/commons/compress/archivers/Lister.java b/src/main/java/org/apache/commons/compress/archivers/Lister.java index 819141ddfbd..117e632ddb6 100644 --- a/src/main/java/org/apache/commons/compress/archivers/Lister.java +++ b/src/main/java/org/apache/commons/compress/archivers/Lister.java @@ -155,7 +155,7 @@ private void listStream(final Path file, final String[] args) throws ArchiveExc } private void listZipUsingTarFile(final Path file) throws IOException { - try (TarFile tarFile = new TarFile(file)) { + try (TarFile tarFile = TarFile.builder().setPath(file).get()) { println("Created " + tarFile); tarFile.getEntries().forEach(this::println); } diff --git a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java index 9423d8a6407..ec9e8b888d5 100644 --- a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.regex.Pattern; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.utils.ArchiveUtils; @@ -52,7 +53,7 @@ public class ArArchiveInputStream extends ArchiveInputStream { * * @since 1.29.0 */ - public static final class Builder extends AbstractBuilder { + public static final class Builder extends AbstractArchiveBuilder { private Builder() { setCharset(StandardCharsets.US_ASCII); @@ -167,7 +168,7 @@ public static boolean matches(final byte[] buffer, final int ignored) { private final byte[] metaData = new byte[NAME_LEN + LAST_MODIFIED_LEN + USER_ID_LEN + GROUP_ID_LEN + FILE_MODE_LEN + LENGTH_LEN]; private ArArchiveInputStream(final Builder builder) throws IOException { - this(builder.getInputStream(), builder); + super(builder); } /** @@ -180,7 +181,7 @@ public ArArchiveInputStream(final InputStream inputStream) { } private ArArchiveInputStream(final InputStream inputStream, final Builder builder) { - super(inputStream, builder.getCharset()); + super(inputStream, builder); } private int asInt(final byte[] byteArray, final int offset, final int len, final boolean treatBlankAsZero) throws IOException { diff --git a/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java index 44aca37590a..6c6633d1c18 100644 --- a/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.zip.CRC32; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; @@ -60,7 +61,7 @@ public class ArjArchiveInputStream extends ArchiveInputStream { * * @since 1.29.0 */ - public static final class Builder extends AbstractBuilder { + public static final class Builder extends AbstractArchiveBuilder { private Builder() { setCharset(ENCODING_NAME); @@ -117,7 +118,7 @@ public ArjArchiveInputStream(final InputStream inputStream) throws ArchiveExcept } private ArjArchiveInputStream(final InputStream inputStream, final Builder builder) throws ArchiveException { - super(new DataInputStream(inputStream), builder.getCharset()); + super(new DataInputStream(inputStream), builder); dis = (DataInputStream) in; try { mainHeader = readMainHeader(); diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java index d996954072c..ff801d02516 100644 --- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipEncoding; @@ -79,7 +80,7 @@ public class CpioArchiveInputStream extends ArchiveInputStream * * @since 1.29.0 */ - public static final class Builder extends AbstractBuilder { + public static final class Builder extends AbstractArchiveBuilder { private int blockSize = BLOCK_SIZE; @@ -211,7 +212,7 @@ public CpioArchiveInputStream(final InputStream in) { } private CpioArchiveInputStream(final InputStream in, final Builder builder) { - super(in, builder.getCharset()); + super(in, builder); if (builder.blockSize <= 0) { throw new IllegalArgumentException("blockSize must be bigger than 0"); } diff --git a/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java index be4aba459db..cd73b4e91d6 100644 --- a/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java @@ -29,6 +29,7 @@ import java.util.Queue; import java.util.Stack; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipEncoding; @@ -60,7 +61,7 @@ public class DumpArchiveInputStream extends ArchiveInputStream * * @since 1.29.0 */ - public static final class Builder extends AbstractBuilder { + public static final class Builder extends AbstractArchiveBuilder { private Builder() { } @@ -153,7 +154,7 @@ public DumpArchiveInputStream(final InputStream is) throws ArchiveException { } private DumpArchiveInputStream(final InputStream is, final Builder builder) throws ArchiveException { - super(is, builder.getCharset()); + super(is, builder); this.raw = new TapeInputStream(is); this.hasHitEOF = false; this.zipEncoding = ZipEncodingHelper.getZipEncoding(builder.getCharset()); diff --git a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java index e2a1b87c88d..e1e8e2303df 100644 --- a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java +++ b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java @@ -395,11 +395,11 @@ public void expand(final String format, final SeekableByteChannel archive, final if (!prefersSeekableByteChannel(format)) { expand(format, c.track(Channels.newInputStream(archive)), targetDirectory, CloseableConsumer.NULL_CONSUMER); } else if (ArchiveStreamFactory.TAR.equalsIgnoreCase(format)) { - expand(c.track(new TarFile(archive)), targetDirectory); + expand(c.track(TarFile.builder().setChannel(archive).get()), targetDirectory); } else if (ArchiveStreamFactory.ZIP.equalsIgnoreCase(format)) { - expand(c.track(ZipFile.builder().setSeekableByteChannel(archive).get()), targetDirectory); + expand(c.track(ZipFile.builder().setChannel(archive).get()), targetDirectory); } else if (ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(format)) { - expand(c.track(SevenZFile.builder().setSeekableByteChannel(archive).get()), targetDirectory); + expand(c.track(SevenZFile.builder().setChannel(archive).get()), targetDirectory); } else { // never reached as prefersSeekableByteChannel only returns true for TAR, ZIP and 7z throw new ArchiveException("Don't know how to handle format '%s'", format); diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java index c75544f2a5c..c282f134dbc 100644 --- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java @@ -34,14 +34,9 @@ import java.nio.ByteOrder; import java.nio.channels.Channels; import java.nio.channels.SeekableByteChannel; -import java.nio.file.Files; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; -import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -51,12 +46,10 @@ import java.util.zip.CheckedInputStream; import org.apache.commons.compress.MemoryLimitException; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.InputStreamStatistics; -import org.apache.commons.io.build.AbstractOrigin.ByteArrayOrigin; -import org.apache.commons.io.build.AbstractOrigin.ChannelOrigin; -import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.input.BoundedInputStream; import org.apache.commons.io.input.ChecksumInputStream; import org.apache.commons.lang3.ArrayUtils; @@ -178,13 +171,14 @@ public String toString() { * * @since 1.26.0 */ - public static class Builder extends AbstractStreamBuilder { + public static class Builder extends AbstractArchiveBuilder { static final int MEMORY_LIMIT_KIB = Integer.MAX_VALUE; static final boolean USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES = false; static final boolean TRY_TO_RECOVER_BROKEN_ARCHIVES = false; private String defaultName = DEFAULT_FILE_NAME; + private String name; private byte[] password; private int maxMemoryLimitKiB = MEMORY_LIMIT_KIB; private boolean useDefaultNameForUnnamedEntries = USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES; @@ -198,29 +192,7 @@ public static class Builder extends AbstractStreamBuilder { @SuppressWarnings("resource") // Caller closes @Override public SevenZFile get() throws IOException { - final SeekableByteChannel actualChannel; - final String actualDescription; - final boolean isChannelOrigin = checkOrigin() instanceof ChannelOrigin; - boolean isSeekableByteChannellOrigin = false; - if (isChannelOrigin) { - actualChannel = getChannel(SeekableByteChannel.class); - isSeekableByteChannellOrigin = true; - actualDescription = defaultName; - } else if (checkOrigin() instanceof ByteArrayOrigin) { - actualChannel = getChannel(SeekableByteChannel.class); - actualDescription = defaultName; - } else { - OpenOption[] openOptions = getOpenOptions(); - if (ArrayUtils.isEmpty(openOptions)) { - openOptions = new OpenOption[] { StandardOpenOption.READ }; - } - final Path path = getPath(); - actualChannel = Files.newByteChannel(path, openOptions); - actualDescription = path.toAbsolutePath().toString(); - } - final boolean closeOnError = isSeekableByteChannellOrigin; - return new SevenZFile(actualChannel, actualDescription, password, closeOnError, maxMemoryLimitKiB, useDefaultNameForUnnamedEntries, - tryToRecoverBrokenArchives); + return new SevenZFile(this); } /** @@ -234,6 +206,22 @@ public Builder setDefaultName(final String defaultName) { return this; } + Builder setName(final String name) { + this.name = name; + return this; + } + + String getName() { + if (name == null) { + try { + name = getPath().toAbsolutePath().toString(); + } catch (UnsupportedOperationException e) { + name = defaultName; + } + } + return name; + } + /** * Sets the maximum amount of memory in kilobytes to use for parsing the archive and during extraction. *

@@ -263,6 +251,14 @@ public Builder setMaxMemoryLimitKiB(final int maxMemoryLimitKiB) { return this; } + Builder setOptions(final SevenZFileOptions options) { + Objects.requireNonNull(options, "options"); + this.maxMemoryLimitKiB = options.getMaxMemoryLimitInKb(); + this.useDefaultNameForUnnamedEntries = options.getUseDefaultNameForUnnamedEntries(); + this.tryToRecoverBrokenArchives = options.getTryToRecoverBrokenArchives(); + return this; + } + /** * Sets the password. * @@ -301,7 +297,9 @@ public Builder setPassword(final String password) { * * @param seekableByteChannel the input channel. * @return {@code this} instance. + * @deprecated Since 1.29.0, use {@link #setChannel} instead. */ + @Deprecated public Builder setSeekableByteChannel(final SeekableByteChannel seekableByteChannel) { return setChannel(seekableByteChannel); } @@ -421,10 +419,6 @@ public static boolean matches(final byte[] buffer, final int ignored) { return ArrayUtils.startsWith(buffer, SIGNATURE); } - private static SeekableByteChannel newByteChannel(final File file) throws IOException { - return Files.newByteChannel(file.toPath(), EnumSet.of(StandardOpenOption.READ)); - } - private static long readUint64(final ByteBuffer in) throws IOException { // long rather than int as it might get shifted beyond the range of an int final long firstByte = getUnsignedByte(in); @@ -496,7 +490,7 @@ public static int toNonNegativeInt(final String description, final long value) t */ @Deprecated public SevenZFile(final File fileName) throws IOException { - this(fileName, SevenZFileOptions.DEFAULT); + this(builder().setFile(fileName)); } /** @@ -510,7 +504,7 @@ public SevenZFile(final File fileName) throws IOException { @SuppressWarnings("resource") // caller closes @Deprecated public SevenZFile(final File file, final byte[] password) throws IOException { - this(newByteChannel(file), file.getAbsolutePath(), password, true, SevenZFileOptions.DEFAULT); + this(builder().setFile(file).setPassword(password)); } /** @@ -524,7 +518,7 @@ public SevenZFile(final File file, final byte[] password) throws IOException { */ @Deprecated public SevenZFile(final File file, final char[] password) throws IOException { - this(file, password, SevenZFileOptions.DEFAULT); + this(builder().setFile(file).setPassword(password)); } /** @@ -540,8 +534,7 @@ public SevenZFile(final File file, final char[] password) throws IOException { @SuppressWarnings("resource") // caller closes @Deprecated public SevenZFile(final File file, final char[] password, final SevenZFileOptions options) throws IOException { - this(newByteChannel(file), // NOSONAR - file.getAbsolutePath(), AES256SHA256Decoder.utf16Decode(password), true, options); + this(builder().setFile(file).setPassword(password).setOptions(options)); } /** @@ -555,7 +548,7 @@ public SevenZFile(final File file, final char[] password, final SevenZFileOption */ @Deprecated public SevenZFile(final File file, final SevenZFileOptions options) throws IOException { - this(file, null, options); + this(builder().setFile(file).setOptions(options)); } /** @@ -571,7 +564,7 @@ public SevenZFile(final File file, final SevenZFileOptions options) throws IOExc */ @Deprecated public SevenZFile(final SeekableByteChannel channel) throws IOException { - this(channel, SevenZFileOptions.DEFAULT); + this(builder().setChannel(channel)); } /** @@ -588,7 +581,7 @@ public SevenZFile(final SeekableByteChannel channel) throws IOException { */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final byte[] password) throws IOException { - this(channel, DEFAULT_FILE_NAME, password); + this(builder().setChannel(channel).setPassword(password)); } /** @@ -605,7 +598,7 @@ public SevenZFile(final SeekableByteChannel channel, final byte[] password) thro */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final char[] password) throws IOException { - this(channel, password, SevenZFileOptions.DEFAULT); + this(builder().setChannel(channel).setPassword(password)); } /** @@ -623,7 +616,7 @@ public SevenZFile(final SeekableByteChannel channel, final char[] password) thro */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final char[] password, final SevenZFileOptions options) throws IOException { - this(channel, DEFAULT_FILE_NAME, password, options); + this(builder().setChannel(channel).setPassword(password).setOptions(options)); } /** @@ -640,7 +633,7 @@ public SevenZFile(final SeekableByteChannel channel, final char[] password, fina */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final SevenZFileOptions options) throws IOException { - this(channel, DEFAULT_FILE_NAME, null, options); + this(builder().setChannel(channel).setOptions(options)); } /** @@ -657,7 +650,7 @@ public SevenZFile(final SeekableByteChannel channel, final SevenZFileOptions opt */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final String fileName) throws IOException { - this(channel, fileName, SevenZFileOptions.DEFAULT); + this(builder().setChannel(channel).setName(fileName)); } /** @@ -675,52 +668,30 @@ public SevenZFile(final SeekableByteChannel channel, final String fileName) thro */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final String fileName, final byte[] password) throws IOException { - this(channel, fileName, password, false, SevenZFileOptions.DEFAULT); + this(builder().setChannel(channel).setName(fileName).setPassword(password)); } - private SevenZFile(final SeekableByteChannel channel, final String fileName, final byte[] password, final boolean closeOnError, final int maxMemoryLimitKiB, - final boolean useDefaultNameForUnnamedEntries, final boolean tryToRecoverBrokenArchives) throws IOException { - boolean succeeded = false; - this.channel = channel; - this.fileName = fileName; - this.maxMemoryLimitKiB = maxMemoryLimitKiB; - this.useDefaultNameForUnnamedEntries = useDefaultNameForUnnamedEntries; - this.tryToRecoverBrokenArchives = tryToRecoverBrokenArchives; + private SevenZFile(Builder builder) throws IOException { + this.channel = builder.getChannel(SeekableByteChannel.class); try { + this.fileName = builder.getName(); + this.maxMemoryLimitKiB = builder.maxMemoryLimitKiB; + this.useDefaultNameForUnnamedEntries = builder.useDefaultNameForUnnamedEntries; + this.tryToRecoverBrokenArchives = builder.tryToRecoverBrokenArchives; + final byte[] password = builder.password; archive = readHeaders(password); - if (password != null) { - this.password = Arrays.copyOf(password, password.length); - } else { - this.password = null; - } - succeeded = true; + this.password = password != null ? Arrays.copyOf(password, password.length) : null; } catch (final ArithmeticException | IllegalArgumentException e) { - throw new ArchiveException(e); - } finally { - if (!succeeded && closeOnError) { - this.channel.close(); + final ArchiveException archiveException = new ArchiveException(e); + try { + channel.close(); + } catch (final IOException suppressed) { + archiveException.addSuppressed(suppressed); } + throw archiveException; } } - /** - * Constructs a new instance. - * - * @param channel the channel to read. - * @param fileName name of the archive - only used for error reporting. - * @param password optional password if the archive is encrypted. - * @param closeOnError closes the channel on error. - * @param options options. - * @throws IOException if reading the archive fails - * @deprecated Use {@link Builder#get()}. - */ - @Deprecated - private SevenZFile(final SeekableByteChannel channel, final String fileName, final byte[] password, final boolean closeOnError, - final SevenZFileOptions options) throws IOException { - this(channel, fileName, password, closeOnError, options.getMaxMemoryLimitInKb(), options.getUseDefaultNameForUnnamedEntries(), - options.getTryToRecoverBrokenArchives()); - } - /** * Reads a SeekableByteChannel as 7z archive *

@@ -736,7 +707,7 @@ private SevenZFile(final SeekableByteChannel channel, final String fileName, fin */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final String fileName, final char[] password) throws IOException { - this(channel, fileName, password, SevenZFileOptions.DEFAULT); + this(builder().setChannel(channel).setName(fileName).setPassword(password)); } /** @@ -755,7 +726,7 @@ public SevenZFile(final SeekableByteChannel channel, final String fileName, fina */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final String fileName, final char[] password, final SevenZFileOptions options) throws IOException { - this(channel, fileName, AES256SHA256Decoder.utf16Decode(password), false, options); + this(builder().setChannel(channel).setName(fileName).setPassword(password).setOptions(options)); } /** @@ -773,7 +744,7 @@ public SevenZFile(final SeekableByteChannel channel, final String fileName, fina */ @Deprecated public SevenZFile(final SeekableByteChannel channel, final String fileName, final SevenZFileOptions options) throws IOException { - this(channel, fileName, null, false, options); + this(builder().setChannel(channel).setName(fileName).setOptions(options)); } private InputStream buildDecoderStack(final Folder folder, final long folderOffset, final int firstPackStreamIndex, final SevenZArchiveEntry entry) diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/AbstractTarBuilder.java b/src/main/java/org/apache/commons/compress/archivers/tar/AbstractTarBuilder.java index 5555f5ccc2b..0f471a1ca1f 100644 --- a/src/main/java/org/apache/commons/compress/archivers/tar/AbstractTarBuilder.java +++ b/src/main/java/org/apache/commons/compress/archivers/tar/AbstractTarBuilder.java @@ -19,7 +19,7 @@ package org.apache.commons.compress.archivers.tar; -import org.apache.commons.io.build.AbstractStreamBuilder; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; /** * Abstracts TAR builder operations. @@ -28,7 +28,7 @@ * @param the type of builder subclass. * @since 1.29.0 */ -public abstract class AbstractTarBuilder> extends AbstractStreamBuilder { +public abstract class AbstractTarBuilder> extends AbstractArchiveBuilder { private int blockSize = TarConstants.DEFAULT_BLKSIZE; private int recordSize = TarConstants.DEFAULT_RCDSIZE; diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java index 80dd6859fb1..80ef5f51576 100644 --- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java @@ -204,7 +204,7 @@ public TarArchiveInputStream(final InputStream inputStream, final boolean lenien } private TarArchiveInputStream(final InputStream inputStream, final Builder builder) { - super(inputStream, builder.getCharset()); + super(inputStream, builder); this.zipEncoding = ZipEncodingHelper.getZipEncoding(builder.getCharset()); this.recordBuffer = new byte[builder.getRecordSize()]; this.blockSize = builder.getBlockSize(); diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java index 9ebb6c1d6e1..f6ee3ddf556 100644 --- a/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java @@ -24,8 +24,8 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; -import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -40,7 +40,6 @@ import org.apache.commons.compress.utils.ArchiveUtils; import org.apache.commons.compress.utils.BoundedArchiveInputStream; import org.apache.commons.compress.utils.BoundedSeekableByteChannelInputStream; -import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import org.apache.commons.io.function.IOIterable; import org.apache.commons.io.function.IOIterator; import org.apache.commons.io.input.BoundedInputStream; @@ -159,32 +158,18 @@ private int readSparse(final long pos, final ByteBuffer buf, final int numToRead */ // @formatter:on public static final class Builder extends AbstractTarBuilder { - - private SeekableByteChannel channel; - /** * Constructs a new instance. */ private Builder() { - // empty + // Default options + setOpenOptions(StandardOpenOption.READ); } @Override public TarFile get() throws IOException { return new TarFile(this); } - - /** - * Sets the SeekableByteChannel. - * - * @param channel the SeekableByteChannel. - * @return {@code this} instance. - */ - public Builder setSeekableByteChannel(final SeekableByteChannel channel) { - this.channel = channel; - return asThis(); - } - } /** @@ -234,13 +219,22 @@ public static Builder builder() { private final Map> sparseInputStreams = new HashMap<>(); private TarFile(final Builder builder) throws IOException { - this.archive = builder.channel != null ? builder.channel : Files.newByteChannel(builder.getPath()); - this.zipEncoding = ZipEncodingHelper.getZipEncoding(builder.getCharset()); - this.recordSize = builder.getRecordSize(); - this.recordBuffer = ByteBuffer.allocate(this.recordSize); - this.blockSize = builder.getBlockSize(); - this.lenient = builder.isLenient(); - forEach(entries::add); + this.archive = builder.getChannel(SeekableByteChannel.class); + try { + this.zipEncoding = ZipEncodingHelper.getZipEncoding(builder.getCharset()); + this.recordSize = builder.getRecordSize(); + this.recordBuffer = ByteBuffer.allocate(this.recordSize); + this.blockSize = builder.getBlockSize(); + this.lenient = builder.isLenient(); + forEach(entries::add); + } catch (IOException ex) { + try { + this.archive.close(); + } catch (final IOException e) { + ex.addSuppressed(e); + } + throw ex; + } } /** @@ -252,7 +246,7 @@ private TarFile(final Builder builder) throws IOException { */ @Deprecated public TarFile(final byte[] content) throws IOException { - this(new SeekableInMemoryByteChannel(content)); + this(builder().setByteArray(content)); } /** @@ -266,7 +260,7 @@ public TarFile(final byte[] content) throws IOException { */ @Deprecated public TarFile(final byte[] content, final boolean lenient) throws IOException { - this(new SeekableInMemoryByteChannel(content), TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, null, lenient); + this(builder().setByteArray(content).setLenient(lenient)); } /** @@ -279,7 +273,7 @@ public TarFile(final byte[] content, final boolean lenient) throws IOException { */ @Deprecated public TarFile(final byte[] content, final String encoding) throws IOException { - this(new SeekableInMemoryByteChannel(content), TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, encoding, false); + this(builder().setByteArray(content).setCharset(encoding)); } /** @@ -291,7 +285,7 @@ public TarFile(final byte[] content, final String encoding) throws IOException { */ @Deprecated public TarFile(final File archive) throws IOException { - this(archive.toPath()); + this(builder().setFile(archive)); } /** @@ -305,7 +299,7 @@ public TarFile(final File archive) throws IOException { */ @Deprecated public TarFile(final File archive, final boolean lenient) throws IOException { - this(archive.toPath(), lenient); + this(builder().setFile(archive).setLenient(lenient)); } /** @@ -318,7 +312,7 @@ public TarFile(final File archive, final boolean lenient) throws IOException { */ @Deprecated public TarFile(final File archive, final String encoding) throws IOException { - this(archive.toPath(), encoding); + this(builder().setFile(archive).setCharset(encoding)); } /** @@ -328,7 +322,7 @@ public TarFile(final File archive, final String encoding) throws IOException { * @throws IOException when reading the tar archive fails. */ public TarFile(final Path archivePath) throws IOException { - this(Files.newByteChannel(archivePath), TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, null, false); + this(builder().setPath(archivePath)); } /** @@ -342,7 +336,7 @@ public TarFile(final Path archivePath) throws IOException { */ @Deprecated public TarFile(final Path archivePath, final boolean lenient) throws IOException { - this(Files.newByteChannel(archivePath), TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, null, lenient); + this(builder().setPath(archivePath).setLenient(lenient)); } /** @@ -355,7 +349,7 @@ public TarFile(final Path archivePath, final boolean lenient) throws IOException */ @Deprecated public TarFile(final Path archivePath, final String encoding) throws IOException { - this(Files.newByteChannel(archivePath), TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, encoding, false); + this(builder().setPath(archivePath).setCharset(encoding)); } /** @@ -367,7 +361,7 @@ public TarFile(final Path archivePath, final String encoding) throws IOException */ @Deprecated public TarFile(final SeekableByteChannel content) throws IOException { - this(content, TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, null, false); + this(builder().setChannel(content)); } /** @@ -385,7 +379,7 @@ public TarFile(final SeekableByteChannel content) throws IOException { @Deprecated public TarFile(final SeekableByteChannel archive, final int blockSize, final int recordSize, final String encoding, final boolean lenient) throws IOException { - this(builder().setSeekableByteChannel(archive).setBlockSize(blockSize).setRecordSize(recordSize).setCharset(encoding).setLenient(lenient)); + this(builder().setChannel(archive).setBlockSize(blockSize).setRecordSize(recordSize).setCharset(encoding).setLenient(lenient)); } /** 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 d02e625688a..5eb5bdb7aa8 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 @@ -42,6 +42,7 @@ import java.util.zip.ZipException; import org.apache.commons.compress.MemoryLimitException; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; @@ -85,7 +86,7 @@ public class ZipArchiveInputStream extends ArchiveInputStream i * @since 1.29.0 */ public abstract static class AbstractBuilder> - extends ArchiveInputStream.AbstractBuilder { + extends AbstractArchiveBuilder { private boolean useUnicodeExtraFields = true; private boolean supportStoredEntryDataDescriptor; @@ -421,7 +422,7 @@ public ZipArchiveInputStream(final InputStream inputStream) { } private ZipArchiveInputStream(final InputStream inputStream, final AbstractBuilder builder) { - super(inputStream, builder.getCharset()); + super(inputStream, builder); this.in = new PushbackInputStream(inputStream, buf.capacity()); this.zipEncoding = ZipEncodingHelper.getZipEncoding(builder.getCharset()); this.useUnicodeExtraFields = builder.isUseUnicodeExtraFields(); diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java index fc2a90b339e..40792f977a5 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java @@ -39,7 +39,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.EnumSet; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; @@ -51,6 +50,7 @@ import java.util.zip.Inflater; import java.util.zip.ZipException; +import org.apache.commons.compress.archivers.AbstractArchiveBuilder; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.EntryStreamOffsets; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; @@ -61,11 +61,7 @@ import org.apache.commons.compress.utils.BoundedSeekableByteChannelInputStream; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.InputStreamStatistics; -import org.apache.commons.io.Charsets; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.build.AbstractOrigin.ByteArrayOrigin; -import org.apache.commons.io.build.AbstractOrigin.ChannelOrigin; -import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.IOFunction; import org.apache.commons.io.function.IOStream; import org.apache.commons.io.input.BoundedInputStream; @@ -132,12 +128,13 @@ protected int read(final long pos, final ByteBuffer buf) throws IOException { * * @since 1.26.0 */ - public static class Builder extends AbstractStreamBuilder { + public static class Builder extends AbstractArchiveBuilder { - static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private boolean useUnicodeExtraFields = true; private boolean ignoreLocalFileHeader; private long maxNumberOfDisks = 1; + private String name; private IOFunction zstdInputStreamFactory; /** @@ -146,33 +143,12 @@ public static class Builder extends AbstractStreamBuilder { public Builder() { setCharset(DEFAULT_CHARSET); setCharsetDefault(DEFAULT_CHARSET); + setOpenOptions(StandardOpenOption.READ); } @Override public ZipFile get() throws IOException { - final SeekableByteChannel actualChannel; - final String actualDescription; - final boolean isChannelOrigin = checkOrigin() instanceof ChannelOrigin; - boolean isSeekableByteChannellOrigin = false; - if (isChannelOrigin) { - actualChannel = getChannel(SeekableByteChannel.class); - isSeekableByteChannellOrigin = true; - actualDescription = actualChannel.getClass().getSimpleName(); - } else if (checkOrigin() instanceof ByteArrayOrigin) { - actualChannel = getChannel(SeekableByteChannel.class); - actualDescription = actualChannel.getClass().getSimpleName(); - } else { - OpenOption[] openOptions = getOpenOptions(); - if (openOptions.length == 0) { - openOptions = new OpenOption[] { StandardOpenOption.READ }; - } - final Path path = getPath(); - actualChannel = openZipChannel(path, maxNumberOfDisks, openOptions); - actualDescription = path.toString(); - } - final boolean closeOnError = isSeekableByteChannellOrigin; - return new ZipFile(actualChannel, actualDescription, getCharset(), useUnicodeExtraFields, closeOnError, ignoreLocalFileHeader, - zstdInputStreamFactory); + return new ZipFile(this); } /** @@ -197,12 +173,30 @@ public Builder setMaxNumberOfDisks(final long maxNumberOfDisks) { return this; } + Builder setName(final String name) { + this.name = name; + return this; + } + + String getName() { + if (name == null) { + try { + name = getPath().toAbsolutePath().toString(); + } catch (UnsupportedOperationException ex) { + name = "unknown"; + } + } + return name; + } + /** * The actual channel, overrides any other input aspects like a File, Path, and so on. * * @param seekableByteChannel The actual channel. * @return {@code this} instance. + * @deprecated Since 1.29.0, use {@link #setChannel} instead. */ + @Deprecated public Builder setSeekableByteChannel(final SeekableByteChannel seekableByteChannel) { return setChannel(seekableByteChannel); } @@ -284,10 +278,6 @@ public long getUncompressedCount() { } } - private static final String DEFAULT_CHARSET_NAME = StandardCharsets.UTF_8.name(); - - private static final EnumSet READ = EnumSet.of(StandardOpenOption.READ); - private static final int HASH_SIZE = 509; static final int NIBLET_MASK = 0x0f; static final int BYTE_SHIFT = 8; @@ -512,19 +502,8 @@ public static void closeQuietly(final ZipFile zipFile) { org.apache.commons.io.IOUtils.closeQuietly(zipFile); } - /** - * Creates a new SeekableByteChannel for reading. - * - * @param path the path to the file to open or create - * @return a new seekable byte channel - * @throws IOException if an I/O error occurs - */ - private static SeekableByteChannel newReadByteChannel(final Path path) throws IOException { - return Files.newByteChannel(path, READ); - } - private static SeekableByteChannel openZipChannel(final Path path, final long maxNumberOfDisks, final OpenOption[] openOptions) throws IOException { - final FileChannel channel = FileChannel.open(path, StandardOpenOption.READ); + final FileChannel channel = FileChannel.open(path, openOptions); try { final boolean is64 = positionAtEndOfCentralDirectoryRecord(channel); final long numberOfDisks; @@ -761,7 +740,7 @@ private static boolean tryToLocateSignature(final SeekableByteChannel channel, f */ @Deprecated public ZipFile(final File file) throws IOException { - this(file, DEFAULT_CHARSET_NAME); + this(builder().setFile(file)); } /** @@ -774,7 +753,7 @@ public ZipFile(final File file) throws IOException { */ @Deprecated public ZipFile(final File file, final String encoding) throws IOException { - this(file.toPath(), encoding, true); + this(builder().setFile(file).setCharset(encoding)); } /** @@ -788,7 +767,7 @@ public ZipFile(final File file, final String encoding) throws IOException { */ @Deprecated public ZipFile(final File file, final String encoding, final boolean useUnicodeExtraFields) throws IOException { - this(file.toPath(), encoding, useUnicodeExtraFields, false); + this(builder().setFile(file).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields)); } /** @@ -810,9 +789,8 @@ public ZipFile(final File file, final String encoding, final boolean useUnicodeE * @deprecated Use {@link Builder#get()}. */ @Deprecated - @SuppressWarnings("resource") // Caller closes public ZipFile(final File file, final String encoding, final boolean useUnicodeExtraFields, final boolean ignoreLocalFileHeader) throws IOException { - this(newReadByteChannel(file.toPath()), file.getAbsolutePath(), encoding, useUnicodeExtraFields, true, ignoreLocalFileHeader); + this(builder().setFile(file).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields).setIgnoreLocalFileHeader(ignoreLocalFileHeader)); } /** @@ -825,7 +803,7 @@ public ZipFile(final File file, final String encoding, final boolean useUnicodeE */ @Deprecated public ZipFile(final Path path) throws IOException { - this(path, DEFAULT_CHARSET_NAME); + this(builder().setPath(path)); } /** @@ -839,7 +817,7 @@ public ZipFile(final Path path) throws IOException { */ @Deprecated public ZipFile(final Path path, final String encoding) throws IOException { - this(path, encoding, true); + this(builder().setPath(path).setCharset(encoding)); } /** @@ -854,7 +832,7 @@ public ZipFile(final Path path, final String encoding) throws IOException { */ @Deprecated public ZipFile(final Path path, final String encoding, final boolean useUnicodeExtraFields) throws IOException { - this(path, encoding, useUnicodeExtraFields, false); + this(builder().setPath(path).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields)); } /** @@ -878,7 +856,7 @@ public ZipFile(final Path path, final String encoding, final boolean useUnicodeE @SuppressWarnings("resource") // Caller closes @Deprecated public ZipFile(final Path path, final String encoding, final boolean useUnicodeExtraFields, final boolean ignoreLocalFileHeader) throws IOException { - this(newReadByteChannel(path), path.toAbsolutePath().toString(), encoding, useUnicodeExtraFields, true, ignoreLocalFileHeader); + this(builder().setPath(path).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields).setIgnoreLocalFileHeader(ignoreLocalFileHeader)); } /** @@ -894,7 +872,7 @@ public ZipFile(final Path path, final String encoding, final boolean useUnicodeE */ @Deprecated public ZipFile(final SeekableByteChannel channel) throws IOException { - this(channel, "a SeekableByteChannel", DEFAULT_CHARSET_NAME, true); + this(builder().setChannel(channel)); } /** @@ -911,32 +889,38 @@ public ZipFile(final SeekableByteChannel channel) throws IOException { */ @Deprecated public ZipFile(final SeekableByteChannel channel, final String encoding) throws IOException { - this(channel, "a SeekableByteChannel", encoding, true); + this(builder().setChannel(channel).setCharset(encoding)); } - private ZipFile(final SeekableByteChannel channel, final String channelDescription, final Charset encoding, final boolean useUnicodeExtraFields, - final boolean closeOnError, final boolean ignoreLocalFileHeader, final IOFunction zstdInputStream) throws IOException { - this.isSplitZipArchive = channel instanceof ZipSplitReadOnlySeekableByteChannel; - this.encoding = Charsets.toCharset(encoding, Builder.DEFAULT_CHARSET); - this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); - this.useUnicodeExtraFields = useUnicodeExtraFields; - this.archive = channel; - this.zstdInputStreamFactory = zstdInputStream; - boolean success = false; + private ZipFile(Builder builder) throws IOException { + SeekableByteChannel archive; try { + final Path path = builder.getPath(); + archive = openZipChannel(path, builder.maxNumberOfDisks, builder.getOpenOptions()); + } catch (UnsupportedOperationException e) { + archive = builder.getChannel(SeekableByteChannel.class); + } + this.archive = archive; + try { + this.isSplitZipArchive = this.archive instanceof ZipSplitReadOnlySeekableByteChannel; + this.encoding = builder.getCharset(); + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); + this.useUnicodeExtraFields = builder.useUnicodeExtraFields; + this.zstdInputStreamFactory = builder.zstdInputStreamFactory; final Map entriesWithoutUTF8Flag = populateFromCentralDirectory(); - if (!ignoreLocalFileHeader) { + if (!builder.ignoreLocalFileHeader) { resolveLocalFileHeaderData(entriesWithoutUTF8Flag); } fillNameMap(); - success = true; } catch (final IOException e) { - throw new ArchiveException("Error reading Zip content from " + channelDescription, (Throwable) e); - } finally { - this.closed = !success; - if (!success && closeOnError) { - org.apache.commons.io.IOUtils.closeQuietly(archive); + final ArchiveException archiveException = new ArchiveException("Error reading Zip content from " + builder.getName(), (Throwable) e); + this.closed = true; + try { + this.archive.close(); + } catch (final IOException ioException) { + archiveException.addSuppressed(ioException); } + throw archiveException; } } @@ -957,7 +941,7 @@ private ZipFile(final SeekableByteChannel channel, final String channelDescripti @Deprecated public ZipFile(final SeekableByteChannel channel, final String channelDescription, final String encoding, final boolean useUnicodeExtraFields) throws IOException { - this(channel, channelDescription, encoding, useUnicodeExtraFields, false, false); + this(builder().setChannel(channel).setName(channelDescription).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields)); } /** @@ -985,12 +969,8 @@ public ZipFile(final SeekableByteChannel channel, final String channelDescriptio @Deprecated public ZipFile(final SeekableByteChannel channel, final String channelDescription, final String encoding, final boolean useUnicodeExtraFields, final boolean ignoreLocalFileHeader) throws IOException { - this(channel, channelDescription, encoding, useUnicodeExtraFields, false, ignoreLocalFileHeader); - } - - private ZipFile(final SeekableByteChannel channel, final String channelDescription, final String encoding, final boolean useUnicodeExtraFields, - final boolean closeOnError, final boolean ignoreLocalFileHeader) throws IOException { - this(channel, channelDescription, Charsets.toCharset(encoding), useUnicodeExtraFields, closeOnError, ignoreLocalFileHeader, null); + this(builder().setChannel(channel).setName(channelDescription).setCharset(encoding).setUseUnicodeExtraFields(useUnicodeExtraFields) + .setIgnoreLocalFileHeader(ignoreLocalFileHeader)); } /** @@ -1002,7 +982,7 @@ private ZipFile(final SeekableByteChannel channel, final String channelDescripti */ @Deprecated public ZipFile(final String name) throws IOException { - this(new File(name).toPath(), DEFAULT_CHARSET_NAME); + this(builder().setFile(name)); } /** @@ -1015,7 +995,7 @@ public ZipFile(final String name) throws IOException { */ @Deprecated public ZipFile(final String name, final String encoding) throws IOException { - this(new File(name).toPath(), encoding, true); + this(builder().setFile(name).setCharset(encoding)); } /** diff --git a/src/test/java/org/apache/commons/compress/LegacyConstructorsTest.java b/src/test/java/org/apache/commons/compress/LegacyConstructorsTest.java index 2a3d4122f59..d60863c6e09 100644 --- a/src/test/java/org/apache/commons/compress/LegacyConstructorsTest.java +++ b/src/test/java/org/apache/commons/compress/LegacyConstructorsTest.java @@ -21,20 +21,33 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static org.apache.commons.lang3.reflect.FieldUtils.readDeclaredField; import static org.apache.commons.lang3.reflect.FieldUtils.readField; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; +import java.io.File; +import java.io.IOException; import java.io.InputStream; +import java.nio.channels.SeekableByteChannel; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.stream.Stream; import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream; import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream; import org.apache.commons.compress.archivers.dump.DumpArchiveInputStream; import org.apache.commons.compress.archivers.jar.JarArchiveInputStream; +import org.apache.commons.compress.archivers.sevenz.SevenZFile; +import org.apache.commons.compress.archivers.sevenz.SevenZFileOptions; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarFile; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipEncoding; +import org.apache.commons.compress.archivers.zip.ZipFile; +import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -120,6 +133,63 @@ void testJarConstructor() throws Exception { } } + static Stream testSevenZFileContructors() throws IOException { + final Path path = getPath("bla.7z"); + final String defaultName = "unknown archive"; + final String otherName = path.toAbsolutePath().toString(); + final String customName = "customName"; + final int defaultMemoryLimit = SevenZFileOptions.DEFAULT.getMaxMemoryLimitInKb(); + final boolean defaultUseDefaultNameForUnnamedEntries = SevenZFileOptions.DEFAULT.getUseDefaultNameForUnnamedEntries(); + final boolean defaultTryToRecoverBrokenArchives = SevenZFileOptions.DEFAULT.getTryToRecoverBrokenArchives(); + final SevenZFileOptions otherOptions = + SevenZFileOptions.builder().withMaxMemoryLimitInKb(42).withTryToRecoverBrokenArchives(true).withUseDefaultNameForUnnamedEntries(true).build(); + final char[] otherPassword = "password".toCharArray(); + final byte[] otherPasswordBytes = "password".getBytes(StandardCharsets.UTF_16LE); + return Stream.of( + // From File + Arguments.of(new SevenZFile(path.toFile()), otherName, defaultMemoryLimit, defaultUseDefaultNameForUnnamedEntries, + defaultTryToRecoverBrokenArchives, null), + Arguments.of(new SevenZFile(path.toFile(), otherPasswordBytes), otherName, defaultMemoryLimit, defaultUseDefaultNameForUnnamedEntries, + defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(path.toFile(), otherPassword), otherName, defaultMemoryLimit, defaultUseDefaultNameForUnnamedEntries, + defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(path.toFile(), otherPassword, otherOptions), otherName, 42, true, true, otherPasswordBytes), + Arguments.of(new SevenZFile(path.toFile(), otherOptions), otherName, 42, true, true, null), + // From SeekableByteChannel + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ)), defaultName, defaultMemoryLimit, + defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, null), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), otherPasswordBytes), defaultName, defaultMemoryLimit, + defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), otherPassword), defaultName, defaultMemoryLimit, + defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), otherPassword, otherOptions), defaultName, 42, true, true, + otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), otherOptions), defaultName, 42, true, true, null), + // From SeekableByteChannel with custom name + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), customName), customName, defaultMemoryLimit, + defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, null), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), customName, otherPasswordBytes), customName, + defaultMemoryLimit, defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), customName, otherPassword), customName, defaultMemoryLimit, + defaultUseDefaultNameForUnnamedEntries, defaultTryToRecoverBrokenArchives, otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), customName, otherPassword, otherOptions), customName, 42, + true, true, otherPasswordBytes), + Arguments.of(new SevenZFile(Files.newByteChannel(path, StandardOpenOption.READ), customName, otherOptions), customName, 42, true, + true, null)); + } + + @ParameterizedTest + @MethodSource + void testSevenZFileContructors(final SevenZFile archiveFile, final String expectedName, final int expectedMemoryLimit, + final boolean expectedUseDefaultNameForUnnamedEntries, final boolean expectedTryToRecoverBrokenArchives, + final byte[] expectedPassword) throws Exception { + assertEquals(expectedName, readDeclaredField(archiveFile, "fileName", true)); + assertEquals(expectedMemoryLimit, readDeclaredField(archiveFile, "maxMemoryLimitKiB", true)); + assertEquals(expectedUseDefaultNameForUnnamedEntries, readDeclaredField(archiveFile, "useDefaultNameForUnnamedEntries", true)); + assertEquals(expectedTryToRecoverBrokenArchives, readDeclaredField(archiveFile, "tryToRecoverBrokenArchives", true)); + assertArrayEquals(expectedPassword, (byte[]) readDeclaredField(archiveFile, "password", true)); + } + @ParameterizedTest @MethodSource void testTarConstructors(final TarArchiveInputStream archiveStream, final InputStream expectedInput, final int expectedBlockSize, @@ -132,6 +202,35 @@ void testTarConstructors(final TarArchiveInputStream archiveStream, final InputS assertEquals(expectedLenient, readField(archiveStream, "lenient", true)); } + static Stream testTarFileConstructors() throws IOException { + final Path path = getPath("bla.tar"); + final File file = getFile("bla.tar"); + final SeekableByteChannel channel = mock(SeekableByteChannel.class); + final String defaultEncoding = Charset.defaultCharset().name(); + final String otherEncoding = "UTF-8".equals(defaultEncoding) ? "US-ASCII" : "UTF-8"; + return Stream.of( + Arguments.of(new TarFile(IOUtils.EMPTY_BYTE_ARRAY), defaultEncoding, false), + Arguments.of(new TarFile(IOUtils.EMPTY_BYTE_ARRAY, true), defaultEncoding, true), + Arguments.of(new TarFile(IOUtils.EMPTY_BYTE_ARRAY, otherEncoding), otherEncoding, false), + Arguments.of(new TarFile(file), defaultEncoding, false), + Arguments.of(new TarFile(file, true), defaultEncoding, true), + Arguments.of(new TarFile(file, otherEncoding), otherEncoding, false), + Arguments.of(new TarFile(path), defaultEncoding, false), + Arguments.of(new TarFile(path, true), defaultEncoding, true), + Arguments.of(new TarFile(path, otherEncoding), otherEncoding, false), + Arguments.of(new TarFile(channel), defaultEncoding, false), + Arguments.of(new TarFile(channel, 1024, 1024, otherEncoding, true), otherEncoding, true)); + } + + @ParameterizedTest + @MethodSource + void testTarFileConstructors(final TarFile tarFile, final String expectedEncoding, final boolean expectedLenient) throws Exception { + final ZipEncoding encoding = (ZipEncoding) readDeclaredField(tarFile, "zipEncoding", true); + final Charset charset = (Charset) readDeclaredField(encoding, "charset", true); + assertEquals(Charset.forName(expectedEncoding), charset); + assertEquals(expectedLenient, readDeclaredField(tarFile, "lenient", true)); + } + @ParameterizedTest @MethodSource void testZipConstructors(final ZipArchiveInputStream archiveStream, final InputStream expectedInput, final String expectedEncoding, @@ -144,4 +243,34 @@ void testZipConstructors(final ZipArchiveInputStream archiveStream, final InputS assertEquals(expectedSupportStoredEntryDataDescriptor, readDeclaredField(archiveStream, "supportStoredEntryDataDescriptor", true)); assertEquals(expectedSkipSplitSignature, readDeclaredField(archiveStream, "skipSplitSignature", true)); } + + static Stream testZipFileConstructors() throws IOException { + final Path path = getPath("bla.zip"); + final String defaultEncoding = StandardCharsets.UTF_8.name(); + final String otherEncoding = "UTF-8".equals(defaultEncoding) ? "US-ASCII" : "UTF-8"; + return Stream.of( + Arguments.of(new ZipFile(path.toFile()), defaultEncoding, true), + Arguments.of(new ZipFile(path.toFile(), otherEncoding), otherEncoding, true), + Arguments.of(new ZipFile(path.toFile(), otherEncoding, false), otherEncoding, false), + Arguments.of(new ZipFile(path.toFile(), otherEncoding, false, true), otherEncoding, false), + Arguments.of(new ZipFile(path), defaultEncoding, true), + Arguments.of(new ZipFile(path, otherEncoding), otherEncoding, true), + Arguments.of(new ZipFile(path, otherEncoding, false), otherEncoding, false), + Arguments.of(new ZipFile(path, otherEncoding, false, true), otherEncoding, false), + Arguments.of(new ZipFile(Files.newByteChannel(path, StandardOpenOption.READ)), defaultEncoding, true), + Arguments.of(new ZipFile(Files.newByteChannel(path, StandardOpenOption.READ), otherEncoding), otherEncoding, true), + Arguments.of(new ZipFile(Files.newByteChannel(path, StandardOpenOption.READ), null, otherEncoding, false), + otherEncoding, false), + Arguments.of(new ZipFile(Files.newByteChannel(path, StandardOpenOption.READ), null, otherEncoding, false, true), + otherEncoding, false), + Arguments.of(new ZipFile(path.toAbsolutePath().toString()), defaultEncoding, true), + Arguments.of(new ZipFile(path.toAbsolutePath().toString(), otherEncoding), otherEncoding, true)); + } + + @ParameterizedTest + @MethodSource + void testZipFileConstructors(final ZipFile zipFile, final String expectedEncoding, final boolean expectedUseUnicodeExtraFields) throws Exception { + assertEquals(Charset.forName(expectedEncoding), readDeclaredField(zipFile, "encoding", true)); + assertEquals(expectedUseUnicodeExtraFields, readDeclaredField(zipFile, "useUnicodeExtraFields", true)); + } } diff --git a/src/test/java/org/apache/commons/compress/archivers/TarTest.java b/src/test/java/org/apache/commons/compress/archivers/TarTest.java index 09116d76c2c..f80b05f32ba 100644 --- a/src/test/java/org/apache/commons/compress/archivers/TarTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/TarTest.java @@ -289,7 +289,7 @@ void testTarArchiveLongNameCreation() throws Exception { @Test void testTarFileCOMPRESS114() throws Exception { final File input = getFile("COMPRESS-114.tar"); - try (TarFile tarFile = new TarFile(input, StandardCharsets.ISO_8859_1.name())) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-114.tar")).setCharset(StandardCharsets.ISO_8859_1).get()) { final List entries = tarFile.getEntries(); TarArchiveEntry entry = entries.get(0); assertEquals("3\u00b1\u00b1\u00b1F06\u00b1W2345\u00b1ZB\u00b1la\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1BLA", entry.getName()); @@ -304,7 +304,7 @@ void testTarFileCOMPRESS114() throws Exception { void testTarFileCOMPRESS178() throws Exception { final File input = getFile("COMPRESS-178-fail.tar"); final IOException e = assertThrows(ArchiveException.class, () -> { - try (TarFile tarFile = new TarFile(input)) { + try (TarFile tarFile = TarFile.builder().setFile(input).get()) { // Compared to the TarArchiveInputStream all entries are read when instantiating the tar file } }, "Expected IOException"); @@ -315,7 +315,7 @@ void testTarFileCOMPRESS178() throws Exception { @Test void testTarFileCOMPRESS178Lenient() throws Exception { final File input = getFile("COMPRESS-178-fail.tar"); - try (TarFile tarFile = new TarFile(input, true)) { + try (TarFile tarFile = TarFile.builder().setFile(input).setLenient(true).get()) { // Compared to the TarArchiveInputStream all entries are read when instantiating the tar file } } @@ -330,7 +330,7 @@ void testTarFileDirectoryEntryFromFile() throws Exception { tos.putArchiveEntry(in); tos.closeArchiveEntry(); tos.close(); - try (TarFile tarFile = new TarFile(archive)) { + try (TarFile tarFile = TarFile.builder().setFile(archive).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); assertNotNull(entry); assertEquals("foo/", entry.getName()); @@ -346,7 +346,7 @@ void testTarFileDirectoryEntryFromFile() throws Exception { @Test void testTarFileDirectoryRead() throws IOException { final File input = getFile("directory.tar"); - try (TarFile tarFile = new TarFile(input)) { + try (TarFile tarFile = TarFile.builder().setFile(input).get()) { final TarArchiveEntry directoryEntry = tarFile.getEntries().get(0); assertEquals("directory/", directoryEntry.getName()); assertEquals(TarConstants.LF_DIR, directoryEntry.getLinkFlag()); @@ -368,7 +368,7 @@ void testTarFileEntryFromFile() throws Exception { outputStream.write(file); outputStream.closeArchiveEntry(); outputStream.close(); - try (TarFile tarFile = new TarFile(archive)) { + try (TarFile tarFile = TarFile.builder().setFile(archive).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); assertNotNull(entry); assertEquals("foo", entry.getName()); @@ -390,7 +390,7 @@ void testTarFileExplicitDirectoryEntry() throws Exception { tos.putArchiveEntry(in); tos.closeArchiveEntry(); tos.close(); - try (TarFile tarFile = new TarFile(archive)) { + try (TarFile tarFile = TarFile.builder().setFile(archive).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); assertNotNull(entry); assertEquals("foo/", entry.getName()); @@ -413,7 +413,7 @@ void testTarFileExplicitFileEntry() throws Exception { outputStream.putArchiveEntry(in); outputStream.write(file); outputStream.closeArchiveEntry(); - try (TarFile tarFile = new TarFile(archive)) { + try (TarFile tarFile = TarFile.builder().setFile(archive).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); assertNotNull(entry); assertEquals("foo", entry.getName()); @@ -433,7 +433,7 @@ void testTarFileLongNameLargerThanBuffer() throws IOException { final String fileName = createLongName(length); assertEquals(length.intValue(), fileName.length()); final byte[] data = createTarWithOneLongNameEntry(fileName); - try (TarFile tarFile = new TarFile(data)) { + try (TarFile tarFile = TarFile.builder().setByteArray(data).get()) { final List entries = tarFile.getEntries(); assertEquals(fileName, entries.get(0).getName()); assertEquals(TarConstants.LF_NORMAL, entries.get(0).getLinkFlag()); @@ -444,7 +444,7 @@ void testTarFileLongNameLargerThanBuffer() throws IOException { @Test void testTarFileUnarchive() throws Exception { final File file = getFile("bla.tar"); - try (TarFile tarFile = new TarFile(file)) { + try (TarFile tarFile = TarFile.builder().setFile(file).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); try (InputStream inputStream = tarFile.getInputStream(entry)) { Files.copy(inputStream, newTempFile(entry.getName()).toPath()); diff --git a/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java b/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java index a7ccedc665e..9c6eddbb2b6 100644 --- a/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/examples/ExpanderTest.java @@ -174,7 +174,7 @@ private void setupZip(final String entry) throws IOException, ArchiveException { @Test void testCompress603Tar() throws IOException, ArchiveException { setupTarForCompress603(); - try (TarFile f = new TarFile(archive)) { + try (TarFile f = TarFile.builder().setFile(archive).get()) { new Expander().expand(f, tempResultDir); } verifyTargetDir(); @@ -261,7 +261,7 @@ void testSevenZTwoFileVersionWithAutoDetection() throws IOException, ArchiveExce @Test void testTarFileVersion() throws IOException, ArchiveException { setupTar(); - try (TarFile f = new TarFile(archive)) { + try (TarFile f = TarFile.builder().setFile(archive).get()) { new Expander().expand(f, tempResultDir); } verifyTargetDir(); diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java index 446a2ba6436..6df5b102f40 100644 --- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java @@ -160,10 +160,6 @@ void test7zDeflateUnarchive() throws Exception { @Test void test7zMultiVolumeUnarchive() throws Exception { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(MultiReadOnlySeekableByteChannel.forFiles(getFile("bla-multi.7z.001"), getFile("bla-multi.7z.002")))) { - test7zUnarchive(sevenZFile, SevenZMethod.LZMA2); - } try (SevenZFile sevenZFile = SevenZFile.builder() .setSeekableByteChannel(MultiReadOnlySeekableByteChannel.forFiles(getFile("bla-multi.7z.001"), getFile("bla-multi.7z.002"))).get()) { test7zUnarchive(sevenZFile, SevenZMethod.LZMA2); @@ -184,10 +180,6 @@ private void test7zUnarchive(final File file, final SevenZMethod method, final b } private void test7zUnarchive(final File file, final SevenZMethod method, final byte[] password) throws Exception { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(file, password)) { - test7zUnarchive(sevenZFile, method); - } try (SevenZFile sevenZFile = SevenZFile.builder().setFile(file).setPassword(password).get()) { test7zUnarchive(sevenZFile, method); } @@ -198,11 +190,6 @@ private void test7zUnarchive(final File file, final SevenZMethod m, final char[] } private void test7zUnarchive(final File file, final SevenZMethod m, final char[] password, final boolean tryToRecoverBrokenArchives) throws Exception { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(file, password, - SevenZFileOptions.builder().withTryToRecoverBrokenArchives(tryToRecoverBrokenArchives).build())) { - test7zUnarchive(sevenZFile, m); - } try (SevenZFile sevenZFile = SevenZFile.builder().setFile(file).setPassword(password).setTryToRecoverBrokenArchives(tryToRecoverBrokenArchives).get()) { test7zUnarchive(sevenZFile, m); } @@ -324,8 +311,7 @@ void testExtractSpecifiedFile() throws Exception { @Test void testExtractSpecifiedFileDeprecated() throws Exception { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(getFile("COMPRESS-256.7z"))) { + try (SevenZFile sevenZFile = SevenZFile.builder().setURI(getURI("COMPRESS-256.7z")).get()) { // @formatter:off final String testTxtContents = "111111111111111111111111111000101011\n" @@ -364,10 +350,6 @@ void testGetDefaultName() throws Exception { try (SevenZFile sevenZFile = SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(getFile("bla.deflate64.7z").toPath())).get()) { assertNull(sevenZFile.getDefaultName()); } - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(Files.newByteChannel(getFile("bla.deflate64.7z").toPath()), "foo")) { - assertEquals("foo~", sevenZFile.getDefaultName()); - } try (SevenZFile sevenZFile = SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(getFile("bla.deflate64.7z").toPath())) .setDefaultName("foo").get()) { assertEquals("foo~", sevenZFile.getDefaultName()); @@ -407,16 +389,6 @@ void testGetEntriesOfUnarchiveTest() throws IOException { @Test void testGivenNameWinsOverDefaultName() throws Exception { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"), SevenZFileOptions.builder().withUseDefaultNameForUnnamedEntries(true).build())) { - SevenZArchiveEntry ae = sevenZFile.getNextEntry(); - assertNotNull(ae); - assertEquals("test1.xml", ae.getName()); - ae = sevenZFile.getNextEntry(); - assertNotNull(ae); - assertEquals("test2.xml", ae.getName()); - assertNull(sevenZFile.getNextEntry()); - } try (SevenZFile sevenZFile = SevenZFile.builder().setFile(getFile("bla.7z")).setUseDefaultNameForUnnamedEntries(true).get()) { SevenZArchiveEntry ae = sevenZFile.getNextEntry(); assertNotNull(ae); @@ -512,25 +484,12 @@ void testNoOOMOnCorruptedHeader() throws IOException { testFiles.add(getPath("COMPRESS-542-endheadercorrupted.7z")); testFiles.add(getPath("COMPRESS-542-endheadercorrupted2.7z")); for (final Path file : testFiles) { - { - final IOException e = assertThrows(ArchiveException.class, () -> { - try (@SuppressWarnings("deprecation") - SevenZFile sevenZFile = new SevenZFile(Files.newByteChannel(file), - SevenZFileOptions.builder().withTryToRecoverBrokenArchives(true).build())) { - // do nothing - } - }, "Expected IOException: start header corrupt and unable to guess end header"); - assertEquals("Start header corrupt and unable to guess end header", e.getMessage()); - } - { - final IOException e = assertThrows(ArchiveException.class, () -> { - try (SevenZFile sevenZFile = SevenZFile.builder().setSeekableByteChannel(Files.newByteChannel(file)).setTryToRecoverBrokenArchives(true) - .get()) { - // do nothing - } - }, "Expected IOException: start header corrupt and unable to guess end header"); - assertEquals("Start header corrupt and unable to guess end header", e.getMessage()); - } + final IOException e = assertThrows(ArchiveException.class, () -> { + try (SevenZFile sevenZFile = SevenZFile.builder().setPath(file).setTryToRecoverBrokenArchives(true).get()) { + // do nothing + } + }, "Expected IOException: start header corrupt and unable to guess end header"); + assertEquals("Start header corrupt and unable to guess end header", e.getMessage()); } } @@ -554,8 +513,6 @@ void testNumCyclesPower30() throws IOException { .setPassword(password) .setTryToRecoverBrokenArchives(true) .get().close()); - assertThrows(ArchiveException.class, - () -> new SevenZFile(new File(fixture), password).close()); // @formatter:on } diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/BigFilesIT.java b/src/test/java/org/apache/commons/compress/archivers/tar/BigFilesIT.java index a941dbe0e6e..eab504cfe88 100644 --- a/src/test/java/org/apache/commons/compress/archivers/tar/BigFilesIT.java +++ b/src/test/java/org/apache/commons/compress/archivers/tar/BigFilesIT.java @@ -94,7 +94,7 @@ void testTarFileReadFileHeadersOfArchiveBiggerThan8GByte() throws Exception { GzipCompressorInputStream gzin = new GzipCompressorInputStream(in)) { Files.copy(gzin, output, StandardCopyOption.REPLACE_EXISTING); } - try (TarFile tarFile = new TarFile(output)) { + try (TarFile tarFile = TarFile.builder().setPath(output).get()) { final List entries = tarFile.getEntries(); assertEquals(1, entries.size()); assertNotNull(entries.get(0)); diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/SparseFilesTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/SparseFilesTest.java index 4d09fddcaa3..2e03a978b29 100644 --- a/src/test/java/org/apache/commons/compress/archivers/tar/SparseFilesTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/tar/SparseFilesTest.java @@ -116,7 +116,7 @@ private String getTarBinaryHelp() throws IOException { void testCompareTarArchiveInputStreamWithTarFile() throws IOException { final Path file = getPath("oldgnu_sparse.tar"); try (TarArchiveInputStream tarIn = TarArchiveInputStream.builder().setPath(file).get(); - TarFile tarFile = new TarFile(file)) { + TarFile tarFile = TarFile.builder().setPath(file).get()) { assertNotNull(tarIn.getNextTarEntry()); try (InputStream inputStream = tarFile.getInputStream(tarFile.getEntries().get(0))) { assertArrayEquals(IOUtils.toByteArray(tarIn), IOUtils.toByteArray(inputStream)); @@ -303,7 +303,7 @@ void testPaxGNU() throws Throwable { void testTarFileExtractExtendedOldGNU() throws IOException, InterruptedException { final File file = getFile("oldgnu_extended_sparse.tar"); try (InputStream sparseFileInputStream = extractTarAndGetInputStream(file, "sparse6"); - TarFile tarFile = new TarFile(file)) { + TarFile tarFile = TarFile.builder().setFile(file).get()) { final TarArchiveEntry ae = tarFile.getEntries().get(0); try (InputStream tarInput = tarFile.getInputStream(ae)) { @@ -341,7 +341,7 @@ void testTarFileExtractExtendedOldGNU() throws IOException, InterruptedException void testTarFileExtractOldGNU() throws IOException, InterruptedException { final File file = getFile("oldgnu_sparse.tar"); try (InputStream sparseFileInputStream = extractTarAndGetInputStream(file, "sparsefile"); - TarFile tarFile = new TarFile(file)) { + TarFile tarFile = TarFile.builder().setFile(file).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); try (InputStream tarInput = tarFile.getInputStream(entry)) { assertArrayEquals(IOUtils.toByteArray(tarInput), IOUtils.toByteArray(sparseFileInputStream)); @@ -358,7 +358,7 @@ void testTarFileExtractPaxGNU() throws IOException, InterruptedException { assumeFalse(getTarBinaryHelp().startsWith("tar (GNU tar) 1.28"), "This test should be ignored if GNU tar is version 1.28"); final File file = getFile("pax_gnu_sparse.tar"); - try (TarFile paxGnu = new TarFile(file)) { + try (TarFile paxGnu = TarFile.builder().setFile(file).get()) { final List entries = paxGnu.getEntries(); TarArchiveEntry entry = entries.get(0); @@ -386,12 +386,12 @@ void testTarFileExtractPaxGNU() throws IOException, InterruptedException { void testTarFileExtractSparseTarsOnWindows() throws IOException { final File oldGNUSparseTar = getFile("oldgnu_sparse.tar"); final File paxGNUSparseTar = getFile("pax_gnu_sparse.tar"); - try (TarFile paxGnu = new TarFile(paxGNUSparseTar)) { + try (TarFile paxGnu = TarFile.builder().setFile(paxGNUSparseTar).get()) { final List entries = paxGnu.getEntries(); // compare between old GNU and PAX 0.0 TarArchiveEntry paxGnuEntry = entries.get(0); - try (TarFile oldGnu = new TarFile(oldGNUSparseTar)) { + try (TarFile oldGnu = TarFile.builder().setFile(oldGNUSparseTar).get()) { final TarArchiveEntry oldGnuEntry = oldGnu.getEntries().get(0); try (InputStream old = oldGnu.getInputStream(oldGnuEntry); InputStream pax = paxGnu.getInputStream(paxGnuEntry)) { @@ -401,7 +401,7 @@ void testTarFileExtractSparseTarsOnWindows() throws IOException { // compare between old GNU and PAX 0.1 paxGnuEntry = entries.get(1); - try (TarFile oldGnu = new TarFile(oldGNUSparseTar)) { + try (TarFile oldGnu = TarFile.builder().setFile(oldGNUSparseTar).get()) { final TarArchiveEntry oldGnuEntry = oldGnu.getEntries().get(0); try (InputStream old = oldGnu.getInputStream(oldGnuEntry); InputStream pax = paxGnu.getInputStream(paxGnuEntry)) { @@ -411,7 +411,7 @@ void testTarFileExtractSparseTarsOnWindows() throws IOException { // compare between old GNU and PAX 1.0 paxGnuEntry = entries.get(2); - try (TarFile oldGnu = new TarFile(oldGNUSparseTar)) { + try (TarFile oldGnu = TarFile.builder().setFile(oldGNUSparseTar).get()) { final TarArchiveEntry oldGnuEntry = oldGnu.getEntries().get(0); try (InputStream old = oldGnu.getInputStream(oldGnuEntry); InputStream pax = paxGnu.getInputStream(paxGnuEntry)) { @@ -424,7 +424,7 @@ void testTarFileExtractSparseTarsOnWindows() throws IOException { @Test void testTarFileOldGNU() throws Throwable { final File file = getFile("oldgnu_sparse.tar"); - try (TarFile tarFile = new TarFile(file)) { + try (TarFile tarFile = TarFile.builder().setFile(file).get()) { final TarArchiveEntry ae = tarFile.getEntries().get(0); assertEquals("sparsefile", ae.getName()); assertEquals(TarConstants.LF_GNUTYPE_SPARSE, ae.getLinkFlag()); @@ -464,7 +464,7 @@ void testTarFileOldGNU() throws Throwable { @Test void testTarFilePaxGNU() throws IOException { final File file = getFile("pax_gnu_sparse.tar"); - try (TarFile tarFile = new TarFile(file)) { + try (TarFile tarFile = TarFile.builder().setFile(file).get()) { final List entries = tarFile.getEntries(); assertPaxGNUEntry(entries.get(0), "0.0"); assertPaxGNUEntry(entries.get(1), "0.1"); diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/TarFileTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/TarFileTest.java index 5b8b9a18f3a..87f6766ba6e 100644 --- a/src/test/java/org/apache/commons/compress/archivers/tar/TarFileTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarFileTest.java @@ -32,6 +32,7 @@ import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -51,7 +52,7 @@ class TarFileTest extends AbstractTest { private void datePriorToEpoch(final String archive) throws Exception { - try (TarFile tarFile = new TarFile(getPath(archive))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI(archive)).get()) { final TarArchiveEntry entry = tarFile.getEntries().get(0); assertEquals("foo", entry.getName()); assertEquals(TarConstants.LF_NORMAL, entry.getLinkFlag()); @@ -69,7 +70,7 @@ private void datePriorToEpoch(final String archive) throws Exception { @Test void testArchiveWithTrailer() throws IOException { try (SeekableByteChannel channel = Files.newByteChannel(getPath("archive_with_trailer.tar")); - TarFile tarfile = new TarFile(channel, TarConstants.DEFAULT_BLKSIZE, TarConstants.DEFAULT_RCDSIZE, null, false)) { + TarFile tarfile = TarFile.builder().setChannel(channel).get()) { final String tarAppendix = "Hello, world!\n"; final ByteBuffer buffer = ByteBuffer.allocate(tarAppendix.length()); channel.read(buffer); @@ -81,7 +82,7 @@ void testArchiveWithTrailer() throws IOException { void testBuilderSeekableByteChannel() throws IOException { try (SeekableByteChannel channel = Files.newByteChannel(getPath("archive_with_trailer.tar")); TarFile tarfile = TarFile.builder() - .setSeekableByteChannel(channel) + .setChannel(channel) .setBlockSize(TarConstants.DEFAULT_BLKSIZE) .setRecordSize(TarConstants.DEFAULT_RCDSIZE) .setLenient(false) @@ -95,7 +96,7 @@ void testBuilderSeekableByteChannel() throws IOException { @Test void testCompress197() throws IOException { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-197.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-197.tar")).get()) { // noop } } @@ -122,7 +123,7 @@ void testCompress558() throws IOException { tos.closeArchiveEntry(); } final byte[] data = bos.toByteArray(); - try (TarFile tarFile = new TarFile(data)) { + try (TarFile tarFile = TarFile.builder().setByteArray(data).get()) { final List entries = tarFile.getEntries(); assertEquals(folderName, entries.get(0).getName()); assertEquals(TarConstants.LF_DIR, entries.get(0).getLinkFlag()); @@ -135,7 +136,7 @@ void testCompress558() throws IOException { @Test void testCompress657() throws IOException { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-657/orjson-3.7.8.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-657/orjson-3.7.8.tar")).get()) { for (final TarArchiveEntry entry : tarFile.getEntries()) { if (entry.isDirectory()) { // An entry cannot be a directory and a "normal file" at the same time. @@ -184,7 +185,7 @@ void testDirectoryWithLongNameEndsWithSlash() throws IOException { out.flush(); } // untar these tars - try (TarFile tarFile = new TarFile(tarF)) { + try (TarFile tarFile = TarFile.builder().setFile(tarF).get()) { for (final TarArchiveEntry entry : tarFile.getEntries()) { assertTrue(entry.getName().endsWith("/"), "Entry name: " + entry.getName()); } @@ -195,7 +196,7 @@ void testDirectoryWithLongNameEndsWithSlash() throws IOException { @Test void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws Exception { final byte[] buf = new byte[2]; - try (TarFile tarFile = new TarFile(getPath("bla.tar")); + try (TarFile tarFile = TarFile.builder().setURI(getURI("bla.tar")).get(); InputStream input = tarFile.getInputStream(tarFile.getEntries().get(0))) { IOUtils.toByteArray(input); assertEquals(-1, input.read(buf)); @@ -205,22 +206,22 @@ void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws Exception { @Test void testParseTarTruncatedInContent() { - assertThrows(IOException.class, () -> new TarFile(getPath("COMPRESS-544_truncated_in_content.tar"))); + assertThrows(IOException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-544_truncated_in_content.tar")).get()); } @Test void testParseTarTruncatedInPadding() { - assertThrows(IOException.class, () -> new TarFile(getPath("COMPRESS-544_truncated_in_padding.tar"))); + assertThrows(IOException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-544_truncated_in_padding.tar")).get()); } @Test void testParseTarWithNonNumberPaxHeaders() { - assertThrows(ArchiveException.class, () -> new TarFile(getPath("COMPRESS-529-fail.tar"))); + assertThrows(ArchiveException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-529-fail.tar")).get()); } @Test void testParseTarWithSpecialPaxHeaders() { - assertThrows(ArchiveException.class, () -> new TarFile(getPath("COMPRESS-530-fail.tar"))); + assertThrows(ArchiveException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-530-fail.tar")).get()); } @Test @@ -230,7 +231,7 @@ void testReadsArchiveCompletely_COMPRESS245() { try (GZIPInputStream gin = new GZIPInputStream(Files.newInputStream(getPath("COMPRESS-245.tar.gz")))) { Files.copy(gin, tempTar); } - try (TarFile tarFile = new TarFile(tempTar)) { + try (TarFile tarFile = TarFile.builder().setPath(tempTar).get()) { assertEquals(31, tarFile.getEntries().size()); } } catch (final IOException e) { @@ -240,7 +241,7 @@ void testReadsArchiveCompletely_COMPRESS245() { @Test void testRejectsArchivesWithNegativeSizes() throws Exception { - assertThrows(ArchiveException.class, () -> new TarFile(getFile("COMPRESS-569-fail.tar"))); + assertThrows(ArchiveException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-569-fail.tar")).get()); } @Test @@ -256,7 +257,7 @@ void testShouldReadBigGid() throws Exception { tos.closeArchiveEntry(); } final byte[] data = bos.toByteArray(); - try (TarFile tarFile = new TarFile(data)) { + try (TarFile tarFile = TarFile.builder().setByteArray(data).get()) { final List entries = tarFile.getEntries(); assertEquals(4294967294L, entries.get(0).getLongGroupId()); } @@ -267,7 +268,7 @@ void testShouldReadBigGid() throws Exception { */ @Test void testShouldReadGNULongNameEntryWithWrongName() throws Exception { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-324.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-324.tar")).get()) { final List entries = tarFile.getEntries(); assertEquals( "1234567890123456789012345678901234567890123456789012345678901234567890" @@ -280,15 +281,15 @@ void testShouldReadGNULongNameEntryWithWrongName() throws Exception { @Test void testShouldThrowAnExceptionOnTruncatedEntries() throws Exception { createTempDirectory("COMPRESS-279"); - assertThrows(IOException.class, () -> new TarFile(getPath("COMPRESS-279.tar"))); + assertThrows(IOException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-279.tar")).get()); } @Test void testShouldUseSpecifiedEncodingWhenReadingGNULongNames() throws Exception { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - final String encoding = StandardCharsets.UTF_16.name(); + final Charset encoding = StandardCharsets.UTF_16; final String name = "1234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890\u00e4"; - try (TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, encoding)) { + try (TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, encoding.name())) { tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); final TarArchiveEntry t = new TarArchiveEntry(name); t.setSize(1); @@ -297,7 +298,7 @@ void testShouldUseSpecifiedEncodingWhenReadingGNULongNames() throws Exception { tos.closeArchiveEntry(); } final byte[] data = bos.toByteArray(); - try (TarFile tarFile = new TarFile(data, encoding)) { + try (TarFile tarFile = TarFile.builder().setByteArray(data).setCharset(encoding).get()) { final List entries = tarFile.getEntries(); assertEquals(1, entries.size()); assertEquals(name, entries.get(0).getName()); @@ -306,7 +307,7 @@ void testShouldUseSpecifiedEncodingWhenReadingGNULongNames() throws Exception { @Test void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws Exception { - try (TarFile tarFile = new TarFile(getPath("bla.tar")); + try (TarFile tarFile = TarFile.builder().setURI(getURI("bla.tar")).get(); InputStream input = tarFile.getInputStream(tarFile.getEntries().get(0))) { IOUtils.toByteArray(input); assertEquals(-1, input.read()); @@ -319,7 +320,7 @@ void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws Exception { */ @Test void testSkipsDevNumbersWhenEntryIsNoDevice() throws Exception { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-417.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-417.tar")).get()) { final List entries = tarFile.getEntries(); assertEquals(2, entries.size()); assertEquals("test1.xml", entries.get(0).getName()); @@ -334,7 +335,7 @@ void testSkipsDevNumbersWhenEntryIsNoDevice() throws Exception { */ @Test void testSurvivesBlankLinesInPaxHeader() throws Exception { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-355.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-355.tar")).get()) { final List entries = tarFile.getEntries(); assertEquals(1, entries.size()); assertEquals("package/package.json", entries.get(0).getName()); @@ -347,7 +348,7 @@ void testSurvivesBlankLinesInPaxHeader() throws Exception { */ @Test void testSurvivesPaxHeaderWithNameEndingInSlash() throws Exception { - try (TarFile tarFile = new TarFile(getPath("COMPRESS-356.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("COMPRESS-356.tar")).get()) { final List entries = tarFile.getEntries(); assertEquals(1, entries.size()); assertEquals("package/package.json", entries.get(0).getName()); @@ -357,18 +358,18 @@ void testSurvivesPaxHeaderWithNameEndingInSlash() throws Exception { @Test void testThrowException() { - assertThrows(ArchiveException.class, () -> new TarFile(getPath("COMPRESS-553-fail.tar"))); + assertThrows(ArchiveException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-553-fail.tar")).get()); } @Test void testThrowExceptionWithNullEntry() { // Only on Windows: throws a UnmappableCharacterException - assertThrows(IOException.class, () -> new TarFile(getPath("COMPRESS-554-fail.tar"))); + assertThrows(IOException.class, () -> TarFile.builder().setURI(getURI("COMPRESS-554-fail.tar")).get()); } @Test void testWorkaroundForBrokenTimeHeader() throws IOException { - try (TarFile tarFile = new TarFile(getPath("simple-aix-native-tar.tar"))) { + try (TarFile tarFile = TarFile.builder().setURI(getURI("simple-aix-native-tar.tar")).get()) { final List entries = tarFile.getEntries(); assertEquals(3, entries.size()); final TarArchiveEntry entry = entries.get(1); diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java index aceae288baf..c9dbe374d62 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java @@ -201,8 +201,7 @@ void testRawNameReadFromZipFile() throws IOException { */ @Test void testRead7ZipArchive() throws IOException { - final File archive = getFile("utf8-7zip-test.zip"); - try (ZipFile zf = new ZipFile(archive, CP437, false)) { + try (ZipFile zf = ZipFile.builder().setURI(getURI("utf8-7zip-test.zip")).setCharset(CP437).setUseUnicodeExtraFields(false).get()) { assertNotNull(zf.getEntry(ASCII_TXT)); assertNotNull(zf.getEntry(EURO_FOR_DOLLAR_TXT)); assertNotNull(zf.getEntry(OIL_BARREL_TXT)); diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java index 397a09723c7..3406dc78032 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java @@ -25,7 +25,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Enumeration; @@ -38,18 +37,12 @@ class ZipFileIgnoringLocalFileHeaderTest { private static ZipFile openZipWithoutLocalFileHeader(final String fileName) throws IOException { // @formatter:off return ZipFile.builder() - .setFile(AbstractTest.getFile(fileName)) - .setCharset(StandardCharsets.UTF_8.name()) - .setUseUnicodeExtraFields(true) + .setURI(AbstractTest.getURI(fileName)) .setIgnoreLocalFileHeader(true) .get(); // @formatter:on } - private static ZipFile openZipWithoutLocalFileHeaderDeprecated(final String fileName) throws IOException { - return new ZipFile(AbstractTest.getFile(fileName), StandardCharsets.UTF_8.name(), true, true); - } - @TempDir private File dir; @@ -104,7 +97,7 @@ void testPhysicalOrder() throws IOException { */ @Test void testZipUnarchive() throws Exception { - try (ZipFile zipFile = openZipWithoutLocalFileHeaderDeprecated("bla.zip")) { + try (ZipFile zipFile = openZipWithoutLocalFileHeader("bla.zip")) { zipFile.stream().forEach(entry -> { try (InputStream inputStream = zipFile.getInputStream(entry)) { Files.copy(inputStream, new File(dir, entry.getName()).toPath()); diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java index ba97587aaa9..c417ec823f5 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java @@ -61,6 +61,7 @@ import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.channels.ByteArraySeekableByteChannel; import org.apache.commons.io.function.IORunnable; import org.apache.commons.lang3.ArrayFill; import org.apache.commons.lang3.ArrayUtils; @@ -109,7 +110,7 @@ private static void assertEntryName(final ArrayList entries, fi } private static void nameSource(final String archive, final String entry, final ZipArchiveEntry.NameSource expected) throws Exception { - try (ZipFile zf = ZipFile.builder().setFile(getFile(archive)).get()) { + try (ZipFile zf = ZipFile.builder().setURI(getURI(archive)).get()) { final ZipArchiveEntry ze = zf.getEntry(entry); assertEquals(entry, ze.getName()); assertEquals(expected, ze.getNameSource()); @@ -211,7 +212,7 @@ private void multiByteReadConsistentlyReturnsMinusOneAtEof(final File file) thro * The central directory has ZipFile and ZipUtil swapped so central directory order is different from entry data order. */ private void readOrderTest() throws Exception { - zf = ZipFile.builder().setFile(getFile("ordertest.zip")).get(); + zf = ZipFile.builder().setURI(getURI("ordertest.zip")).get(); } /** @@ -284,14 +285,14 @@ void testCDOrder() throws Exception { @Test void testCDOrderInMemory() throws Exception { final byte[] data = readAllBytes("ordertest.zip"); - zf = ZipFile.builder().setByteArray(data).setCharset(StandardCharsets.UTF_8).get(); + zf = ZipFile.builder().setByteArray(data).get(); testCDOrderInMemory(zf); - try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(data)) { - zf = ZipFile.builder().setSeekableByteChannel(channel).setCharset(StandardCharsets.UTF_8).get(); + try (ByteArraySeekableByteChannel channel = ByteArraySeekableByteChannel.wrap(data)) { + zf = ZipFile.builder().setChannel(channel).get(); testCDOrderInMemory(zf); } - try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(data)) { - zf = new ZipFile(channel, StandardCharsets.UTF_8.name()); + try (ByteArraySeekableByteChannel channel = ByteArraySeekableByteChannel.wrap(data)) { + zf = ZipFile.builder().setChannel(channel).get(); testCDOrderInMemory(zf); } } @@ -326,8 +327,7 @@ private void testCDOrderInMemory(final ZipFile zipFile) { @Test void testConcurrentReadFile() throws Exception { // mixed.zip contains both inflated and stored files - final File archive = getFile("mixed.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("mixed.zip")).get(); final Map content = new HashMap<>(); zf.stream().forEach(entry -> { try (InputStream inputStream = zf.getInputStream(entry)) { @@ -356,7 +356,7 @@ void testConcurrentReadSeekable() throws Exception { data = IOUtils.toByteArray(fis); } try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(data)) { - zf = ZipFile.builder().setSeekableByteChannel(channel).setCharset(StandardCharsets.UTF_8).get(); + zf = ZipFile.builder().setChannel(channel).setCharset(StandardCharsets.UTF_8).get(); final Map content = new HashMap<>(); zf.stream().forEach(entry -> { try (InputStream inputStream = zf.getInputStream(entry)) { @@ -439,8 +439,7 @@ void testDoubleClose() throws Exception { */ @Test void testDuplicateEntry() throws Exception { - final File archive = getFile("COMPRESS-227.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("COMPRESS-227.zip")).get(); final ZipArchiveEntry ze = zf.getEntry("test1.txt"); assertNotNull(ze); @@ -566,8 +565,7 @@ void testEntryAlignmentExceed() throws Exception { */ @Test void testExcessDataInZip64ExtraField() throws Exception { - final File archive = getFile("COMPRESS-228.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("COMPRESS-228.zip")).get(); // actually, if we get here, the test already has passed final ZipArchiveEntry ze = zf.getEntry("src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java"); @@ -578,7 +576,7 @@ void testExcessDataInZip64ExtraField() throws Exception { void testExtractFileLiesAcrossSplitZipSegmentsCreatedByWinrar() throws Exception { final File lastFile = getFile("COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip"); try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile)) { - zf = ZipFile.builder().setSeekableByteChannel(channel).get(); + zf = ZipFile.builder().setChannel(channel).get(); // the compressed content of ZipArchiveInputStream.java lies between .z01 and .z02 final ZipArchiveEntry zipEntry = zf.getEntry("commons-compress/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java"); @@ -591,7 +589,7 @@ void testExtractFileLiesAcrossSplitZipSegmentsCreatedByWinrar() throws Exception void testExtractFileLiesAcrossSplitZipSegmentsCreatedByZip() throws Exception { final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip"); try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile)) { - zf = new ZipFile(channel); + zf = ZipFile.builder().setChannel(channel).get(); // the compressed content of UnsupportedCompressionAlgorithmException.java lies between .z01 and .z02 ZipArchiveEntry zipEntry = zf @@ -610,7 +608,7 @@ void testExtractFileLiesAcrossSplitZipSegmentsCreatedByZip() throws Exception { void testExtractFileLiesAcrossSplitZipSegmentsCreatedByZipOfZip64() throws Exception { final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip_zip64.zip"); try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile)) { - zf = new ZipFile(channel); + zf = ZipFile.builder().setChannel(channel).get(); // the compressed content of UnsupportedCompressionAlgorithmException.java lies between .z01 and .z02 ZipArchiveEntry zipEntry = zf @@ -628,8 +626,7 @@ void testExtractFileLiesAcrossSplitZipSegmentsCreatedByZipOfZip64() throws Excep @Test void testGetEntries() throws Exception { // mixed.zip contains both inflated and stored files - final File archive = getFile("mixed.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("mixed.zip")).get(); final Map content = new HashMap<>(); for (final ZipArchiveEntry entry : Collections.list(zf.getEntries())) { try (InputStream inputStream = zf.getInputStream(entry)) { @@ -644,8 +641,7 @@ void testGetEntries() throws Exception { @Test void testGetEntriesInPhysicalOrder() throws Exception { // mixed.zip contains both inflated and stored files - final File archive = getFile("mixed.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("mixed.zip")).get(); final Map content = new HashMap<>(); for (final ZipArchiveEntry entry : Collections.list(zf.getEntriesInPhysicalOrder())) { try (InputStream inputStream = zf.getInputStream(entry)) { @@ -716,8 +712,7 @@ void testNameSourceIsSetToUnicodeExtraField() throws Exception { @Test void testOffsets() throws Exception { // mixed.zip contains both inflated and stored files - final File archive = getFile("mixed.zip"); - try (ZipFile zf = new ZipFile(archive)) { + try (ZipFile zf = ZipFile.builder().setURI(getURI("mixed.zip")).get()) { final ZipArchiveEntry inflatedEntry = zf.getEntry("inflated.txt"); assertEquals(0x0000, inflatedEntry.getLocalHeaderOffset()); assertEquals(0x0046, inflatedEntry.getDataOffset()); @@ -775,10 +770,8 @@ void testPhysicalOrderOfSpecificFile() throws Exception { */ @Test void testReadDeflate64CompressedStream() throws Exception { - final File input = getFile("COMPRESS-380/COMPRESS-380-input"); - final File archive = getFile("COMPRESS-380/COMPRESS-380.zip"); - try (InputStream in = Files.newInputStream(input.toPath()); - ZipFile zf = new ZipFile(archive)) { + try (InputStream in = Files.newInputStream(getPath("COMPRESS-380/COMPRESS-380-input")); + ZipFile zf = ZipFile.builder().setURI(getURI("COMPRESS-380/COMPRESS-380.zip")).get()) { final byte[] orig = IOUtils.toByteArray(in); final ZipArchiveEntry e = zf.getEntry("input2"); try (InputStream s = zf.getInputStream(e)) { @@ -796,7 +789,7 @@ void testReadingOfExtraDataBeforeZip() throws IOException { final byte[] fileHeader = "Before Zip file".getBytes(UTF_8); final String entryName = "COMPRESS-621.txt"; final byte[] entryContent = "https://issues.apache.org/jira/browse/COMPRESS-621".getBytes(UTF_8); - try (ZipFile archive = new ZipFile(getFile("COMPRESS-621.zip"))) { + try (ZipFile archive = ZipFile.builder().setURI(getURI("COMPRESS-621.zip")).get()) { assertEquals(fileHeader.length, archive.getFirstLocalFileHeaderOffset()); try (InputStream input = archive.getContentBeforeFirstLocalFileHeader()) { assertArrayEquals(fileHeader, IOUtils.toByteArray(input)); @@ -815,8 +808,7 @@ void testReadingOfExtraDataBeforeZip() throws IOException { */ @Test void testReadingOfFirstStoredEntry() throws Exception { - final File archive = getFile("COMPRESS-264.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("COMPRESS-264.zip")).get(); final ZipArchiveEntry ze = zf.getEntry("test.txt"); assertEquals(5, ze.getSize()); try (InputStream inputStream = zf.getInputStream(ze)) { @@ -839,7 +831,7 @@ void testReadingOfStoredEntry() throws Exception { zo.closeArchiveEntry(); } - zf = new ZipFile(file); + zf = ZipFile.builder().setFile(file).get(); ze = zf.getEntry("foo"); assertNotNull(ze); try (InputStream i = zf.getInputStream(ze)) { @@ -965,8 +957,7 @@ void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingUnshrink() throws Ex */ @Test void testSkipsPK00Prefix() throws Exception { - final File archive = getFile("COMPRESS-208.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("COMPRESS-208.zip")).get(); assertNotNull(zf.getEntry("test1.xml")); assertNotNull(zf.getEntry("test2.xml")); } @@ -998,8 +989,7 @@ void testUnixSymlinkSampleFile() throws Exception { expectedVals.put(entryPrefix + "link6", "../COMPRESS-214_unix_symlinks/././a/b/"); // I looked into creating a test with hard links, but ZIP does not appear to // support hard links, so nevermind. - final File archive = getFile("COMPRESS-214_unix_symlinks.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("COMPRESS-214_unix_symlinks.zip")).get(); zf.stream().forEach(zae -> { final String link = zf.getUnixSymlink(zae); if (zae.isUnixSymlink()) { @@ -1015,7 +1005,7 @@ void testUnixSymlinkSampleFile() throws Exception { @Test void testUnshrinking() throws Exception { - zf = new ZipFile(getFile("SHRUNK.ZIP")); + zf = ZipFile.builder().setURI(getURI("SHRUNK.ZIP")).get(); ZipArchiveEntry test = zf.getEntry("TEST1.XML"); try (InputStream original = newInputStream("test1.xml"); InputStream inputStream = zf.getInputStream(test)) { @@ -1030,8 +1020,7 @@ void testUnshrinking() throws Exception { @Test void testUnzipBZip2CompressedEntry() throws Exception { - final File archive = getFile("bzip2-zip.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("bzip2-zip.zip")).get(); final ZipArchiveEntry ze = zf.getEntry("lots-of-as"); assertEquals(42, ze.getSize()); final byte[] expected = ArrayFill.fill(new byte[42], (byte) 'a'); @@ -1045,8 +1034,7 @@ void testUnzipBZip2CompressedEntry() throws Exception { */ @Test void testWinzipBackSlashWorkaround() throws Exception { - final File archive = getFile("test-winzip.zip"); - zf = new ZipFile(archive); + zf = ZipFile.builder().setURI(getURI("test-winzip.zip")).get(); assertNull(zf.getEntry("\u00e4\\\u00fc.txt")); assertNotNull(zf.getEntry("\u00e4/\u00fc.txt")); } diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipMemoryFileSystemTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipMemoryFileSystemTest.java index 60c6fadbd0a..e44e01888ab 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipMemoryFileSystemTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipMemoryFileSystemTest.java @@ -32,7 +32,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.SeekableByteChannel; -import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; @@ -230,8 +229,7 @@ void testScatterFileWithCompressionAndTargetInMemory() throws IOException { } } - try (ZipFile zf = new ZipFile(Files.newByteChannel(target, StandardOpenOption.READ), target.getFileName().toString(), StandardCharsets.UTF_8.name(), - true)) { + try (ZipFile zf = ZipFile.builder().setPath(target).get()) { final ZipArchiveEntry b_entry = zf.getEntries("b.txt").iterator().next(); assertEquals(8, b_entry.getSize()); try (InputStream inputStream = zf.getInputStream(b_entry)) { @@ -245,8 +243,7 @@ void testScatterFileWithCompressionAndTargetInMemory() throws IOException { } } - try (ZipFile zf = new ZipFile(Files.newByteChannel(target, StandardOpenOption.READ), target.getFileName().toString(), StandardCharsets.UTF_8.name(), - true, false)) { + try (ZipFile zf = ZipFile.builder().setPath(target).get()) { final ZipArchiveEntry b_entry = zf.getEntries("b.txt").iterator().next(); assertEquals(8, b_entry.getSize()); try (InputStream inputStream = zf.getInputStream(b_entry)) { @@ -328,7 +325,7 @@ void testZipFileInMemory() throws IOException { } } - try (ZipFile zf = new ZipFile(target)) { + try (ZipFile zf = ZipFile.builder().setPath(target).get()) { final ZipArchiveEntry b_entry = zf.getEntries("b.txt").iterator().next(); assertEquals(8, b_entry.getSize()); try (InputStream inputStream = zf.getInputStream(b_entry)) {