diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java index c086771cbe..ce6ad5123b 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,13 +19,16 @@ package org.springframework.expression.spel.support; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodParameter; import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.AccessException; @@ -37,7 +40,6 @@ import org.springframework.expression.MethodResolver; import org.springframework.expression.TypeConverter; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.SpelMessage; -import org.springframework.util.CollectionUtils; /** * Reflection-based {@link MethodResolver} used by default in @@ -92,25 +94,16 @@ public class ReflectiveMethodResolver implements MethodResolver { try { TypeConverter typeConverter = context.getTypeConverter(); Class type = (targetObject instanceof Class ? (Class) targetObject : targetObject.getClass()); - Method[] methods = getMethods(type, targetObject); + List methods = new ArrayList(Arrays.asList(getMethods(type, targetObject))); // If a filter is registered for this type, call it MethodFilter filter = (this.filters != null ? this.filters.get(type) : null); if (filter != null) { - List methodsForFiltering = new ArrayList(); - for (Method method: methods) { - methodsForFiltering.add(method); - } - List methodsFiltered = filter.filter(methodsForFiltering); - if (CollectionUtils.isEmpty(methodsFiltered)) { - methods = NO_METHODS; - } - else { - methods = methodsFiltered.toArray(new Method[methodsFiltered.size()]); - } + methods = filter.filter(methods); } - Arrays.sort(methods, new Comparator() { + // Sort methods into a sensible order + Collections.sort(methods, new Comparator() { public int compare(Method m1, Method m2) { int m1pl = m1.getParameterTypes().length; int m2pl = m2.getParameterTypes().length; @@ -118,6 +111,14 @@ public class ReflectiveMethodResolver implements MethodResolver { } }); + // Resolve any bridge methods + for (int i = 0; i < methods.size(); i++) { + methods.set(i, BridgeMethodResolver.findBridgedMethod(methods.get(i))); + } + + // Remove duplicate methods (possible due to resolved bridge methods) + methods = new ArrayList(new LinkedHashSet(methods)); + Method closeMatch = null; int closeMatchDistance = Integer.MAX_VALUE; int[] argsToConvert = null; @@ -125,9 +126,6 @@ public class ReflectiveMethodResolver implements MethodResolver { boolean multipleOptions = false; for (Method method : methods) { - if (method.isBridge()) { - continue; - } if (method.getName().equals(name)) { Class[] paramTypes = method.getParameterTypes(); List paramDescriptors = new ArrayList(paramTypes.length); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java index fdf04c7ba8..d84ef3bd99 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -1736,6 +1737,14 @@ public class SpelReproTests extends ExpressionTestCase { assertThat(fromClass, is("interfaceValue")); } + @Test + public void SPR_10210() throws Exception { + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setVariable("bridgeExample", new org.springframework.expression.spel.spr10210.D()); + Expression parseExpression = parser.parseExpression("#bridgeExample.bridgetMethod()"); + parseExpression.getValue(context); + } + public static class BooleanHolder { private Boolean simpleProperty = true; @@ -1796,4 +1805,5 @@ public class SpelReproTests extends ExpressionTestCase { public static class StaticFinalImpl2 extends AbstractStaticFinal { } + } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/A.java b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/A.java new file mode 100644 index 0000000000..9d8d6395ef --- /dev/null +++ b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/A.java @@ -0,0 +1,23 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.expression.spel.spr10210; + +import org.springframework.expression.spel.spr10210.comp.B; +import org.springframework.expression.spel.spr10210.infra.C; + +abstract class A extends B { +} diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/D.java b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/D.java new file mode 100644 index 0000000000..e4776d70e6 --- /dev/null +++ b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/D.java @@ -0,0 +1,20 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.expression.spel.spr10210; + +public class D extends A { +} diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/comp/B.java b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/comp/B.java new file mode 100644 index 0000000000..3250836265 --- /dev/null +++ b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/comp/B.java @@ -0,0 +1,24 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.expression.spel.spr10210.comp; + +import java.io.Serializable; + +import org.springframework.expression.spel.spr10210.infra.C; + +public class B implements Serializable { +} diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/infra/C.java b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/infra/C.java new file mode 100644 index 0000000000..2f0a32e53b --- /dev/null +++ b/spring-expression/src/test/java/org/springframework/expression/spel/spr10210/infra/C.java @@ -0,0 +1,20 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.expression.spel.spr10210.infra; + +public interface C { +}