This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit 227bc78fae854a7161fc262c6a7fda9268469247
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Jul 31 11:20:37 2026 -0400

    Throw ArchiveException instead of IOException.
    
    - Add missing Javadoc.
    - Reduce vertical space.
    - Make some methods private.
---
 .../archivers/lha/LhaArchiveInputStream.java       | 368 +++++++++------------
 1 file changed, 156 insertions(+), 212 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/compress/archivers/lha/LhaArchiveInputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/lha/LhaArchiveInputStream.java
index bda9b8c62..c7570550d 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/lha/LhaArchiveInputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/lha/LhaArchiveInputStream.java
@@ -47,7 +47,7 @@
 import org.apache.commons.io.input.ChecksumInputStream;
 
 /**
- * Implements the LHA archive format as an InputStream.
+ * LHA archive format as an InputStream.
  *
  * @NotThreadSafe
  * @since 1.29.0
@@ -59,11 +59,9 @@ public class LhaArchiveInputStream extends 
ArchiveInputStream<LhaArchiveEntry> {
      * <p>
      * For example:
      * </p>
+     *
      * <pre>{@code
-     * LhaArchiveInputStream in = LhaArchiveInputStream.builder()
-     *   .setPath(inputPath)
-     *   .setCharset(StandardCharsets.UTF_8)
-     *   .get();
+     * LhaArchiveInputStream in = 
LhaArchiveInputStream.builder().setPath(inputPath).setCharset(StandardCharsets.UTF_8).get();
      * }</pre>
      */
     public static class Builder extends 
