From 23877f8216243df6b2f1dddac2a02b8403d2435d Mon Sep 17 00:00:00 2001
From: Emmanuel Bourg <ebourg@apache.org>
Date: Thu, 24 Oct 2024 19:13:47 +0200
Subject: [PATCH] Removed the runtime dependency on commons-lang3

---
 pom.xml                                       |  3 +--
 src/changes/changes.xml                       |  1 +
 .../archivers/tar/TarArchiveEntry.java        |  3 +--
 .../archivers/tar/TarArchiveOutputStream.java |  5 ++--
 .../compress/archivers/zip/BinaryTree.java    |  5 ++--
 .../compressors/deflate64/HuffmanDecoder.java |  4 +--
 .../lz77support/LZ77Compressor.java           |  6 ++---
 .../compress/harmony/unpack200/Archive.java   |  2 +-
 .../unpack200/Pack200UnpackerAdapter.java     | 27 ++++++++++---------
 .../tar/TarArchiveOutputStreamTest.java       |  4 +--
 .../zip/ZipArchiveInputStreamTest.java        |  5 ++--
 .../compress/archivers/zip/ZipFileTest.java   |  4 +--
 .../BlockLZ4CompressorOutputStreamTest.java   |  5 ++--
 13 files changed, 40 insertions(+), 34 deletions(-)

--- a/pom.xml
+++ b/pom.xml
@@ -64,8 +64,6 @@
       javax.crypto.*;resolution:=optional,
       org.apache.commons.io;resolution:=optional,
       org.apache.commons.io.*;resolution:=optional,
-      org.apache.commons.lang3;resolution:=optional,
-      org.apache.commons.lang3.reflect;resolution:=optional,
       org.apache.commons.codec;resolution:=optional,
       org.apache.commons.codec.digest;resolution:=optional,
       *
@@ -218,6 +216,7 @@
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
       <version>3.16.0</version>
+      <scope>test</scope>
     </dependency>    
     <dependency>
       <groupId>org.osgi</groupId>
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
@@ -53,7 +53,6 @@
 import org.apache.commons.compress.utils.ParsingUtils;
 import org.apache.commons.compress.utils.TimeUtils;
 import org.apache.commons.io.file.attribute.FileTimes;
