Browse Source

SpelExpression consistently exposes EvaluationContext to compiled AST

Operator includes explicit support for Boolean comparisons now.

Issue: SPR-17229

(cherry picked from commit 51cee658d5)
pull/1998/head
Juergen Hoeller 7 years ago
parent
commit
e332e32a88
  1. 35
      spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java
  2. 26
      spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java

35
spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -41,7 +41,7 @@ import org.springframework.util.ObjectUtils; @@ -41,7 +41,7 @@ import org.springframework.util.ObjectUtils;
public abstract class Operator extends SpelNodeImpl {
private final String operatorName;
// The descriptors of the runtime operand values are used if the discovered declared
// descriptors are not providing enough information (for example a generic type
// whose accessors seem to only be returning 'Object' - the actual descriptors may
@ -73,7 +73,8 @@ public abstract class Operator extends SpelNodeImpl { @@ -73,7 +73,8 @@ public abstract class Operator extends SpelNodeImpl {
}
/**
* String format for all operators is the same '(' [operand] [operator] [operand] ')'
* String format for all operators is the same
* {@code '(' [operand] [operator] [operand] ')'}.
*/
@Override
public String toStringAST() {
@ -103,8 +104,8 @@ public abstract class Operator extends SpelNodeImpl { @@ -103,8 +104,8 @@ public abstract class Operator extends SpelNodeImpl {
return (dc.areNumbers && dc.areCompatible);
}
/**
* Numeric comparison operators share very similar generated code, only differing in
/**
* Numeric comparison operators share very similar generated code, only differing in
* two comparison instructions.
*/
protected void generateComparisonCode(MethodVisitor mv, CodeFlow cf, int compInstruction1, int compInstruction2) {
@ -112,20 +113,20 @@ public abstract class Operator extends SpelNodeImpl { @@ -112,20 +113,20 @@ public abstract class Operator extends SpelNodeImpl {
SpelNodeImpl right = getRightOperand();
String leftDesc = left.exitTypeDescriptor;
String rightDesc = right.exitTypeDescriptor;
boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc);
boolean unboxRight = !CodeFlow.isPrimitive(rightDesc);
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
cf.enterCompilationScope();
left.generateCode(mv, cf);
cf.exitCompilationScope();
if (unboxLeft) {
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
}
cf.enterCompilationScope();
right.generateCode(mv, cf);
cf.exitCompilationScope();
@ -141,11 +142,11 @@ public abstract class Operator extends SpelNodeImpl { @@ -141,11 +142,11 @@ public abstract class Operator extends SpelNodeImpl {
mv.visitJumpInsn(compInstruction1, elseTarget);
}
else if (targetType == 'F') {
mv.visitInsn(FCMPG);
mv.visitInsn(FCMPG);
mv.visitJumpInsn(compInstruction1, elseTarget);
}
else if (targetType == 'J') {
mv.visitInsn(LCMP);
mv.visitInsn(LCMP);
mv.visitJumpInsn(compInstruction1, elseTarget);
}
else if (targetType == 'I') {
@ -217,6 +218,10 @@ public abstract class Operator extends SpelNodeImpl { @@ -217,6 +218,10 @@ public abstract class Operator extends SpelNodeImpl {
return left.toString().equals(right.toString());
}
if (left instanceof Boolean && right instanceof Boolean) {
return left.equals(right);
}
if (ObjectUtils.nullSafeEquals(left, right)) {
return true;
}
@ -230,7 +235,7 @@ public abstract class Operator extends SpelNodeImpl { @@ -230,7 +235,7 @@ public abstract class Operator extends SpelNodeImpl {
return false;
}
/**
* A descriptor comparison encapsulates the result of comparing descriptor
@ -253,7 +258,7 @@ public abstract class Operator extends SpelNodeImpl { @@ -253,7 +258,7 @@ public abstract class Operator extends SpelNodeImpl {
this.areCompatible = areCompatible;
this.compatibleType = compatibleType;
}
/**
* Return an object that indicates whether the input descriptors are compatible.
* <p>A declared descriptor is what could statically be determined (e.g. from looking
@ -277,7 +282,7 @@ public abstract class Operator extends SpelNodeImpl { @@ -277,7 +282,7 @@ public abstract class Operator extends SpelNodeImpl {
boolean leftNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(ld);
boolean rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
// If the declared descriptors aren't providing the information, try the actual descriptors
if (!leftNumeric && !ObjectUtils.nullSafeEquals(ld, leftActualDescriptor)) {
ld = leftActualDescriptor;
@ -287,7 +292,7 @@ public abstract class Operator extends SpelNodeImpl { @@ -287,7 +292,7 @@ public abstract class Operator extends SpelNodeImpl {
rd = rightActualDescriptor;
rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
}
if (leftNumeric && rightNumeric) {
if (CodeFlow.areBoxingCompatible(ld, rd)) {
return new DescriptorComparison(true, true, CodeFlow.toPrimitiveTargetDesc(ld));
@ -298,7 +303,7 @@ public abstract class Operator extends SpelNodeImpl { @@ -298,7 +303,7 @@ public abstract class Operator extends SpelNodeImpl {
}
else {
return DescriptorComparison.NOT_NUMBERS;
}
}
}
}

26
spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -118,10 +118,8 @@ public class SpelExpression implements Expression { @@ -118,10 +118,8 @@ public class SpelExpression implements Expression {
public Object getValue() throws EvaluationException {
if (this.compiledAst != null) {
try {
TypedValue contextRoot =
(this.evaluationContext != null ? this.evaluationContext.getRootObject() : null);
return this.compiledAst.getValue(
(contextRoot != null ? contextRoot.getValue() : null), this.evaluationContext);
EvaluationContext context = getEvaluationContext();
return this.compiledAst.getValue(context.getRootObject().getValue(), context);
}
catch (Throwable ex) {
// If running in mixed mode, revert to interpreted
@ -148,10 +146,8 @@ public class SpelExpression implements Expression { @@ -148,10 +146,8 @@ public class SpelExpression implements Expression {
public <T> T getValue(@Nullable Class<T> expectedResultType) throws EvaluationException {
if (this.compiledAst != null) {
try {
TypedValue contextRoot =
(this.evaluationContext != null ? this.evaluationContext.getRootObject() : null);
Object result = this.compiledAst.getValue(
(contextRoot != null ? contextRoot.getValue() : null), this.evaluationContext);
EvaluationContext context = getEvaluationContext();
Object result = this.compiledAst.getValue(context.getRootObject().getValue(), context);
if (expectedResultType == null) {
return (T) result;
}
@ -185,7 +181,7 @@ public class SpelExpression implements Expression { @@ -185,7 +181,7 @@ public class SpelExpression implements Expression {
public Object getValue(Object rootObject) throws EvaluationException {
if (this.compiledAst != null) {
try {
return this.compiledAst.getValue(rootObject, evaluationContext);
return this.compiledAst.getValue(rootObject, getEvaluationContext());
}
catch (Throwable ex) {
// If running in mixed mode, revert to interpreted
@ -213,7 +209,7 @@ public class SpelExpression implements Expression { @@ -213,7 +209,7 @@ public class SpelExpression implements Expression {
public <T> T getValue(Object rootObject, @Nullable Class<T> expectedResultType) throws EvaluationException {
if (this.compiledAst != null) {
try {
Object result = this.compiledAst.getValue(rootObject, null);
Object result = this.compiledAst.getValue(rootObject, getEvaluationContext());
if (expectedResultType == null) {
return (T)result;
}
@ -250,8 +246,7 @@ public class SpelExpression implements Expression { @@ -250,8 +246,7 @@ public class SpelExpression implements Expression {
if (this.compiledAst != null) {
try {
TypedValue contextRoot = context.getRootObject();
return this.compiledAst.getValue(contextRoot.getValue(), context);
return this.compiledAst.getValue(context.getRootObject().getValue(), context);
}
catch (Throwable ex) {
// If running in mixed mode, revert to interpreted
@ -280,8 +275,7 @@ public class SpelExpression implements Expression { @@ -280,8 +275,7 @@ public class SpelExpression implements Expression {
if (this.compiledAst != null) {
try {
TypedValue contextRoot = context.getRootObject();
Object result = this.compiledAst.getValue(contextRoot.getValue(), context);
Object result = this.compiledAst.getValue(context.getRootObject().getValue(), context);
if (expectedResultType != null) {
return ExpressionUtils.convertTypedValue(context, new TypedValue(result), expectedResultType);
}
@ -315,7 +309,7 @@ public class SpelExpression implements Expression { @@ -315,7 +309,7 @@ public class SpelExpression implements Expression {
if (this.compiledAst != null) {
try {
return this.compiledAst.getValue(rootObject,context);
return this.compiledAst.getValue(rootObject, context);
}
catch (Throwable ex) {
// If running in mixed mode, revert to interpreted

Loading…
Cancel
Save