AbstractArchiveBuilder<LhaArchiveInputStream, Builder> {
@@ -105,46 +103,71 @@ Builder setFileSeparatorChar(final char 
fileSeparatorChar) {
 
     // Fields that are the same across all header levels
     private static final int HEADER_GENERIC_MINIMUM_HEADER_LENGTH = 22;
+
     private static final int HEADER_GENERIC_OFFSET_COMPRESSION_METHOD = 2;
+
     private static final int HEADER_GENERIC_OFFSET_HEADER_LEVEL = 20;
 
     // Header Level 0
     private static final int HEADER_LEVEL_0_OFFSET_HEADER_SIZE = 0;
+
     private static final int HEADER_LEVEL_0_OFFSET_HEADER_CHECKSUM = 1;
+
     private static final int HEADER_LEVEL_0_OFFSET_COMPRESSED_SIZE = 7;
+
     private static final int HEADER_LEVEL_0_OFFSET_ORIGINAL_SIZE = 11;
+
     private static final int HEADER_LEVEL_0_OFFSET_LAST_MODIFIED_DATE_TIME = 
15;
+
     private static final int HEADER_LEVEL_0_OFFSET_FILENAME_LENGTH = 21;
+
     private static final int HEADER_LEVEL_0_OFFSET_FILENAME = 22;
 
     // Header Level 1
     private static final int HEADER_LEVEL_1_OFFSET_BASE_HEADER_SIZE = 0;
+
     private static final int HEADER_LEVEL_1_OFFSET_BASE_HEADER_CHECKSUM = 1;
+
     private static final int HEADER_LEVEL_1_OFFSET_SKIP_SIZE = 7;
+
     private static final int HEADER_LEVEL_1_OFFSET_ORIGINAL_SIZE = 11;
+
     private static final int HEADER_LEVEL_1_OFFSET_LAST_MODIFIED_DATE_TIME = 
15;
+
     private static final int HEADER_LEVEL_1_OFFSET_FILENAME_LENGTH = 21;
+
     private static final int HEADER_LEVEL_1_OFFSET_FILENAME = 22;
 
     // Header Level 2
     private static final int HEADER_LEVEL_2_MINIMUM_HEADER_LENGTH = 26;
+
     private static final int HEADER_LEVEL_2_OFFSET_HEADER_SIZE = 0;
+
     private static final int HEADER_LEVEL_2_OFFSET_COMPRESSED_SIZE = 7;
+
     private static final int HEADER_LEVEL_2_OFFSET_ORIGINAL_SIZE = 11;
+
     private static final int HEADER_LEVEL_2_OFFSET_LAST_MODIFIED_DATE_TIME = 
15;
+
     private static final int HEADER_LEVEL_2_OFFSET_CRC = 21;
+
     private static final int HEADER_LEVEL_2_OFFSET_OS_ID = 23;
+
     private static final int HEADER_LEVEL_2_OFFSET_FIRST_EXTENDED_HEADER_SIZE 
= 24;
 
     // Extended header types
     private static final int EXTENDED_HEADER_TYPE_COMMON = 0x00;
+
     private static final int EXTENDED_HEADER_TYPE_FILENAME = 0x01;
+
     private static final int EXTENDED_HEADER_TYPE_DIRECTORY_NAME = 0x02;
 
     private static final int EXTENDED_HEADER_TYPE_MSDOS_FILE_ATTRIBUTES = 0x40;
 
     private static final int EXTENDED_HEADER_TYPE_UNIX_PERMISSION = 0x50;
+
     private static final int EXTENDED_HEADER_TYPE_UNIX_UID_GID = 0x51;
+
     private static final int EXTENDED_HEADER_TYPE_UNIX_TIMESTAMP = 0x54;
 
     /**
@@ -158,18 +181,28 @@ Builder setFileSeparatorChar(final char 
fileSeparatorChar) {
     private static final int MIN_EXTENDED_HEADER_LENGTH = 3;
 
     private static final int EXTENDED_HEADER_TYPE_COMMON_MIN_PAYLOAD_LENGTH = 
2;
+
     private static final int 
EXTENDED_HEADER_TYPE_MSDOS_FILE_ATTRIBUTES_PAYLOAD_LENGTH = 2;
+
     private static final int 
EXTENDED_HEADER_TYPE_UNIX_PERMISSION_PAYLOAD_LENGTH = 2;
+
     private static final int EXTENDED_HEADER_TYPE_UNIX_UID_GID_PAYLOAD_LENGTH 
= 4;
+
     private static final int 
EXTENDED_HEADER_TYPE_UNIX_TIMESTAMP_PAYLOAD_LENGTH = 4;
 
     // Compression methods
     private static final String COMPRESSION_METHOD_DIRECTORY = "-lhd-"; // 
Directory entry
+
     private static final String COMPRESSION_METHOD_LH0 = "-lh0-";
+
     private static final String COMPRESSION_METHOD_LH4 = "-lh4-";
+
     private static final String COMPRESSION_METHOD_LH5 = "-lh5-";
+
     private static final String COMPRESSION_METHOD_LH6 = "-lh6-";
+
     private static final String COMPRESSION_METHOD_LH7 = "-lh7-";
+
     private static final String COMPRESSION_METHOD_LZ4 = "-lz4-";
 
     /**
@@ -190,76 +223,65 @@ Builder setFileSeparatorChar(final char 
fileSeparatorChar) {
     public static Builder builder() {
         return new Builder();
     }
+
     /**
-     * Get a byte array from the ByteBuffer at the specified position and 
length.
-     * This is needed until this repo has been updated to use Java 9+ where we
-     * can use buffer.get(position, dst) directly.
+     * Gets a byte array from the ByteBuffer at the specified position and 
length. This is needed until this repo has been updated to use Java 9+ where we 
can
+     * use buffer.get(position, dst) directly.
      *
-     * @param buffer the buffer to get the byte array from
-     * @param position the position in the buffer to start reading from
-     * @param dst the destination byte array to fill
+     * @param buffer   the buffer to get the byte array from.
+     * @param position the position in the buffer to start reading from.
+     * @param dst      the destination byte array to fill.
      */
     private static void byteBufferGet(final ByteBuffer buffer, final int 
position, final byte[] dst) {
         for (int i = 0; i < dst.length; i++) {
             dst[i] = buffer.get(position + i);
         }
     }
+
     /**
      * Gets the compression method from the header. It is always located at 
the same offset for all header levels.
      *
-     * @param buffer the buffer containing the header data
-     * @return compression method, e.g. -lh5-
-     * @throws ArchiveException if the compression method is invalid
+     * @param buffer the buffer containing the header data.
+     * @return compression method, e.g. -lh5-.
+     * @throws ArchiveException if the compression method is invalid.
      */
     static String getCompressionMethod(final ByteBuffer buffer) throws 
ArchiveException {
         final byte[] compressionMethodBuffer = new byte[5];
         byteBufferGet(buffer, HEADER_GENERIC_OFFSET_COMPRESSION_METHOD, 
compressionMethodBuffer);
-
         // Validate the compression method
-        if (compressionMethodBuffer[0] == '-' &&
-            Character.isLowerCase(compressionMethodBuffer[1]) &&
-            Character.isLowerCase(compressionMethodBuffer[2]) &&
-            (Character.isLowerCase(compressionMethodBuffer[3]) || 
Character.isDigit(compressionMethodBuffer[3])) &&
-            compressionMethodBuffer[4] == '-') {
+        if (compressionMethodBuffer[0] == '-' && 
Character.isLowerCase(compressionMethodBuffer[1]) && 
Character.isLowerCase(compressionMethodBuffer[2])
+                && (Character.isLowerCase(compressionMethodBuffer[3]) || 
Character.isDigit(compressionMethodBuffer[3])) && compressionMethodBuffer[4] == 
'-') {
             return new String(compressionMethodBuffer, 
StandardCharsets.US_ASCII);
         }
-        throw new ArchiveException("Invalid compression method: 0x%02x 0x%02x 
0x%02x 0x%02x 0x%02x",
-                compressionMethodBuffer[0],
-                compressionMethodBuffer[1],
-                compressionMethodBuffer[2],
-                compressionMethodBuffer[3],
-                compressionMethodBuffer[4]);
+        throw new ArchiveException("Invalid compression method: 0x%02x 0x%02x 
0x%02x 0x%02x 0x%02x", compressionMethodBuffer[0], compressionMethodBuffer[1],
+                compressionMethodBuffer[2], compressionMethodBuffer[3], 
compressionMethodBuffer[4]);
     }
+
     /**
-     * Checks if the signature matches what is expected for an LHA file. There 
is no specific
-     * signature for LHA files, so this method checks if the header level and 
the compression
-     * method are valid for an LHA archive. The signature must be at least the 
minimum header
-     * length of 22 bytes for this check to work properly.
+     * Checks if the signature matches what is expected for an LHA file. There 
is no specific signature for LHA files, so this method checks if the header 
level
+     * and the compression method are valid for an LHA archive. The signature 
must be at least the minimum header length of 22 bytes for this check to work
+     * properly.
      *
-     * @param signature the bytes to check
-     * @param length the number of bytes to check
-     * @return true, if this stream is an LHA archive stream, false otherwise
+     * @param signature the bytes to check.
+     * @param length    the number of bytes to check.
+     * @return true, if this stream is an LHA archive stream, false otherwise.
      */
     public static boolean matches(final byte[] signature, final int length) {
         if (signature.length < HEADER_GENERIC_MINIMUM_HEADER_LENGTH || length 
< HEADER_GENERIC_MINIMUM_HEADER_LENGTH) {
             return false;
         }
-
         final ByteBuffer header = 
ByteBuffer.wrap(signature).order(ByteOrder.LITTLE_ENDIAN);
-
         // Determine header level. Only levels 0-2 are supported for reading.
         final byte headerLevel = 
header.get(HEADER_GENERIC_OFFSET_HEADER_LEVEL);
         if (headerLevel < 0 || headerLevel > 2) {
             return false;
         }
-
         // Check if the compression method is valid for LHA archives
         try {
             getCompressionMethod(header);
         } catch (final ArchiveException e) {
             return false;
         }
-
         return true;
     }
 
@@ -277,13 +299,13 @@ private LhaArchiveInputStream(final Builder builder) 
throws IOException {
     }
 
     /**
-     * Create a new ByteBuffer slice from the provided buffer at the specified 
position and length. This is needed until this
-     * repo has been updated to use Java 9+ where we can use 
buffer.position(position).slice().limit(length) directly.
+     * Create a new ByteBuffer slice from the provided buffer at the specified 
position and length. This is needed until this repo has been updated to use Java
+     * 9+ where we can use buffer.position(position).slice().limit(length) 
directly.
      *
-     * @param buffer the buffer to slice from
-     * @param position the position in the buffer to start slicing from
-     * @param length the length of the slice
-     * @return a new ByteBuffer slice with the specified position and length
+     * @param buffer   the buffer to slice from.
+     * @param position the position in the buffer to start slicing from.
+     * @param length   the length of the slice.
+     * @return a new ByteBuffer slice with the specified position and length.
      */
     private ByteBuffer byteBufferSlice(final ByteBuffer buffer, final int 
position, final int length) {
         return ByteBuffer.wrap(buffer.array(), position, length);
@@ -292,32 +314,29 @@ private ByteBuffer byteBufferSlice(final ByteBuffer 
buffer, final int position,
     /**
      * Calculate the CRC16 checksum of the provided buffers.
      *
-     * @param buffers the buffers to calculate the CRC16 checksum for
-     * @return CRC16 checksum
+     * @param buffers the buffers to calculate the CRC16 checksum for.
+     * @return CRC16 checksum.
      */
     private long calculateCRC16(final ByteBuffer... buffers) {
         final Checksum crc = Crc16.arc();
         for (final ByteBuffer buffer : buffers) {
             crc.update(buffer.array(), 0, buffer.limit());
         }
-
         return crc.getValue();
     }
 
     /**
-     * Calculate the header sum for level 0 and 1 headers. The checksum is 
calculated by summing the
-     * value of all bytes in the header except for the first two bytes (header 
length and header checksum)
-     * and get the low 8 bits.
+     * Calculate the header sum for level 0 and 1 headers. The checksum is 
calculated by summing the value of all bytes in the header except for the first 
two
+     * bytes (header length and header checksum) and get the low 8 bits.
      *
-     * @param buffer the buffer containing the header
-     * @return checksum
+     * @param buffer the buffer containing the header.
+     * @return checksum.
      */
     private int calculateHeaderChecksum(final ByteBuffer buffer) {
         int sum = 0;
         for (int i = 2; i < buffer.limit(); i++) {
             sum += Byte.toUnsignedInt(buffer.get(i));
         }
-
         return sum & 0xff;
     }
 
@@ -331,26 +350,21 @@ public LhaArchiveEntry getNextEntry() throws IOException {
         if (this.currentCompressedStream != null) {
             // Consume the entire compressed stream to end up at the next entry
             IOUtils.consume(this.currentCompressedStream);
-
             this.currentCompressedStream = null;
             this.currentDecompressedStream = null;
         }
-
         this.currentEntry = readHeader();
-
         return this.currentEntry;
     }
 
     /**
-     * Gets the pathname from the current position in the provided buffer. Any 
0xFF bytes
-     * and '\' chars will be converted into the configured file path separator 
char.
-     * Any leading file path separator char will be removed to avoid 
extracting to
-     * absolute locations.
+     * Gets the pathname from the current position in the provided buffer. Any 
0xFF bytes and '\' chars will be converted into the configured file path
+     * separator char. Any leading file path separator char will be removed to 
avoid extracting to absolute locations.
      *
-     * @param buffer the buffer where to get the pathname from
-     * @param pathnameLength the length of the pathname
-     * @return pathname
-     * @throws ArchiveException if the pathname is too long
+     * @param buffer         the buffer where to get the pathname from.
+     * @param pathnameLength the length of the pathname.
+     * @return pathname.
+     * @throws ArchiveException if the pathname is too long.
      */
     String getPathname(final ByteBuffer buffer, final int pathnameLength) 
throws ArchiveException {
         // Check pathname length to ensure we don't allocate too much memory
@@ -359,13 +373,12 @@ String getPathname(final ByteBuffer buffer, final int 
pathnameLength) throws Arc
         }
         if (pathnameLength < 0) {
             throw new ArchiveException("Pathname length is negative");
-        } else if (pathnameLength > buffer.limit() - buffer.position()) {
+        }
+        if (pathnameLength > buffer.limit() - buffer.position()) {
             throw new ArchiveException("Invalid pathname length");
         }
-
         final byte[] pathnameBuffer = new byte[pathnameLength];
         buffer.get(pathnameBuffer);
-
         // Split the pathname into parts by 0xFF bytes
         final StringBuilder pathnameStringBuilder = new StringBuilder();
         int start = 0;
@@ -375,36 +388,30 @@ String getPathname(final ByteBuffer buffer, final int 
pathnameLength) throws Arc
                     // Decode the path segment into a string using the 
specified charset and append it to the result
                     pathnameStringBuilder.append(new String(pathnameBuffer, 
start, i - start, getCharset())).append(fileSeparatorChar);
                 }
-
                 start = i + 1; // Move start to the next segment
             }
         }
-
         // Append the last segment if it exists
         if (start < pathnameLength) {
             pathnameStringBuilder.append(new String(pathnameBuffer, start, 
pathnameLength - start, getCharset()));
         }
-
         String pathname = pathnameStringBuilder.toString();
-
         // If the path separator char is not '\', replace all '\' characters 
with the path separator char
         if (fileSeparatorChar != '\\') {
             pathname = pathname.replace('\\', fileSeparatorChar);
         }
-
         // Remove leading file separator chars to avoid extracting to absolute 
locations
         while (pathname.length() > 0 && pathname.charAt(0) == 
fileSeparatorChar) {
             pathname = pathname.substring(1);
         }
-
         return pathname;
     }
 
     /**
      * Tests whether the compression method is a directory entry.
      *
-     * @param compressionMethod the compression method
-     * @return true if the compression method is a directory entry, false 
otherwise
+     * @param compressionMethod the compression method.
+     * @return true if the compression method is a directory entry, false 
otherwise.
      */
     private boolean isDirectory(final String compressionMethod) {
         return COMPRESSION_METHOD_DIRECTORY.equals(compressionMethod);
@@ -413,16 +420,15 @@ private boolean isDirectory(final String 
compressionMethod) {
     /**
      * Parse the extended header and set the values in the provided entry.
      *
-     * @param extendedHeaderBuffer the buffer containing the extended header
-     * @param entryBuilder the entry builder to set the values in
-     * @throws IOException
+     * @param extendedHeaderBuffer the buffer containing the extended header.
+     * @param entryBuilder         the entry builder to set the values in.
+     * @throws ArchiveException Thrown on invalid input.
      */
-    void parseExtendedHeader(final ByteBuffer extendedHeaderBuffer, final 
LhaArchiveEntry.Builder entryBuilder) throws IOException {
+    void parseExtendedHeader(final ByteBuffer extendedHeaderBuffer, final 
LhaArchiveEntry.Builder entryBuilder) throws ArchiveException {
         final int extendedHeaderLength = extendedHeaderBuffer.limit() - 
extendedHeaderBuffer.position();
         if (extendedHeaderLength < MIN_EXTENDED_HEADER_LENGTH) {
             throw new ArchiveException("Invalid extended header length");
         }
-
         final int extendedHeaderType = 
Byte.toUnsignedInt(extendedHeaderBuffer.get());
         switch (extendedHeaderType) {
         case EXTENDED_HEADER_TYPE_COMMON: {
@@ -441,7 +447,7 @@ void parseExtendedHeader(final ByteBuffer 
extendedHeaderBuffer, final LhaArchive
             // File name header
             final int filenameLength = extendedHeaderBuffer.limit() - 
extendedHeaderBuffer.position() - EXTENDED_HEADER_NEXT_HEADER_SIZE_LENGTH;
             final String filename = getPathname(extendedHeaderBuffer, 
filenameLength);
-            entryBuilder.setFilename(filename);
+            entryBuilder.setFileName(filename);
             break;
         }
         case EXTENDED_HEADER_TYPE_DIRECTORY_NAME: {
@@ -488,55 +494,36 @@ void parseExtendedHeader(final ByteBuffer 
extendedHeaderBuffer, final LhaArchive
         default:
             break;
         }
-
         // Ignore unknown extended header
     }
 
-    private void prepareDecompression(final LhaArchiveEntry entry) throws 
IOException {
+    private LhaArchiveEntry prepareDecompression(final LhaArchiveEntry entry) 
throws IOException {
         // Make sure we never read more than the compressed size of the entry
-        this.currentCompressedStream = BoundedInputStream.builder()
-                .setInputStream(in)
-                .setMaxCount(entry.getCompressedSize())
-                .get();
-
+        this.currentCompressedStream = 
BoundedInputStream.builder().setInputStream(in).setMaxCount(entry.getCompressedSize()).get();
         if (isDirectory(entry.getCompressionMethod())) {
             // Directory entry
-            this.currentDecompressedStream = new ByteArrayInputStream(new byte 
[0]);
+            this.currentDecompressedStream = new ByteArrayInputStream(new 
byte[0]);
         } else if (COMPRESSION_METHOD_LH0.equals(entry.getCompressionMethod()) 
|| COMPRESSION_METHOD_LZ4.equals(entry.getCompressionMethod())) {
             // No compression
-            this.currentDecompressedStream = ChecksumInputStream.builder()
-                    .setChecksum(Crc16.arc())
-                    .setExpectedChecksumValue(entry.getCrcValue())
-                    .setInputStream(this.currentCompressedStream)
-                    .get();
+            this.currentDecompressedStream = 
ChecksumInputStream.builder().setChecksum(Crc16.arc()).setExpectedChecksumValue(entry.getCrcValue())
+                    .setInputStream(this.currentCompressedStream).get();
         } else if 
(COMPRESSION_METHOD_LH4.equals(entry.getCompressionMethod())) {
-            this.currentDecompressedStream = ChecksumInputStream.builder()
-                    .setChecksum(Crc16.arc())
-                    .setExpectedChecksumValue(entry.getCrcValue())
-                    .setInputStream(new 
Lh4CompressorInputStream(this.currentCompressedStream))
-                    .get();
+            this.currentDecompressedStream = 
ChecksumInputStream.builder().setChecksum(Crc16.arc()).setExpectedChecksumValue(entry.getCrcValue())
+                    .setInputStream(new 
Lh4CompressorInputStream(this.currentCompressedStream)).get();
         } else if 
(COMPRESSION_METHOD_LH5.equals(entry.getCompressionMethod())) {
-            this.currentDecompressedStream = ChecksumInputStream.builder()
-                    .setChecksum(Crc16.arc())
-                    .setExpectedChecksumValue(entry.getCrcValue())
-                    .setInputStream(new 
Lh5CompressorInputStream(this.currentCompressedStream))
-                    .get();
+            this.currentDecompressedStream = 
ChecksumInputStream.builder().setChecksum(Crc16.arc()).setExpectedChecksumValue(entry.getCrcValue())
+                    .setInputStream(new 
Lh5CompressorInputStream(this.currentCompressedStream)).get();
         } else if 
(COMPRESSION_METHOD_LH6.equals(entry.getCompressionMethod())) {
-            this.currentDecompressedStream = ChecksumInputStream.builder()
-                    .setChecksum(Crc16.arc())
-                    .setExpectedChecksumValue(entry.getCrcValue())
-                    .setInputStream(new 
Lh6CompressorInputStream(this.currentCompressedStream))
-                    .get();
+            this.currentDecompressedStream = 
ChecksumInputStream.builder().setChecksum(Crc16.arc()).setExpectedChecksumValue(entry.getCrcValue())
+                    .setInputStream(new 
Lh6CompressorInputStream(this.currentCompressedStream)).get();
         } else if 
(COMPRESSION_METHOD_LH7.equals(entry.getCompressionMethod())) {
-            this.currentDecompressedStream = ChecksumInputStream.builder()
-                    .setChecksum(Crc16.arc())
-                    .setExpectedChecksumValue(entry.getCrcValue())
-                    .setInputStream(new 
Lh7CompressorInputStream(this.currentCompressedStream))
-                    .get();
+            this.currentDecompressedStream = 
ChecksumInputStream.builder().setChecksum(Crc16.arc()).setExpectedChecksumValue(entry.getCrcValue())
+                    .setInputStream(new 
Lh7CompressorInputStream(this.currentCompressedStream)).get();
         } else {
             // Unsupported compression
             this.currentDecompressedStream = null;
         }
+        return entry;
     }
 
     @Override
@@ -544,11 +531,9 @@ public int read(final byte[] buffer, final int offset, 
final int length) throws
         if (currentEntry == null) {
             throw new IllegalStateException("No current entry");
         }
-
         if (currentDecompressedStream == null) {
             throw new ArchiveException("Unsupported compression method: %s", 
currentEntry.getCompressionMethod());
         }
-
         final int read = currentDecompressedStream.read(buffer, offset, 
length);
         count(read);
         return read;
@@ -557,9 +542,9 @@ public int read(final byte[] buffer, final int offset, 
final int length) throws
     /**
      * Read extended header from the input stream.
      *
-     * @param headerSize the size of the extended header to read
-     * @return the extended header as a ByteBuffer
-     * @throws IOException
+     * @param headerSize the size of the extended header to read.
+     * @return the extended header as a ByteBuffer.
+     * @throws IOException Thrown if a read error occurs.
      */
     private ByteBuffer readExtendedHeader(final int headerSize) throws 
IOException {
         final byte[] extensionHeader = new byte[headerSize];
@@ -567,33 +552,27 @@ private ByteBuffer readExtendedHeader(final int 
headerSize) throws IOException {
         if (len != extensionHeader.length) {
             throw new ArchiveException("Error reading extended header");
         }
-
         return ByteBuffer.wrap(extensionHeader).order(ByteOrder.LITTLE_ENDIAN);
     }
 
     /**
      * Read the next LHA header from the input stream.
      *
-     * @return the next header entry, or null if there are no more entries
-     * @throws IOException
+     * @return the next header entry, or null if there are no more entries.
+     * @throws IOException Thrown if a read error occurs.
      */
-    LhaArchiveEntry readHeader() throws IOException {
+    private LhaArchiveEntry readHeader() throws IOException {
         // Header level is not known yet. Read the minimum length header.
         final byte[] buffer = new byte[HEADER_GENERIC_MINIMUM_HEADER_LENGTH];
         final int len = IOUtils.read(in, buffer);
-        if (len == 0) {
-            // EOF
-            return null;
-        }
-        if (len == 1 && buffer[0] == 0) {
+        if (len == 0 || len == 1 && buffer[0] == 0) {
             // Last byte of the file is zero indicating no more entries
             return null;
-        } else if (len < HEADER_GENERIC_MINIMUM_HEADER_LENGTH) {
+        }
+        if (len < HEADER_GENERIC_MINIMUM_HEADER_LENGTH) {
             throw new ArchiveException("Invalid header length");
         }
-
         final ByteBuffer header = 
ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
-
         // Determine header level
         final byte headerLevel = 
header.get(HEADER_GENERIC_OFFSET_HEADER_LEVEL);
         switch (headerLevel) {
@@ -611,50 +590,42 @@ LhaArchiveEntry readHeader() throws IOException {
     /**
      * Read LHA header level 0.
      *
-     * @param buffer the buffer containing the header data
-     * @return the LhaArchiveEntry read from the buffer
-     * @throws IOException
+     * @param buffer the buffer containing the header data.
+     * @return the LhaArchiveEntry read from the buffer.
+     * @throws IOException Thrown if a read error occurs.
      */
-    LhaArchiveEntry readHeaderLevel0(ByteBuffer buffer) throws IOException {
+    private LhaArchiveEntry readHeaderLevel0(ByteBuffer buffer) throws 
IOException {
         // Add two to the header size as the first two bytes are not included
         final int headerSize = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_0_OFFSET_HEADER_SIZE)) + 2;
         if (headerSize < HEADER_GENERIC_MINIMUM_HEADER_LENGTH) {
             throw new ArchiveException("Invalid header level 0 length: %d", 
headerSize);
         }
-
         buffer = readRemainingHeaderData(buffer, headerSize);
-
         final int headerChecksum = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_0_OFFSET_HEADER_CHECKSUM));
-
         final String compressionMethod = getCompressionMethod(buffer);
-
+        // @formatter:off
         final LhaArchiveEntry.Builder entryBuilder = new 
LhaArchiveEntry.Builder()
-            .setCompressionMethod(compressionMethod)
-            
.setCompressedSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_COMPRESSED_SIZE)))
-            
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_ORIGINAL_SIZE)))
-            .setLastModifiedDate(new 
Date(ZipUtil.dosToJavaTime(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_LAST_MODIFIED_DATE_TIME)))));
-
+                .setCompressionMethod(compressionMethod)
+                
.setCompressedSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_COMPRESSED_SIZE)))
+                
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_ORIGINAL_SIZE)))
+                .setLastModifiedDate(new 
Date(ZipUtil.dosToJavaTime(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_0_OFFSET_LAST_MODIFIED_DATE_TIME)))));
+        // @formatter:on
         final int filenameLength = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_0_OFFSET_FILENAME_LENGTH));
