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