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-beanutils.git
The following commit(s) were added to refs/heads/master by this push:
new ad69d00c Suppress case variants of mapped names in
isPropertySuppressed (#431)
ad69d00c is described below
commit ad69d00cec1637729c9d03950af25a27d9747565
Author: Naveed Khan <[email protected]>
AuthorDate: Thu Jul 30 11:03:47 2026 +0000
Suppress case variants of mapped names in isPropertySuppressed (#431)
* suppress case variants of mapped names in isPropertySuppressed
The check compared the raw expression token, while the mapped-descriptor
fallback it guards derives its accessor names from the capitalized property
name, so a name differing only in the case of its first character resolved the
same accessors and was still readable and writable.
* skip null suppressed names in isPropertySuppressed
SuppressPropertiesBeanIntrospector only rejects a null collection, so the
suppressed set can hold null entries. Capitalizing them threw a
NullPointerException where the previous Set.contains just never matched.
---
.../beanutils2/MappedPropertyDescriptor.java | 2 +-
.../commons/beanutils2/PropertyUtilsBean.java | 12 ++++++---
.../commons/beanutils2/PropertyUtilsTest.java | 31 ++++++++++++++++++++++
3 files changed, 41 insertions(+), 4 deletions(-)
diff --git
a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
index 21d69d46..9a5b07e4 100644
--- a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
+++ b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
@@ -162,7 +162,7 @@ public class MappedPropertyDescriptor extends
PropertyDescriptor {
*
* @param s The property name
*/
- private static String capitalizePropertyName(final String s) {
+ static String capitalizePropertyName(final String s) {
if (s.isEmpty()) {
return s;
}
diff --git a/src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java
b/src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java
index be0f3066..36c653f0 100644
--- a/src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java
+++ b/src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java
@@ -1068,15 +1068,21 @@ public class PropertyUtilsBean {
/**
* Tests whether a property name has been removed by a registered {@link
SuppressPropertiesBeanIntrospector}. The mapped-descriptor fallback in
* {@link #getPropertyDescriptor(Object, String)} bypasses the
introspection pipeline, so suppressed mapped property names must be filtered
explicitly.
+ * {@link MappedPropertyDescriptor} derives its accessor names from the
capitalized property name, so names differing only in the case of their first
+ * character resolve the same accessors and are compared on that
capitalized form here.
*
* @param name The property name to test.
* @return {@code true} if the name is suppressed by an introspector.
*/
private boolean isPropertySuppressed(final String name) {
+ final String base =
MappedPropertyDescriptor.capitalizePropertyName(name);
for (final BeanIntrospector introspector : introspectors) {
- if (introspector instanceof SuppressPropertiesBeanIntrospector
- && ((SuppressPropertiesBeanIntrospector)
introspector).getSuppressedProperties().contains(name)) {
- return true;
+ if (introspector instanceof SuppressPropertiesBeanIntrospector) {
+ for (final String suppressed :
((SuppressPropertiesBeanIntrospector) introspector).getSuppressedProperties()) {
+ if (suppressed != null &&
base.equals(MappedPropertyDescriptor.capitalizePropertyName(suppressed))) {
+ return true;
+ }
+ }
}
}
return false;
diff --git a/src/test/java/org/apache/commons/beanutils2/PropertyUtilsTest.java
b/src/test/java/org/apache/commons/beanutils2/PropertyUtilsTest.java
index 68338950..8e10a0ec 100644
--- a/src/test/java/org/apache/commons/beanutils2/PropertyUtilsTest.java
+++ b/src/test/java/org/apache/commons/beanutils2/PropertyUtilsTest.java
@@ -315,6 +315,37 @@ class PropertyUtilsTest {
assertEquals("First Value", unsuppressed.getProperty(bean,
"mappedProperty(First Key)"), "Mapped property should be readable when not
suppressed");
}
+ /**
+ * {@link MappedPropertyDescriptor} capitalizes the first character of the
property name to build the accessor names, so {@code MappedProperty(key)}
+ * resolves the same {@code getMappedProperty}/{@code setMappedProperty}
pair as {@code mappedProperty(key)} and must be suppressed with it.
+ */
+ @Test
+ void testCustomIntrospectionSuppressedMappedPropertyCaseVariant() throws
Exception {
+ final PropertyUtilsBean pub = new PropertyUtilsBean();
+ pub.addBeanIntrospector(new
SuppressPropertiesBeanIntrospector(Arrays.asList("mappedProperty")));
+
+ assertNull(pub.getPropertyDescriptor(bean, "MappedProperty"), "Case
variant of a suppressed mapped property should have no descriptor");
+ assertThrows(NoSuchMethodException.class, () -> pub.getProperty(bean,
"MappedProperty(First Key)"),
+ "Case variant of a suppressed mapped property must not be
readable");
+ assertThrows(NoSuchMethodException.class, () -> pub.setProperty(bean,
"MappedProperty(First Key)", "changed"),
+ "Case variant of a suppressed mapped property must not be
writable");
+ assertEquals("First Value", bean.getMappedProperty("First Key"),
"Suppressed mapped property must be unchanged");
+ }
+
+ /**
+ * {@link SuppressPropertiesBeanIntrospector} only rejects a null
collection, so the set of suppressed names may hold null entries. Those must be
skipped
+ * rather than capitalized when the mapped-descriptor fallback is checked.
+ */
+ @Test
+ void testCustomIntrospectionSuppressedMappedPropertyNullEntry() throws
Exception {
+ final PropertyUtilsBean pub = new PropertyUtilsBean();
+ pub.addBeanIntrospector(new
SuppressPropertiesBeanIntrospector(Arrays.asList(null, "mappedProperty")));
+
+ assertNull(pub.getPropertyDescriptor(bean, "MappedProperty"), "Case
variant of a suppressed mapped property should have no descriptor");
+ assertNull(pub.getPropertyDescriptor(bean, "mappedProperty"),
"Suppressed mapped property should have no descriptor");
+ assertNotNull(pub.getPropertyDescriptor(bean, "stringProperty"), "A
null suppressed entry must not hide unrelated properties");
+ }
+
/**
* Test the describe() method.
*/