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 dab61232 Suppress class and declaringClass pseudo-properties in
BeanMap (#412)
dab61232 is described below
commit dab61232c2e39f0c6f9afa90e3148802e3f24ed0
Author: Naveed Khan <[email protected]>
AuthorDate: Sat Jul 11 12:35:04 2026 +0000
Suppress class and declaringClass pseudo-properties in BeanMap (#412)
* suppress class and declaringClass properties in BeanMap
BeanMap.initialize introspected the bean directly and registered the
class/declaringClass pseudo-properties, so BeanMap.get("class") returned
the bean's class loader that PropertyUtilsBean suppresses by default. Skip
both names during initialization.
* use imported DayOfWeek instead of fully-qualified name in test
---
.../org/apache/commons/beanutils2/BeanMap.java | 5 ++++
.../org/apache/commons/beanutils2/BeanMapTest.java | 31 +++++++++++++++++-----
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/src/main/java/org/apache/commons/beanutils2/BeanMap.java
b/src/main/java/org/apache/commons/beanutils2/BeanMap.java
index 927573c2..4c0d2cd3 100644
--- a/src/main/java/org/apache/commons/beanutils2/BeanMap.java
+++ b/src/main/java/org/apache/commons/beanutils2/BeanMap.java
@@ -479,6 +479,11 @@ public class BeanMap extends AbstractMap<String, Object>
implements Cloneable {
for (final PropertyDescriptor propertyDescriptor :
propertyDescriptors) {
if (propertyDescriptor != null) {
final String name = propertyDescriptor.getName();
+ if ("class".equals(name) ||
"declaringClass".equals(name)) {
+ // These pseudo-properties expose the bean's
ClassLoader; skip them to match the
+ // suppression PropertyUtilsBean applies by
default (see SuppressPropertiesBeanIntrospector).
+ continue;
+ }
final Method readMethod =
propertyDescriptor.getReadMethod();
final Method writeMethod =
propertyDescriptor.getWriteMethod();
final Class<?> aType =
propertyDescriptor.getPropertyType();
diff --git a/src/test/java/org/apache/commons/beanutils2/BeanMapTest.java
b/src/test/java/org/apache/commons/beanutils2/BeanMapTest.java
index 6604cfe1..33f5f706 100644
--- a/src/test/java/org/apache/commons/beanutils2/BeanMapTest.java
+++ b/src/test/java/org/apache/commons/beanutils2/BeanMapTest.java
@@ -17,13 +17,16 @@
package org.apache.commons.beanutils2;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.time.DayOfWeek;
import java.util.Map;
import java.util.function.Function;
@@ -176,7 +179,7 @@ class BeanMapTest extends AbstractMapTest<BeanMap, String,
Object> {
@Override
public Object[] getNewSampleValues() {
final Object[] values = { Integer.valueOf(223),
Long.valueOf(23341928234L), Double.valueOf(23423.34), Float.valueOf(213332.12f),
- Short.valueOf((short) 234), Byte.valueOf((byte) 20),
Character.valueOf('b'), Integer.valueOf(232), "SomeNewStringValue", new
Object(), null, };
+ Short.valueOf((short) 234), Byte.valueOf((byte) 20),
Character.valueOf('b'), Integer.valueOf(232), "SomeNewStringValue", new
Object(), };
return values;
}
@@ -188,12 +191,12 @@ class BeanMapTest extends AbstractMapTest<BeanMap,
String, Object> {
// To:
// "some\2Value",
//
- // Then, I manually added the "class" key, which is a property that exists
for
- // all beans (and all objects for that matter.
+ // The "class" pseudo-property is intentionally absent: it is suppressed
so the bean's
+ // ClassLoader is not reachable through the map.
@Override
public String[] getSampleKeys() {
final String[] keys = { "someIntValue", "someLongValue",
"someDoubleValue", "someFloatValue", "someShortValue", "someByteValue",
"someCharValue",
- "someIntegerValue", "someStringValue", "someObjectValue",
"class", };
+ "someIntegerValue", "someStringValue", "someObjectValue", };
return keys;
}
@@ -201,8 +204,7 @@ class BeanMapTest extends AbstractMapTest<BeanMap, String,
Object> {
@Override
public Object[] getSampleValues() {
final Object[] values = { Integer.valueOf(1234),
Long.valueOf(1298341928234L), Double.valueOf(123423.34),
Float.valueOf(1213332.12f),
- Short.valueOf((short) 134), Byte.valueOf((byte) 10),
Character.valueOf('a'), Integer.valueOf(1432), "SomeStringValue",
objectInFullMap,
- BeanWithProperties.class, };
+ Short.valueOf((short) 134), Byte.valueOf((byte) 10),
Character.valueOf('a'), Integer.valueOf(1432), "SomeStringValue",
objectInFullMap, };
return values;
}
@@ -283,6 +285,23 @@ class BeanMapTest extends AbstractMapTest<BeanMap, String,
Object> {
}
}
+ /**
+ * The {@code class} and (for enums) {@code declaringClass}
pseudo-properties expose the bean's {@link ClassLoader} and must not be
reachable through the map,
+ * matching the suppression {@link PropertyUtilsBean} applies by default.
+ */
+ @Test
+ void testClassPropertyNotExposed() {
+ final BeanMap map = new BeanMap(new BeanWithProperties());
+ assertFalse(map.containsKey("class"), "class must not be exposed as a
property");
+ assertNull(map.get("class"));
+ assertNull(map.getReadMethod("class"));
+
+ final BeanMap enumMap = new BeanMap(DayOfWeek.MONDAY);
+ assertFalse(enumMap.containsKey("class"), "class must not be exposed
as a property");
+ assertFalse(enumMap.containsKey("declaringClass"), "declaringClass
must not be exposed as a property");
+ assertNull(enumMap.get("declaringClass"));
+ }
+
@Test
void testBeanMapPutAllWriteable() {
final BeanMap map1 = (BeanMap) makeFullMap();