-import org.apache.commons.lang3.SystemProperties;
 
 /**
  * An entry in a <a href="https://www.gnu.org/software/tar/manual/html_node/Standard.html">Tar archive</a>.
@@ -229,7 +228,7 @@
      */
     private static String normalizeFileName(String fileName, final boolean preserveAbsolutePath) {
         if (!preserveAbsolutePath) {
-            final String property = SystemProperties.getOsName();
+            final String property = System.getProperty("os.name");
             if (property != null) {
                 final String osName = property.toLowerCase(Locale.ROOT);
 
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
@@ -32,6 +32,7 @@
 import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
 import java.time.Instant;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -43,7 +44,6 @@
 import org.apache.commons.io.Charsets;
 import org.apache.commons.io.file.attribute.FileTimes;
 import org.apache.commons.io.output.CountingOutputStream;
-import org.apache.commons.lang3.ArrayFill;
 
 /**
  * The TarOutputStream writes a UNIX tar archive as an OutputStream. Methods are provided to put entries, and then write their contents by writing to this
@@ -649,7 +649,8 @@
      * Writes an EOF (end of archive) record to the tar archive. An EOF record consists of a record of all zeros.
      */
     private void writeEOFRecord() throws IOException {
-        writeRecord(ArrayFill.fill(recordBuf, (byte) 0));
+        Arrays.fill(recordBuf, (byte) 0);
+        writeRecord(recordBuf);
     }
 
     /**
--- a/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
@@ -22,9 +22,9 @@
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 
 import org.apache.commons.compress.utils.IOUtils;
-import org.apache.commons.lang3.ArrayFill;
 
 /**
  * Binary tree of positive values.
@@ -140,7 +140,8 @@
         if (depth < 0 || depth > 30) {
             throw new IllegalArgumentException("depth must be bigger than 0 and not bigger than 30" + " but is " + depth);
         }
-        tree = ArrayFill.fill(new int[(int) ((1L << depth + 1) - 1)], UNDEFINED);
+        tree = new int[(int) ((1L << depth + 1) - 1)];
+        Arrays.fill(tree, UNDEFINED);
     }
 
     /**
--- a/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java
+++ b/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java
@@ -31,7 +31,6 @@
 import org.apache.commons.compress.utils.BitInputStream;
 import org.apache.commons.compress.utils.ByteUtils;
 import org.apache.commons.compress.utils.ExactMath;
-import org.apache.commons.lang3.ArrayFill;
 
 /**
  * TODO This class can't be final because it is mocked by Mockito.
@@ -362,7 +361,8 @@
         Arrays.fill(FIXED_LITERALS, 256, 280, 7);
         Arrays.fill(FIXED_LITERALS, 280, 288, 8);
 
-        FIXED_DISTANCE = ArrayFill.fill(new int[32], 5);
+        FIXED_DISTANCE = new int[32];
+        Arrays.fill(FIXED_DISTANCE, 5);
     }
 
     private static BinaryTreeNode buildTree(final int[] litTable) {
--- a/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lz77support/LZ77Compressor.java
@@ -19,10 +19,9 @@
 package org.apache.commons.compress.compressors.lz77support;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Objects;
 
-import org.apache.commons.lang3.ArrayFill;
-
 /**
  * Helper class for compression algorithms that use the ideas of LZ77.
  *
@@ -286,7 +285,8 @@
         final int wSize = params.getWindowSize();
         window = new byte[wSize * 2];
         wMask = wSize - 1;
-        head = ArrayFill.fill(new int[HASH_SIZE], NO_MATCH);
+        head = new int[HASH_SIZE];
+        Arrays.fill(head, NO_MATCH);
         prev = new int[wSize];
     }
 
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/Archive.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/Archive.java
@@ -78,7 +78,7 @@
         this.inputStream = Pack200UnpackerAdapter.newBoundedInputStream(inputStream);
         this.outputStream = outputStream;
         if (inputStream instanceof FileInputStream) {
-            inputPath = Paths.get(Pack200UnpackerAdapter.readPathString((FileInputStream) inputStream));
+            inputPath = Pack200UnpackerAdapter.readPath((FileInputStream) inputStream);
         } else {
             inputPath = null;
         }
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/Pack200UnpackerAdapter.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/Pack200UnpackerAdapter.java
@@ -22,6 +22,7 @@
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Field;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.Files;
@@ -34,7 +35,6 @@
 import org.apache.commons.compress.java.util.jar.Pack200.Unpacker;
 import org.apache.commons.io.input.BoundedInputStream;
 import org.apache.commons.io.input.CloseShieldInputStream;
-import org.apache.commons.lang3.reflect.FieldUtils;
 
 /**
  * This class provides the binding between the standard Pack200 interface and the internal interface for (un)packing.
@@ -56,7 +56,7 @@
     }
 
     private static BoundedInputStream newBoundedInputStream(final FileInputStream fileInputStream) throws IOException {
-        return newBoundedInputStream(readPathString(fileInputStream));
+        return newBoundedInputStream(readPath(fileInputStream));
     }
 
     @SuppressWarnings("resource") // Caller closes.
@@ -130,19 +130,16 @@
         return newBoundedInputStream(Paths.get(url.toURI()));
     }
 
-    @SuppressWarnings("unchecked")
-    private static <T> T readField(final Object object, final String fieldName) {
+    static Path readPath(final FileInputStream fis) {
         try {
-            return (T) FieldUtils.readField(object, fieldName, true);
-        } catch (final IllegalAccessException e) {
-            return null;
+            Field field = FileInputStream.class.getDeclaredField("path");
+            field.setAccessible(true);
+            return Paths.get((String) field.get(fis));
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new RuntimeException("Failed to read the path from the FileInputStream", e);
         }
     }
 
-    static String readPathString(final FileInputStream fis) {
-        return readField(fis, "path");
-    }
-
     /**
      * Unwraps the given FilterInputStream to return its wrapped InputStream.
      *
@@ -150,7 +147,13 @@
      * @return The wrapped InputStream
      */
     static InputStream unwrap(final FilterInputStream filterInputStream) {
-        return readField(filterInputStream, "in");
+        try {
+            Field field = FilterInputStream.class.getDeclaredField("in");
+            field.setAccessible(true);
+            return (InputStream) field.get(filterInputStream);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new RuntimeException("Failed to unwrap the FilterInputStream", e);
+        }
     }
 
     /**
--- a/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
@@ -48,7 +48,6 @@
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.NullOutputStream;
-import org.apache.commons.lang3.ArrayFill;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
@@ -148,7 +147,8 @@
         assertThrows(IllegalArgumentException.class, () -> testPadding(0, fileName, contents));
 
         // test with "content" that is an exact multiple of record length
-        final byte[] contents2 = ArrayFill.fill(new byte[2048], (byte) 42);
+        final byte[] contents2 = new byte[2048];
+        java.util.Arrays.fill(contents2, (byte) 42);
         testPadding(TarConstants.DEFAULT_BLKSIZE, fileName, contents2);
     }
 
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
@@ -40,6 +40,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.time.Instant;
+import java.util.Arrays;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 
@@ -49,7 +50,6 @@
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.compress.utils.ByteUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.ArrayFill;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
@@ -666,7 +666,8 @@
         try (ZipArchiveInputStream in = new ZipArchiveInputStream(newInputStream("bzip2-zip.zip"))) {
             final ZipArchiveEntry ze = in.getNextZipEntry();
             assertEquals(42, ze.getSize());
-            final byte[] expected = ArrayFill.fill(new byte[42], (byte) 'a');
+            final byte[] expected = new byte[42];
+            Arrays.fill(expected, (byte) 'a');
             assertArrayEquals(expected, IOUtils.toByteArray(in));
         }
     }
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
@@ -58,7 +58,6 @@
 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.function.IORunnable;
-import org.apache.commons.lang3.ArrayFill;
 import org.apache.commons.lang3.SystemUtils;
 import org.junit.Assume;
 import org.junit.jupiter.api.AfterEach;
@@ -944,7 +943,8 @@
         zf = new ZipFile(archive);
         final ZipArchiveEntry ze = zf.getEntry("lots-of-as");
         assertEquals(42, ze.getSize());
-        final byte[] expected = ArrayFill.fill(new byte[42], (byte) 'a');
+        final byte[] expected = new byte[42];
+        Arrays.fill(expected, (byte) 'a');
         try (InputStream inputStream = zf.getInputStream(ze)) {
             assertArrayEquals(expected, IOUtils.toByteArray(inputStream));
         }
--- a/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java
@@ -28,7 +28,6 @@
 import java.util.Arrays;
 
 import org.apache.commons.compress.compressors.lz77support.LZ77Compressor;
-import org.apache.commons.lang3.ArrayFill;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
@@ -75,7 +74,9 @@
     }
 
     private byte[] prepareExpected(final int length) {
-        return ArrayFill.fill(new byte[length], (byte) -1);
+        final byte[] b = new byte[length];
+        Arrays.fill(b, (byte) -1);
+        return b;
     }
 
     @Test
