Skip to content

Commit 85b0bff

Browse files
author
Phillip Webb
committed
Only consider "is" methods with boolean returns
Fix regression introduced in b25e91a where ReflectivePropertyAccessor does not consider the return type for "is" getters. Issue: SPR-11142
1 parent 8f56926 commit 85b0bff

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
import java.lang.reflect.Method;
2323
import java.lang.reflect.Modifier;
2424
import java.util.Arrays;
25+
import java.util.Collections;
2526
import java.util.Comparator;
27+
import java.util.HashSet;
2628
import java.util.Map;
29+
import java.util.Set;
2730
import java.util.concurrent.ConcurrentHashMap;
2831

2932
import org.springframework.core.MethodParameter;
@@ -50,6 +53,17 @@
5053
*/
5154
public class ReflectivePropertyAccessor implements PropertyAccessor {
5255

56+
private static final Set<Class<?>> BOOLEAN_TYPES;
57+
static {
58+
Set<Class<?>> booleanTypes = new HashSet<Class<?>>();
59+
booleanTypes.add(Boolean.class);
60+
booleanTypes.add(Boolean.TYPE);
61+
BOOLEAN_TYPES = Collections.unmodifiableSet(booleanTypes);
62+
}
63+
64+
private static final Set<Class<?>> ANY_TYPES = Collections.emptySet();
65+
66+
5367
private final Map<CacheKey, InvokerPair> readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>(64);
5468

5569
private final Map<CacheKey, Member> writerCache = new ConcurrentHashMap<CacheKey, Member>(64);
@@ -319,29 +333,33 @@ private Field findField(String name, Class<?> clazz, Object target) {
319333
* Find a getter method for the specified property.
320334
*/
321335
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
322-
return findMethodForProperty(getPropertyMethodSuffixes(propertyName),
323-
new String[] { "get", "is" }, clazz, mustBeStatic, 0);
336+
Method method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
337+
"get", clazz, mustBeStatic, 0, ANY_TYPES);
338+
if (method == null) {
339+
method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
340+
"is", clazz, mustBeStatic, 0, BOOLEAN_TYPES);
341+
}
342+
return method;
324343
}
325344

326345
/**
327346
* Find a setter method for the specified property.
328347
*/
329348
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
330349
return findMethodForProperty(getPropertyMethodSuffixes(propertyName),
331-
new String[] { "set" }, clazz, mustBeStatic, 1);
350+
"set", clazz, mustBeStatic, 1, ANY_TYPES);
332351
}
333352

334-
private Method findMethodForProperty(String[] methodSuffixes, String[] prefixes, Class<?> clazz,
335-
boolean mustBeStatic, int numberOfParams) {
353+
private Method findMethodForProperty(String[] methodSuffixes, String prefix, Class<?> clazz,
354+
boolean mustBeStatic, int numberOfParams, Set<Class<?>> requiredReturnTypes) {
336355
Method[] methods = getSortedClassMethods(clazz);
337356
for (String methodSuffix : methodSuffixes) {
338-
for (String prefix : prefixes) {
339-
for (Method method : methods) {
340-
if (method.getName().equals(prefix + methodSuffix)
341-
&& method.getParameterTypes().length == numberOfParams
342-
&& (!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
343-
return method;
344-
}
357+
for (Method method : methods) {
358+
if (method.getName().equals(prefix + methodSuffix)
359+
&& method.getParameterTypes().length == numberOfParams
360+
&& (!mustBeStatic || Modifier.isStatic(method.getModifiers()))
361+
&& (requiredReturnTypes.isEmpty() || requiredReturnTypes.contains(method.getReturnType()))) {
362+
return method;
345363
}
346364
}
347365
}

spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,17 @@ public void testOperatorEq_SPR9194() {
18521852
assertTrue(classNameExpression.getValue(map,Boolean.class));
18531853
}
18541854

1855+
@Test
1856+
public void SPR_11142() throws Exception {
1857+
SpelExpressionParser parser = new SpelExpressionParser();
1858+
StandardEvaluationContext context = new StandardEvaluationContext();
1859+
SPR11142 rootObject = new SPR11142();
1860+
Expression expression = parser.parseExpression("something");
1861+
thrown.expect(SpelEvaluationException.class);
1862+
thrown.expectMessage("property 'something' cannot be found");
1863+
expression.getValue(context, rootObject);
1864+
}
1865+
18551866

18561867
private static enum ABC {A, B, C}
18571868

@@ -1956,4 +1967,12 @@ public boolean equals(Object o) {
19561967
}
19571968

19581969
}
1970+
1971+
static class SPR11142 {
1972+
1973+
public String isSomething() {
1974+
return "";
1975+
}
1976+
1977+
}
19591978
}

0 commit comments

Comments
 (0)