diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index 4258aa896e..ed5c8e1205 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -209,37 +209,37 @@ class ExtendedBeanInfo implements BeanInfo { @Override public BeanInfo[] getAdditionalBeanInfo() { - return delegate.getAdditionalBeanInfo(); + return this.delegate.getAdditionalBeanInfo(); } @Override public BeanDescriptor getBeanDescriptor() { - return delegate.getBeanDescriptor(); + return this.delegate.getBeanDescriptor(); } @Override public int getDefaultEventIndex() { - return delegate.getDefaultEventIndex(); + return this.delegate.getDefaultEventIndex(); } @Override public int getDefaultPropertyIndex() { - return delegate.getDefaultPropertyIndex(); + return this.delegate.getDefaultPropertyIndex(); } @Override public EventSetDescriptor[] getEventSetDescriptors() { - return delegate.getEventSetDescriptors(); + return this.delegate.getEventSetDescriptors(); } @Override public Image getIcon(int iconKind) { - return delegate.getIcon(iconKind); + return this.delegate.getIcon(iconKind); } @Override public MethodDescriptor[] getMethodDescriptors() { - return delegate.getMethodDescriptors(); + return this.delegate.getMethodDescriptors(); } } @@ -293,7 +293,7 @@ class SimplePropertyDescriptor extends PropertyDescriptor { this.propertyType = findPropertyType(this.readMethod, this.writeMethod); } catch (IntrospectionException ex) { - // ignore, as does PropertyDescriptor#getPropertyType + // Ignore, as does PropertyDescriptor#getPropertyType } } return this.propertyType; @@ -383,7 +383,7 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor { this.propertyType = findPropertyType(this.readMethod, this.writeMethod); } catch (IntrospectionException ex) { - // ignore, as does IndexedPropertyDescriptor#getPropertyType + // Ignore, as does IndexedPropertyDescriptor#getPropertyType } } return this.propertyType; @@ -417,7 +417,7 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor { getName(), getPropertyType(), this.indexedReadMethod, this.indexedWriteMethod); } catch (IntrospectionException ex) { - // ignore, as does IndexedPropertyDescriptor#getIndexedPropertyType + // Ignore, as does IndexedPropertyDescriptor#getIndexedPropertyType } } return this.indexedPropertyType; @@ -482,14 +482,14 @@ class PropertyDescriptorUtils { target.setShortDescription(source.getShortDescription()); target.setDisplayName(source.getDisplayName()); - // copy all attributes (emulating behavior of private FeatureDescriptor#addTable) + // Copy all attributes (emulating behavior of private FeatureDescriptor#addTable) Enumeration keys = source.attributeNames(); while (keys.hasMoreElements()) { String key = keys.nextElement(); target.setValue(key, source.getValue(key)); } - // see java.beans.PropertyDescriptor#PropertyDescriptor(PropertyDescriptor) + // See java.beans.PropertyDescriptor#PropertyDescriptor(PropertyDescriptor) target.setPropertyEditorClass(source.getPropertyEditorClass()); target.setBound(source.isBound()); target.setConstrained(source.isConstrained()); @@ -503,24 +503,34 @@ class PropertyDescriptorUtils { if (readMethod != null) { Class[] params = readMethod.getParameterTypes(); if (params.length != 0) { - throw new IntrospectionException("bad read method arg count: " + readMethod); + throw new IntrospectionException("Bad read method arg count: " + readMethod); } propertyType = readMethod.getReturnType(); if (propertyType == Void.TYPE) { - throw new IntrospectionException("read method " - + readMethod.getName() + " returns void"); + throw new IntrospectionException("Read method returns void: " + readMethod); } } if (writeMethod != null) { Class params[] = writeMethod.getParameterTypes(); if (params.length != 1) { - throw new IntrospectionException("bad write method arg count: " + writeMethod); + throw new IntrospectionException("Bad write method arg count: " + writeMethod); } - if (propertyType != null - && !params[0].isAssignableFrom(propertyType)) { - throw new IntrospectionException("type mismatch between read and write methods"); + if (propertyType != null) { + if (propertyType.isAssignableFrom(params[0])) { + // Write method's property type potentially more specific + propertyType = params[0]; + } + else if (params[0].isAssignableFrom(propertyType)) { + // Proceed with read method's property type + } + else { + throw new IntrospectionException( + "Type mismatch between read and write methods: " + readMethod + " - " + writeMethod); + } + } + else { + propertyType = params[0]; } - propertyType = params[0]; } return propertyType; } @@ -532,44 +542,48 @@ class PropertyDescriptorUtils { Method indexedReadMethod, Method indexedWriteMethod) throws IntrospectionException { Class indexedPropertyType = null; - if (indexedReadMethod != null) { Class params[] = indexedReadMethod.getParameterTypes(); if (params.length != 1) { - throw new IntrospectionException( - "bad indexed read method arg count"); + throw new IntrospectionException("Bad indexed read method arg count: " + indexedReadMethod); } if (params[0] != Integer.TYPE) { - throw new IntrospectionException( - "non int index to indexed read method"); + throw new IntrospectionException("Non int index to indexed read method: " + indexedReadMethod); } indexedPropertyType = indexedReadMethod.getReturnType(); if (indexedPropertyType == Void.TYPE) { - throw new IntrospectionException( - "indexed read method returns void"); + throw new IntrospectionException("Indexed read method returns void: " + indexedReadMethod); } } if (indexedWriteMethod != null) { Class params[] = indexedWriteMethod.getParameterTypes(); if (params.length != 2) { - throw new IntrospectionException( - "bad indexed write method arg count"); + throw new IntrospectionException("Bad indexed write method arg count: " + indexedWriteMethod); } if (params[0] != Integer.TYPE) { - throw new IntrospectionException( - "non int index to indexed write method"); + throw new IntrospectionException("Non int index to indexed write method: " + indexedWriteMethod); } - if (indexedPropertyType != null && indexedPropertyType != params[1]) { - throw new IntrospectionException( - "type mismatch between indexed read and indexed write methods: " + name); + if (indexedPropertyType != null) { + if (indexedPropertyType.isAssignableFrom(params[1])) { + // Write method's property type potentially more specific + indexedPropertyType = params[1]; + } + else if (params[1].isAssignableFrom(indexedPropertyType)) { + // Proceed with read method's property type + } + else { + throw new IntrospectionException("Type mismatch between indexed read and write methods: " + + indexedReadMethod + " - " + indexedWriteMethod); + } + } + else { + indexedPropertyType = params[1]; } - indexedPropertyType = params[1]; } - if (propertyType != null - && (!propertyType.isArray() || - propertyType.getComponentType() != indexedPropertyType)) { - throw new IntrospectionException( - "type mismatch between indexed and non-indexed methods: " + name); + if (propertyType != null && (!propertyType.isArray() || + propertyType.getComponentType() != indexedPropertyType)) { + throw new IntrospectionException("Type mismatch between indexed and non-indexed methods: " + + indexedReadMethod + " - " + indexedWriteMethod); } return indexedPropertyType; } @@ -590,15 +604,12 @@ class PropertyDescriptorUtils { if (!compareMethods(pd1.getReadMethod(), pd2.getReadMethod())) { return false; } - if (!compareMethods(pd1.getWriteMethod(), pd2.getWriteMethod())) { return false; } - - if (pd1.getPropertyType() == pd2.getPropertyType() - && pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() - && pd1.isBound() == pd2.isBound() - && pd1.isConstrained() == pd2.isConstrained()) { + if (pd1.getPropertyType() == pd2.getPropertyType() && + pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() && + pd1.isBound() == pd2.isBound() && pd1.isConstrained() == pd2.isConstrained()) { return true; } } @@ -612,7 +623,7 @@ class PropertyDescriptorUtils { if ((a == null) != (b == null)) { return false; } - if (a != null && b != null) { + if (a != null) { if (!a.equals(b)) { return false; } diff --git a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java index de7f35f099..c8216c2b51 100644 --- a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java @@ -323,10 +323,8 @@ public class ExtendedBeanInfoTests { BeanInfo ebi = new ExtendedBeanInfo(bi); assertThat(hasReadMethodForProperty(bi, "foo"), is(true)); - assertThat(hasWriteMethodForProperty(bi, "foo"), is(false)); - assertThat(hasReadMethodForProperty(ebi, "foo"), is(true)); - assertThat(hasWriteMethodForProperty(ebi, "foo"), is(false)); + assertEquals(hasWriteMethodForProperty(bi, "foo"), hasWriteMethodForProperty(ebi, "foo")); } @Test @@ -340,10 +338,8 @@ public class ExtendedBeanInfoTests { BeanInfo ebi = new ExtendedBeanInfo(bi); assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true)); - assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(false)); - assertThat(hasIndexedReadMethodForProperty(ebi, "foos"), is(true)); - assertThat(hasIndexedWriteMethodForProperty(ebi, "foos"), is(false)); + assertEquals(hasIndexedWriteMethodForProperty(bi, "foos"), hasIndexedWriteMethodForProperty(ebi, "foos")); } /**