1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.el;
18
19 import java.io.Reader;
20 import java.io.StringReader;
21 import java.text.MessageFormat;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.servlet.jsp.el.ELException;
27 import javax.servlet.jsp.el.ExpressionEvaluator;
28 import javax.servlet.jsp.el.FunctionMapper;
29 import javax.servlet.jsp.el.VariableResolver;
30
31 import org.apache.commons.el.parser.ELParser;
32 import org.apache.commons.el.parser.ParseException;
33 import org.apache.commons.el.parser.Token;
34 import org.apache.commons.el.parser.TokenMgrError;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class ExpressionEvaluatorImpl
87 extends ExpressionEvaluator
88 {
89
90
91
92
93
94 static Map sCachedExpressionStrings =
95 Collections.synchronizedMap (new HashMap ());
96
97
98
99 static Map sCachedExpectedTypes = new HashMap ();
100
101
102
103
104
105
106 boolean mBypassCache;
107
108
109
110
111
112
113 public ExpressionEvaluatorImpl () { }
114
115
116
117
118
119
120
121
122 public ExpressionEvaluatorImpl (boolean pBypassCache)
123 {
124 mBypassCache = pBypassCache;
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 public javax.servlet.jsp.el.Expression parseExpression(String expression,
152 Class expectedType,
153 FunctionMapper fMapper)
154 throws ELException
155 {
156
157 final Object parsedExpression = parseExpressionString(expression);
158 if (parsedExpression instanceof Expression) {
159 return new JSTLExpression(this, (Expression)parsedExpression, expectedType, fMapper);
160 } else {
161
162 return new JSTLExpression(this, (String)parsedExpression, expectedType, fMapper);
163 }
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 public Object evaluate (String pExpressionString,
181 Class pExpectedType,
182 VariableResolver pResolver,
183 FunctionMapper functions)
184 throws ELException
185 {
186
187 if (pExpressionString == null) {
188 throw new ELException
189 (Constants.NULL_EXPRESSION_STRING);
190 }
191
192
193 Object parsedValue = parseExpressionString (pExpressionString);
194 return evaluate (parsedValue, pExpectedType, pResolver, functions);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 public Object evaluate (Object parsedExpression, Class pExpectedType,
212 VariableResolver pResolver, FunctionMapper functions) throws ELException
213 {
214 return evaluateParsedValue(parsedExpression, pExpectedType, pResolver, functions);
215 }
216
217 private Object evaluateParsedValue(Object parsedValue, Class pExpectedType, VariableResolver pResolver, FunctionMapper functions) throws ELException {
218
219 if (parsedValue instanceof String) {
220
221 String strValue = (String) parsedValue;
222 return convertStaticValueToExpectedType (strValue, pExpectedType);
223 }
224
225 else if (parsedValue instanceof Expression) {
226
227 Object value =
228 ((Expression) parsedValue).evaluate (pResolver,
229 functions);
230 return convertToExpectedType (value, pExpectedType);
231 }
232
233 else {
234
235 return null;
236 }
237 }
238
239
240
241
242
243
244
245
246
247 public Object parseExpressionString (String pExpressionString)
248 throws ELException
249 {
250
251 if (pExpressionString.length () == 0) {
252 return "";
253 }
254
255
256 Object ret =
257 mBypassCache ?
258 null :
259 sCachedExpressionStrings.get (pExpressionString);
260
261 if (ret == null) {
262
263 Reader r = new StringReader (pExpressionString);
264 ELParser parser = new ELParser (r);
265 try {
266 ret = parser.ExpressionString ();
267 sCachedExpressionStrings.put (pExpressionString, ret);
268 }
269 catch (ParseException exc)
270 {
271 throw new ELException
272 (formatParseException (pExpressionString,
273 exc));
274 }
275 catch (TokenMgrError exc)
276 {
277
278
279
280
281 throw new ELException (exc.getMessage ());
282 }
283 }
284 return ret;
285 }
286
287
288
289
290
291
292 Object convertToExpectedType (Object pValue,
293 Class pExpectedType)
294 throws ELException
295 {
296 return Coercions.coerce (pValue, pExpectedType);
297 }
298
299
300
301
302
303
304
305 Object convertStaticValueToExpectedType (String pValue, Class pExpectedType)
306 throws ELException
307 {
308
309 if (pExpectedType == String.class ||
310 pExpectedType == Object.class) {
311 return pValue;
312 }
313
314
315 Map valueByString = getOrCreateExpectedTypeMap (pExpectedType);
316 if (!mBypassCache &&
317 valueByString.containsKey (pValue)) {
318 return valueByString.get (pValue);
319 }
320 else {
321
322 Object ret = Coercions.coerce (pValue, pExpectedType);
323 valueByString.put (pValue, ret);
324 return ret;
325 }
326 }
327
328
329
330
331
332
333
334 static Map getOrCreateExpectedTypeMap (Class pExpectedType)
335 {
336 synchronized (sCachedExpectedTypes) {
337 Map ret = (Map) sCachedExpectedTypes.get (pExpectedType);
338 if (ret == null) {
339 ret = Collections.synchronizedMap (new HashMap ());
340 sCachedExpectedTypes.put (pExpectedType, ret);
341 }
342 return ret;
343 }
344 }
345
346
347
348
349
350
351
352
353
354 static String formatParseException (String pExpressionString,
355 ParseException pExc)
356 {
357
358 StringBuffer expectedBuf = new StringBuffer ();
359 int maxSize = 0;
360 boolean printedOne = false;
361
362 if (pExc.expectedTokenSequences == null)
363 return pExc.toString();
364
365 for (int i = 0; i < pExc.expectedTokenSequences.length; i++) {
366 if (maxSize < pExc.expectedTokenSequences [i].length) {
367 maxSize = pExc.expectedTokenSequences [i].length;
368 }
369 for (int j = 0; j < pExc.expectedTokenSequences[i].length; j++) {
370 if (printedOne) {
371 expectedBuf.append (", ");
372 }
373 expectedBuf.append
374 (pExc.tokenImage [pExc.expectedTokenSequences [i] [j]]);
375 printedOne = true;
376 }
377 }
378 String expected = expectedBuf.toString ();
379
380
381 StringBuffer encounteredBuf = new StringBuffer ();
382 Token tok = pExc.currentToken.next;
383 for (int i = 0; i < maxSize; i++) {
384 if (i != 0) encounteredBuf.append (" ");
385
386 if (tok.kind == 0) {
387 encounteredBuf.append (pExc.tokenImage[0]);
388 break;
389 }
390 encounteredBuf.append (addEscapes (tok.image));
391 tok = tok.next;
392 }
393 String encountered = encounteredBuf.toString ();
394
395
396 return MessageFormat.format
397 (Constants.PARSE_EXCEPTION,
398 new Object[] {
399 expected,
400 encountered,
401 });
402 }
403
404
405
406
407
408
409
410
411 static String addEscapes (String str)
412 {
413 StringBuffer retval = new StringBuffer ();
414 char ch;
415 for (int i = 0, length = str.length (); i < length; i++) {
416 switch (str.charAt (i)) {
417 case 0:
418 continue;
419 case '\b':
420 retval.append ("\\b");
421 continue;
422 case '\t':
423 retval.append ("\\t");
424 continue;
425 case '\n':
426 retval.append ("\\n");
427 continue;
428 case '\f':
429 retval.append ("\\f");
430 continue;
431 case '\r':
432 retval.append ("\\r");
433 continue;
434 default:
435 if ((ch = str.charAt (i)) < 0x20 || ch > 0x7e) {
436 String s = "0000" + Integer.toString (ch, 16);
437 retval.append ("\\u" + s.substring (s.length () - 4, s.length ()));
438 }
439 else {
440 retval.append (ch);
441 }
442 continue;
443 }
444 }
445 return retval.toString ();
446 }
447
448
449
450
451
452
453
454
455
456 public String parseAndRender (String pExpressionString)
457 throws ELException
458 {
459 Object val = parseExpressionString (pExpressionString);
460 if (val instanceof String) {
461 return (String) val;
462 }
463 else if (val instanceof Expression) {
464 return "${" + ((Expression) val).getExpressionString () + "}";
465 }
466 else if (val instanceof ExpressionString) {
467 return ((ExpressionString) val).getExpressionString ();
468 }
469 else {
470 return "";
471 }
472 }
473
474
475
476
477
478 private class JSTLExpression
479 extends javax.servlet.jsp.el.Expression
480 {
481 private ExpressionEvaluatorImpl evaluator;
482 private Object parsedExpression;
483 private Class expectedType;
484
485 public JSTLExpression(
486 final ExpressionEvaluatorImpl evaluator,
487 final Expression expression,
488 final Class expectedType,
489 final FunctionMapper fMapper)
490 throws ELException {
491 this.evaluator = evaluator;
492 this.parsedExpression = expression.bindFunctions(fMapper);
493 this.expectedType = expectedType;
494 }
495 public JSTLExpression(
496 final ExpressionEvaluatorImpl evaluator,
497 final String expressionString,
498 final Class expectedType,
499 final FunctionMapper fMapper)
500 throws ELException {
501 this.evaluator = evaluator;
502 this.parsedExpression = expressionString;
503 this.expectedType = expectedType;
504 }
505
506 public Object evaluate( VariableResolver vResolver )
507 throws ELException
508 {
509 return evaluator.evaluateParsedValue(this.parsedExpression,
510 this.expectedType,
511 vResolver,
512 null);
513 }
514 }
515
516
517
518 }