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 <garydgreg...@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);
     }
 
     /**

Reply via email to