use of org.springframework.expression.spel.SpelEvaluationException in project spring-framework by spring-projects.
the class PropertyOrFieldReference method writeProperty.
private void writeProperty(TypedValue contextObject, EvaluationContext evalContext, String name, Object newValue) throws EvaluationException {
if (contextObject.getValue() == null && this.nullSafe) {
return;
}
PropertyAccessor accessorToUse = this.cachedWriteAccessor;
if (accessorToUse != null) {
try {
accessorToUse.write(evalContext, contextObject.getValue(), name, newValue);
return;
} catch (Exception ex) {
// This is OK - it may have gone stale due to a class change,
// let's try to get a new one and call it before giving up...
this.cachedWriteAccessor = null;
}
}
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
if (accessorsToTry != null) {
try {
for (PropertyAccessor accessor : accessorsToTry) {
if (accessor.canWrite(evalContext, contextObject.getValue(), name)) {
this.cachedWriteAccessor = accessor;
accessor.write(evalContext, contextObject.getValue(), name, newValue);
return;
}
}
} catch (AccessException ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE, name, ex.getMessage());
}
}
if (contextObject.getValue() == null) {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
} else {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
}
}
use of org.springframework.expression.spel.SpelEvaluationException in project spring-framework by spring-projects.
the class PropertyOrFieldReference method getValueInternal.
private TypedValue getValueInternal(TypedValue contextObject, EvaluationContext evalContext, boolean isAutoGrowNullReferences) throws EvaluationException {
TypedValue result = readProperty(contextObject, evalContext, this.name);
// Dynamically create the objects if the user has requested that optional behavior
if (result.getValue() == null && isAutoGrowNullReferences && nextChildIs(Indexer.class, PropertyOrFieldReference.class)) {
TypeDescriptor resultDescriptor = result.getTypeDescriptor();
// Create a new collection or map ready for the indexer
if (List.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
List<?> newList = new ArrayList<>();
writeProperty(contextObject, evalContext, this.name, newList);
result = readProperty(contextObject, evalContext, this.name);
}
} else if (Map.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Map<?, ?> newMap = new HashMap<>();
writeProperty(contextObject, evalContext, this.name, newMap);
result = readProperty(contextObject, evalContext, this.name);
}
} else {
// 'simple' object
try {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Class<?> clazz = result.getTypeDescriptor().getType();
Object newObject = ReflectionUtils.accessibleConstructor(clazz).newInstance();
writeProperty(contextObject, evalContext, this.name, newObject);
result = readProperty(contextObject, evalContext, this.name);
}
} catch (InvocationTargetException ex) {
throw new SpelEvaluationException(getStartPosition(), ex.getTargetException(), SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
} catch (Throwable ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
}
}
}
return result;
}
use of org.springframework.expression.spel.SpelEvaluationException in project spring-framework by spring-projects.
the class ReflectiveMethodResolver method resolve.
/**
* Locate a method on a type. There are three kinds of match that might occur:
* <ol>
* <li>an exact match where the types of the arguments match the types of the constructor
* <li>an in-exact match where the types we are looking for are subtypes of those defined on the constructor
* <li>a match where we are able to convert the arguments into those expected by the constructor,
* according to the registered type converter
* </ol>
*/
@Override
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, List<TypeDescriptor> argumentTypes) throws AccessException {
try {
TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
List<Method> methods = new ArrayList<>(getMethods(type, targetObject));
// If a filter is registered for this type, call it
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
if (filter != null) {
List<Method> filtered = filter.filter(methods);
methods = (filtered instanceof ArrayList ? filtered : new ArrayList<>(filtered));
}
// Sort methods into a sensible order
if (methods.size() > 1) {
Collections.sort(methods, new Comparator<Method>() {
@Override
public int compare(Method m1, Method m2) {
int m1pl = m1.getParameterCount();
int m2pl = m2.getParameterCount();
// varargs methods go last
if (m1pl == m2pl) {
if (!m1.isVarArgs() && m2.isVarArgs()) {
return -1;
} else if (m1.isVarArgs() && !m2.isVarArgs()) {
return 1;
} else {
return 0;
}
}
return (m1pl < m2pl ? -1 : (m1pl > m2pl ? 1 : 0));
}
});
}
// Resolve any bridge methods
for (int i = 0; i < methods.size(); i++) {
methods.set(i, BridgeMethodResolver.findBridgedMethod(methods.get(i)));
}
// Remove duplicate methods (possible due to resolved bridge methods)
Set<Method> methodsToIterate = new LinkedHashSet<>(methods);
Method closeMatch = null;
int closeMatchDistance = Integer.MAX_VALUE;
Method matchRequiringConversion = null;
boolean multipleOptions = false;
for (Method method : methodsToIterate) {
if (method.getName().equals(name)) {
Class<?>[] paramTypes = method.getParameterTypes();
List<TypeDescriptor> paramDescriptors = new ArrayList<>(paramTypes.length);
for (int i = 0; i < paramTypes.length; i++) {
paramDescriptors.add(new TypeDescriptor(new MethodParameter(method, i)));
}
ReflectionHelper.ArgumentsMatchInfo matchInfo = null;
if (method.isVarArgs() && argumentTypes.size() >= (paramTypes.length - 1)) {
// *sigh* complicated
matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter);
} else if (paramTypes.length == argumentTypes.size()) {
// Name and parameter number match, check the arguments
matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter);
}
if (matchInfo != null) {
if (matchInfo.isExactMatch()) {
return new ReflectiveMethodExecutor(method);
} else if (matchInfo.isCloseMatch()) {
if (this.useDistance) {
int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes);
if (closeMatch == null || matchDistance < closeMatchDistance) {
// This is a better match...
closeMatch = method;
closeMatchDistance = matchDistance;
}
} else {
// Take this as a close match if there isn't one already
if (closeMatch == null) {
closeMatch = method;
}
}
} else if (matchInfo.isMatchRequiringConversion()) {
if (matchRequiringConversion != null) {
multipleOptions = true;
}
matchRequiringConversion = method;
}
}
}
}
if (closeMatch != null) {
return new ReflectiveMethodExecutor(closeMatch);
} else if (matchRequiringConversion != null) {
if (multipleOptions) {
throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name);
}
return new ReflectiveMethodExecutor(matchRequiringConversion);
} else {
return null;
}
} catch (EvaluationException ex) {
throw new AccessException("Failed to resolve method", ex);
}
}
use of org.springframework.expression.spel.SpelEvaluationException in project spring-framework by spring-projects.
the class OpInc method getValueInternal.
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
SpelNodeImpl operand = getLeftOperand();
ValueRef valueRef = operand.getValueRef(state);
TypedValue typedValue = valueRef.getValue();
Object value = typedValue.getValue();
TypedValue returnValue = typedValue;
TypedValue newValue = null;
if (value instanceof Number) {
Number op1 = (Number) value;
if (op1 instanceof BigDecimal) {
newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), typedValue.getTypeDescriptor());
} else if (op1 instanceof Double) {
newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
} else if (op1 instanceof Float) {
newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor());
} else if (op1 instanceof BigInteger) {
newValue = new TypedValue(((BigInteger) op1).add(BigInteger.ONE), typedValue.getTypeDescriptor());
} else if (op1 instanceof Long) {
newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor());
} else if (op1 instanceof Integer) {
newValue = new TypedValue(op1.intValue() + 1, typedValue.getTypeDescriptor());
} else if (op1 instanceof Short) {
newValue = new TypedValue(op1.shortValue() + (short) 1, typedValue.getTypeDescriptor());
} else if (op1 instanceof Byte) {
newValue = new TypedValue(op1.byteValue() + (byte) 1, typedValue.getTypeDescriptor());
} else {
// Unknown Number subtype -> best guess is double increment
newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
}
}
if (newValue == null) {
try {
newValue = state.operate(Operation.ADD, returnValue.getValue(), 1);
} catch (SpelEvaluationException ex) {
if (ex.getMessageCode() == SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES) {
// This means the operand is not incrementable
throw new SpelEvaluationException(operand.getStartPosition(), SpelMessage.OPERAND_NOT_INCREMENTABLE, operand.toStringAST());
}
throw ex;
}
}
// set the name value
try {
valueRef.setValue(newValue.getValue());
} catch (SpelEvaluationException see) {
// If unable to set the value the operand is not writable (e.g. 1++ )
if (see.getMessageCode() == SpelMessage.SETVALUE_NOT_SUPPORTED) {
throw new SpelEvaluationException(operand.getStartPosition(), SpelMessage.OPERAND_NOT_INCREMENTABLE);
} else {
throw see;
}
}
if (!this.postfix) {
// The return value is the new value, not the original value
returnValue = newValue;
}
return returnValue;
}
use of org.springframework.expression.spel.SpelEvaluationException in project spring-framework by spring-projects.
the class SpelExpression method getValue.
@SuppressWarnings("unchecked")
@Override
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
if (this.compiledAst != null) {
try {
TypedValue contextRoot = evaluationContext == null ? null : evaluationContext.getRootObject();
Object result = this.compiledAst.getValue(contextRoot == null ? null : contextRoot.getValue(), evaluationContext);
if (expectedResultType == null) {
return (T) result;
} else {
return ExpressionUtils.convertTypedValue(getEvaluationContext(), new TypedValue(result), expectedResultType);
}
} catch (Throwable ex) {
// If running in mixed mode, revert to interpreted
if (this.configuration.getCompilerMode() == SpelCompilerMode.MIXED) {
this.interpretedCount = 0;
this.compiledAst = null;
} else {
// Running in SpelCompilerMode.immediate mode - propagate exception to caller
throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION);
}
}
}
ExpressionState expressionState = new ExpressionState(getEvaluationContext(), this.configuration);
TypedValue typedResultValue = this.ast.getTypedValue(expressionState);
checkCompile(expressionState);
return ExpressionUtils.convertTypedValue(expressionState.getEvaluationContext(), typedResultValue, expectedResultType);
}
Aggregations