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