Skip to content

Commit 4bc3e0c

Browse files
committed
Add SimpleEvaluationContext
Issue: SPR-16588
1 parent d57d914 commit 4bc3e0c

File tree

2 files changed

+294
-115
lines changed

2 files changed

+294
-115
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright 2002-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.expression.spel.support;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collections;
21+
import java.util.HashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
25+
import org.springframework.expression.BeanResolver;
26+
import org.springframework.expression.ConstructorResolver;
27+
import org.springframework.expression.EvaluationContext;
28+
import org.springframework.expression.EvaluationException;
29+
import org.springframework.expression.MethodResolver;
30+
import org.springframework.expression.OperatorOverloader;
31+
import org.springframework.expression.PropertyAccessor;
32+
import org.springframework.expression.TypeComparator;
33+
import org.springframework.expression.TypeConverter;
34+
import org.springframework.expression.TypeLocator;
35+
import org.springframework.expression.TypedValue;
36+
import org.springframework.expression.spel.SpelEvaluationException;
37+
import org.springframework.expression.spel.SpelMessage;
38+
39+
/**
40+
* A basic implementation of {@link EvaluationContext} that focuses on a subset
41+
* of essential SpEL features and configuration options, and relies on default
42+
* strategies otherwise.
43+
*
44+
* <p>In many cases, the full extent of the SpEL is not
45+
* required and should be meaningfully restricted. Examples include but are not
46+
* limited to data binding expressions, property-based filters, and others. To
47+
* that effect, {@code SimpleEvaluationContext} supports only a subset of the
48+
* SpEL language syntax that excludes references to Java types, constructors,
49+
* and bean references.
50+
*
51+
* <p>Note that {@code SimpleEvaluationContext} cannot be configured with a
52+
* default root object. Instead it is meant to be created once and used
53+
* repeatedly through method variants on
54+
* {@link org.springframework.expression.Expression Expression} that accept
55+
* both an {@code EvaluationContext} and a root object.
56+
*
57+
* @author Rossen Stoyanchev
58+
* @since 4.3.15
59+
*/
60+
public class SimpleEvaluationContext implements EvaluationContext {
61+
62+
private static final TypeLocator typeNotFoundTypeLocator = new TypeLocator() {
63+
64+
@Override
65+
public Class<?> findType(String typeName) throws EvaluationException {
66+
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
67+
}
68+
};
69+
70+
71+
private final List<PropertyAccessor> propertyAccessors;
72+
73+
private final List<ConstructorResolver> constructorResolvers =
74+
Collections.<ConstructorResolver>singletonList(new ReflectiveConstructorResolver());
75+
76+
private final List<MethodResolver> methodResolvers =
77+
Collections.<MethodResolver>singletonList(new ReflectiveMethodResolver());
78+
79+
private final TypeConverter typeConverter;
80+
81+
private final TypeComparator typeComparator = new StandardTypeComparator();
82+
83+
private final OperatorOverloader operatorOverloader = new StandardOperatorOverloader();
84+
85+
private final Map<String, Object> variables = new HashMap<String, Object>();
86+
87+
88+
public SimpleEvaluationContext() {
89+
this(null, null);
90+
}
91+
92+
public SimpleEvaluationContext(List<PropertyAccessor> accessors, TypeConverter converter) {
93+
this.propertyAccessors = initPropertyAccessors(accessors);
94+
this.typeConverter = converter != null ? converter : new StandardTypeConverter();
95+
}
96+
97+
98+
private static List<PropertyAccessor> initPropertyAccessors(List<PropertyAccessor> accessors) {
99+
if (accessors == null) {
100+
accessors = new ArrayList<PropertyAccessor>(5);
101+
accessors.add(new ReflectivePropertyAccessor());
102+
}
103+
return accessors;
104+
}
105+
106+
107+
/**
108+
* {@code SimpleEvaluationContext} cannot be configured with a root object.
109+
* It is meant for repeated use with
110+
* {@link org.springframework.expression.Expression Expression} method
111+
* variants that accept both an {@code EvaluationContext} and a root object.
112+
* @return Always returns {@link TypedValue#NULL}.
113+
*/
114+
@Override
115+
public TypedValue getRootObject() {
116+
return TypedValue.NULL;
117+
}
118+
119+
@Override
120+
public List<PropertyAccessor> getPropertyAccessors() {
121+
return this.propertyAccessors;
122+
}
123+
124+
/**
125+
* Return a single {@link ReflectiveConstructorResolver}.
126+
*/
127+
@Override
128+
public List<ConstructorResolver> getConstructorResolvers() {
129+
return this.constructorResolvers;
130+
}
131+
132+
/**
133+
* Return a single {@link ReflectiveMethodResolver}.
134+
*/
135+
@Override
136+
public List<MethodResolver> getMethodResolvers() {
137+
return this.methodResolvers;
138+
}
139+
140+
/**
141+
* {@code SimpleEvaluationContext} does not support use of bean references.
142+
* @return Always returns {@code null}
143+
*/
144+
@Override
145+
public BeanResolver getBeanResolver() {
146+
return null;
147+
}
148+
149+
/**
150+
* {@code SimpleEvaluationContext} does not support use of type references.
151+
* @return {@code TypeLocator} implementation that raises a
152+
* {@link SpelEvaluationException} with {@link SpelMessage#TYPE_NOT_FOUND}.
153+
*/
154+
@Override
155+
public TypeLocator getTypeLocator() {
156+
return typeNotFoundTypeLocator;
157+
}
158+
159+
/**
160+
* The configured {@link TypeConverter}.
161+
* <p>By default this is {@link StandardTypeConverter}.
162+
*/
163+
@Override
164+
public TypeConverter getTypeConverter() {
165+
return this.typeConverter;
166+
}
167+
168+
/**
169+
* Return an instance of {@link StandardTypeComparator}.
170+
*/
171+
@Override
172+
public TypeComparator getTypeComparator() {
173+
return this.typeComparator;
174+
}
175+
176+
177+
/**
178+
* Return an instance of {@link StandardOperatorOverloader}.
179+
*/
180+
@Override
181+
public OperatorOverloader getOperatorOverloader() {
182+
return this.operatorOverloader;
183+
}
184+
185+
@Override
186+
public void setVariable(String name, Object value) {
187+
this.variables.put(name, value);
188+
}
189+
190+
@Override
191+
public Object lookupVariable(String name) {
192+
return this.variables.get(name);
193+
}
194+
195+
}

0 commit comments

Comments
 (0)