-
         // Make sure the filename is not overflowing into the CRC field
         if (filenameLength > headerSize - HEADER_LEVEL_0_OFFSET_FILENAME - 2) {
             throw new ArchiveException("Invalid pathname length");
         }
-
         buffer.position(HEADER_LEVEL_0_OFFSET_FILENAME);
-        entryBuilder.setFilename(getPathname(buffer, filenameLength))
+        // @formatter:off
+        entryBuilder
+            .setFileName(getPathname(buffer, filenameLength))
             .setDirectory(isDirectory(compressionMethod))
-            .setCrcValue(Short.toUnsignedInt(buffer.getShort()));
-
+            .setCrc(Short.toUnsignedInt(buffer.getShort()));
+        // @formatter:on
         if (calculateHeaderChecksum(buffer) != headerChecksum) {
             throw new ArchiveException("Invalid header level 0 checksum");
         }
-
-        final LhaArchiveEntry entry = entryBuilder.get();
-
-        prepareDecompression(entry);
-
-        return entry;
+        return prepareDecompression(entryBuilder.get());
     }
 
     /**
@@ -662,75 +633,63 @@ LhaArchiveEntry readHeaderLevel0(ByteBuffer buffer) 
throws IOException {
      *
      * @param buffer the buffer containing the header data
      * @return the LhaArchiveEntry read from the buffer
-     * @throws IOException
+     * @throws IOException Thrown if a read error occurs.
      */
