You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2019/08/20 19:30:20 UTC
[commons-compress] branch master updated: COMPRESS-478 allow 7z
default name to override null file name
This is an automated email from the ASF dual-hosted git repository.
bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push:
new c937e01 COMPRESS-478 allow 7z default name to override null file name
c937e01 is described below
commit c937e01ae3ad2f258b5a2c94f2a03e8c8e740e7d
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Tue Aug 20 21:28:47 2019 +0200
COMPRESS-478 allow 7z default name to override null file name
---
.../apache/commons/compress/archivers/Lister.java | 4 +-
.../compress/archivers/sevenz/SevenZFile.java | 157 ++++++---------------
.../archivers/sevenz/SevenZFileOptions.java | 116 +++++++++++++++
.../compress/archivers/sevenz/SevenZFileTest.java | 44 +++++-
src/test/resources/bla-nonames.7z | Bin 0 -> 556 bytes
5 files changed, 208 insertions(+), 113 deletions(-)
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 481cc30..dd404a5 100644
--- a/src/main/java/org/apache/commons/compress/archivers/Lister.java
+++ b/src/main/java/org/apache/commons/compress/archivers/Lister.java
@@ -89,7 +89,9 @@ public final class Lister {
System.out.println("Created " + z.toString());
ArchiveEntry ae;
while ((ae = z.getNextEntry()) != null) {
- System.out.println(ae.getName());
+ String name = ae.getName() == null ? z.getDefaultName() + " (entry name was null)"
+ : ae.getName();
+ System.out.println(name);
}
}
}
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 00d2fde..ac148e5 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
@@ -92,7 +92,7 @@ public class SevenZFile implements Closeable {
private int currentFolderIndex = -1;
private InputStream currentFolderInputStream = null;
private byte[] password;
- private int maxMemoryLimitInKb;
+ private final SevenZFileOptions options;
private long compressedBytesReadFromCurrentEntry;
private long uncompressedBytesReadFromCurrentEntry;
@@ -113,22 +113,21 @@ public class SevenZFile implements Closeable {
* @since 1.17
*/
public SevenZFile(final File fileName, final char[] password) throws IOException {
- this(fileName, password, Integer.MAX_VALUE);
+ this(fileName, password, SevenZFileOptions.DEFAULT);
}
/**
- * Reads a file as 7z archive with memory limitation
+ * Reads a file as 7z archive with additional options.
*
* @param fileName the file to read
* @param password optional password if the archive is encrypted
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
- public SevenZFile(final File fileName, final char[] password, final int maxMemoryLimitInKb) throws IOException {
+ public SevenZFile(final File fileName, final char[] password, SevenZFileOptions options) throws IOException {
this(Files.newByteChannel(fileName.toPath(), EnumSet.of(StandardOpenOption.READ)),
- fileName.getAbsolutePath(), utf16Decode(password), true, maxMemoryLimitInKb);
+ fileName.getAbsolutePath(), utf16Decode(password), true, options);
}
/**
@@ -142,25 +141,8 @@ public class SevenZFile implements Closeable {
* @deprecated use the char[]-arg version for the password instead
*/
public SevenZFile(final File fileName, final byte[] password) throws IOException {
- this(fileName, password, Integer.MAX_VALUE);
- }
-
- /**
- * Reads a file as 7z archive with memory limitation
- *
- * @param fileName the file to read
- * @param password optional password if the archive is encrypted -
- * the byte array is supposed to be the UTF16-LE encoded
- * representation of the password.
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
- * @deprecated use the char[]-arg version for the password instead
- * @since 1.19
- */
- public SevenZFile(final File fileName, final byte[] password, final int maxMemoryLimitInKb) throws IOException {
- this(Files.newByteChannel(fileName.toPath(), EnumSet.of(StandardOpenOption.READ)), fileName.getAbsolutePath(),
- password, true, maxMemoryLimitInKb);
+ this(Files.newByteChannel(fileName.toPath(), EnumSet.of(StandardOpenOption.READ)),
+ fileName.getAbsolutePath(), password, true, SevenZFileOptions.DEFAULT);
}
/**
@@ -175,24 +157,23 @@ public class SevenZFile implements Closeable {
* @since 1.13
*/
public SevenZFile(final SeekableByteChannel channel) throws IOException {
- this(channel, Integer.MAX_VALUE);
+ this(channel, SevenZFileOptions.DEFAULT);
}
/**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
+ * Reads a SeekableByteChannel as 7z archive with addtional options.
*
* <p>{@link
* org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
* allows you to read from an in-memory archive.</p>
*
* @param channel the channel to read
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
- public SevenZFile(final SeekableByteChannel channel, final int maxMemoryLimitInKb) throws IOException {
- this(channel, DEFAULT_FILE_NAME, (char[]) null, maxMemoryLimitInKb);
+ public SevenZFile(final SeekableByteChannel channel, SevenZFileOptions options) throws IOException {
+ this(channel, DEFAULT_FILE_NAME, (char[]) null, options);
}
/**
@@ -209,11 +190,11 @@ public class SevenZFile implements Closeable {
*/
public SevenZFile(final SeekableByteChannel channel,
final char[] password) throws IOException {
- this(channel, password, Integer.MAX_VALUE);
+ this(channel, password, SevenZFileOptions.DEFAULT);
}
/**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
+ * Reads a SeekableByteChannel as 7z archive with additional options.
*
* <p>{@link
* org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
@@ -221,14 +202,13 @@ public class SevenZFile implements Closeable {
*
* @param channel the channel to read
* @param password optional password if the archive is encrypted
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
- public SevenZFile(final SeekableByteChannel channel, final char[] password, final int maxMemoryLimitInKb)
+ public SevenZFile(final SeekableByteChannel channel, final char[] password, final SevenZFileOptions options)
throws IOException {
- this(channel, DEFAULT_FILE_NAME, utf16Decode(password), maxMemoryLimitInKb);
+ this(channel, DEFAULT_FILE_NAME, password, options);
}
/**
@@ -246,11 +226,11 @@ public class SevenZFile implements Closeable {
*/
public SevenZFile(final SeekableByteChannel channel, String fileName,
final char[] password) throws IOException {
- this(channel, fileName, password, Integer.MAX_VALUE);
+ this(channel, fileName, password, SevenZFileOptions.DEFAULT);
}
/**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
+ * Reads a SeekableByteChannel as 7z archive with addtional options.
*
* <p>{@link
* org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
@@ -259,14 +239,13 @@ public class SevenZFile implements Closeable {
* @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 maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
public SevenZFile(final SeekableByteChannel channel, String fileName, final char[] password,
- final int maxMemoryLimitInKb) throws IOException {
- this(channel, fileName, utf16Decode(password), false, maxMemoryLimitInKb);
+ final SevenZFileOptions options) throws IOException {
+ this(channel, fileName, utf16Decode(password), false, options);
}
/**
@@ -283,11 +262,11 @@ public class SevenZFile implements Closeable {
*/
public SevenZFile(final SeekableByteChannel channel, String fileName)
throws IOException {
- this(channel, fileName, Integer.MAX_VALUE);
+ this(channel, fileName, SevenZFileOptions.DEFAULT);
}
/**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
+ * Reads a SeekableByteChannel as 7z archive with additional options.
*
* <p>{@link
* org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
@@ -295,14 +274,13 @@ public class SevenZFile implements Closeable {
*
* @param channel the channel to read
* @param fileName name of the archive - only used for error reporting
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
- public SevenZFile(final SeekableByteChannel channel, String fileName, final int maxMemoryLimitInKb)
+ public SevenZFile(final SeekableByteChannel channel, String fileName, final SevenZFileOptions options)
throws IOException {
- this(channel, fileName, null, false, maxMemoryLimitInKb);
+ this(channel, fileName, null, false, options);
}
/**
@@ -326,28 +304,6 @@ public class SevenZFile implements Closeable {
}
/**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
- *
- * <p>{@link
- * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
- * allows you to read from an in-memory archive.</p>
- *
- * @param channel the channel to read
- * @param password optional password if the archive is encrypted -
- * the byte array is supposed to be the UTF16-LE encoded
- * representation of the password.
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
- * @since 1.19
- * @deprecated use the char[]-arg version for the password instead
- */
- public SevenZFile(final SeekableByteChannel channel, final byte[] password, final int maxMemoryLimitInKb)
- throws IOException {
- this(channel, DEFAULT_FILE_NAME, password, maxMemoryLimitInKb);
- }
-
- /**
* Reads a SeekableByteChannel as 7z archive
*
* <p>{@link
@@ -365,38 +321,15 @@ public class SevenZFile implements Closeable {
*/
public SevenZFile(final SeekableByteChannel channel, String fileName,
final byte[] password) throws IOException {
- this(channel, fileName, password, false, Integer.MAX_VALUE);
- }
-
- /**
- * Reads a SeekableByteChannel as 7z archive with memory limitation
- *
- * <p>{@link
- * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
- * allows you to read from an in-memory archive.</p>
- *
- * @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 -
- * the byte array is supposed to be the UTF16-LE encoded
- * representation of the password.
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
- * @since 1.19
- * @deprecated use the char[]-arg version for the password instead
- */
- public SevenZFile(final SeekableByteChannel channel, String fileName, final byte[] password,
- final int maxMemoryLimitInKb) throws IOException {
- this(channel, fileName, password, false, maxMemoryLimitInKb);
+ this(channel, fileName, password, false, SevenZFileOptions.DEFAULT);
}
private SevenZFile(final SeekableByteChannel channel, String filename,
- final byte[] password, boolean closeOnError, final int maxMemoryLimitInKb) throws IOException {
+ final byte[] password, boolean closeOnError, SevenZFileOptions options) throws IOException {
boolean succeeded = false;
this.channel = channel;
this.fileName = filename;
- this.maxMemoryLimitInKb = maxMemoryLimitInKb;
+ this.options = options;
try {
archive = readHeaders(password);
if (password != null) {
@@ -419,20 +352,19 @@ public class SevenZFile implements Closeable {
* @throws IOException if reading the archive fails
*/
public SevenZFile(final File fileName) throws IOException {
- this(fileName, Integer.MAX_VALUE);
+ this(fileName, SevenZFileOptions.DEFAULT);
}
/**
* Reads a file as unencrypted 7z archive
*
* @param fileName the file to read
- * @param maxMemoryLimitInKb limit of the maximum amount of memory to use for extraction. Not all codecs will honor
- * this setting. Currently only lzma and lzma2 are supported.
- * @throws IOException if reading the archive fails or the memory limit is too small
+ * @param options the options to apply
+ * @throws IOException if reading the archive fails or the memory limit (if set) is too small
* @since 1.19
*/
- public SevenZFile(final File fileName, final int maxMemoryLimitInKb) throws IOException {
- this(fileName, (char[]) null, maxMemoryLimitInKb);
+ public SevenZFile(final File fileName, final SevenZFileOptions options) throws IOException {
+ this(fileName, (char[]) null, options);
}
/**
@@ -467,6 +399,9 @@ public class SevenZFile implements Closeable {
}
++currentEntryIndex;
final SevenZArchiveEntry entry = archive.files[currentEntryIndex];
+ if (entry.getName() == null && options.getUseDefaultNameForUnnamedEntries()) {
+ entry.setName(getDefaultName());
+ }
buildDecodingStream();
uncompressedBytesReadFromCurrentEntry = compressedBytesReadFromCurrentEntry = 0;
return entry;
@@ -606,7 +541,7 @@ public class SevenZFile implements Closeable {
throw new IOException("Multi input/output stream coders are not yet supported");
}
inputStreamStack = Coders.addDecoder(fileName, inputStreamStack, //NOSONAR
- folder.getUnpackSizeForCoder(coder), coder, password, maxMemoryLimitInKb);
+ folder.getUnpackSizeForCoder(coder), coder, password, options.getMaxMemoryLimitInKb());
}
if (folder.hasCrc) {
inputStreamStack = new CRC32VerifyingInputStream(inputStreamStack,
@@ -1216,7 +1151,7 @@ public class SevenZFile implements Closeable {
}
final SevenZMethod method = SevenZMethod.byId(coder.decompressionMethodId);
inputStreamStack = Coders.addDecoder(fileName, inputStreamStack,
- folder.getUnpackSizeForCoder(coder), coder, password, maxMemoryLimitInKb);
+ folder.getUnpackSizeForCoder(coder), coder, password, options.getMaxMemoryLimitInKb());
methods.addFirst(new SevenZMethodConfiguration(method,
Coders.findByMethod(method).getOptionsFromCoder(coder, inputStreamStack)));
}
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
new file mode 100644
index 0000000..1ce913f
--- /dev/null
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFileOptions.java
@@ -0,0 +1,116 @@
+/*
+ * 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
+ *
+ * http://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.sevenz;
+
+/**
+ * Collects options for reading 7z archives.
+ *
+ * @since 1.19
+ * @Immutable
+ */
+public class SevenZFileOptions {
+ private static final int DEFAUL_MEMORY_LIMIT_IN_KB = Integer.MAX_VALUE;
+ private static final boolean DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES= false;
+
+ private final int maxMemoryLimitInKb;
+ private final boolean useDefaultNameForUnnamedEntries;
+
+ private SevenZFileOptions(int maxMemoryLimitInKb, boolean useDefaultNameForUnnamedEntries) {
+ this.maxMemoryLimitInKb = maxMemoryLimitInKb;
+ this.useDefaultNameForUnnamedEntries = useDefaultNameForUnnamedEntries;
+ }
+
+ /**
+ * The default options.
+ *
+ * <ul>
+ * <li>no memory limit</li>
+ * <li>don't modifiy the name of unnamed entries</li>
+ * </ul>
+ */
+ public static SevenZFileOptions DEFAULT = new SevenZFileOptions(DEFAUL_MEMORY_LIMIT_IN_KB,
+ DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES);
+
+ /**
+ * Obtains a builder for SevenZFileOptions.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Gets the maximum amount of memory to use for extraction. Not
+ * all codecs will honor this setting. Currently only lzma and
+ * lzma2 are supported.
+ */
+ public int getMaxMemoryLimitInKb() {
+ return maxMemoryLimitInKb;
+ }
+
+ /**
+ * Gets whether entries without a name should get their names set
+ * to the archive's default file name.
+ */
+ public boolean getUseDefaultNameForUnnamedEntries() {
+ return useDefaultNameForUnnamedEntries;
+ }
+
+ /**
+ * Mutable builder for the immutable {@link SevenZFileOptions}.
+ *
+ * @since 1.19
+ */
+ public static class Builder {
+ private int maxMemoryLimitInKb = DEFAUL_MEMORY_LIMIT_IN_KB;
+ private boolean useDefaultNameForUnnamedEntries = DEFAULT_USE_DEFAULTNAME_FOR_UNNAMED_ENTRIES;
+ /**
+ * Sets the maximum amount of memory to use for
+ * extraction. Not all codecs will honor this
+ * setting. Currently only lzma and lzma2 are supported.
+ *
+ * @param maxMemoryLimitInKb limit of the maximum amount of memory to use
+ * @return the reconfigured builder
+ */
+ public Builder withMaxMemoryLimitInKb(int maxMemoryLimitInKb) {
+ this.maxMemoryLimitInKb = maxMemoryLimitInKb;
+ return this;
+ }
+
+ /**
+ * Sets whether entries without a name should get their names
+ * set to the archive's default file name.
+ *
+ * @param useDefaultNameForUnnamedEntries if true the name of
+ * unnamed entries will be set to the archive's default name
+ * @return the reconfigured builder
+ */
+ public Builder withUseDefaultNameForUnnamedEntries(boolean useDefaultNameForUnnamedEntries) {
+ this.useDefaultNameForUnnamedEntries = useDefaultNameForUnnamedEntries;
+ return this;
+ }
+
+ /**
+ * Create the {@link SevenZFileOptions}.
+ *
+ * @return configured {@link SevenZFileOptions}.
+ */
+ public SevenZFileOptions build() {
+ return new SevenZFileOptions(maxMemoryLimitInKb, useDefaultNameForUnnamedEntries);
+ }
+ }
+}
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 0982259..c996935 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
@@ -299,7 +299,8 @@ public class SevenZFileTest extends AbstractTestCase {
@Test(expected = MemoryLimitException.class)
public void limitExtractionMemory() throws IOException {
- try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"), 1)) {
+ try (SevenZFile sevenZFile = new SevenZFile(getFile("bla.7z"),
+ SevenZFileOptions.builder().withMaxMemoryLimitInKb(1).build())) {
// Do nothing. Exception should be thrown
}
}
@@ -328,6 +329,47 @@ public class SevenZFileTest extends AbstractTestCase {
}
}
+ @Test
+ public void noNameMeansNoNameByDefault() throws Exception {
+ try (SevenZFile sevenZFile = new SevenZFile(getFile("bla-nonames.7z"))) {
+ SevenZArchiveEntry ae = sevenZFile.getNextEntry();
+ assertNotNull(ae);
+ assertNull(ae.getName());
+ ae = sevenZFile.getNextEntry();
+ assertNotNull(ae);
+ assertNull(ae.getName());
+ assertNull(sevenZFile.getNextEntry());
+ }
+ }
+
+ @Test
+ public void noNameCanBeReplacedByDefaultName() throws Exception {
+ try (SevenZFile sevenZFile = new SevenZFile(getFile("bla-nonames.7z"),
+ SevenZFileOptions.builder().withUseDefaultNameForUnnamedEntries(true).build())) {
+ SevenZArchiveEntry ae = sevenZFile.getNextEntry();
+ assertNotNull(ae);
+ assertEquals("bla-nonames", ae.getName());
+ ae = sevenZFile.getNextEntry();
+ assertNotNull(ae);
+ assertEquals("bla-nonames", ae.getName());
+ assertNull(sevenZFile.getNextEntry());
+ }
+ }
+
+ @Test
+ public void givenNameWinsOverDefaultName() throws Exception {
+ try (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());
+ }
+ }
+
private void test7zUnarchive(final File f, final SevenZMethod m, final byte[] password) throws Exception {
try (SevenZFile sevenZFile = new SevenZFile(f, password)) {
test7zUnarchive(sevenZFile, m);
diff --git a/src/test/resources/bla-nonames.7z b/src/test/resources/bla-nonames.7z
new file mode 100644
index 0000000..904a897
Binary files /dev/null and b/src/test/resources/bla-nonames.7z differ