Skip to content

Commit 5962fc2

Browse files
committed
EQ/NE do not fail in case of a Comparable mismatch and apply a specific CharSequence equality check
Issue: SPR-11708 (cherry picked from commit 66bae99)
1 parent 1b59b4e commit 5962fc2

File tree

6 files changed

+238
-160
lines changed

6 files changed

+238
-160
lines changed

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,22 +21,19 @@
2121
import org.springframework.expression.spel.support.BooleanTypedValue;
2222

2323
/**
24-
* Implements equality operator.
24+
* Implements the equality operator.
2525
*
2626
* @author Andy Clement
2727
* @since 3.0
2828
*/
2929
public class OpEQ extends Operator {
3030

31-
3231
public OpEQ(int pos, SpelNodeImpl... operands) {
3332
super("==", pos, operands);
3433
}
3534

36-
3735
@Override
38-
public BooleanTypedValue getValueInternal(ExpressionState state)
39-
throws EvaluationException {
36+
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
4037
Object left = getLeftOperand().getValueInternal(state).getValue();
4138
Object right = getRightOperand().getValueInternal(state).getValue();
4239
return BooleanTypedValue.forValue(equalityCheck(state, left, right));

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,20 +24,19 @@
2424
import org.springframework.util.NumberUtils;
2525

2626
/**
27-
* Implements greater-than operator.
27+
* Implements the greater-than operator.
2828
*
2929
* @author Andy Clement
30+
* @author Juergen Hoeller
3031
* @author Giovanni Dall'Oglio Risso
3132
* @since 3.0
3233
*/
3334
public class OpGT extends Operator {
3435

35-
3636
public OpGT(int pos, SpelNodeImpl... operands) {
3737
super(">", pos, operands);
3838
}
3939

40-
4140
@Override
4241
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
4342
Object left = getLeftOperand().getValueInternal(state).getValue();
@@ -67,6 +66,12 @@ public BooleanTypedValue getValueInternal(ExpressionState state) throws Evaluati
6766

6867
return BooleanTypedValue.forValue(leftNumber.intValue() > rightNumber.intValue());
6968
}
69+
70+
if (left instanceof CharSequence && right instanceof CharSequence) {
71+
left = left.toString();
72+
right = right.toString();
73+
}
74+
7075
return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) > 0);
7176
}
7277

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,20 +27,18 @@
2727
* Implements the less-than operator.
2828
*
2929
* @author Andy Clement
30+
* @author Juergen Hoeller
3031
* @author Giovanni Dall'Oglio Risso
3132
* @since 3.0
3233
*/
3334
public class OpLT extends Operator {
3435

35-
3636
public OpLT(int pos, SpelNodeImpl... operands) {
3737
super("<", pos, operands);
3838
}
3939

40-
4140
@Override
42-
public BooleanTypedValue getValueInternal(ExpressionState state)
43-
throws EvaluationException {
41+
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
4442
Object left = getLeftOperand().getValueInternal(state).getValue();
4543
Object right = getRightOperand().getValueInternal(state).getValue();
4644

@@ -68,6 +66,12 @@ public BooleanTypedValue getValueInternal(ExpressionState state)
6866

6967
return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue());
7068
}
69+
70+
if (left instanceof CharSequence && right instanceof CharSequence) {
71+
left = left.toString();
72+
right = right.toString();
73+
}
74+
7175
return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) < 0);
7276
}
7377

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,12 +28,10 @@
2828
*/
2929
public class OpNE extends Operator {
3030

31-
3231
public OpNE(int pos, SpelNodeImpl... operands) {
3332
super("!=", pos, operands);
3433
}
3534

36-
3735
@Override
3836
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
3937
Object left = getLeftOperand().getValueInternal(state).getValue();

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

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,15 +19,17 @@
1919
import java.math.BigDecimal;
2020

2121
import org.springframework.expression.spel.ExpressionState;
22+
import org.springframework.util.ClassUtils;
2223
import org.springframework.util.NumberUtils;
2324
import org.springframework.util.ObjectUtils;
2425

2526
/**
26-
* Common supertype for operators that operate on either one or two operands. In the case
27-
* of multiply or divide there would be two operands, but for unary plus or minus, there
28-
* is only one.
27+
* Common supertype for operators that operate on either one or two operands.
28+
* In the case of multiply or divide there would be two operands, but for
29+
* unary plus or minus, there is only one.
2930
*
3031
* @author Andy Clement
32+
* @author Juergen Hoeller
3133
* @author Giovanni Dall'Oglio Risso
3234
* @since 3.0
3335
*/
@@ -70,6 +72,7 @@ public String toStringAST() {
7072
return sb.toString();
7173
}
7274

75+
7376
protected boolean equalityCheck(ExpressionState state, Object left, Object right) {
7477
if (left instanceof Number && right instanceof Number) {
7578
Number leftNumber = (Number) left;
@@ -96,11 +99,22 @@ protected boolean equalityCheck(ExpressionState state, Object left, Object right
9699
return (leftNumber.intValue() == rightNumber.intValue());
97100
}
98101

99-
if (left != null && (left instanceof Comparable)) {
100-
return (state.getTypeComparator().compare(left, right) == 0);
102+
if (left instanceof CharSequence && right instanceof CharSequence) {
103+
return left.toString().equals(right.toString());
104+
}
105+
106+
if (ObjectUtils.nullSafeEquals(left, right)) {
107+
return true;
108+
}
109+
110+
if (left instanceof Comparable && right instanceof Comparable) {
111+
Class<?> ancestor = ClassUtils.determineCommonAncestor(left.getClass(), right.getClass());
112+
if (ancestor != null && Comparable.class.isAssignableFrom(ancestor)) {
113+
return (state.getTypeComparator().compare(left, right) == 0);
114+
}
101115
}
102116

103-
return ObjectUtils.nullSafeEquals(left, right);
117+
return false;
104118
}
105119

106120
}

0 commit comments

Comments
 (0)