|
|
|
@ -186,9 +186,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Class<?> contextObjectClass = getObjectClass(contextObject.getValue()); |
|
|
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), eContext.getPropertyAccessors()); |
|
|
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, eContext.getPropertyAccessors()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
|
|
|
|
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
|
|
|
|
// get the accessor and use it. If they are not cacheable but report they can read the property
|
|
|
|
// get the accessor and use it. If they are not cacheable but report they can read the property
|
|
|
|
// then ask them to read it
|
|
|
|
// then ask them to read it
|
|
|
|
@ -214,7 +212,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl { |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name, |
|
|
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name, |
|
|
|
FormatHelper.formatClassNameForMessage(contextObjectClass)); |
|
|
|
FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue()))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -236,9 +234,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Class<?> contextObjectClass = getObjectClass(contextObject.getValue()); |
|
|
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), eContext.getPropertyAccessors()); |
|
|
|
|
|
|
|
|
|
|
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, eContext.getPropertyAccessors()); |
|
|
|
|
|
|
|
if (accessorsToTry != null) { |
|
|
|
if (accessorsToTry != null) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
for (PropertyAccessor accessor : accessorsToTry) { |
|
|
|
for (PropertyAccessor accessor : accessorsToTry) { |
|
|
|
@ -259,18 +255,16 @@ public class PropertyOrFieldReference extends SpelNodeImpl { |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, |
|
|
|
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, |
|
|
|
FormatHelper.formatClassNameForMessage(contextObjectClass)); |
|
|
|
FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue()))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean isWritableProperty(String name, TypedValue contextObject, EvaluationContext eContext) throws SpelEvaluationException { |
|
|
|
public boolean isWritableProperty(String name, TypedValue contextObject, EvaluationContext eContext) throws SpelEvaluationException { |
|
|
|
Object contextObjectValue = contextObject.getValue(); |
|
|
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), eContext.getPropertyAccessors()); |
|
|
|
// TypeDescriptor td = state.getActiveContextObject().getTypeDescriptor();
|
|
|
|
if (accessorsToTry != null) { |
|
|
|
List<PropertyAccessor> resolversToTry = getPropertyAccessorsToTry(getObjectClass(contextObjectValue), eContext.getPropertyAccessors()); |
|
|
|
for (PropertyAccessor accessor : accessorsToTry) { |
|
|
|
if (resolversToTry != null) { |
|
|
|
|
|
|
|
for (PropertyAccessor pfResolver : resolversToTry) { |
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
if (pfResolver.canWrite(eContext, contextObjectValue, name)) { |
|
|
|
if (accessor.canWrite(eContext, contextObject.getValue(), name)) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -290,27 +284,28 @@ public class PropertyOrFieldReference extends SpelNodeImpl { |
|
|
|
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and |
|
|
|
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and |
|
|
|
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the |
|
|
|
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the |
|
|
|
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors. |
|
|
|
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors. |
|
|
|
* @param targetType the type upon which property access is being attempted |
|
|
|
* @param contextObject the object upon which property access is being attempted |
|
|
|
* @return a list of resolvers that should be tried in order to access the property |
|
|
|
* @return a list of resolvers that should be tried in order to access the property |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private List<PropertyAccessor> getPropertyAccessorsToTry(Class<?> targetType, List<PropertyAccessor> propertyAccessors) { |
|
|
|
private List<PropertyAccessor> getPropertyAccessorsToTry(Object contextObject, List<PropertyAccessor> propertyAccessors) { |
|
|
|
|
|
|
|
Class<?> targetType = (contextObject != null ? contextObject.getClass() : null); |
|
|
|
|
|
|
|
|
|
|
|
List<PropertyAccessor> specificAccessors = new ArrayList<PropertyAccessor>(); |
|
|
|
List<PropertyAccessor> specificAccessors = new ArrayList<PropertyAccessor>(); |
|
|
|
List<PropertyAccessor> generalAccessors = new ArrayList<PropertyAccessor>(); |
|
|
|
List<PropertyAccessor> generalAccessors = new ArrayList<PropertyAccessor>(); |
|
|
|
for (PropertyAccessor resolver : propertyAccessors) { |
|
|
|
for (PropertyAccessor resolver : propertyAccessors) { |
|
|
|
Class<?>[] targets = resolver.getSpecificTargetClasses(); |
|
|
|
Class<?>[] targets = resolver.getSpecificTargetClasses(); |
|
|
|
if (targets == null) { // generic resolver that says it can be used for any type
|
|
|
|
if (targets == null) { |
|
|
|
|
|
|
|
// generic resolver that says it can be used for any type
|
|
|
|
generalAccessors.add(resolver); |
|
|
|
generalAccessors.add(resolver); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else if (targetType != null) { |
|
|
|
if (targetType != null) { |
|
|
|
for (Class<?> clazz : targets) { |
|
|
|
for (Class<?> clazz : targets) { |
|
|
|
if (clazz == targetType) { |
|
|
|
if (clazz == targetType) { |
|
|
|
specificAccessors.add(resolver); |
|
|
|
specificAccessors.add( resolver); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (clazz.isAssignableFrom(targetType)) { |
|
|
|
else if (clazz.isAssignableFrom(targetType)) { |
|
|
|
generalAccessors.add(resolver); |
|
|
|
generalAccessors.add(resolver); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|