-    LhaArchiveEntry readHeaderLevel1(ByteBuffer buffer) throws IOException {
+    private LhaArchiveEntry readHeaderLevel1(ByteBuffer buffer) throws 
IOException {
         // Add two to the header size as the first two bytes are not included
         final int baseHeaderSize = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_1_OFFSET_BASE_HEADER_SIZE)) + 2;
         if (baseHeaderSize < HEADER_GENERIC_MINIMUM_HEADER_LENGTH) {
             throw new ArchiveException("Invalid header level 1 length: %d", 
baseHeaderSize);
         }
-
         buffer = readRemainingHeaderData(buffer, baseHeaderSize);
-
         final int baseHeaderChecksum = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_1_OFFSET_BASE_HEADER_CHECKSUM));
-
         final String compressionMethod = getCompressionMethod(buffer);
         long skipSize = 
Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_1_OFFSET_SKIP_SIZE));
-
+        // @formatter:off
         final LhaArchiveEntry.Builder entryBuilder = new 
LhaArchiveEntry.Builder()
-            .setCompressionMethod(compressionMethod)
-            
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_1_OFFSET_ORIGINAL_SIZE)))
-            .setLastModifiedDate(new 
Date(ZipUtil.dosToJavaTime(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_1_OFFSET_LAST_MODIFIED_DATE_TIME)))));
-
+                .setCompressionMethod(compressionMethod)
+                
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_1_OFFSET_ORIGINAL_SIZE)))
+                .setLastModifiedDate(new 
Date(ZipUtil.dosToJavaTime(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_1_OFFSET_LAST_MODIFIED_DATE_TIME)))));
+        // @formatter:on
         final int filenameLength = 
Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_1_OFFSET_FILENAME_LENGTH));
-
         // Make sure the filename is not overflowing into the CRC, OS ID and 
