1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.el;
20
21 import java.io.IOException;
22 import java.io.Writer;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.el.ELContext;
27 import javax.el.ELException;
28 import javax.el.ExpressionFactory;
29 import javax.el.ValueExpression;
30 import javax.faces.component.UIComponent;
31 import javax.faces.context.ResponseWriter;
32 import javax.faces.view.Location;
33
34 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
35
36
37
38
39
40
41
42
43
44 public class ELText
45 {
46
47 private static final class LiteralValueExpression extends ValueExpression
48 {
49
50
51
52
53 private static final long serialVersionUID = 1L;
54
55 private final String text;
56
57 public LiteralValueExpression(String text)
58 {
59 this.text = text;
60 }
61
62 public boolean isLiteralText()
63 {
64 return false;
65 }
66
67 public int hashCode()
68 {
69 return 0;
70 }
71
72 public String getExpressionString()
73 {
74 return this.text;
75 }
76
77 public boolean equals(Object obj)
78 {
79 return false;
80 }
81
82 public void setValue(ELContext context, Object value)
83 {
84 }
85
86 public boolean isReadOnly(ELContext context)
87 {
88 return false;
89 }
90
91 public Object getValue(ELContext context)
92 {
93 return null;
94 }
95
96 public Class<?> getType(ELContext context)
97 {
98 return null;
99 }
100
101 public Class<?> getExpectedType()
102 {
103 return null;
104 }
105
106 }
107
108 private static final class ELTextComposite extends ELText
109 {
110 private final ELText[] txt;
111
112 public ELTextComposite(ELText[] txt)
113 {
114 super(null);
115 this.txt = txt;
116 }
117
118 public void write(Writer out, ELContext ctx) throws ELException, IOException
119 {
120 for (int i = 0; i < this.txt.length; i++)
121 {
122 this.txt[i].write(out, ctx);
123 }
124 }
125
126 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
127 {
128 for (int i = 0; i < this.txt.length; i++)
129 {
130 this.txt[i].writeText(out, ctx);
131 }
132 }
133
134 public String toString(ELContext ctx)
135 {
136 StringBuffer sb = new StringBuffer();
137 for (int i = 0; i < this.txt.length; i++)
138 {
139 sb.append(this.txt[i].toString(ctx));
140 }
141 return sb.toString();
142 }
143
144
145
146
147
148
149 public String toString()
150 {
151 StringBuffer sb = new StringBuffer();
152 for (int i = 0; i < this.txt.length; i++)
153 {
154 sb.append(this.txt[i].toString());
155 }
156 return sb.toString();
157 }
158
159 public boolean isLiteral()
160 {
161 return false;
162 }
163
164 public ELText apply(ExpressionFactory factory, ELContext ctx)
165 {
166 int len = this.txt.length;
167 ELText[] nt = new ELText[len];
168 for (int i = 0; i < len; i++)
169 {
170 nt[i] = this.txt[i].apply(factory, ctx);
171 }
172 return new ELTextComposite(nt);
173 }
174 }
175
176 private static final class ELTextVariable extends ELText
177 {
178 private final ValueExpression ve;
179
180 public ELTextVariable(ValueExpression ve)
181 {
182 super(ve.getExpressionString());
183 this.ve = ve;
184 }
185
186 public boolean isLiteral()
187 {
188 return false;
189 }
190
191 public ELText apply(ExpressionFactory factory, ELContext ctx)
192 {
193 return new ELTextVariable(factory.createValueExpression(ctx, this.ve.getExpressionString(), String.class));
194 }
195
196 public void write(Writer out, ELContext ctx) throws ELException, IOException
197 {
198 Object v = this.ve.getValue(ctx);
199 if (v != null)
200 {
201 out.write((String) v);
202 }
203 }
204
205 public String toString(ELContext ctx) throws ELException
206 {
207 Object v = this.ve.getValue(ctx);
208 if (v != null)
209 {
210 return v.toString();
211 }
212
213 return null;
214 }
215
216 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
217 {
218 Object v = this.ve.getValue(ctx);
219 if (v != null)
220 {
221 out.writeText((String) v, null);
222 }
223 }
224 }
225
226 private static final class ELCacheableTextVariable extends ELText
227 {
228 private final ValueExpression ve;
229
230
231 private final static int EL_CC = 2;
232
233 private final static int EL_RESOURCE = 8;
234
235 private final int capabilities;
236
237 private volatile ELTextVariable cached;
238
239 public ELCacheableTextVariable(ValueExpression ve)
240 {
241 super(ve.getExpressionString());
242 this.ve = ve;
243 boolean compositeComponentExpression
244 = CompositeComponentELUtils.isCompositeComponentExpression(ve.getExpressionString());
245 boolean resourceExpression = ResourceELUtils.isResourceExpression(ve.getExpressionString());
246 this.capabilities = (compositeComponentExpression ? EL_CC : 0) | ( resourceExpression ? EL_RESOURCE : 0);
247 }
248
249 public boolean isLiteral()
250 {
251 return false;
252 }
253
254 public ELText apply(ExpressionFactory factory, ELContext ctx)
255 {
256 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
257
258 if (actx.isAllowCacheELExpressions() && cached != null)
259 {
260
261
262
263
264
265
266
267
268 if ((this.capabilities & EL_CC) != 0)
269 {
270 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
271 if (cc != null)
272 {
273 Location location = (Location) cc.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
274 if (location != null)
275 {
276 return new ELTextVariable(((LocationValueExpression)cached.ve).apply(
277 actx.getFaceletCompositionContext().getCompositeComponentLevel(), location));
278 }
279 }
280 return new ELTextVariable(((LocationValueExpression)cached.ve).apply(
281 actx.getFaceletCompositionContext().getCompositeComponentLevel()));
282 }
283 return cached;
284 }
285
286 actx.beforeConstructELExpression();
287 try
288 {
289 ValueExpression valueExpression
290 = factory.createValueExpression(ctx, this.ve.getExpressionString(), String.class);
291
292 if ((this.capabilities & EL_CC) != 0)
293 {
294 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
295 if (cc != null)
296 {
297 Location location = (Location) cc.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
298 if (location != null)
299 {
300 valueExpression = new LocationValueExpression(location, valueExpression,
301 actx.getFaceletCompositionContext().getCompositeComponentLevel());
302 }
303 }
304 }
305 else if ((this.capabilities & EL_RESOURCE) != 0)
306 {
307 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
308 if (cc != null)
309 {
310 Location location = (Location) cc.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
311 if (location != null)
312 {
313 valueExpression = new ResourceLocationValueExpression(location, valueExpression);
314 }
315 }
316 }
317
318 ELTextVariable eltv = new ELTextVariable(valueExpression);
319
320 if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
321 {
322 cached = eltv;
323 }
324 return eltv;
325 }
326 finally
327 {
328 actx.afterConstructELExpression();
329 }
330 }
331
332 public void write(Writer out, ELContext ctx) throws ELException, IOException
333 {
334 Object v = this.ve.getValue(ctx);
335 if (v != null)
336 {
337 out.write((String) v);
338 }
339 }
340
341 public String toString(ELContext ctx) throws ELException
342 {
343 Object v = this.ve.getValue(ctx);
344 if (v != null)
345 {
346 return v.toString();
347 }
348
349 return null;
350 }
351
352 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
353 {
354 Object v = this.ve.getValue(ctx);
355 if (v != null)
356 {
357 out.writeText((String) v, null);
358 }
359 }
360 }
361
362 protected final String literal;
363
364 public ELText(String literal)
365 {
366 this.literal = literal;
367 }
368
369
370
371
372
373
374 public boolean isLiteral()
375 {
376 return true;
377 }
378
379
380
381
382
383
384
385
386
387
388 public ELText apply(ExpressionFactory factory, ELContext ctx)
389 {
390 return this;
391 }
392
393
394
395
396
397
398
399
400
401
402
403 public void write(Writer out, ELContext ctx) throws ELException, IOException
404 {
405 out.write(this.literal);
406 }
407
408 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
409 {
410 out.writeText(this.literal, null);
411 }
412
413
414
415
416
417
418
419
420
421 public String toString(ELContext ctx) throws ELException
422 {
423 return this.literal;
424 }
425
426 public String toString()
427 {
428 return this.literal;
429 }
430
431
432
433
434
435
436
437
438 public static boolean isLiteral(String in)
439 {
440
441
442 return isLiteral(null, null, in);
443 }
444
445
446
447
448
449
450
451
452
453
454 public static ELText parse(String in) throws ELException
455 {
456 return parse(null, null, in);
457 }
458
459 public static ELText parseAllowEmptyString(String in) throws ELException
460 {
461 if (in != null && in.length() == 0)
462 {
463 return new ELText(in);
464 }
465 else
466 {
467 return parse(null, null, in);
468 }
469 }
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485 public static ELText parse(ExpressionFactory fact, ELContext ctx, String in) throws ELException
486 {
487 char[] ca = in.toCharArray();
488 int i = 0;
489 char c = 0;
490 int len = ca.length;
491 int end = len - 1;
492 boolean esc = false;
493 int vlen = 0;
494
495 StringBuffer buff = new StringBuffer(128);
496 List<ELText> text = new ArrayList<ELText>();
497 ELText t = null;
498 ValueExpression ve = null;
499
500 while (i < len)
501 {
502 c = ca[i];
503 if ('\\' == c)
504 {
505 esc = !esc;
506 if (esc && i < end && (ca[i + 1] == '$' || ca[i + 1] == '#'))
507 {
508 i++;
509 continue;
510 }
511 }
512 else if (!esc && ('$' == c || '#' == c))
513 {
514 if (i < end)
515 {
516 if ('{' == ca[i + 1])
517 {
518 if (buff.length() > 0)
519 {
520 text.add(new ELText(buff.toString()));
521 buff.setLength(0);
522 }
523 vlen = findVarLength(ca, i);
524 if (ctx != null && fact != null)
525 {
526 ve = fact.createValueExpression(ctx, new String(ca, i, vlen), String.class);
527 t = new ELCacheableTextVariable(ve);
528 }
529 else
530 {
531 t = new ELCacheableTextVariable(new LiteralValueExpression(new String(ca, i, vlen)));
532 }
533 text.add(t);
534 i += vlen;
535 continue;
536 }
537 }
538 }
539 esc = false;
540 buff.append(c);
541 i++;
542 }
543
544 if (buff.length() > 0)
545 {
546 text.add(new ELText(buff.toString()));
547 buff.setLength(0);
548 }
549
550 if (text.isEmpty())
551 {
552 return null;
553 }
554 else if (text.size() == 1)
555 {
556 return (ELText) text.get(0);
557 }
558 else
559 {
560 ELText[] ta = (ELText[]) text.toArray(new ELText[text.size()]);
561 return new ELTextComposite(ta);
562 }
563 }
564
565 public static ELText[] parseAsArray(String in) throws ELException
566 {
567 return parseAsArray(null, null, in);
568 }
569
570 public static ELText[] parseAsArray(ExpressionFactory fact, ELContext ctx, String in) throws ELException
571 {
572 char[] ca = in.toCharArray();
573 int i = 0;
574 char c = 0;
575 int len = ca.length;
576 int end = len - 1;
577 boolean esc = false;
578 int vlen = 0;
579
580 StringBuffer buff = new StringBuffer(128);
581 List<ELText> text = new ArrayList<ELText>();
582 ELText t = null;
583 ValueExpression ve = null;
584
585 while (i < len)
586 {
587 c = ca[i];
588 if ('\\' == c)
589 {
590 esc = !esc;
591 if (esc && i < end && (ca[i + 1] == '$' || ca[i + 1] == '#'))
592 {
593 i++;
594 continue;
595 }
596 }
597 else if (!esc && ('$' == c || '#' == c))
598 {
599 if (i < end)
600 {
601 if ('{' == ca[i + 1])
602 {
603 if (buff.length() > 0)
604 {
605 text.add(new ELText(buff.toString()));
606 buff.setLength(0);
607 }
608 vlen = findVarLength(ca, i);
609 if (ctx != null && fact != null)
610 {
611 ve = fact.createValueExpression(ctx, new String(ca, i, vlen), String.class);
612 t = new ELCacheableTextVariable(ve);
613 }
614 else
615 {
616 t = new ELCacheableTextVariable(new LiteralValueExpression(new String(ca, i, vlen)));
617 }
618 text.add(t);
619 i += vlen;
620 continue;
621 }
622 }
623 }
624 esc = false;
625 buff.append(c);
626 i++;
627 }
628
629 if (buff.length() > 0)
630 {
631 text.add(new ELText(buff.toString()));
632 buff.setLength(0);
633 }
634
635 if (text.isEmpty())
636 {
637 return null;
638 }
639 else if (text.size() == 1)
640 {
641 return new ELText[]{text.get(0)};
642 }
643 else
644 {
645 ELText[] ta = (ELText[]) text.toArray(new ELText[text.size()]);
646 return ta;
647 }
648 }
649
650 public static boolean isLiteral(ExpressionFactory fact, ELContext ctx, String in) throws ELException
651 {
652 char[] ca = in.toCharArray();
653 int i = 0;
654 char c = 0;
655 int len = ca.length;
656 int end = len - 1;
657 boolean esc = false;
658
659
660 while (i < len)
661 {
662 c = ca[i];
663 if ('\\' == c)
664 {
665 esc = !esc;
666 if (esc && i < end && (ca[i + 1] == '$' || ca[i + 1] == '#'))
667 {
668 i++;
669 continue;
670 }
671 }
672 else if (!esc && ('$' == c || '#' == c))
673 {
674 if (i < end)
675 {
676 if ('{' == ca[i + 1])
677 {
678
679
680 return false;
681 }
682 }
683 }
684 esc = false;
685 i++;
686 }
687 return true;
688 }
689
690 private static int findVarLength(char[] ca, int s) throws ELException
691 {
692 int i = s;
693 int len = ca.length;
694 char c = 0;
695 int str = 0;
696 int nest = 0;
697 while (i < len)
698 {
699 c = ca[i];
700 if ('\\' == c && i < len - 1)
701 {
702 i++;
703 }
704 else if ('\'' == c || '"' == c)
705 {
706 if (str == c)
707 {
708 str = 0;
709 }
710 else
711 {
712 str = c;
713 }
714 }
715 else if ('{' == c && str == 0)
716 {
717 ++nest;
718 }
719 else if ('}' == c && str == 0 && nest > 1)
720 {
721 --nest;
722 }
723 else if (str == 0 && ('}' == c && nest == 1))
724 {
725 return i - s + 1;
726 }
727 i++;
728 }
729 throw new ELException("EL Expression Unbalanced: ... " + new String(ca, s, i - s));
730 }
731
732 }