diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java index 449ea5a0a00..f966b3b5a11 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -576,7 +576,16 @@ class TypeConverterDelegate { if (methodParam != null) { methodParam.decreaseNestingLevel(); } - convertedCopy.add(convertedElement); + try { + convertedCopy.add(convertedElement); + } + catch (Throwable ex) { + if (logger.isDebugEnabled()) { + logger.debug("Collection type [" + original.getClass().getName() + + "] seems to be read-only - injecting original Collection as-is", ex); + } + return original; + } originalAllowed = originalAllowed && (element == convertedElement); } return (originalAllowed ? original : convertedCopy); @@ -650,7 +659,16 @@ class TypeConverterDelegate { if (methodParam != null) { methodParam.decreaseNestingLevel(); } - convertedCopy.put(convertedKey, convertedValue); + try { + convertedCopy.put(convertedKey, convertedValue); + } + catch (Throwable ex) { + if (logger.isDebugEnabled()) { + logger.debug("Map type [" + original.getClass().getName() + + "] seems to be read-only - injecting original Map as-is", ex); + } + return original; + } originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue); } return (originalAllowed ? original : convertedCopy); diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/BeanWrapperTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/BeanWrapperTests.java index 3ba479a1aa8..ee9b59e510a 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/BeanWrapperTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/BeanWrapperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -16,8 +16,6 @@ package org.springframework.beans; -import static org.junit.Assert.*; - import java.beans.PropertyEditorSupport; import java.math.BigDecimal; import java.math.BigInteger; @@ -38,7 +36,14 @@ import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.logging.LogFactory; +import static org.junit.Assert.*; import org.junit.Test; +import test.beans.BooleanTestBean; +import test.beans.ITestBean; +import test.beans.IndexedTestBean; +import test.beans.NumberTestBean; +import test.beans.TestBean; + import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; @@ -47,12 +52,6 @@ import org.springframework.beans.support.DerivedFromProtectedBaseBean; import org.springframework.util.StopWatch; import org.springframework.util.StringUtils; -import test.beans.BooleanTestBean; -import test.beans.ITestBean; -import test.beans.IndexedTestBean; -import test.beans.NumberTestBean; -import test.beans.TestBean; - /** * @author Rod Johnson * @author Juergen Hoeller @@ -1056,6 +1055,14 @@ public final class BeanWrapperTests { assertFalse(readOnlyMap.isAccessed()); } + @Test + public void testTypedMapReadOnlyMap() { + TypedReadOnlyMap map = new TypedReadOnlyMap(Collections.singletonMap("key", new TestBean())); + TypedReadOnlyMapClient bean = new TypedReadOnlyMapClient(); + BeanWrapper bw = new BeanWrapperImpl(bean); + bw.setPropertyValue("map", map); + } + @Test public void testPrimitiveArray() { PrimitiveArrayBean tb = new PrimitiveArrayBean(); @@ -1717,7 +1724,7 @@ public final class BeanWrapperTests { @SuppressWarnings("serial") - public static class ReadOnlyMap extends HashMap { + public static class ReadOnlyMap extends HashMap { private boolean frozen = false; @@ -1727,12 +1734,12 @@ public final class BeanWrapperTests { this.frozen = true; } - public ReadOnlyMap(Map map) { + public ReadOnlyMap(Map map) { super(map); this.frozen = true; } - public Object put(Object key, Object value) { + public V put(K key, V value) { if (this.frozen) { throw new UnsupportedOperationException(); } @@ -1741,12 +1748,12 @@ public final class BeanWrapperTests { } } - public Set> entrySet() { + public Set> entrySet() { this.accessed = true; return super.entrySet(); } - public Set keySet() { + public Set keySet() { this.accessed = true; return super.keySet(); } @@ -1761,7 +1768,27 @@ public final class BeanWrapperTests { } } + + public static class TypedReadOnlyMap extends ReadOnlyMap { + + public TypedReadOnlyMap() { + } + + public TypedReadOnlyMap(Map map) { + super(map); + } + } + + + public static class TypedReadOnlyMapClient { + + public void setMap(TypedReadOnlyMap map) { + } + } + + public static class EnumConsumer { + private Enum enumValue; public Enum getEnumValue() { @@ -1773,7 +1800,9 @@ public final class BeanWrapperTests { } } + public static class WildcardEnumConsumer { + private Enum enumValue; public Enum getEnumValue() { @@ -1785,7 +1814,9 @@ public final class BeanWrapperTests { } } + public enum TestEnum { + TEST_VALUE }