diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ebcb2fa20..c1a58c9f6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -109,6 +109,8 @@ The type attribute can be add,update,fix,remove. Deprecate ThreadUtils 0-argument constructor. Deprecate TypeUtils 0-argument constructor. Make ArrayFill null-safe. + Make ArraySorter null-safe. + Make ArrayUtils.removeAll() null-safe. Bump commons-parent from 64 to 66. Bump org.codehaus.mojo:exec-maven-plugin from 3.1.1 to 3.2.0 #1175. diff --git a/src/main/java/org/apache/commons/lang3/ArraySorter.java b/src/main/java/org/apache/commons/lang3/ArraySorter.java index 334e5cae3..7c80c9051 100644 --- a/src/main/java/org/apache/commons/lang3/ArraySorter.java +++ b/src/main/java/org/apache/commons/lang3/ArraySorter.java @@ -35,7 +35,9 @@ public class ArraySorter { * @see Arrays#sort(byte[]) */ public static byte[] sort(final byte[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -47,7 +49,9 @@ public class ArraySorter { * @see Arrays#sort(char[]) */ public static char[] sort(final char[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -59,7 +63,9 @@ public class ArraySorter { * @see Arrays#sort(double[]) */ public static double[] sort(final double[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -71,7 +77,9 @@ public class ArraySorter { * @see Arrays#sort(float[]) */ public static float[] sort(final float[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -83,7 +91,9 @@ public class ArraySorter { * @see Arrays#sort(int[]) */ public static int[] sort(final int[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -95,7 +105,9 @@ public class ArraySorter { * @see Arrays#sort(long[]) */ public static long[] sort(final long[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -107,7 +119,9 @@ public class ArraySorter { * @see Arrays#sort(short[]) */ public static short[] sort(final short[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -120,7 +134,9 @@ public class ArraySorter { * @see Arrays#sort(Object[]) */ public static T[] sort(final T[] array) { - Arrays.sort(array); + if (array != null) { + Arrays.sort(array); + } return array; } @@ -135,7 +151,9 @@ public class ArraySorter { * @see Arrays#sort(Object[]) */ public static T[] sort(final T[] array, final Comparator comparator) { - Arrays.sort(array, comparator); + if (array != null) { + Arrays.sort(array, comparator); + } return array; } diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java index 93c95b71b..88e690041 100644 --- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java +++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java @@ -5296,6 +5296,9 @@ public class ArrayUtils { */ // package protected for access by unit tests static Object removeAll(final Object array, final int... indices) { + if (array == null) { + return null; + } final int length = getLength(array); int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed final int[] clonedIndices = ArraySorter.sort(clone(indices)); @@ -5319,7 +5322,7 @@ public class ArrayUtils { // create result array final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff); - if (diff < length) { + if (diff < length && clonedIndices != null) { int end = length; // index just after last copy int dest = length - diff; // number of entries so far not copied for (int i = clonedIndices.length - 1; i >= 0; i--) { diff --git a/src/test/java/org/apache/commons/lang3/ArraySorterTest.java b/src/test/java/org/apache/commons/lang3/ArraySorterTest.java index d3664321b..b56e0ae8e 100644 --- a/src/test/java/org/apache/commons/lang3/ArraySorterTest.java +++ b/src/test/java/org/apache/commons/lang3/ArraySorterTest.java @@ -18,11 +18,15 @@ package org.apache.commons.lang3; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import java.util.Arrays; import org.junit.jupiter.api.Test; +/** + * Tests {@link ArraySorter}. + */ public class ArraySorterTest extends AbstractLangTest { @Test @@ -31,6 +35,7 @@ public class ArraySorterTest extends AbstractLangTest { final byte[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((byte[]) null)); } @Test @@ -39,6 +44,7 @@ public class ArraySorterTest extends AbstractLangTest { final char[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((char[]) null)); } @Test @@ -47,6 +53,7 @@ public class ArraySorterTest extends AbstractLangTest { final String[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2, String::compareTo)); + assertNull(ArraySorter.sort((String[]) null)); } @Test @@ -55,6 +62,7 @@ public class ArraySorterTest extends AbstractLangTest { final double[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((double[]) null)); } @Test @@ -63,6 +71,7 @@ public class ArraySorterTest extends AbstractLangTest { final float[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((float[]) null)); } @Test @@ -71,6 +80,7 @@ public class ArraySorterTest extends AbstractLangTest { final int[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((int[]) null)); } @Test @@ -79,6 +89,7 @@ public class ArraySorterTest extends AbstractLangTest { final long[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((long[]) null)); } @Test @@ -87,6 +98,7 @@ public class ArraySorterTest extends AbstractLangTest { final String[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((String[]) null)); } @Test @@ -95,6 +107,7 @@ public class ArraySorterTest extends AbstractLangTest { final short[] array2 = array1.clone(); Arrays.sort(array1); assertArrayEquals(array1, ArraySorter.sort(array2)); + assertNull(ArraySorter.sort((short[]) null)); } } diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java index a5151d015..4b74d9e2d 100644 --- a/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java +++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java @@ -26,10 +26,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; /** - * Tests ArrayUtils remove and removeElement methods. + * Tests {@link ArrayUtils} remove and removeElement methods. */ public class ArrayUtilsRemoveMultipleTest extends AbstractLangTest { + private static final int[] NULL_INDICES = null; + @Test public void testRemoveAllBooleanArray() { boolean[] array; @@ -550,47 +552,110 @@ public class ArrayUtilsRemoveMultipleTest extends AbstractLangTest { @Test public void testRemoveAllNullBooleanArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((boolean[]) null, 0)); + assertNull(ArrayUtils.removeAll((boolean[]) null, 0)); + assertNull(ArrayUtils.removeAll((boolean[]) null, NULL_INDICES)); + final boolean[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final boolean[] array1 = new boolean[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullByteArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((byte[]) null, 0)); + assertNull(ArrayUtils.removeAll((byte[]) null, 0)); + assertNull(ArrayUtils.removeAll((byte[]) null, NULL_INDICES)); + final byte[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final byte[] array1 = new byte[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullCharArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((char[]) null, 0)); + assertNull(ArrayUtils.removeAll((char[]) null, 0)); + assertNull(ArrayUtils.removeAll((char[]) null, NULL_INDICES)); + final char[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final char[] array1 = new char[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullDoubleArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((double[]) null, 0)); + assertNull(ArrayUtils.removeAll((double[]) null, 0)); + assertNull(ArrayUtils.removeAll((double[]) null, NULL_INDICES)); + final double[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final double[] array1 = new double[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullFloatArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((float[]) null, 0)); + assertNull(ArrayUtils.removeAll((float[]) null, 0)); + assertNull(ArrayUtils.removeAll((float[]) null, NULL_INDICES)); + final float[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final float[] array1 = new float[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullIntArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((int[]) null, 0)); + assertNull(ArrayUtils.removeAll((int[]) null, 0)); + assertNull(ArrayUtils.removeAll((int[]) null, NULL_INDICES)); + final int[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final int[] array1 = new int[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullLongArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((long[]) null, 0)); + assertNull(ArrayUtils.removeAll((long[]) null, 0)); + assertNull(ArrayUtils.removeAll((long[]) null, NULL_INDICES)); + final long[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final long[] array1 = new long[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullObjectArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.remove((Object[]) null, 0)); + assertNull(ArrayUtils.removeAll((Object[]) null, 0)); + assertNull(ArrayUtils.removeAll((Object[]) null, NULL_INDICES)); + final Object[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final Object[] array1 = new Object[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test public void testRemoveAllNullShortArray() { - assertThrows(IndexOutOfBoundsException.class, () -> ArrayUtils.removeAll((short[]) null, 0)); + assertNull(ArrayUtils.removeAll((short[]) null, 0)); + assertNull(ArrayUtils.removeAll((short[]) null, NULL_INDICES)); + final short[] array0 = {}; + assertArrayEquals(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + assertNotSame(array0, ArrayUtils.removeAll(array0, NULL_INDICES)); + final short[] array1 = new short[1]; + assertArrayEquals(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); + assertNotSame(array1, ArrayUtils.removeAll(array1, NULL_INDICES)); } @Test @@ -953,34 +1018,34 @@ public class ArrayUtilsRemoveMultipleTest extends AbstractLangTest { assertArrayEquals(new double[]{2, 1}, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements((double[]) null, (double) 1, (double) 2); + array = ArrayUtils.removeElements((double[]) null, 1, 2); assertNull(array); - array = ArrayUtils.removeElements(ArrayUtils.EMPTY_DOUBLE_ARRAY, (double) 1, (double) 2); + array = ArrayUtils.removeElements(ArrayUtils.EMPTY_DOUBLE_ARRAY, 1, 2); assertArrayEquals(ArrayUtils.EMPTY_DOUBLE_ARRAY, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1 }, (double) 1, (double) 2); + array = ArrayUtils.removeElements(new double[] { 1 }, 1, 2); assertArrayEquals(ArrayUtils.EMPTY_DOUBLE_ARRAY, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1, 2 }, (double) 1, (double) 2); + array = ArrayUtils.removeElements(new double[] { 1, 2 }, 1, 2); assertArrayEquals(ArrayUtils.EMPTY_DOUBLE_ARRAY, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1, 2 }, (double) 1, (double) 1); + array = ArrayUtils.removeElements(new double[] { 1, 2 }, 1, 1); assertArrayEquals(new double[]{2}, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, (double) 1, (double) 2); + array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, 1, 2); assertArrayEquals(new double[]{1}, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, (double) 1, (double) 1); + array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, 1, 1); assertArrayEquals(new double[]{2}, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, (double) 1, (double) 1, (double) 1, (double) 1); + array = ArrayUtils.removeElements(new double[] { 1, 2, 1 }, 1, 1, 1, 1); assertArrayEquals(new double[]{2}, array); assertEquals(Double.TYPE, array.getClass().getComponentType()); } @@ -1009,34 +1074,34 @@ public class ArrayUtilsRemoveMultipleTest extends AbstractLangTest { assertArrayEquals(new float[]{2, 1}, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements((float[]) null, (float) 1, (float) 1); + array = ArrayUtils.removeElements((float[]) null, 1, 1); assertNull(array); - array = ArrayUtils.removeElements(ArrayUtils.EMPTY_FLOAT_ARRAY, (float) 1, (float) 1); + array = ArrayUtils.removeElements(ArrayUtils.EMPTY_FLOAT_ARRAY, 1, 1); assertArrayEquals(ArrayUtils.EMPTY_FLOAT_ARRAY, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1 }, (float) 1, (float) 1); + array = ArrayUtils.removeElements(new float[] { 1 }, 1, 1); assertArrayEquals(ArrayUtils.EMPTY_FLOAT_ARRAY, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1, 2 }, (float) 1, (float) 2); + array = ArrayUtils.removeElements(new float[] { 1, 2 }, 1, 2); assertArrayEquals(ArrayUtils.EMPTY_FLOAT_ARRAY, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1, 2 }, (float) 1, (float) 1); + array = ArrayUtils.removeElements(new float[] { 1, 2 }, 1, 1); assertArrayEquals(new float[]{2}, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, (float) 1, (float) 1); + array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, 1, 1); assertArrayEquals(new float[]{2}, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, (float) 1, (float) 2); + array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, 1, 2); assertArrayEquals(new float[]{1}, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); - array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, (float) 1, (float) 1, (float) 1, (float) 1); + array = ArrayUtils.removeElements(new float[] { 1, 2, 1 }, 1, 1, 1, 1); assertArrayEquals(new float[]{2}, array); assertEquals(Float.TYPE, array.getClass().getComponentType()); }