Fail-fast with a NullPointerException if a SubsetConfiguration
constructor is called with a null Configuration
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 7dc01c2..83c218d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -27,6 +27,7 @@
<!-- FIX -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">Fail-fast with a NullPointerException if DataConfiguration.DataConfiguration(Configuration) is called with null.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">Fail-fast with a NullPointerException if XMLPropertiesConfiguration.XMLPropertiesConfiguration(Element) is called with null.</action>
+ <action type="fix" dev="ggregory" due-to="Gary Gregory">Fail-fast with a NullPointerException if a SubsetConfiguration constructor is called with a null Configuration.</action>
</release>
<release version="2.10.1" date="2024-03-17" description="Minor release with new features and updated dependencies; requires Java 8 or above.">
<!-- FIX -->
diff --git a/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java b/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
index fd87053..5bc63db 100644
--- a/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
@@ -18,6 +18,7 @@
package org.apache.commons.configuration2;
import java.util.Iterator;
+import java.util.Objects;
import org.apache.commons.configuration2.convert.ListDelimiterHandler;
import org.apache.commons.lang3.StringUtils;
@@ -59,14 +60,10 @@
* @param parent The parent configuration (must not be <b>null</b>)
* @param prefix The prefix used to select the properties
* @param delimiter The prefix delimiter
- * @throws IllegalArgumentException if the parent configuration is <b>null</b>
+ * @throws NullPointerException if the parent configuration is <b>null</b>
*/
public SubsetConfiguration(final Configuration parent, final String prefix, final String delimiter) {
- if (parent == null) {
- throw new IllegalArgumentException("Parent configuration must not be null!");
- }
-
- this.parent = parent;
+ this.parent = Objects.requireNonNull(parent, "parent");
this.prefix = prefix;
this.delimiter = delimiter;
initInterpolator();
diff --git a/src/test/java/org/apache/commons/configuration2/TestSubsetConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestSubsetConfiguration.java
index 4ba2456..c3a6ba1 100644
--- a/src/test/java/org/apache/commons/configuration2/TestSubsetConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestSubsetConfiguration.java
@@ -60,6 +60,14 @@
assertFalse(config.isEmpty());
}
+ /**
+ * Tries to create an instance without a parent configuration.
+ */
+ @Test
+ public void testConstructNullParent() {
+ assertThrows(NullPointerException.class, () -> new SubsetConfiguration(null, ""));
+ }
+
@Test
public void testGetChildKey() {
final Configuration conf = new BaseConfiguration();
@@ -170,14 +178,6 @@
assertFalse(subset.containsKey("ng.key2"));
}
- /**
- * Tries to create an instance without a parent configuration.
- */
- @Test
- public void testInitNoParent() {
- assertThrows(IllegalArgumentException.class, () -> new SubsetConfiguration(null, ""));
- }
-
@Test
public void testInterpolationForKeysOfTheParent() {
final BaseConfiguration config = new BaseConfiguration();
@@ -243,6 +243,63 @@
assertTrue(keys.isEmpty());
}
+ @Test
+ public void testPrefixDelimiter(){
+ final BaseConfiguration config = new BaseConfiguration();
+ config.setProperty("part1.part2@test.key1", "value1");
+ config.setProperty("part1.part2", "value2");
+ config.setProperty("part3.part4@testing.key2", "value3");
+
+ final SubsetConfiguration subset = new SubsetConfiguration(config, "part1.part2", "@");
+ // Check subset properties
+ assertEquals("value1", subset.getString("test.key1"));
+ assertEquals("value2", subset.getString(""));
+ assertNull(subset.getString("testing.key2"));
+
+ // Check for empty subset configuration and iterator
+ assertEquals(2, subset.size());
+ assertFalse(subset.isEmpty());
+ assertTrue(subset.getKeys().hasNext());
+ }
+
+ @Test
+ public void testPrefixDelimiterNegativeTest(){
+ final BaseConfiguration config = new BaseConfiguration();
+ config.setProperty("part1.part2@test.key1", "value1");
+ config.setProperty("part3.part4@testing.key2", "value2");
+
+ final SubsetConfiguration subset = new SubsetConfiguration(config, "part1.part2", "@") {
+ // Anonymous inner class declaration to override SubsetConfiguration.getKeysInternal() - Call
+ // ImutableConfiguration.getKeys(String) on the parent configuration of the SubsetConfiguration in order to
+ // not consequently pass the prefix delimiter
+ @Override
+ protected Iterator<String> getKeysInternal() {
+ Class<?> subsetIteratorClass;
+ try {
+ subsetIteratorClass = Class
+ .forName("org.apache.commons.configuration2.SubsetConfiguration$SubsetIterator");
+ final Constructor<?> ctor = subsetIteratorClass.getDeclaredConstructor(SubsetConfiguration.class,
+ Iterator.class);
+ ctor.setAccessible(true);
+
+ return (Iterator<String>) ctor.newInstance(this, parent.getKeys("part1.part2"));
+ } catch (final Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+ };
+
+ // Check subset properties - contains one property
+ assertEquals("value1", subset.getString("test.key1"));
+ assertNull(subset.getString("testing.key2"));
+
+ // Check for empty subset configuration and iterator - even if the SubsetConfiguration contains properties, like
+ // checked previously its states that it is empty
+ assertEquals(0, subset.size());
+ assertTrue(subset.isEmpty());
+ assertFalse(subset.getKeys().hasNext());
+ }
+
/**
* Tests whether the list delimiter handler is also set for the parent configuration.
*/
@@ -308,61 +365,4 @@
subset.setThrowExceptionOnMissing(true);
assertThrows(NoSuchElementException.class, () -> config.getString("foo"));
}
-
- @Test
- public void testPrefixDelimiter(){
- final BaseConfiguration config = new BaseConfiguration();
- config.setProperty("part1.part2@test.key1", "value1");
- config.setProperty("part1.part2", "value2");
- config.setProperty("part3.part4@testing.key2", "value3");
-
- final SubsetConfiguration subset = new SubsetConfiguration(config, "part1.part2", "@");
- // Check subset properties
- assertEquals("value1", subset.getString("test.key1"));
- assertEquals("value2", subset.getString(""));
- assertNull(subset.getString("testing.key2"));
-
- // Check for empty subset configuration and iterator
- assertEquals(2, subset.size());
- assertFalse(subset.isEmpty());
- assertTrue(subset.getKeys().hasNext());
- }
-
- @Test
- public void testPrefixDelimiterNegativeTest(){
- final BaseConfiguration config = new BaseConfiguration();
- config.setProperty("part1.part2@test.key1", "value1");
- config.setProperty("part3.part4@testing.key2", "value2");
-
- final SubsetConfiguration subset = new SubsetConfiguration(config, "part1.part2", "@") {
- // Anonymous inner class declaration to override SubsetConfiguration.getKeysInternal() - Call
- // ImutableConfiguration.getKeys(String) on the parent configuration of the SubsetConfiguration in order to
- // not consequently pass the prefix delimiter
- @Override
- protected Iterator<String> getKeysInternal() {
- Class<?> subsetIteratorClass;
- try {
- subsetIteratorClass = Class
- .forName("org.apache.commons.configuration2.SubsetConfiguration$SubsetIterator");
- final Constructor<?> ctor = subsetIteratorClass.getDeclaredConstructor(SubsetConfiguration.class,
- Iterator.class);
- ctor.setAccessible(true);
-
- return (Iterator<String>) ctor.newInstance(this, parent.getKeys("part1.part2"));
- } catch (final Exception ex) {
- throw new IllegalArgumentException(ex);
- }
- }
- };
-
- // Check subset properties - contains one property
- assertEquals("value1", subset.getString("test.key1"));
- assertNull(subset.getString("testing.key2"));
-
- // Check for empty subset configuration and iterator - even if the SubsetConfiguration contains properties, like
- // checked previously its states that it is empty
- assertEquals(0, subset.size());
- assertTrue(subset.isEmpty());
- assertFalse(subset.getKeys().hasNext());
- }
}