1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.el;
20
21 import java.io.StringReader;
22 import java.util.List;
23
24 import javax.faces.application.Application;
25 import javax.faces.component.UIComponent;
26 import javax.faces.context.FacesContext;
27 import javax.faces.el.EvaluationException;
28 import javax.faces.el.ReferenceSyntaxException;
29 import javax.servlet.jsp.el.ELException;
30 import javax.servlet.jsp.el.FunctionMapper;
31 import javax.servlet.jsp.el.VariableResolver;
32
33 import org.apache.myfaces.shared_impl.util.StringUtils;
34
35 import org.apache.commons.el.ArraySuffix;
36 import org.apache.commons.el.BinaryOperatorExpression;
37 import org.apache.commons.el.Coercions;
38 import org.apache.commons.el.ComplexValue;
39 import org.apache.commons.el.ConditionalExpression;
40 import org.apache.commons.el.Expression;
41 import org.apache.commons.el.ExpressionString;
42 import org.apache.commons.el.FunctionInvocation;
43 import org.apache.commons.el.Literal;
44 import org.apache.commons.el.Logger;
45 import org.apache.commons.el.NamedValue;
46 import org.apache.commons.el.PropertySuffix;
47 import org.apache.commons.el.UnaryOperatorExpression;
48 import org.apache.commons.el.ValueSuffix;
49 import org.apache.commons.el.parser.ELParser;
50 import org.apache.commons.el.parser.ParseException;
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54
55
56
57
58
59
60
61
62 public class ELParserHelper
63 {
64 static final Log log = LogFactory.getLog(ELParserHelper.class);
65 public static final Logger LOGGER = new Logger(System.out);
66
67 private ELParserHelper()
68 {
69
70 }
71
72
73
74
75
76 public static Object parseExpression(String expressionString)
77 {
78 expressionString = toJspElExpression(expressionString);
79
80 ELParser parser = new ELParser(new StringReader(expressionString));
81 try
82 {
83 Object expression = parser.ExpressionString();
84 if (!(expression instanceof Expression)
85 && !(expression instanceof ExpressionString))
86 {
87 throw new ReferenceSyntaxException("Invalid expression: '"
88 + expressionString
89 + "'. Parsed Expression of unexpected type "
90 + expression.getClass().getName());
91 }
92
93 replaceSuffixes(expression);
94
95 return expression;
96 }
97 catch (ParseException e)
98 {
99 String msg = "Invalid expression: '" + expressionString + "'";
100 throw new ReferenceSyntaxException(msg, e);
101 }
102 }
103
104
105
106
107
108
109
110
111 static String toJspElExpression(String expressionString)
112 {
113 StringBuffer sb = new StringBuffer(expressionString.length());
114 int remainsPos = 0;
115
116 for (int posOpenBrace = expressionString.indexOf('{'); posOpenBrace >= 0;
117 posOpenBrace = expressionString.indexOf('{', remainsPos))
118 {
119 if (posOpenBrace > 0)
120 {
121 if( posOpenBrace-1 > remainsPos )
122 sb.append(expressionString.substring(remainsPos, posOpenBrace - 1));
123
124 if (expressionString.charAt(posOpenBrace - 1) == '$')
125 {
126 sb.append("${'${'}");
127 remainsPos = posOpenBrace+1;
128 continue;
129 }
130 else if (expressionString.charAt(posOpenBrace - 1) == '#')
131 {
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 sb.append("${");
153 int posCloseBrace = indexOfMatchingClosingBrace(expressionString, posOpenBrace);
154 sb.append(expressionString.substring(posOpenBrace + 1, posCloseBrace + 1));
155 remainsPos = posCloseBrace + 1;
156 continue;
157
158 }else{
159 if( posOpenBrace > remainsPos )
160 sb.append( expressionString.charAt(posOpenBrace - 1) );
161 }
162 }
163
164
165 sb.append('{');
166 remainsPos = posOpenBrace + 1;
167 }
168
169 sb.append(expressionString.substring(remainsPos));
170
171
172 return new String(sb.toString());
173 }
174
175 private static int findQuote(String expressionString, int start)
176 {
177 int indexofSingleQuote = expressionString.indexOf('\'', start);
178 int indexofDoubleQuote = expressionString.indexOf('"', start);
179 return StringUtils.minIndex(indexofSingleQuote, indexofDoubleQuote);
180 }
181
182
183
184
185
186
187
188
189
190
191
192 private static int indexOfMatchingClosingBrace(String expressionString,
193 int indexofOpeningBrace)
194 {
195 int len = expressionString.length();
196 int i = indexofOpeningBrace + 1;
197
198
199 for (;;)
200 {
201 if (i >= len)
202 {
203 throw new ReferenceSyntaxException(
204 "Missing closing brace. Expression: '" + expressionString
205 + "'");
206 }
207
208 int indexofClosingBrace = expressionString.indexOf('}', i);
209 i = StringUtils.minIndex(indexofClosingBrace, findQuote(
210 expressionString, i));
211
212 if (i < 0)
213 {
214
215 throw new ReferenceSyntaxException(
216 "Missing closing brace. Expression: '" + expressionString
217 + "'");
218 }
219
220
221 if (i != indexofClosingBrace)
222 {
223 i = indexOfMatchingClosingQuote(expressionString, i) + 1;
224 if (i == 0)
225 {
226
227 throw new ReferenceSyntaxException(
228 "Missing closing quote. Expression: '"
229 + expressionString + "'");
230 }
231 }
232 else
233 {
234
235 return i;
236 }
237 }
238 }
239
240
241
242
243
244
245
246
247
248 private static int indexOfMatchingClosingQuote(String expressionString,
249 int indexOfOpeningQuote)
250 {
251 char quote = expressionString.charAt(indexOfOpeningQuote);
252 for (int i = expressionString.indexOf(quote, indexOfOpeningQuote + 1);
253 i >= 0; i = expressionString.indexOf(quote, i + 1))
254 {
255 if (!isEscaped(expressionString, i))
256 {
257 return i;
258 }
259 }
260
261
262 return -1;
263 }
264
265 private static boolean isEscaped(String expressionString, int i)
266 {
267 int escapeCharCount = 0;
268 while ((--i >= 0) && (expressionString.charAt(i) == '\\'))
269 {
270 escapeCharCount++;
271 }
272
273 return (escapeCharCount % 2) != 0;
274 }
275
276
277
278
279
280
281
282
283
284
285
286 private static void replaceSuffixes(Object expression)
287 {
288 if (expression instanceof Expression)
289 {
290 replaceSuffixes((Expression) expression);
291 }
292 else if (expression instanceof ExpressionString)
293 {
294 replaceSuffixes((ExpressionString) expression);
295 }
296 else
297 {
298 throw new IllegalStateException(
299 "Expression element of unknown class: "
300 + expression.getClass().getName());
301 }
302 }
303
304 private static void replaceSuffixes(ExpressionString expressionString)
305 {
306 Object[] expressions = expressionString.getElements();
307 for (int i = 0, len = expressions.length; i < len; i++)
308 {
309 Object expression = expressions[i];
310 if (expression instanceof Expression)
311 {
312 replaceSuffixes((Expression) expression);
313 }
314 else if (expression instanceof ExpressionString)
315 {
316 replaceSuffixes((ExpressionString) expression);
317 }
318 else if (!(expression instanceof String))
319 {
320 throw new IllegalStateException(
321 "Expression element of unknown class: "
322 + expression.getClass().getName());
323 }
324
325 }
326 }
327
328 static void replaceSuffixes(Expression expression)
329 {
330 if (expression instanceof BinaryOperatorExpression)
331 {
332 BinaryOperatorExpression boe = (BinaryOperatorExpression) expression;
333 replaceSuffixes(boe.getExpression());
334 for (int i = 0; i < boe.getExpressions().size(); i++)
335 {
336 replaceSuffixes(boe.getExpressions().get(i));
337 }
338 }
339 else if (expression instanceof ComplexValue)
340 {
341 replaceSuffixes((ComplexValue) expression);
342 }
343 else if (expression instanceof ConditionalExpression)
344 {
345 ConditionalExpression conditionalExpression =
346 (ConditionalExpression) expression;
347 replaceSuffixes(conditionalExpression.getTrueBranch());
348 replaceSuffixes(conditionalExpression.getFalseBranch());
349 }
350 else if (expression instanceof UnaryOperatorExpression)
351 {
352 replaceSuffixes(((UnaryOperatorExpression) expression)
353 .getExpression());
354 }
355
356
357 else if (!(expression instanceof FunctionInvocation
358 || expression instanceof Literal || expression instanceof NamedValue))
359 {
360 throw new IllegalStateException(
361 "Expression element of unknown class: "
362 + expression.getClass().getName());
363 }
364 }
365
366 private static void replaceSuffixes(ComplexValue complexValue)
367 {
368 Application application = FacesContext.getCurrentInstance()
369 .getApplication();
370
371 List suffixes = complexValue.getSuffixes();
372 for (int i = 0, len = suffixes.size(); i < len; i++)
373 {
374 ValueSuffix suffix = (ValueSuffix) suffixes.get(i);
375 if (suffix instanceof PropertySuffix)
376 {
377 if (suffix instanceof MyPropertySuffix)
378 {
379 throw new IllegalStateException(
380 "Suffix is MyPropertySuffix and must not be");
381 }
382
383 suffixes.set(i, new MyPropertySuffix((PropertySuffix) suffix,
384 application));
385 }
386 else if (suffix instanceof ArraySuffix)
387 {
388 if (suffix instanceof MyArraySuffix)
389 {
390 throw new IllegalStateException(
391 "Suffix is MyArraySuffix and must not be");
392 }
393
394 suffixes.set(i, new MyArraySuffix((ArraySuffix) suffix,
395 application));
396 }
397 else
398 {
399 throw new IllegalStateException("Unknown suffix class: "
400 + suffix.getClass().getName());
401 }
402 }
403 }
404
405 private static Integer coerceToIntegerWrapper(Object base, Object index)
406 throws EvaluationException, ELException
407 {
408 Integer integer = Coercions.coerceToInteger(index, LOGGER);
409 if (integer != null)
410 {
411 return integer;
412 }
413 throw new ReferenceSyntaxException(
414 "Cannot convert index to int for base " + base.getClass().getName()
415 + " and index " + index);
416 }
417
418
419
420
421
422
423
424
425
426
427
428
429
430 public static Integer toIndex(Object base, Object index)
431 throws ELException, EvaluationException
432 {
433 if ((base instanceof List) || (base.getClass().isArray()))
434 {
435 return coerceToIntegerWrapper(base, index);
436 }
437 if (base instanceof UIComponent)
438 {
439 try
440 {
441 return coerceToIntegerWrapper(base, index);
442 }
443 catch (Throwable t)
444 {
445
446 return null;
447 }
448 }
449
450
451 return null;
452 }
453
454
455
456
457 public static class MyArraySuffix extends ArraySuffix
458 {
459 private Application _application;
460
461 public MyArraySuffix(ArraySuffix arraySuffix, Application application)
462 {
463 super(arraySuffix.getIndex());
464 replaceSuffixes(getIndex());
465 _application = application;
466 }
467
468
469
470
471
472 public Object evaluate(Object base, VariableResolver variableResolver,
473 FunctionMapper functions, Logger logger)
474 throws ELException
475 {
476
477 if (base == null)
478 {
479 return null;
480 }
481
482
483 Object indexVal = getIndex().evaluate(variableResolver, functions,
484 logger);
485 if (indexVal == null)
486 {
487 return null;
488 }
489
490 Integer index = toIndex(base, indexVal);
491 if (index == null)
492 {
493 return _application.getPropertyResolver().getValue(base,
494 indexVal);
495 }
496 else
497 {
498 return _application.getPropertyResolver().getValue(base,
499 index.intValue());
500 }
501 }
502 }
503
504 public static class MyPropertySuffix extends PropertySuffix
505 {
506 private Application _application;
507
508 public MyPropertySuffix(PropertySuffix propertySuffix,
509 Application application)
510 {
511 super(propertySuffix.getName());
512 _application = application;
513 }
514
515
516
517
518
519 public Object evaluate(Object base, VariableResolver variableResolver,
520 FunctionMapper functions, Logger logger)
521 throws ELException
522 {
523
524 if (base == null)
525 {
526 return null;
527 }
528
529
530 String indexVal = getName();
531 if (indexVal == null)
532 {
533 return null;
534 }
535
536 Integer index = toIndex(base, indexVal);
537 if (index == null)
538 {
539 return _application.getPropertyResolver().getValue(base,
540 indexVal);
541 }
542 else
543 {
544 return _application.getPropertyResolver().getValue(base,
545 index.intValue());
546 }
547 }
548 }
549 }