Skip to content

Commit c306afe

Browse files
author
Keith Donald
committed
polishing
1 parent c84cccf commit c306afe

File tree

8 files changed

+86
-29
lines changed

8 files changed

+86
-29
lines changed

org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.core.MethodParameter;
3131
import org.springframework.core.convert.ConversionService;
3232
import org.springframework.core.convert.TypeDescriptor;
33+
import org.springframework.core.type.filter.TypeFilter;
3334
import org.springframework.util.ClassUtils;
3435
import org.springframework.util.StringUtils;
3536

@@ -131,7 +132,7 @@ public <T> T convertIfNecessary(String propertyName, Object oldValue, Object new
131132
// No custom editor but custom ConversionService specified?
132133
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
133134
if (editor == null && conversionService != null && convertedValue != null) {
134-
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
135+
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
135136
TypeDescriptor targetTypeDesc = typeDescriptor;
136137
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
137138
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
@@ -458,7 +459,7 @@ protected Collection convertToTypedCollection(
458459
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
459460
return original;
460461
}
461-
462+
typeDescriptor = typeDescriptor.narrow(original);
462463
TypeDescriptor elementType = typeDescriptor.getElementType();
463464
if (elementType == null && originalAllowed &&
464465
!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
@@ -530,7 +531,7 @@ protected Map convertToTypedMap(
530531
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
531532
return original;
532533
}
533-
534+
typeDescriptor = typeDescriptor.narrow(original);
534535
TypeDescriptor keyType = typeDescriptor.getMapKeyType();
535536
TypeDescriptor valueType = typeDescriptor.getMapValueType();
536537
if (keyType == null && valueType == null && originalAllowed &&

org.springframework.beans/src/test/java/org/springframework/beans/factory/support/security/CallbacksSecurityTests.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,21 @@ public void destroy() {
9696
public void setProperty(Object value) {
9797
checkCurrentContext();
9898
}
99-
99+
100100
public Object getProperty() {
101101
checkCurrentContext();
102102
return null;
103103
}
104104

105+
public void setListProperty(Object value) {
106+
checkCurrentContext();
107+
}
108+
109+
public Object getListProperty() {
110+
checkCurrentContext();
111+
return null;
112+
}
113+
105114
private void checkCurrentContext() {
106115
assertEquals(expectedName, getCurrentSubjectName());
107116
}

org.springframework.beans/src/test/java/org/springframework/beans/factory/support/security/callbacks.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@
8282
<entry key-ref="trusted-property-injection" value-ref="trusted-factory-method"/>
8383
</map>
8484
</property>
85+
<property name="listProperty">
86+
<list>
87+
<value>foo</value>
88+
<value>bar</value>
89+
</list>
90+
</property>
8591
</bean>
8692

8793
</beans>

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

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ public static TypeDescriptor nested(Class<?> beanClass, PropertyDescriptor prope
186186
return nested(new BeanPropertyDescriptor(beanClass, property), nestingLevel);
187187
}
188188

189+
/**
190+
* Create a new type descriptor for an object.
191+
* Use this factory method to introspect a source object before asking the conversion system to convert it to some another type.
192+
* If the provided object is null, returns null, else calls {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
193+
* @param object the source object
194+
* @return the type descriptor
195+
*/
189196
public static TypeDescriptor forObject(Object source) {
190197
return source != null ? valueOf(source.getClass()) : null;
191198
}
@@ -206,12 +213,24 @@ public Class<?> getObjectType() {
206213
return ClassUtils.resolvePrimitiveIfNecessary(getType());
207214
}
208215

209-
public TypeDescriptor narrowType(Object value) {
216+
/**
217+
* Narrows this {@link TypeDescriptor} by setting its type to the class of the provided value.
218+
* If the value is null, no narrowing is performed and this TypeDescriptor is returned unchanged.
219+
* Designed to be called by binding frameworks when they read property, field, or method return values.
220+
* Allows such frameworks to narrow a TypeDescriptor built from a declared property, field, or method return value type.
221+
* For example, a field declared as java.lang.Object would be narrowed to java.util.HashMap if it was set to a java.util.HashMap value.
222+
* The narrowed TypeDescriptor can then be used to convert the HashMap to some other type.
223+
* Annotation and nested type context is preserved by the narrowed copy.
224+
* @param value the value to use for narrowing this type descriptor
225+
* @return this TypeDescriptor narrowed (returns a copy with its type updated to the class of the provided value)
226+
*/
227+
public TypeDescriptor narrow(Object value) {
210228
if (value == null) {
211229
return this;
212230
}
213231
return new TypeDescriptor(value.getClass(), elementType, mapKeyType, mapValueType, annotations);
214232
}
233+
215234
/**
216235
* Returns the name of this type: the fully qualified class name.
217236
*/
@@ -292,15 +311,19 @@ public boolean isArray() {
292311
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
293312
*/
294313
public TypeDescriptor getElementType() {
295-
if (!isCollection() && !isArray()) {
296-
throw new IllegalStateException("Not a java.util.Collection or Array");
297-
}
314+
assertCollectionOrArray();
298315
return this.elementType;
299316
}
300317

318+
/**
319+
* Creates a elementType descriptor from the provided collection or array element.
320+
* @param element the collection or array element
321+
* @return the element type descriptor
322+
*/
301323
public TypeDescriptor elementType(Object element) {
324+
assertCollectionOrArray();
302325
if (elementType != null) {
303-
return elementType.narrowType(element);
326+
return elementType.narrow(element);
304327
} else {
305328
return element != null ? new TypeDescriptor(element.getClass(), null, null, null, annotations) : null;
306329
}
@@ -322,15 +345,19 @@ public boolean isMap() {
322345
* @throws IllegalStateException if this type is not a java.util.Map.
323346
*/
324347
public TypeDescriptor getMapKeyType() {
325-
if (!isMap()) {
326-
throw new IllegalStateException("Not a map");
327-
}
348+
assertMap();
328349
return this.mapKeyType;
329350
}
330351

352+
/**
353+
* Creates a mapKeyType descriptor from the provided map key.
354+
* @param mapKey the map key
355+
* @return the map key type descriptor
356+
*/
331357
public TypeDescriptor mapKeyType(Object mapKey) {
358+
assertMap();
332359
if (mapKeyType != null) {
333-
return mapKeyType.narrowType(mapKey);
360+
return mapKeyType.narrow(mapKey);
334361
} else {
335362
return mapKey != null ? new TypeDescriptor(mapKey.getClass(), null, null, null, annotations) : null;
336363
}
@@ -343,15 +370,19 @@ public TypeDescriptor mapKeyType(Object mapKey) {
343370
* @throws IllegalStateException if this type is not a java.util.Map.
344371
*/
345372
public TypeDescriptor getMapValueType() {
346-
if (!isMap()) {
347-
throw new IllegalStateException("Not a map");
348-
}
373+
assertMap();
349374
return this.mapValueType;
350375
}
351376

377+
/**
378+
* Creates a mapValueType descriptor from the provided map value.
379+
* @param mapValue the map value
380+
* @return the map value type descriptor
381+
*/
352382
public TypeDescriptor mapValueType(Object mapValue) {
383+
assertMap();
353384
if (mapValueType != null) {
354-
return mapValueType.narrowType(mapValue);
385+
return mapValueType.narrow(mapValue);
355386
} else {
356387
return mapValue != null ? new TypeDescriptor(mapValue.getClass(), null, null, null, annotations) : null;
357388
}
@@ -481,6 +512,18 @@ private boolean mapValuesAssignable(TypeDescriptor targetValueType) {
481512
return valueType.isAssignableTo(targetValueType);
482513
}
483514

515+
private void assertCollectionOrArray() {
516+
if (!isCollection() && !isArray()) {
517+
throw new IllegalStateException("Not a java.util.Collection or Array");
518+
}
519+
}
520+
521+
private void assertMap() {
522+
if (!isMap()) {
523+
throw new IllegalStateException("Not a java.util.Map");
524+
}
525+
}
526+
484527
private String wildcard(TypeDescriptor nestedType) {
485528
return nestedType != null ? nestedType.toString() : "?";
486529
}

org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private TypedValue executeFunctionJLRMethod(ExpressionState state, Method method
106106
try {
107107
ReflectionUtils.makeAccessible(method);
108108
Object result = method.invoke(method.getClass(), functionArgs);
109-
return new TypedValue(result, new TypeDescriptor(new MethodParameter(method,-1)).narrowType(result));
109+
return new TypedValue(result, new TypeDescriptor(new MethodParameter(method,-1)).narrow(result));
110110
}
111111
catch (Exception ex) {
112112
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.EXCEPTION_DURING_FUNCTION_CALL,

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.springframework.util.Assert;
3131
import org.springframework.util.ClassUtils;
3232
import org.springframework.util.MethodInvoker;
33-
import org.springframework.util.ObjectUtils;
3433

3534
/**
3635
* Utility methods used by the reflection resolver code to discover the appropriate
@@ -219,13 +218,12 @@ else if (typeConverter.canConvert(suppliedArg, expectedArg)) {
219218
// All remaining parameters must be of this type or convertable to this type
220219
for (int i = expectedArgTypes.size() - 1; i < suppliedArgTypes.size(); i++) {
221220
TypeDescriptor suppliedArg = suppliedArgTypes.get(i);
222-
if (!ObjectUtils.nullSafeEquals(varargsParameterType, suppliedArg)) {
223-
if (suppliedArg == null) {
224-
if (varargsParameterType.isPrimitive()) {
225-
match = null;
226-
}
227-
}
228-
else {
221+
if (suppliedArg == null) {
222+
if (varargsParameterType.isPrimitive()) {
223+
match = null;
224+
}
225+
} else {
226+
if (varargsParameterType != suppliedArg.getType()) {
229227
if (ClassUtils.isAssignable(varargsParameterType, suppliedArg.getType())) {
230228
if (match != ArgsMatchKind.REQUIRES_CONVERSION) {
231229
match = ArgsMatchKind.CLOSE;

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public TypedValue execute(EvaluationContext context, Object target, Object... ar
6767
}
6868
ReflectionUtils.makeAccessible(this.method);
6969
Object value = this.method.invoke(target, arguments);
70-
return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.method, -1)).narrowType(value));
70+
return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.method, -1)).narrow(value));
7171
}
7272
catch (Exception ex) {
7373
throw new AccessException("Problem invoking method: " + this.method, ex);

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ public TypedValue read(EvaluationContext context, Object target, String name) th
509509
ReflectionUtils.makeAccessible((Method) member);
510510
}
511511
Object value = ((Method) member).invoke(target);
512-
return new TypedValue(value, typeDescriptor.narrowType(value));
512+
return new TypedValue(value, typeDescriptor.narrow(value));
513513
}
514514
catch (Exception ex) {
515515
throw new AccessException("Unable to access property '" + name + "' through getter", ex);
@@ -521,7 +521,7 @@ public TypedValue read(EvaluationContext context, Object target, String name) th
521521
ReflectionUtils.makeAccessible((Field)member);
522522
}
523523
Object value = ((Field)member).get(target);
524-
return new TypedValue(value, typeDescriptor.narrowType(value));
524+
return new TypedValue(value, typeDescriptor.narrow(value));
525525
}
526526
catch (Exception ex) {
527527
throw new AccessException("Unable to access field: " + name, ex);

0 commit comments

Comments
 (0)