first extended header length fields.
         // This check is not bulletproof because there might also be an 
extended area after the filename that
         // we cannot detect for corrupt archives.
         if (filenameLength > baseHeaderSize - HEADER_LEVEL_1_OFFSET_FILENAME - 
5) {
             throw new ArchiveException("Invalid pathname length");
         }
-
         buffer.position(HEADER_LEVEL_1_OFFSET_FILENAME);
-        entryBuilder.setFilename(getPathname(buffer, filenameLength))
+        // @formatter:off
+        entryBuilder
+            .setFileName(getPathname(buffer, filenameLength))
             .setDirectory(isDirectory(compressionMethod))
-            .setCrcValue(Short.toUnsignedInt(buffer.getShort()))
+            .setCrc(Short.toUnsignedInt(buffer.getShort()))
             .setOsId(Byte.toUnsignedInt(buffer.get()));
-
+        // @formatter:on
         if (calculateHeaderChecksum(buffer) != baseHeaderChecksum) {
             throw new ArchiveException("Invalid header level 1 checksum");
         }
-
         // Create a list to store base header and all extended headers
         // to be able to calculate the CRC of the full header
         final List<ByteBuffer> headerParts = new ArrayList<>();
         headerParts.add(buffer);
-
         buffer.position(baseHeaderSize - 2); // First extended header length 
