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();

Reply via email to