1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.parser;
18
19 import org.apache.commons.jexl3.JexlException;
20 import org.apache.commons.jexl3.JexlFeatures;
21 import org.apache.commons.jexl3.JexlInfo;
22 import org.apache.commons.jexl3.internal.Debugger;
23 import org.apache.commons.jexl3.internal.ScriptVisitor;
24
25
26
27
28 public class FeatureController extends ScriptVisitor {
29
30
31 private JexlFeatures features;
32
33
34
35
36 public FeatureController(final JexlFeatures features) {
37 this.features = features;
38 }
39
40
41
42
43
44
45
46
47 public void controlNode(final JexlNode node) {
48 node.jjtAccept(this, null);
49 }
50
51 private Object controlSideEffect(final JexlNode node, final Object data) {
52 final JexlNode lv = node.jjtGetChild(0);
53 if (!features.supportsSideEffectGlobal() && lv.isGlobalVar()) {
54 throwFeatureException(JexlFeatures.SIDE_EFFECT_GLOBAL, lv);
55 }
56 if (features.supportsConstCapture() && lv instanceof ASTIdentifier && ((ASTIdentifier) lv).isCaptured()) {
57 throwFeatureException(JexlFeatures.CONST_CAPTURE, lv);
58 }
59 if (!features.supportsSideEffect()) {
60 throwFeatureException(JexlFeatures.SIDE_EFFECT, lv);
61 }
62 return data;
63 }
64
65
66
67
68 public JexlFeatures getFeatures() {
69 return features;
70 }
71
72
73
74
75
76
77
78 private boolean isArrayReferenceLiteral(final JexlNode child) {
79 if (child instanceof ASTStringLiteral) {
80 return true;
81 }
82 if (child instanceof ASTNumberLiteral && ((ASTNumberLiteral) child).isInteger()) {
83 return true;
84 }
85 return false;
86 }
87
88
89
90
91
92
93 public void setFeatures(final JexlFeatures fdesc) {
94 this.features = fdesc;
95 }
96
97
98
99
100
101
102
103 public void throwFeatureException(final int feature, final JexlNode node) {
104 final JexlInfo dbgInfo = node.jexlInfo();
105 final Debugger dbg = new Debugger().depth(1);
106 final String msg = dbg.data(node);
107 throw new JexlException.Feature(dbgInfo, feature, msg);
108 }
109
110 @Override
111 protected Object visit(final ASTAnnotation node, final Object data) {
112 if (!features.supportsAnnotation()) {
113 throwFeatureException(JexlFeatures.ANNOTATION, node);
114 }
115 return data;
116 }
117
118 @Override
119 protected Object visit(final ASTArrayAccess node, final Object data) {
120 if (!features.supportsArrayReferenceExpr()) {
121 for (int i = 0; i < node.jjtGetNumChildren(); ++i) {
122 final JexlNode child = node.jjtGetChild(i);
123 if (!isArrayReferenceLiteral(child)) {
124 throwFeatureException(JexlFeatures.ARRAY_REF_EXPR, child);
125 }
126 }
127 }
128 return data;
129 }
130
131 @Override
132 protected Object visit(final ASTArrayLiteral node, final Object data) {
133 if (!features.supportsStructuredLiteral()) {
134 throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
135 }
136 return data;
137 }
138
139 @Override
140 protected Object visit(final ASTAssignment node, final Object data) {
141 return controlSideEffect(node, data);
142 }
143
144 @Override
145 protected Object visit(final ASTConstructorNode node, final Object data) {
146 if (!features.supportsNewInstance()) {
147 throwFeatureException(JexlFeatures.NEW_INSTANCE, node);
148 }
149 return data;
150 }
151
152 @Override
153 protected Object visit(final ASTDecrementGetNode node, final Object data) {
154 return controlSideEffect(node, data);
155 }
156
157 @Override
158 protected Object visit(final ASTDoWhileStatement node, final Object data) {
159 if (!features.supportsLoops()) {
160 throwFeatureException(JexlFeatures.LOOP, node);
161 }
162 return data;
163 }
164
165 @Override
166 protected Object visit(final ASTForeachStatement node, final Object data) {
167 if (!features.supportsLoops()) {
168 throwFeatureException(JexlFeatures.LOOP, node);
169 }
170 return data;
171 }
172
173 @Override
174 protected Object visit(final ASTGetDecrementNode node, final Object data) {
175 return controlSideEffect(node, data);
176 }
177
178 @Override
179 protected Object visit(final ASTGetIncrementNode node, final Object data) {
180 return controlSideEffect(node, data);
181 }
182
183 @Override
184 protected Object visit(final ASTIncrementGetNode node, final Object data) {
185 return controlSideEffect(node, data);
186 }
187
188 @Override
189 protected Object visit(final ASTMapLiteral node, final Object data) {
190 if (!features.supportsStructuredLiteral()) {
191 throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
192 }
193 return data;
194 }
195
196 @Override
197 protected Object visit(final ASTMethodNode node, final Object data) {
198 if (!features.supportsMethodCall()) {
199 throwFeatureException(JexlFeatures.METHOD_CALL, node);
200 }
201 return data;
202 }
203
204 @Override
205 protected Object visit(final ASTRangeNode node, final Object data) {
206 if (!features.supportsStructuredLiteral()) {
207 throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
208 }
209 return data;
210 }
211
212 @Override
213 protected Object visit(final ASTSetAddNode node, final Object data) {
214 return controlSideEffect(node, data);
215 }
216
217 @Override
218 protected Object visit(final ASTSetAndNode node, final Object data) {
219 return controlSideEffect(node, data);
220 }
221
222 @Override
223 protected Object visit(final ASTSetDivNode node, final Object data) {
224 return controlSideEffect(node, data);
225 }
226
227 @Override
228 protected Object visit(final ASTSetLiteral node, final Object data) {
229 if (!features.supportsStructuredLiteral()) {
230 throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
231 }
232 return data;
233 }
234
235 @Override
236 protected Object visit(final ASTSetModNode node, final Object data) {
237 return controlSideEffect(node, data);
238 }
239
240 @Override
241 protected Object visit(final ASTSetMultNode node, final Object data) {
242 return controlSideEffect(node, data);
243 }
244
245 @Override
246 protected Object visit(final ASTSetOrNode node, final Object data) {
247 return controlSideEffect(node, data);
248 }
249
250 @Override
251 protected Object visit(final ASTSetShiftLeftNode node, final Object data) {
252 return controlSideEffect(node, data);
253 }
254
255 @Override
256 protected Object visit(final ASTSetShiftRightNode node, final Object data) {
257 return controlSideEffect(node, data);
258 }
259
260 @Override
261 protected Object visit(final ASTSetShiftRightUnsignedNode node, final Object data) {
262 return controlSideEffect(node, data);
263 }
264
265 @Override
266 protected Object visit(final ASTSetSubNode node, final Object data) {
267 return controlSideEffect(node, data);
268 }
269
270 @Override
271 protected Object visit(final ASTSetXorNode node, final Object data) {
272 return controlSideEffect(node, data);
273 }
274
275 @Override
276 protected Object visit(final ASTTryStatement node, final Object data) {
277
278
279
280 return data;
281 }
282
283 @Override
284 protected Object visit(final ASTWhileStatement node, final Object data) {
285 if (!features.supportsLoops()) {
286 throwFeatureException(JexlFeatures.LOOP, node);
287 }
288 return data;
289 }
290
291 @Override
292 protected Object visitNode(final JexlNode node, final Object data) {
293
294 return data;
295 }
296 }