is at the end of the base header
         int extendedHeaderSize = Short.toUnsignedInt(buffer.getShort());
         while (extendedHeaderSize > 0) {
             final ByteBuffer extendedHeaderBuffer = 
readExtendedHeader(extendedHeaderSize);
             skipSize -= extendedHeaderSize;
-
             parseExtendedHeader(extendedHeaderBuffer, entryBuilder);
-
             headerParts.add(extendedHeaderBuffer);
-
             extendedHeaderSize = 
Short.toUnsignedInt(extendedHeaderBuffer.getShort(extendedHeaderBuffer.limit() 
- 2));
         }
-
         // The compressed size is derived by subtracting the extended header 
sizes from the skip size. A
         // corrupt archive whose extended headers exceed the skip size would 
yield a negative compressed
         // size, which must be rejected as it would otherwise disable the 
per-entry read bound.
         if (skipSize < 0) {
             throw new ArchiveException("Invalid compressed size");
         }
-
         entryBuilder.setCompressedSize(skipSize);
-
         final LhaArchiveEntry entry = entryBuilder.get();
-
         if (entry.getHeaderCrc() != null) {
             // Calculate CRC16 of full header
             final long headerCrc = calculateCRC16(headerParts.toArray(new 
ByteBuffer[headerParts.size()]));
@@ -738,57 +697,46 @@ LhaArchiveEntry readHeaderLevel1(ByteBuffer buffer) 
throws IOException {
                 throw new ArchiveException("Invalid header CRC expected=0x%04x 
found=0x%04x", headerCrc, entry.getHeaderCrc());
             }
         }
-
-        prepareDecompression(entry);
-
-        return entry;
+        return prepareDecompression(entry);
     }
 
     /**
      * Read LHA header level 2.
      *
-     * @param buffer the buffer containing the header data
-     * @return the LhaArchiveEntry read from the buffer
-     * @throws IOException
+     * @param buffer the buffer containing the header data.
+     * @return the LhaArchiveEntry read from the buffer.
+     * @throws IOException Thrown if a read error occurs.
      */
