1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel;
18
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Stack;
23
24 import org.springframework.core.convert.TypeDescriptor;
25 import org.springframework.expression.EvaluationContext;
26 import org.springframework.expression.EvaluationException;
27 import org.springframework.expression.Operation;
28 import org.springframework.expression.OperatorOverloader;
29 import org.springframework.expression.PropertyAccessor;
30 import org.springframework.expression.TypeComparator;
31 import org.springframework.expression.TypeConverter;
32 import org.springframework.expression.TypedValue;
33 import org.springframework.util.Assert;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class ExpressionState {
50
51 private final EvaluationContext relatedContext;
52
53 private final TypedValue rootObject;
54
55 private final SpelParserConfiguration configuration;
56
57 private Stack<VariableScope> variableScopes;
58
59 private Stack<TypedValue> contextObjects;
60
61
62 public ExpressionState(EvaluationContext context) {
63 this(context, context.getRootObject(), new SpelParserConfiguration(false, false));
64 }
65
66 public ExpressionState(EvaluationContext context, SpelParserConfiguration configuration) {
67 this(context, context.getRootObject(), configuration);
68 }
69
70 public ExpressionState(EvaluationContext context, TypedValue rootObject) {
71 this(context, rootObject, new SpelParserConfiguration(false, false));
72 }
73
74 public ExpressionState(EvaluationContext context, TypedValue rootObject, SpelParserConfiguration configuration) {
75 Assert.notNull(context, "EvaluationContext must not be null");
76 Assert.notNull(configuration, "SpelParserConfiguration must not be null");
77 this.relatedContext = context;
78 this.rootObject = rootObject;
79 this.configuration = configuration;
80 }
81
82
83 private void ensureVariableScopesInitialized() {
84 if (this.variableScopes == null) {
85 this.variableScopes = new Stack<VariableScope>();
86
87 this.variableScopes.add(new VariableScope());
88 }
89 }
90
91
92
93
94 public TypedValue getActiveContextObject() {
95 if (this.contextObjects == null || this.contextObjects.isEmpty()) {
96 return this.rootObject;
97 }
98 return this.contextObjects.peek();
99 }
100
101 public void pushActiveContextObject(TypedValue obj) {
102 if (this.contextObjects == null) {
103 this.contextObjects = new Stack<TypedValue>();
104 }
105 this.contextObjects.push(obj);
106 }
107
108 public void popActiveContextObject() {
109 if (this.contextObjects == null) {
110 this.contextObjects = new Stack<TypedValue>();
111 }
112 this.contextObjects.pop();
113 }
114
115 public TypedValue getRootContextObject() {
116 return this.rootObject;
117 }
118
119 public void setVariable(String name, Object value) {
120 this.relatedContext.setVariable(name, value);
121 }
122
123 public TypedValue lookupVariable(String name) {
124 Object value = this.relatedContext.lookupVariable(name);
125 if (value == null) {
126 return TypedValue.NULL;
127 }
128 else {
129 return new TypedValue(value);
130 }
131 }
132
133 public TypeComparator getTypeComparator() {
134 return this.relatedContext.getTypeComparator();
135 }
136
137 public Class<?> findType(String type) throws EvaluationException {
138 return this.relatedContext.getTypeLocator().findType(type);
139 }
140
141 public Object convertValue(Object value, TypeDescriptor targetTypeDescriptor) throws EvaluationException {
142 return this.relatedContext.getTypeConverter().convertValue(value,
143 TypeDescriptor.forObject(value), targetTypeDescriptor);
144 }
145
146 public TypeConverter getTypeConverter() {
147 return this.relatedContext.getTypeConverter();
148 }
149
150 public Object convertValue(TypedValue value, TypeDescriptor targetTypeDescriptor) throws EvaluationException {
151 Object val = value.getValue();
152 return this.relatedContext.getTypeConverter().convertValue(val, TypeDescriptor.forObject(val), targetTypeDescriptor);
153 }
154
155
156
157
158 public void enterScope(Map<String, Object> argMap) {
159 ensureVariableScopesInitialized();
160 this.variableScopes.push(new VariableScope(argMap));
161 }
162
163 public void enterScope(String name, Object value) {
164 ensureVariableScopesInitialized();
165 this.variableScopes.push(new VariableScope(name, value));
166 }
167
168 public void exitScope() {
169 ensureVariableScopesInitialized();
170 this.variableScopes.pop();
171 }
172
173 public void setLocalVariable(String name, Object value) {
174 ensureVariableScopesInitialized();
175 this.variableScopes.peek().setVariable(name, value);
176 }
177
178 public Object lookupLocalVariable(String name) {
179 ensureVariableScopesInitialized();
180 int scopeNumber = this.variableScopes.size() - 1;
181 for (int i = scopeNumber; i >= 0; i--) {
182 if (this.variableScopes.get(i).definesVariable(name)) {
183 return this.variableScopes.get(i).lookupVariable(name);
184 }
185 }
186 return null;
187 }
188
189 public TypedValue operate(Operation op, Object left, Object right) throws EvaluationException {
190 OperatorOverloader overloader = this.relatedContext.getOperatorOverloader();
191 if (overloader.overridesOperation(op, left, right)) {
192 Object returnValue = overloader.operate(op, left, right);
193 return new TypedValue(returnValue);
194 }
195 else {
196 String leftType = (left == null ? "null" : left.getClass().getName());
197 String rightType = (right == null? "null" : right.getClass().getName());
198 throw new SpelEvaluationException(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, op, leftType, rightType);
199 }
200 }
201
202 public List<PropertyAccessor> getPropertyAccessors() {
203 return this.relatedContext.getPropertyAccessors();
204 }
205
206 public EvaluationContext getEvaluationContext() {
207 return this.relatedContext;
208 }
209
210 public SpelParserConfiguration getConfiguration() {
211 return this.configuration;
212 }
213
214
215
216
217
218
219
220
221
222 private static class VariableScope {
223
224 private final Map<String, Object> vars = new HashMap<String, Object>();
225
226 public VariableScope() {
227 }
228
229 public VariableScope(Map<String, Object> arguments) {
230 if (arguments != null) {
231 this.vars.putAll(arguments);
232 }
233 }
234
235 public VariableScope(String name, Object value) {
236 this.vars.put(name,value);
237 }
238
239 public Object lookupVariable(String name) {
240 return this.vars.get(name);
241 }
242
243 public void setVariable(String name, Object value) {
244 this.vars.put(name,value);
245 }
246
247 public boolean definesVariable(String name) {
248 return this.vars.containsKey(name);
249 }
250 }
251
252 }