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 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 int capabilities;
234
235 private volatile ELTextVariable cached;
236
237 public ELCacheableTextVariable(ValueExpression ve)
238 {
239 super(ve.getExpressionString());
240 this.ve = ve;
241 boolean compositeComponentExpression = CompositeComponentELUtils.isCompositeComponentExpression(ve.getExpressionString());
242 this.capabilities = (compositeComponentExpression ? EL_CC : 0);
243 }
244
245 public boolean isLiteral()
246 {
247 return false;
248 }
249
250 public ELText apply(ExpressionFactory factory, ELContext ctx)
251 {
252 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
253
254 if (actx.isAllowCacheELExpressions() && cached != null)
255 {
256 return cached;
257 }
258
259 actx.beforeConstructELExpression();
260 try
261 {
262 ValueExpression valueExpression = factory.createValueExpression(ctx, this.ve.getExpressionString(), String.class);
263
264 if ((this.capabilities & EL_CC) != 0)
265 {
266 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
267 if (cc != null)
268 {
269 Location location = (Location) cc.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
270 if (location != null)
271 {
272 if (ExternalSpecifications.isUnifiedELAvailable())
273 {
274 valueExpression = new LocationValueExpressionUEL(location, valueExpression);
275 }
276 else
277 {
278 valueExpression = new LocationValueExpression(location, valueExpression);
279 }
280 }
281 }
282 }
283
284 ELTextVariable eltv = new ELTextVariable(valueExpression);
285
286 if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
287 {
288 cached = eltv;
289 }
290 return eltv;
291 }
292 finally
293 {
294 actx.afterConstructELExpression();
295 }
296 }
297
298 public void write(Writer out, ELContext ctx) throws ELException, IOException
299 {
300 Object v = this.ve.getValue(ctx);
301 if (v != null)
302 {
303 out.write((String) v);
304 }
305 }
306
307 public String toString(ELContext ctx) throws ELException
308 {
309 Object v = this.ve.getValue(ctx);
310 if (v != null)
311 {
312 return v.toString();
313 }
314
315 return null;
316 }
317
318 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
319 {
320 Object v = this.ve.getValue(ctx);
321 if (v != null)
322 {
323 out.writeText((String) v, null);
324 }
325 }
326 }
327
328 protected final String literal;
329
330 public ELText(String literal)
331 {
332 this.literal = literal;
333 }
334
335
336
337
338
339
340 public boolean isLiteral()
341 {
342 return true;
343 }
344
345
346
347
348
349
350
351
352
353
354 public ELText apply(ExpressionFactory factory, ELContext ctx)
355 {
356 return this;
357 }
358
359
360
361
362
363
364
365
366
367
368
369 public void write(Writer out, ELContext ctx) throws ELException, IOException
370 {
371 out.write(this.literal);
372 }
373
374 public void writeText(ResponseWriter out, ELContext ctx) throws ELException, IOException
375 {
376 out.writeText(this.literal, null);
377 }
378
379
380
381
382
383
384
385
386
387 public String toString(ELContext ctx) throws ELException
388 {
389 return this.literal;
390 }
391
392 public String toString()
393 {
394 return this.literal;
395 }
396
397
398
399
400
401
402
403
404 public static boolean isLiteral(String in)
405 {
406 ELText txt = parse(in);
407 return txt == null || txt.isLiteral();
408 }
409
410
411
412
413
414
415
416
417
418
419 public static ELText parse(String in) throws ELException
420 {
421 return parse(null, null, in);
422 }
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 public static ELText parse(ExpressionFactory fact, ELContext ctx, String in) throws ELException
439 {
440 char[] ca = in.toCharArray();
441 int i = 0;
442 char c = 0;
443 int len = ca.length;
444 int end = len - 1;
445 boolean esc = false;
446 int vlen = 0;
447
448 StringBuffer buff = new StringBuffer(128);
449 List<ELText> text = new ArrayList<ELText>();
450 ELText t = null;
451 ValueExpression ve = null;
452
453 while (i < len)
454 {
455 c = ca[i];
456 if ('\\' == c)
457 {
458 esc = !esc;
459 if (esc && i < end && (ca[i + 1] == '$' || ca[i + 1] == '#'))
460 {
461 i++;
462 continue;
463 }
464 }
465 else if (!esc && ('$' == c || '#' == c))
466 {
467 if (i < end)
468 {
469 if ('{' == ca[i + 1])
470 {
471 if (buff.length() > 0)
472 {
473 text.add(new ELText(buff.toString()));
474 buff.setLength(0);
475 }
476 vlen = findVarLength(ca, i);
477 if (ctx != null && fact != null)
478 {
479 ve = fact.createValueExpression(ctx, new String(ca, i, vlen), String.class);
480 t = new ELCacheableTextVariable(ve);
481 }
482 else
483 {
484 t = new ELCacheableTextVariable(new LiteralValueExpression(new String(ca, i, vlen)));
485 }
486 text.add(t);
487 i += vlen;
488 continue;
489 }
490 }
491 }
492 esc = false;
493 buff.append(c);
494 i++;
495 }
496
497 if (buff.length() > 0)
498 {
499 text.add(new ELText(new String(buff.toString())));
500 buff.setLength(0);
501 }
502
503 if (text.size() == 0)
504 {
505 return null;
506 }
507 else if (text.size() == 1)
508 {
509 return (ELText) text.get(0);
510 }
511 else
512 {
513 ELText[] ta = (ELText[]) text.toArray(new ELText[text.size()]);
514 return new ELTextComposite(ta);
515 }
516 }
517
518 private static int findVarLength(char[] ca, int s) throws ELException
519 {
520 int i = s;
521 int len = ca.length;
522 char c = 0;
523 int str = 0;
524 while (i < len)
525 {
526 c = ca[i];
527 if ('\\' == c && i < len - 1)
528 {
529 i++;
530 }
531 else if ('\'' == c || '"' == c)
532 {
533 if (str == c)
534 {
535 str = 0;
536 }
537 else
538 {
539 str = c;
540 }
541 }
542 else if (str == 0 && ('}' == c))
543 {
544 return i - s + 1;
545 }
546 i++;
547 }
548 throw new ELException("EL Expression Unbalanced: ... " + new String(ca, s, i - s));
549 }
550
551 }