-    LhaArchiveEntry readHeaderLevel2(ByteBuffer buffer) throws IOException {
+    private LhaArchiveEntry readHeaderLevel2(ByteBuffer buffer) throws 
IOException {
         final int headerSize = 
Short.toUnsignedInt(buffer.getShort(HEADER_LEVEL_2_OFFSET_HEADER_SIZE));
         if (headerSize < HEADER_LEVEL_2_MINIMUM_HEADER_LENGTH) {
             throw new ArchiveException("Invalid header level 2 length: %d", 
headerSize);
         }
-
         buffer = readRemainingHeaderData(buffer, headerSize);
-
         final String compressionMethod = getCompressionMethod(buffer);
-
+        // @formatter:off
         final LhaArchiveEntry.Builder entryBuilder = new 
LhaArchiveEntry.Builder()
-            .setCompressionMethod(compressionMethod)
-            
.setCompressedSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_COMPRESSED_SIZE)))
-            
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_ORIGINAL_SIZE)))
-            .setLastModifiedDate(new 
Date(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_LAST_MODIFIED_DATE_TIME))
 * 1000))
-            .setDirectory(isDirectory(compressionMethod))
-            
.setCrcValue(Short.toUnsignedInt(buffer.getShort(HEADER_LEVEL_2_OFFSET_CRC)))
-            
.setOsId(Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_2_OFFSET_OS_ID)));
-
+                .setCompressionMethod(compressionMethod)
+                
.setCompressedSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_COMPRESSED_SIZE)))
+                
.setSize(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_ORIGINAL_SIZE)))
+                .setLastModifiedDate(new 
Date(Integer.toUnsignedLong(buffer.getInt(HEADER_LEVEL_2_OFFSET_LAST_MODIFIED_DATE_TIME))
 * 1000))
