Skip to content

Commit 3db5a29

Browse files
committed
canConvert checks Collection/Map element types as well (SPR-6564)
1 parent cef44f6 commit 3db5a29

File tree

4 files changed

+155
-8
lines changed

4 files changed

+155
-8
lines changed

org.springframework.context/src/test/java/org/springframework/beans/ResourceTestBean.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
1+
/*
2+
* Copyright 2002-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package org.springframework.beans;
218

319
import java.io.InputStream;
20+
import java.util.Map;
421

522
import org.springframework.core.io.Resource;
623

@@ -14,6 +31,13 @@ public class ResourceTestBean {
1431

1532
private InputStream inputStream;
1633

34+
private Resource[] resourceArray;
35+
36+
private Map<String, Resource> resourceMap;
37+
38+
private Map<String, Resource[]> resourceArrayMap;
39+
40+
1741
public ResourceTestBean() {
1842
}
1943

@@ -22,6 +46,7 @@ public ResourceTestBean(Resource resource, InputStream inputStream) {
2246
this.inputStream = inputStream;
2347
}
2448

49+
2550
public void setResource(Resource resource) {
2651
this.resource = resource;
2752
}
@@ -38,4 +63,28 @@ public InputStream getInputStream() {
3863
return inputStream;
3964
}
4065

66+
public Resource[] getResourceArray() {
67+
return resourceArray;
68+
}
69+
70+
public void setResourceArray(Resource[] resourceArray) {
71+
this.resourceArray = resourceArray;
72+
}
73+
74+
public Map<String, Resource> getResourceMap() {
75+
return resourceMap;
76+
}
77+
78+
public void setResourceMap(Map<String, Resource> resourceMap) {
79+
this.resourceMap = resourceMap;
80+
}
81+
82+
public Map<String, Resource[]> getResourceArrayMap() {
83+
return resourceArrayMap;
84+
}
85+
86+
public void setResourceArrayMap(Map<String, Resource[]> resourceArrayMap) {
87+
this.resourceArrayMap = resourceArrayMap;
88+
}
89+
4190
}

org.springframework.context/src/test/java/org/springframework/context/support/ConversionServiceFactoryBeanTests.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,42 @@
1-
package org.springframework.context.support;
1+
/*
2+
* Copyright 2002-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
216

3-
import static org.junit.Assert.assertTrue;
17+
package org.springframework.context.support;
418

19+
import java.util.Collections;
520
import java.util.HashSet;
621
import java.util.Set;
7-
import java.util.Collections;
822

23+
import static org.junit.Assert.*;
924
import org.junit.Test;
25+
26+
import org.springframework.beans.ResourceTestBean;
27+
import org.springframework.context.ApplicationContext;
1028
import org.springframework.core.convert.ConversionService;
1129
import org.springframework.core.convert.TypeDescriptor;
1230
import org.springframework.core.convert.converter.Converter;
1331
import org.springframework.core.convert.converter.ConverterFactory;
1432
import org.springframework.core.convert.converter.GenericConverter;
33+
import org.springframework.core.io.ClassPathResource;
34+
import org.springframework.core.io.FileSystemResource;
1535

36+
/**
37+
* @author Keith Donald
38+
* @author Juergen Hoeller
39+
*/
1640
public class ConversionServiceFactoryBeanTests {
1741

1842
@Test
@@ -67,15 +91,27 @@ public void createDefaultConversionServiceWithInvalidSupplements() {
6791
factory.afterPropertiesSet();
6892
}
6993

94+
@Test
95+
public void conversionServiceInApplicationContext() {
96+
ApplicationContext ctx = new ClassPathXmlApplicationContext("conversionService.xml", getClass());
97+
ResourceTestBean tb = ctx.getBean("resourceTestBean", ResourceTestBean.class);
98+
assertTrue(tb.getResource() instanceof ClassPathResource);
99+
assertTrue(tb.getResourceArray().length > 1);
100+
assertTrue(tb.getResourceArray()[0] instanceof FileSystemResource);
101+
assertTrue(tb.getResourceMap().size() == 1);
102+
assertTrue(tb.getResourceMap().get("key1") instanceof ClassPathResource);
103+
assertTrue(tb.getResourceArrayMap().size() == 1);
104+
assertTrue(tb.getResourceArrayMap().get("key1").length > 1);
105+
assertTrue(tb.getResourceArrayMap().get("key1")[0] instanceof FileSystemResource);
106+
}
107+
108+
70109
public static class Foo {
71-
72110
}
73111

74112
public static class Bar {
75-
76113
}
77114

78115
public static class Baz {
79-
80116
}
81117
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
3+
4+
<beans>
5+
6+
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
7+
<property name="customEditors">
8+
<map key-type="java.lang.String" value-type="java.lang.Class">
9+
<entry key="org.springframework.core.io.Resource[]" value="org.springframework.core.io.support.ResourceArrayPropertyEditor"/>
10+
</map>
11+
</property>
12+
</bean>
13+
14+
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"/>
15+
16+
<bean id="resourceTestBean" class="org.springframework.beans.ResourceTestBean">
17+
<property name="resource" value="org/springframework/context/support/conversionService.xml"/>
18+
<property name="resourceArray" value="org/springframework/context/support/*.xml"/>
19+
<property name="resourceMap">
20+
<map>
21+
<entry key="key1" value="org/springframework/context/support/conversionService.xml"/>
22+
</map>
23+
</property>
24+
<property name="resourceArrayMap">
25+
<map>
26+
<entry key="key1" value="org/springframework/context/support/*.xml"/>
27+
</map>
28+
</property>
29+
</bean>
30+
31+
</beans>

org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public boolean isMapEntryTypeKnown() {
269269
@SuppressWarnings("unchecked")
270270
public Class<?> getMapKeyType() {
271271
if (this.field != null) {
272-
return GenericCollectionTypeResolver.getMapKeyFieldType(field);
272+
return GenericCollectionTypeResolver.getMapKeyFieldType(this.field);
273273
}
274274
else if (this.methodParameter != null) {
275275
return GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter);
@@ -370,7 +370,38 @@ public Annotation getAnnotation(Class<? extends Annotation> annotationType) {
370370
* @return true if this type is assignable to the target
371371
*/
372372
public boolean isAssignableTo(TypeDescriptor targetType) {
373-
return isTypeAssignableTo(targetType.getType());
373+
Class targetClass = targetType.getType();
374+
if (!isTypeAssignableTo(targetClass)) {
375+
return false;
376+
}
377+
if (targetClass != null) {
378+
if (Collection.class.isAssignableFrom(targetClass)) {
379+
Class<?> elementType = targetType.getCollectionElementType();
380+
if (elementType != null) {
381+
Class<?> sourceElementType = getCollectionElementType();
382+
if (sourceElementType == null || !elementType.isAssignableFrom(sourceElementType)) {
383+
return false;
384+
}
385+
}
386+
}
387+
else if (Map.class.isAssignableFrom(targetClass)) {
388+
Class<?> keyType = targetType.getMapKeyType();
389+
if (keyType != null) {
390+
Class<?> sourceKeyType = getMapKeyType();
391+
if (sourceKeyType == null || !keyType.isAssignableFrom(sourceKeyType)) {
392+
return false;
393+
}
394+
}
395+
Class<?> valueType = targetType.getMapValueType();
396+
if (valueType != null) {
397+
Class<?> sourceValueType = getMapValueType();
398+
if (sourceValueType == null || !valueType.isAssignableFrom(sourceValueType)) {
399+
return false;
400+
}
401+
}
402+
}
403+
}
404+
return true;
374405
}
375406

376407
/**

0 commit comments

Comments
 (0)