Browse Source

BeanWrapper auto-grows arrays if necessary

Previously, only indexed access for collections were supported. When
attempting to access the element of an array that had not the requested
size, the call would fail with an IndexOutOfBoundException

This commit harmonize the binding support so that the array is updated
according to the requested index if necessary.

Issue: SPR-12706
pull/738/head
Stephane Nicoll 11 years ago
parent
commit
aa213396b4
  1. 11
      spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java
  2. 46
      spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java

11
spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -78,6 +78,7 @@ import org.springframework.util.StringUtils; @@ -78,6 +78,7 @@ import org.springframework.util.StringUtils;
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
* @author Stephane Nicoll
* @since 15 April 2001
* @see #registerCustomEditor
* @see #setPropertyValues
@ -978,6 +979,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra @@ -978,6 +979,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
setPropertyValue(actualName, newArray);
propValue = getPropertyValue(actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {

46
spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -518,6 +518,36 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor @@ -518,6 +518,36 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2"));
}
@Test
public void testStringArrayAutoGrow() throws Exception {
StringArrayBean target = new StringArrayBean();
BeanWrapper bw = new BeanWrapperImpl(target);
bw.setAutoGrowNestedPaths(true);
bw.setPropertyValue("array[0]", "Test0");
assertEquals(1, target.getArray().length);
bw.setPropertyValue("array[2]", "Test2");
assertEquals(3, target.getArray().length);
assertTrue("correct values", target.getArray()[0].equals("Test0") && target.getArray()[1] == null &&
target.getArray()[2].equals("Test2"));
}
@Test
public void testPrimitiveArrayAutoGrow() throws Exception {
PrimitiveArrayBean target = new PrimitiveArrayBean();
BeanWrapper bw = new BeanWrapperImpl(target);
bw.setAutoGrowNestedPaths(true);
bw.setPropertyValue("array[0]", 1);
assertEquals(1, target.getArray().length);
bw.setPropertyValue("array[2]", 3);
assertEquals(3, target.getArray().length);
assertTrue("correct values", target.getArray()[0] == 1 && target.getArray()[1] == 0 &&
target.getArray()[2] == 3);
}
@Test
public void testStringPropertyWithCustomEditor() throws Exception {
TestBean tb = new TestBean();
@ -1723,6 +1753,20 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor @@ -1723,6 +1753,20 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
}
}
@SuppressWarnings("unused")
private static class StringArrayBean {
private String[] array;
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
}
@SuppressWarnings("unused")
private static class NumberPropertyBean {

Loading…
Cancel
Save