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