+                .setDirectory(isDirectory(compressionMethod))
+                
.setCrc(Short.toUnsignedInt(buffer.getShort(HEADER_LEVEL_2_OFFSET_CRC)))
+                
.setOsId(Byte.toUnsignedInt(buffer.get(HEADER_LEVEL_2_OFFSET_OS_ID)));
+        // @formatter:on
         int extendedHeaderSize = 
Short.toUnsignedInt(buffer.getShort(HEADER_LEVEL_2_OFFSET_FIRST_EXTENDED_HEADER_SIZE));
         int extendedHeaderOffset = 
HEADER_LEVEL_2_OFFSET_FIRST_EXTENDED_HEADER_SIZE + 2;
         while (extendedHeaderSize > 0) {
             if (extendedHeaderOffset + extendedHeaderSize > buffer.limit()) {
                 throw new ArchiveException("Invalid extended header length");
             }
-
             // Create new ByteBuffer as a slice from the full header. Set 
limit to the extended header length.
             final ByteBuffer extendedHeaderBuffer = byteBufferSlice(buffer, 
extendedHeaderOffset, extendedHeaderSize).order(ByteOrder.LITTLE_ENDIAN);
-
             extendedHeaderOffset += extendedHeaderSize;
-
             parseExtendedHeader(extendedHeaderBuffer, entryBuilder);
-
             extendedHeaderSize = 
Short.toUnsignedInt(extendedHeaderBuffer.getShort(extendedHeaderBuffer.limit() 
- 2));
         }
-
         final LhaArchiveEntry entry = entryBuilder.get();
-
         if (entry.getHeaderCrc() != null) {
             // Calculate CRC16 of full header
             final long headerCrc = calculateCRC16(buffer);
@@ -796,19 +744,16 @@ LhaArchiveEntry readHeaderLevel2(ByteBuffer buffer) 
throws IOException {
                 throw new ArchiveException("Invalid header CRC expected=0x%04x 
found=0x%04x", headerCrc, entry.getHeaderCrc());
             }
         }
-
-        prepareDecompression(entry);
-
-        return entry;
+        return prepareDecompression(entry);
     }
 
     /**
      * Read the remaining part of the header and append it to the already 
loaded parts.
      *
-     * @param currentHeader all header parts that have already been loaded 
into memory
-     * @param headerSize total header size
-     * @return header the complete header as a ByteBuffer
-     * @throws IOException
+     * @param currentHeader All header parts that have already been loaded 
into memory.
+     * @param headerSize    Total header size.
+     * @return header The complete header as a ByteBuffer.
+     * @throws IOException Thrown if a read error occurs.
      */
     private ByteBuffer readRemainingHeaderData(final ByteBuffer currentHeader, 
final int headerSize) throws IOException {
         final byte[] remainingData = new byte[headerSize - 
currentHeader.capacity()];
@@ -816,7 +761,6 @@ private ByteBuffer readRemainingHeaderData(final ByteBuffer 
currentHeader, final
         if (len != remainingData.length) {
             throw new ArchiveException("Error reading remaining header");
         }
-
         return ByteBuffer.allocate(currentHeader.capacity() + 
len).put(currentHeader.array()).put(remainingData).order(ByteOrder.LITTLE_ENDIAN);
     }
 }

Reply via email to