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