Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Objects;

import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -56,7 +57,7 @@
* <p>
* This class is more tolerant with regards to the return type of a set method. It basically iterates over all methods of a class and filters them for a
* configurable prefix (the default prefix is {@code set}). It then generates corresponding {@code PropertyDescriptor} objects for the methods found which use
* these methods as write methods.
* these methods as write methods. Static methods are ignored, as they are by default ignored in introspection.
* </p>
* <p>
* An instance of this class is intended to collaborate with a {@link DefaultBeanIntrospector} object. So best results are achieved by adding this instance as
Expand Down Expand Up @@ -128,6 +129,10 @@ public String getWriteMethodPrefix() {
@Override
public void introspect(final IntrospectionContext icontext) throws IntrospectionException {
for (final Method m : icontext.getTargetClass().getMethods()) {
// Static methods are not property accessors; default introspection skips them as well.
if (Modifier.isStatic(m.getModifiers())) {
continue;
}
if (m.getName().startsWith(getWriteMethodPrefix())) {
final String propertyName = propertyName(m);
final PropertyDescriptor pd = icontext.getPropertyDescriptor(propertyName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ private static Method getMethod(final Class<?> clazz, final String methodName, f
}

final Method method = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, parameterTypes);
if (method != null) {
// skip static methods, as internalGetMethod does.
if (method != null && !Modifier.isStatic(method.getModifiers())) {
return method;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.commons.beanutils2;

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.assertThrows;
Expand Down Expand Up @@ -45,6 +46,23 @@ public void setURI(final URI theURI) {
}
}

public static final class StaticSetterBean {
private static String staticValue;

public static void setStaticOnly(final String value) {
staticValue = value;
}

public static StaticSetterBean setStaticProperty(final String value) {
staticValue = value;
return new StaticSetterBean();
}

public String getStaticProperty() {
return staticValue;
}
}

/**
* Puts all property descriptors into a map so that they can be accessed by property name.
*
Expand Down Expand Up @@ -119,4 +137,19 @@ void testIntrospectionCaps() throws Exception {

assertNull(props.get("uRI"), "Should not find mis-capitalized property");
}

/**
* Tests that static methods are not treated as write methods.
*/
@Test
void testIntrospectionStaticMethods() throws Exception {
final PropertyUtilsBean pu = new PropertyUtilsBean();
pu.addBeanIntrospector(new FluentPropertyBeanIntrospector());
final Map<String, PropertyDescriptor> props = createDescriptorMap(pu.getPropertyDescriptors(StaticSetterBean.class));
assertNull(props.get("staticOnly"), "Property created from static method");
final PropertyDescriptor pd = fetchDescriptor(props, "staticProperty");
assertNotNull(pd.getReadMethod(), "No read method for staticProperty");
assertNull(pd.getWriteMethod(), "Static method used as write method");
assertFalse(pu.isWriteable(new StaticSetterBean(), "staticProperty"), "staticProperty is writeable");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,16 @@ void testProtected() {
assertThrows(IntrospectionException.class, () -> new MappedPropertyDescriptor(property, clazz));
}

/**
* Test static mapped accessors are ignored
*/
@Test
void testStaticMapped() {
final String property = "staticMapped";
final Class<?> clazz = MappedPropertyTestBean.class;
assertThrows(IntrospectionException.class, () -> new MappedPropertyDescriptor(property, clazz));
}

/**
* Test 'protected' method in parent
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ public class MappedPropertyTestBean {
private final Map<Object, Object> map = new HashMap<>();
private final Map<Object, Object> myMap = new HashMap<>();

public static String getStaticMapped(final String key) {
return "static-" + key;
}

public static void setStaticMapped(final String key, final String value) {
// empty
}

public Long getDifferentTypes(final String key) {
return Long.valueOf(((Number) map.get(key)).longValue());
}
Expand Down
Loading