Repository: tapestry-5 Updated Branches: refs/heads/master 4400d5dd3 -> af6518b97
TAP5-1885: Error in PropertyAccess service TAP5-1548: Property expressions fails when using a supertype that implements an interface with a matching method Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/af6518b9 Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/af6518b9 Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/af6518b9 Branch: refs/heads/master Commit: af6518b97e1ef307e64c1664115d67345a68d274 Parents: 4400d5d Author: Thiago H. de Paula Figueiredo <thiag...@apache.org> Authored: Sat Jun 28 10:37:05 2014 -0300 Committer: Thiago H. de Paula Figueiredo <thiag...@apache.org> Committed: Sat Jun 28 10:37:05 2014 -0300 ---------------------------------------------------------------------- .../services/ClassPropertyAdapterImpl.java | 52 ++++++++++++++++- .../ioc/specs/PropertyAccessImplSpec.groovy | 60 ++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6518b9/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java index 939fa54..c916cd9 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java @@ -48,7 +48,8 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter // Indexed properties will have a null propertyType (and a non-null // indexedPropertyType). We ignore indexed properties. - if (pd.getPropertyType() == null) + final Class<?> thisPropertyType = pd.getPropertyType(); + if (thisPropertyType == null) continue; Method readMethod = pd.getReadMethod(); @@ -63,6 +64,27 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter } readMethod = findMethodWithSameNameAndParamCount(readMethod, nonBridgeMethods); } + + // TAP5-1548, TAP5-1885: trying to find a getter which Introspector missed + if (readMethod == null) { + final String prefix = thisPropertyType != boolean.class ? "get" : "is"; + try + { + Method method = beanType.getMethod(prefix + capitalize(pd.getName())); + final Class<?> returnType = method.getReturnType(); + if (returnType.equals(thisPropertyType) || returnType.isInstance(thisPropertyType)) { + readMethod = method; + } + } + catch (SecurityException e) { + // getter not usable. + } + catch (NoSuchMethodException e) + { + // getter doesn't exist. + } + } + if (writeMethod != null && writeMethod.isBridge()) { if (nonBridgeMethods == null) @@ -71,8 +93,29 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter } writeMethod = findMethodWithSameNameAndParamCount(writeMethod, nonBridgeMethods); } + + // TAP5-1548, TAP5-1885: trying to find a setter which Introspector missed + if (writeMethod == null) { + try + { + Method method = beanType.getMethod("set" + capitalize(pd.getName()), pd.getPropertyType()); + final Class<?> returnType = method.getReturnType(); + if (returnType.equals(void.class)) { + writeMethod = method; + } + } + catch (SecurityException e) { + // setter not usable. + e.printStackTrace(); + } + catch (NoSuchMethodException e) + { + // setter doesn't exist. + e.printStackTrace(); + } + } - Class propertyType = readMethod == null ? pd.getPropertyType() : GenericsUtils.extractGenericReturnType( + Class propertyType = readMethod == null ? thisPropertyType : GenericsUtils.extractGenericReturnType( beanType, readMethod); PropertyAdapter pa = new PropertyAdapterImpl(this, pd.getName(), propertyType, readMethod, writeMethod); @@ -96,6 +139,11 @@ public class ClassPropertyAdapterImpl implements ClassPropertyAdapter } } + private static String capitalize(String name) + { + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + /** * Find a replacement for the method (if one exists) * @param method A method http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6518b9/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy index f0ac187..5e62147 100644 --- a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy +++ b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyAccessImplSpec.groovy @@ -12,6 +12,7 @@ import org.apache.tapestry5.ioc.internal.util.Pair import org.apache.tapestry5.ioc.internal.util.StringLongPair import org.apache.tapestry5.ioc.services.ClassPropertyAdapter import org.apache.tapestry5.ioc.services.PropertyAccess +import org.apache.tapestry5.ioc.internal.PropertyAccessImplClasses import spock.lang.* @@ -709,6 +710,65 @@ class PropertyAccessImplSpec extends Specification { pa.type == String pa.declaringClass == GenericBean } + + interface GetterInterface { + int getValue(); + } + + interface SetterGetterInterface extends GetterInterface { + void setValue(int value); + } + + interface SetterInterface { + void setValue(int value); + } + + interface GetterSetterInterface extends SetterInterface { + int getValue(); + } + + final class GetterSetterClass implements GetterSetterInterface { + public void setValue(int value) {} + public int getValue() {} + } + + // TAP5-1885 + def "split properties (getter in one supertype, setter in another)"() { + + when: + def pa1 = getPropertyAdapter SetterGetterInterface, "value"; + def pa2 = getPropertyAdapter GetterSetterInterface, "value"; + def pa3 = getPropertyAdapter GetterSetterClass, "value"; + + then: + pa1.isRead(); + pa1.isUpdate(); + pa2.isRead(); + pa2.isUpdate(); + pa3.isRead(); + pa3.isUpdate(); + } + + public interface Baz { String getBar(); } + + public class AbstractFoo implements Baz { + private String bar; + public String getBar() { return bar; } + public void setBar(String bar){ this.bar =bar; } + } + + public class Foo extends AbstractFoo {} + + // TAP5-1548 + def "property expressions fails when using a supertype that implements an interface with a matching method"() { + + when: + def pa = getPropertyAdapter AbstractFoo, "bar"; + + then: + pa.isRead(); + pa.isUpdate(); + } def getPropertyAdapter(clazz, name) {