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.tag;
20
21 import java.util.Arrays;
22
23 import javax.el.ELException;
24 import javax.el.ExpressionFactory;
25 import javax.el.MethodExpression;
26 import javax.el.ValueExpression;
27 import javax.faces.component.UIComponent;
28 import javax.faces.view.Location;
29 import javax.faces.view.facelets.FaceletContext;
30 import javax.faces.view.facelets.TagAttribute;
31 import javax.faces.view.facelets.TagAttributeException;
32
33 import org.apache.myfaces.util.ExternalSpecifications;
34 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
35 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
36 import org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression;
37 import org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression;
38 import org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpressionUEL;
39 import org.apache.myfaces.view.facelets.el.ELText;
40 import org.apache.myfaces.view.facelets.el.LocationMethodExpression;
41 import org.apache.myfaces.view.facelets.el.LocationValueExpression;
42 import org.apache.myfaces.view.facelets.el.LocationValueExpressionUEL;
43 import org.apache.myfaces.view.facelets.el.ResourceELUtils;
44 import org.apache.myfaces.view.facelets.el.ResourceLocationValueExpression;
45 import org.apache.myfaces.view.facelets.el.ResourceLocationValueExpressionUEL;
46 import org.apache.myfaces.view.facelets.el.TagMethodExpression;
47 import org.apache.myfaces.view.facelets.el.TagValueExpression;
48 import org.apache.myfaces.view.facelets.el.TagValueExpressionUEL;
49 import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
50
51
52
53
54
55
56
57 public final class TagAttributeImpl extends TagAttribute
58 {
59
60 private final static int EL_LITERAL = 1;
61
62 private final static int EL_CC = 2;
63
64 private final static int EL_CC_ATTR_ME = 4;
65
66 private final static int EL_RESOURCE = 8;
67
68 private final int capabilities;
69
70 private final String localName;
71
72 private final Location location;
73
74 private final String namespace;
75
76 private final String qName;
77
78 private final String value;
79
80 private String string;
81
82
83
84
85
86
87
88 private volatile Object[] cachedExpression;
89
90 public TagAttributeImpl(Location location, String ns, String localName, String qName, String value)
91 {
92 boolean literal;
93 boolean compositeComponentExpression;
94 boolean compositeComponentAttrMethodExpression;
95 boolean resourceExpression;
96 this.location = location;
97 this.namespace = ns;
98
99
100
101 this.localName = (localName == null) ? qName : ((localName.length() > 0) ? localName : qName);
102 this.qName = qName;
103 this.value = value;
104
105 try
106 {
107 literal = ELText.isLiteral(this.value);
108 }
109 catch (ELException e)
110 {
111 throw new TagAttributeException(this, e);
112 }
113
114 compositeComponentExpression = !literal ?
115 CompositeComponentELUtils.isCompositeComponentExpression(this.value) :
116 false;
117 compositeComponentAttrMethodExpression = compositeComponentExpression ?
118 CompositeComponentELUtils.isCompositeComponentAttrsMethodExpression(this.value) :
119 false;
120 resourceExpression = !literal ? ResourceELUtils.isResourceExpression(this.value) : false;
121
122 this.capabilities = (literal ? EL_LITERAL : 0) | (compositeComponentExpression ? EL_CC : 0) |
123 (compositeComponentAttrMethodExpression ? EL_CC_ATTR_ME : 0) | ( resourceExpression ? EL_RESOURCE : 0);
124 }
125
126
127
128
129
130
131
132
133
134
135
136 public boolean getBoolean(FaceletContext ctx)
137 {
138 if ((this.capabilities & EL_LITERAL) != 0)
139 {
140 return Boolean.valueOf(this.value).booleanValue();
141 }
142 else
143 {
144 return ((Boolean) this.getObject(ctx, Boolean.class)).booleanValue();
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157
158 public int getInt(FaceletContext ctx)
159 {
160 if ((this.capabilities & EL_LITERAL) != 0)
161 {
162 return Integer.parseInt(this.value);
163 }
164 else
165 {
166 return ((Number) this.getObject(ctx, Integer.class)).intValue();
167 }
168 }
169
170
171
172
173
174
175 public String getLocalName()
176 {
177 return this.localName;
178 }
179
180
181
182
183
184
185 public Location getLocation()
186 {
187 return this.location;
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public MethodExpression getMethodExpression(FaceletContext ctx, Class type, Class[] paramTypes)
205 {
206 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
207
208
209 Object[] localCachedExpression = cachedExpression;
210
211 if (actx.isAllowCacheELExpressions() && localCachedExpression != null &&
212 (localCachedExpression.length % 3 == 0))
213 {
214
215 for (int i = 0; i < (localCachedExpression.length/3); i++)
216 {
217 if ( ((type == null && localCachedExpression[(i*3)] == null ) ||
218 (type != null && type.equals(localCachedExpression[(i*3)])) ) &&
219 (Arrays.equals(paramTypes, (Class[]) localCachedExpression[(i*3)+1])) )
220 {
221 if ((this.capabilities & EL_CC) != 0 &&
222 localCachedExpression[(i*3)+2] instanceof LocationMethodExpression)
223 {
224 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
225 if (cc != null)
226 {
227 Location location = (Location) cc.getAttributes().get(
228 CompositeComponentELUtils.LOCATION_KEY);
229 if (location != null)
230 {
231 return ((LocationMethodExpression)localCachedExpression[(i*3)+2]).apply(
232 actx.getFaceletCompositionContext().getCompositeComponentLevel(), location);
233 }
234 }
235 return ((LocationMethodExpression)localCachedExpression[(i*3)+2]).apply(
236 actx.getFaceletCompositionContext().getCompositeComponentLevel());
237 }
238 return (MethodExpression) localCachedExpression[(i*3)+2];
239 }
240 }
241 }
242
243 actx.beforeConstructELExpression();
244 try
245 {
246 MethodExpression methodExpression = null;
247
248
249
250
251
252
253 if ((this.capabilities & EL_CC_ATTR_ME) != 0)
254 {
255
256
257
258
259
260 if (ExternalSpecifications.isUnifiedELAvailable() && this.value.contains("("))
261 {
262
263
264
265 throw new ELException("Cannot add parameters to a MethodExpression "
266 + "pointing to cc.attrs");
267 }
268
269 ValueExpression valueExpr = this.getValueExpression(ctx, Object.class);
270 methodExpression = new ValueExpressionMethodExpression(valueExpr);
271
272 if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
273 {
274 methodExpression = new ContextAwareTagMethodExpression(this, methodExpression);
275 }
276 else
277 {
278 methodExpression = new TagMethodExpression(this, methodExpression);
279 }
280 }
281 else
282 {
283 ExpressionFactory f = ctx.getExpressionFactory();
284 methodExpression = f.createMethodExpression(ctx, this.value, type, paramTypes);
285
286 if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
287 {
288 methodExpression = new ContextAwareTagMethodExpression(this, methodExpression);
289 }
290 else
291 {
292 methodExpression = new TagMethodExpression(this, methodExpression);
293 }
294
295
296
297
298
299
300 if ((this.capabilities & EL_CC) != 0)
301 {
302 Location currentLocation = getLocation();
303 Location ccLocation = (Location) actx.getFaceletCompositionContext().
304 getCompositeComponentFromStack().getAttributes().get(
305 CompositeComponentELUtils.LOCATION_KEY);
306 if (ccLocation != null && !ccLocation.getPath().equals(currentLocation.getPath()))
307 {
308
309
310
311 currentLocation = ccLocation;
312 }
313 methodExpression = new LocationMethodExpression(currentLocation, methodExpression,
314 actx.getFaceletCompositionContext().getCompositeComponentLevel());
315 }
316 }
317
318
319 if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
320 {
321 if (localCachedExpression != null && (localCachedExpression.length % 3 == 0))
322 {
323
324
325 Object[] array = new Object[localCachedExpression.length+3];
326 array[0] = type;
327 array[1] = paramTypes;
328 array[2] = methodExpression;
329 for (int i = 0; i < localCachedExpression.length; i++)
330 {
331 array[i+3] = localCachedExpression[i];
332 }
333 cachedExpression = array;
334 }
335 else
336 {
337 cachedExpression = new Object[]{type, paramTypes, methodExpression};
338 }
339 }
340
341 return methodExpression;
342 }
343 catch (Exception e)
344 {
345 throw new TagAttributeException(this, e);
346 }
347 finally
348 {
349 actx.afterConstructELExpression();
350 }
351 }
352
353
354
355
356
357
358 public String getNamespace()
359 {
360 return this.namespace;
361 }
362
363
364
365
366
367
368
369
370
371 public Object getObject(FaceletContext ctx)
372 {
373 return this.getObject(ctx, Object.class);
374 }
375
376
377
378
379
380
381 public String getQName()
382 {
383 return this.qName;
384 }
385
386
387
388
389
390
391 public String getValue()
392 {
393 return this.value;
394 }
395
396
397
398
399
400
401
402
403
404 public String getValue(FaceletContext ctx)
405 {
406 if ((this.capabilities & EL_LITERAL) != 0)
407 {
408 return this.value;
409 }
410 else
411 {
412 return (String) this.getObject(ctx, String.class);
413 }
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 public Object getObject(FaceletContext ctx, Class type)
430 {
431 if ((this.capabilities & EL_LITERAL) != 0)
432 {
433 if (String.class.equals(type))
434 {
435 return this.value;
436 }
437 else
438 {
439 try
440 {
441 return ctx.getExpressionFactory().coerceToType(this.value, type);
442 }
443 catch (Exception e)
444 {
445 throw new TagAttributeException(this, e);
446 }
447 }
448 }
449 else
450 {
451 ValueExpression ve = this.getValueExpression(ctx, type);
452 try
453 {
454 return ve.getValue(ctx);
455 }
456 catch (Exception e)
457 {
458 throw new TagAttributeException(this, e);
459 }
460 }
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474 public ValueExpression getValueExpression(FaceletContext ctx, Class type)
475 {
476 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
477
478
479 Object[] localCachedExpression = cachedExpression;
480 if (actx.isAllowCacheELExpressions() && localCachedExpression != null && localCachedExpression.length == 2)
481 {
482
483 if (localCachedExpression[0] == null && type == null)
484 {
485
486 if ((this.capabilities & EL_CC) != 0)
487 {
488 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
489 if (cc != null)
490 {
491 Location location = (Location) cc.getAttributes().get(
492 CompositeComponentELUtils.LOCATION_KEY);
493 if (location != null)
494 {
495 return ((LocationValueExpression)localCachedExpression[1]).apply(
496 actx.getFaceletCompositionContext().getCompositeComponentLevel(), location);
497 }
498 }
499 return ((LocationValueExpression)localCachedExpression[1]).apply(
500 actx.getFaceletCompositionContext().getCompositeComponentLevel());
501 }
502 return (ValueExpression) localCachedExpression[1];
503 }
504 else if (localCachedExpression[0] != null && localCachedExpression[0].equals(type))
505 {
506
507 if ((this.capabilities & EL_CC) != 0)
508 {
509 UIComponent cc = actx.getFaceletCompositionContext().getCompositeComponentFromStack();
510 if (cc != null)
511 {
512 Location location = (Location) cc.getAttributes().get(
513 CompositeComponentELUtils.LOCATION_KEY);
514 if (location != null)
515 {
516 return ((LocationValueExpression)localCachedExpression[1]).apply(
517 actx.getFaceletCompositionContext().getCompositeComponentLevel(), location);
518 }
519 }
520 return ((LocationValueExpression)localCachedExpression[1]).apply(
521 actx.getFaceletCompositionContext().getCompositeComponentLevel());
522 }
523 return (ValueExpression) localCachedExpression[1];
524 }
525 }
526
527 actx.beforeConstructELExpression();
528 try
529 {
530 ExpressionFactory f = ctx.getExpressionFactory();
531 ValueExpression valueExpression = f.createValueExpression(ctx, this.value, type);
532
533 if (ExternalSpecifications.isUnifiedELAvailable())
534 {
535 if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
536 {
537 valueExpression = new ContextAwareTagValueExpressionUEL(this, valueExpression);
538 }
539 else
540 {
541 valueExpression = new TagValueExpressionUEL(this, valueExpression);
542 }
543 }
544 else
545 {
546 if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
547 {
548 valueExpression = new ContextAwareTagValueExpression(this, valueExpression);
549 }
550 else
551 {
552 valueExpression = new TagValueExpression(this, valueExpression);
553 }
554 }
555
556
557
558
559
560
561 if ((this.capabilities & EL_CC) != 0)
562 {
563
564
565
566
567 Location currentLocation = getLocation();
568 Location ccLocation = (Location) actx.getFaceletCompositionContext().
569 getCompositeComponentFromStack().getAttributes().get(
570 CompositeComponentELUtils.LOCATION_KEY);
571 if (ccLocation != null && !ccLocation.getPath().equals(currentLocation.getPath()))
572 {
573
574
575
576
577 currentLocation = ccLocation;
578 }
579 if (ExternalSpecifications.isUnifiedELAvailable())
580 {
581 valueExpression = new LocationValueExpressionUEL(currentLocation, valueExpression,
582 actx.getFaceletCompositionContext().getCompositeComponentLevel());
583 }
584 else
585 {
586 valueExpression = new LocationValueExpression(currentLocation, valueExpression,
587 actx.getFaceletCompositionContext().getCompositeComponentLevel());
588 }
589 }
590 else if ((this.capabilities & EL_RESOURCE) != 0)
591 {
592 if (ExternalSpecifications.isUnifiedELAvailable())
593 {
594 valueExpression = new ResourceLocationValueExpressionUEL(getLocation(), valueExpression);
595 }
596 else
597 {
598 valueExpression = new ResourceLocationValueExpression(getLocation(), valueExpression);
599 }
600 }
601
602
603 if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
604 {
605 cachedExpression = new Object[]{type, valueExpression};
606 }
607 return valueExpression;
608 }
609 catch (Exception e)
610 {
611 throw new TagAttributeException(this, e);
612 }
613 finally
614 {
615 actx.afterConstructELExpression();
616 }
617 }
618
619
620
621
622
623
624 public boolean isLiteral()
625 {
626 return (this.capabilities & EL_LITERAL) != 0;
627 }
628
629
630
631
632
633
634 public String toString()
635 {
636 if (this.string == null)
637 {
638 this.string = this.location + " " + this.qName + "=\"" + this.value + "\"";
639 }
640 return this.string;
641 }
642
643 }