You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2023/10/29 13:36:41 UTC
(commons-compress) 02/02: Add a generic type parameter to ArchiveOutputStream and avoid unchecked/unconfirmed type casts in subclasses
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit 519d752b104f03de8575936308f5c7d661c35547
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Oct 29 09:36:33 2023 -0400
Add a generic type parameter to ArchiveOutputStream and avoid
unchecked/unconfirmed type casts in subclasses
---
src/changes/changes.xml | 1 +
.../compress/archivers/ArchiveOutputStream.java | 9 +++--
.../archivers/ar/ArArchiveOutputStream.java | 28 +++++++-------
.../archivers/cpio/CpioArchiveOutputStream.java | 27 +++++++------
.../archivers/jar/JarArchiveOutputStream.java | 6 +--
.../archivers/tar/TarArchiveOutputStream.java | 44 +++++++++++-----------
.../archivers/zip/ZipArchiveOutputStream.java | 14 +++----
7 files changed, 63 insertions(+), 66 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 19103f92..85550977 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -79,6 +79,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="Gary Gregory">Refactor internal SevenZ AES256SHA256Decoder InputStream into a named static inner class.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">Refactor internal SevenZ AES256SHA256Decoder OutputStream into a named static inner class.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">Use the root Locale for string conversion of command line options in org.apache.commons.compress.archivers.sevenz.CLI.</action>
+ <action type="fix" dev="ggregory" due-to="Gary Gregory">Add a generic type parameter to ArchiveOutputStream and avoid unchecked/unconfirmed type casts in subclasses.</action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Dependabot">Bump org.slf4j:slf4j-api from 2.0.8 to 2.0.9 #413.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump commons-io:commons-io from 2.13.0 to 2.15.0.</action>
diff --git a/src/main/java/org/apache/commons/compress/archivers/ArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/ArchiveOutputStream.java
index 2d5fbfa5..0bd61ea9 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ArchiveOutputStream.java
@@ -45,8 +45,9 @@ import java.nio.file.Path;
* <li> optionally write additional data, provided format supports it,</li>
* <li>{@link #close()}.</li>
* </ul>
+ * @param <E> The type of {@link ArchiveEntry} produced.
*/
-public abstract class ArchiveOutputStream extends OutputStream {
+public abstract class ArchiveOutputStream<E extends ArchiveEntry> extends OutputStream {
static final int BYTE_MASK = 0xFF;
/** Temporary buffer used for the {@link #write(int)} method */
@@ -110,7 +111,7 @@ public abstract class ArchiveOutputStream extends OutputStream {
*
* @throws IOException if an I/O error occurs
*/
- public abstract ArchiveEntry createArchiveEntry(File inputFile, String entryName) throws IOException;
+ public abstract E createArchiveEntry(File inputFile, String entryName) throws IOException;
// Generic implementations of OutputStream methods that may be useful to sub-classes
@@ -130,7 +131,7 @@ public abstract class ArchiveOutputStream extends OutputStream {
* @throws IOException if an I/O error occurs
* @since 1.21
*/
- public ArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
+ public E createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
return createArchiveEntry(inputPath.toFile(), entryName);
}
@@ -170,7 +171,7 @@ public abstract class ArchiveOutputStream extends OutputStream {
* @param entry describes the entry
* @throws IOException if an I/O error occurs
*/
- public abstract void putArchiveEntry(ArchiveEntry entry) throws IOException;
+ public abstract void putArchiveEntry(E entry) throws IOException;
/**
* Writes a byte to the current archive entry.
diff --git a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
index ebfbacfc..5c363a9b 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java
@@ -26,7 +26,6 @@ import java.io.OutputStream;
import java.nio.file.LinkOption;
import java.nio.file.Path;
-import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.utils.ArchiveUtils;
@@ -35,7 +34,7 @@ import org.apache.commons.compress.utils.ArchiveUtils;
*
* @NotThreadSafe
*/
-public class ArArchiveOutputStream extends ArchiveOutputStream {
+public class ArArchiveOutputStream extends ArchiveOutputStream<ArArchiveEntry> {
/** Fail if a long file name is required in the archive. */
public static final int LONGFILE_ERROR = 0;
@@ -85,7 +84,7 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
}
@Override
- public ArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
+ public ArArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -99,7 +98,7 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
* @since 1.21
*/
@Override
- public ArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
+ public ArArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
}
@@ -130,12 +129,11 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
}
@Override
- public void putArchiveEntry(final ArchiveEntry pEntry) throws IOException {
+ public void putArchiveEntry(final ArArchiveEntry entry) throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
}
- final ArArchiveEntry pArEntry = (ArArchiveEntry) pEntry;
if (prevEntry == null) {
writeArchiveHeader();
} else {
@@ -148,9 +146,9 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
}
}
- prevEntry = pArEntry;
+ prevEntry = entry;
- writeEntryHeader(pArEntry);
+ writeEntryHeader(entry);
entryOffset = 0;
haveUnclosedEntry = true;
@@ -186,12 +184,12 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
out.write(header);
}
- private void writeEntryHeader(final ArArchiveEntry pEntry) throws IOException {
+ private void writeEntryHeader(final ArArchiveEntry entry) throws IOException {
long offset = 0;
boolean mustAppendName = false;
- final String n = pEntry.getName();
+ final String n = entry.getName();
final int nLength = n.length();
if (LONGFILE_ERROR == longFileMode && nLength > 16) {
throw new IOException("File name too long, > 16 chars: "+n);
@@ -205,28 +203,28 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
}
offset = fill(offset, 16, ' ');
- final String m = "" + pEntry.getLastModified();
+ final String m = "" + entry.getLastModified();
if (m.length() > 12) {
throw new IOException("Last modified too long");
}
offset += write(m);
offset = fill(offset, 28, ' ');
- final String u = "" + pEntry.getUserId();
+ final String u = "" + entry.getUserId();
if (u.length() > 6) {
throw new IOException("User id too long");
}
offset += write(u);
offset = fill(offset, 34, ' ');
- final String g = "" + pEntry.getGroupId();
+ final String g = "" + entry.getGroupId();
if (g.length() > 6) {
throw new IOException("Group id too long");
}
offset += write(g);
offset = fill(offset, 40, ' ');
- final String fm = "" + Integer.toString(pEntry.getMode(), 8);
+ final String fm = "" + Integer.toString(entry.getMode(), 8);
if (fm.length() > 8) {
throw new IOException("Filemode too long");
}
@@ -234,7 +232,7 @@ public class ArArchiveOutputStream extends ArchiveOutputStream {
offset = fill(offset, 48, ' ');
final String s =
- String.valueOf(pEntry.getLength()
+ String.valueOf(entry.getLength()
+ (mustAppendName ? nLength : 0));
if (s.length() > 10) {
throw new IOException("Size too long");
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
index de3a6e76..70ad4342 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
@@ -64,7 +64,7 @@ import org.apache.commons.compress.utils.CharsetNames;
*
* <p>based on code from the jRPM project (jrpm.sourceforge.net)</p>
*/
-public class CpioArchiveOutputStream extends ArchiveOutputStream implements
+public class CpioArchiveOutputStream extends ArchiveOutputStream<CpioArchiveEntry> implements
CpioConstants {
private CpioArchiveEntry entry;
@@ -248,12 +248,12 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
}
/**
- * Creates a new ArchiveEntry. The entryName must be an ASCII encoded string.
+ * Creates a new CpioArchiveEntry. The entryName must be an ASCII encoded string.
*
* @see org.apache.commons.compress.archivers.ArchiveOutputStream#createArchiveEntry(java.io.File, String)
*/
@Override
- public ArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
+ public CpioArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -262,12 +262,12 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
}
/**
- * Creates a new ArchiveEntry. The entryName must be an ASCII encoded string.
+ * Creates a new CpioArchiveEntry. The entryName must be an ASCII encoded string.
*
* @see org.apache.commons.compress.archivers.ArchiveOutputStream#createArchiveEntry(java.io.File, String)
*/
@Override
- public ArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options)
+ public CpioArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -356,31 +356,30 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
* @throws ClassCastException if entry is not an instance of CpioArchiveEntry
*/
@Override
- public void putArchiveEntry(final ArchiveEntry entry) throws IOException {
+ public void putArchiveEntry(final CpioArchiveEntry entry) throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
}
- final CpioArchiveEntry e = (CpioArchiveEntry) entry;
ensureOpen();
if (this.entry != null) {
closeArchiveEntry(); // close previous entry
}
- if (e.getTime() == -1) {
- e.setTime(System.currentTimeMillis() / 1000);
+ if (entry.getTime() == -1) {
+ entry.setTime(System.currentTimeMillis() / 1000);
}
- final short format = e.getFormat();
+ final short format = entry.getFormat();
if (format != this.entryFormat){
throw new IOException("Header format: "+format+" does not match existing format: "+this.entryFormat);
}
- if (this.names.put(e.getName(), e) != null) {
- throw new IOException("Duplicate entry: " + e.getName());
+ if (this.names.put(entry.getName(), entry) != null) {
+ throw new IOException("Duplicate entry: " + entry.getName());
}
- writeHeader(e);
- this.entry = e;
+ writeHeader(entry);
+ this.entry = entry;
this.written = 0;
}
diff --git a/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java
index 68550593..ed9b26ca 100644
--- a/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java
@@ -55,11 +55,11 @@ public class JarArchiveOutputStream extends ZipArchiveOutputStream {
// @throws ClassCastException if entry is not an instance of ZipArchiveEntry
@Override
- public void putArchiveEntry(final ArchiveEntry ze) throws IOException {
+ public void putArchiveEntry(final ZipArchiveEntry entry) throws IOException {
if (!jarMarkerAdded) {
- ((ZipArchiveEntry) ze).addAsFirstExtraField(JarMarker.getInstance());
+ entry.addAsFirstExtraField(JarMarker.getInstance());
jarMarkerAdded = true;
}
- super.putArchiveEntry(ze);
+ super.putArchiveEntry(entry);
}
}
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
index 625a6c4c..2c1a7511 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
@@ -35,7 +35,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipEncoding;
import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
@@ -58,7 +57,7 @@ import org.apache.commons.compress.utils.TimeUtils;
*
* @NotThreadSafe
*/
-public class TarArchiveOutputStream extends ArchiveOutputStream {
+public class TarArchiveOutputStream extends ArchiveOutputStream<TarArchiveEntry> {
/**
* Fail if a long file name is required in the archive.
@@ -361,7 +360,7 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
}
@Override
- public ArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
+ public TarArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -370,7 +369,7 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
}
@Override
- public ArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
+ public TarArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
}
@@ -565,35 +564,34 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
* exceeds the limits of a traditional tar header.
*/
@Override
- public void putArchiveEntry(final ArchiveEntry archiveEntry) throws IOException {
+ public void putArchiveEntry(final TarArchiveEntry archiveEntry) throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
}
- final TarArchiveEntry entry = (TarArchiveEntry) archiveEntry;
- if (entry.isGlobalPaxHeader()) {
- final byte[] data = encodeExtendedPaxHeadersContents(entry.getExtraPaxHeaders());
- entry.setSize(data.length);
- entry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR);
+ if (archiveEntry.isGlobalPaxHeader()) {
+ final byte[] data = encodeExtendedPaxHeadersContents(archiveEntry.getExtraPaxHeaders());
+ archiveEntry.setSize(data.length);
+ archiveEntry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR);
writeRecord(recordBuf);
- currSize= entry.getSize();
+ currSize= archiveEntry.getSize();
currBytes = 0;
this.haveUnclosedEntry = true;
write(data);
closeArchiveEntry();
} else {
final Map<String, String> paxHeaders = new HashMap<>();
- final String entryName = entry.getName();
- final boolean paxHeaderContainsPath = handleLongName(entry, entryName, paxHeaders, "path",
+ final String entryName = archiveEntry.getName();
+ final boolean paxHeaderContainsPath = handleLongName(archiveEntry, entryName, paxHeaders, "path",
TarConstants.LF_GNUTYPE_LONGNAME, "file name");
- final String linkName = entry.getLinkName();
+ final String linkName = archiveEntry.getLinkName();
final boolean paxHeaderContainsLinkPath = linkName != null && !linkName.isEmpty()
- && handleLongName(entry, linkName, paxHeaders, "linkpath",
+ && handleLongName(archiveEntry, linkName, paxHeaders, "linkpath",
TarConstants.LF_GNUTYPE_LONGLINK, "link name");
if (bigNumberMode == BIGNUMBER_POSIX) {
- addPaxHeadersForBigNumbers(paxHeaders, entry);
+ addPaxHeadersForBigNumbers(paxHeaders, archiveEntry);
} else if (bigNumberMode != BIGNUMBER_STAR) {
- failForBigNumbers(entry);
+ failForBigNumbers(archiveEntry);
}
if (addPaxHeadersForNonAsciiNames && !paxHeaderContainsPath
@@ -602,25 +600,25 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
}
if (addPaxHeadersForNonAsciiNames && !paxHeaderContainsLinkPath
- && (entry.isLink() || entry.isSymbolicLink())
+ && (archiveEntry.isLink() || archiveEntry.isSymbolicLink())
&& !ASCII.canEncode(linkName)) {
paxHeaders.put("linkpath", linkName);
}
- paxHeaders.putAll(entry.getExtraPaxHeaders());
+ paxHeaders.putAll(archiveEntry.getExtraPaxHeaders());
if (!paxHeaders.isEmpty()) {
- writePaxHeaders(entry, entryName, paxHeaders);
+ writePaxHeaders(archiveEntry, entryName, paxHeaders);
}
- entry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR);
+ archiveEntry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR);
writeRecord(recordBuf);
currBytes = 0;
- if (entry.isDirectory()) {
+ if (archiveEntry.isDirectory()) {
currSize = 0;
} else {
- currSize = entry.getSize();
+ currSize = archiveEntry.getSize();
}
currName = entryName;
haveUnclosedEntry = true;
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
index fc3c4ba7..ab6d797e 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
@@ -59,7 +59,7 @@ import org.apache.commons.compress.utils.IOUtils;
* calculate them yourself. Unfortunately, this is not possible for
* the {@link #STORED STORED} method, where setting the CRC and
* uncompressed size information is required before {@link
- * #putArchiveEntry(ArchiveEntry)} can be called.</p>
+ * #putArchiveEntry(ZipArchiveEntry)} can be called.</p>
*
* <p>As of Apache Commons Compress 1.3, the class transparently supports Zip64
* extensions and thus individual entries and archives larger than 4
@@ -70,7 +70,7 @@ import org.apache.commons.compress.utils.IOUtils;
*
* @NotThreadSafe
*/
-public class ZipArchiveOutputStream extends ArchiveOutputStream {
+public class ZipArchiveOutputStream extends ArchiveOutputStream<ZipArchiveEntry> {
/**
* Structure collecting information for the entry that is
@@ -713,7 +713,7 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
* <p>Must not be used if the stream has already been closed.</p>
*/
@Override
- public ArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
+ public ZipArchiveEntry createArchiveEntry(final File inputFile, final String entryName)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -739,7 +739,7 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
* @since 1.21
*/
@Override
- public ArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options)
+ public ZipArchiveEntry createArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options)
throws IOException {
if (finished) {
throw new IOException("Stream has already been finished");
@@ -1259,7 +1259,7 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
*
* <p>For seekable streams, you don't need to calculate the CRC or
* uncompressed size for {@link #STORED} entries before
- * invoking {@link #putArchiveEntry(ArchiveEntry)}.
+ * invoking {@link #putArchiveEntry(ZipArchiveEntry)}.
* @return true if seekable
*/
public boolean isSeekable() {
@@ -1296,8 +1296,8 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
* is {@link Zip64Mode#Never}.
*/
@Override
- public void putArchiveEntry(final ArchiveEntry archiveEntry) throws IOException {
- putArchiveEntry((ZipArchiveEntry) archiveEntry, false);
+ public void putArchiveEntry(final ZipArchiveEntry archiveEntry) throws IOException {
+ putArchiveEntry(archiveEntry, false);
}
/**