1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.el;
20
21 import java.lang.reflect.Method;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.faces.application.Application;
26 import javax.faces.component.StateHolder;
27 import javax.faces.context.ExternalContext;
28 import javax.faces.context.FacesContext;
29 import javax.faces.el.EvaluationException;
30 import javax.faces.el.PropertyNotFoundException;
31 import javax.faces.el.PropertyResolver;
32 import javax.faces.el.ReferenceSyntaxException;
33 import javax.faces.el.ValueBinding;
34 import javax.servlet.jsp.el.ELException;
35 import javax.servlet.jsp.el.FunctionMapper;
36 import javax.servlet.jsp.el.VariableResolver;
37
38 import org.apache.myfaces.config.RuntimeConfig;
39 import org.apache.myfaces.config.element.ManagedBean;
40 import org.apache.myfaces.shared_impl.util.BiLevelCacheMap;
41
42 import org.apache.commons.el.ArraySuffix;
43 import org.apache.commons.el.Coercions;
44 import org.apache.commons.el.ComplexValue;
45 import org.apache.commons.el.ConditionalExpression;
46 import org.apache.commons.el.Expression;
47 import org.apache.commons.el.ExpressionString;
48 import org.apache.commons.el.NamedValue;
49 import org.apache.commons.el.PropertySuffix;
50 import org.apache.commons.el.ValueSuffix;
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54
55
56
57
58
59
60 public class ValueBindingImpl extends ValueBinding implements StateHolder
61 {
62
63
64 static final Log log = LogFactory.getLog(ValueBindingImpl.class);
65
66
67
68
69
70 protected static FunctionMapper s_functionMapper = new FunctionMapper()
71 {
72 public Method resolveFunction(String prefix, String localName)
73 {
74 throw new ReferenceSyntaxException(
75 "Functions not supported in expressions. Function: "
76 + prefix + ":" + localName);
77 }
78 };
79
80 private static final BiLevelCacheMap s_expressionCache =
81 new BiLevelCacheMap(90)
82 {
83 protected Object newInstance(Object key)
84 {
85 return ELParserHelper.parseExpression((String) key);
86 }
87 };
88
89
90
91 protected Application _application;
92 protected String _expressionString;
93 protected Object _expression;
94
95
96
97
98
99 private RuntimeConfig _runtimeConfig;
100
101
102
103 public ValueBindingImpl(Application application, String expression)
104 {
105 if (application == null)
106 {
107 throw new NullPointerException("application");
108 }
109
110
111 if ((expression == null) || (expression.length() == 0))
112 {
113 throw new ReferenceSyntaxException("Expression: empty or null");
114 }
115 _application = application;
116 _expressionString = expression;
117
118 _expression = s_expressionCache.get(expression);
119 }
120
121
122
123 public String getExpressionString()
124 {
125 return _expressionString;
126 }
127
128 public boolean isReadOnly(FacesContext facesContext)
129 {
130 if (facesContext == null) {
131 throw new NullPointerException("facesContext");
132 }
133 try
134 {
135 Object base_ = resolveToBaseAndProperty(facesContext);
136 if (base_ instanceof String)
137 {
138 return VariableResolverImpl.s_standardImplicitObjects
139 .containsKey(base_);
140 }
141
142 Object[] baseAndProperty = (Object[]) base_;
143 Object base = baseAndProperty[0];
144 Object property = baseAndProperty[1];
145
146 Integer index = ELParserHelper.toIndex(base, property);
147 return (index == null)
148 ? _application.getPropertyResolver().isReadOnly(base, property)
149 : _application.getPropertyResolver()
150 .isReadOnly(base, index.intValue());
151 }
152 catch (NotVariableReferenceException e)
153 {
154
155
156 return true;
157 }
158 catch (Exception e)
159 {
160 log.info("Exception while determining read-only state of value-binding : "+_expressionString);
161
162
163
164 return true;
165 }
166 }
167
168 public Class getType(FacesContext facesContext)
169 {
170 if (facesContext == null) {
171 throw new NullPointerException("facesContext");
172 }
173 try
174 {
175 Object base_ = resolveToBaseAndProperty(facesContext);
176 if (base_ instanceof String)
177 {
178 String name = (String) base_;
179
180
181
182
183 ManagedBean mbConfig =
184 getRuntimeConfig(facesContext).getManagedBean(name);
185 if (mbConfig != null)
186 {
187
188
189 return mbConfig.getManagedBeanClass();
190 }
191
192 Object val = _application.getVariableResolver()
193 .resolveVariable(facesContext, name);
194
195
196
197
198 return (val != null) ? val.getClass() : Object.class;
199 }
200 else
201 {
202 Object[] baseAndProperty = (Object[]) base_;
203 Object base = baseAndProperty[0];
204 Object property = baseAndProperty[1];
205
206 Integer index = ELParserHelper.toIndex(base, property);
207 return (index == null)
208 ? _application.getPropertyResolver().getType(base, property)
209 : _application.getPropertyResolver()
210 .getType(base, index.intValue());
211 }
212 }
213 catch (NotVariableReferenceException e)
214 {
215
216
217
218
219
220 try
221 {
222 return getValue(facesContext).getClass();
223 }
224 catch (Exception e1)
225 {
226
227 return null;
228 }
229 }
230 catch (PropertyNotFoundException e) {
231 throw e;
232 }
233 catch (Exception e)
234 {
235 if(log.isDebugEnabled())
236 log.debug("Exception while retrieving type for ValueBinding.",e);
237
238
239 return null;
240 }
241 }
242
243 public void setValue(FacesContext facesContext, Object newValue)
244 throws EvaluationException, PropertyNotFoundException
245 {
246 if (facesContext == null) {
247 throw new NullPointerException("facesContext");
248 }
249 try
250 {
251 Object base_ = resolveToBaseAndProperty(facesContext);
252 if (base_ instanceof String)
253 {
254 String name = (String) base_;
255 if (VariableResolverImpl.s_standardImplicitObjects
256 .containsKey(name))
257 {
258 String errorMessage =
259 "Cannot set value of implicit object '"
260 + name + "' for expression '" + _expressionString + "'";
261 throw new ReferenceSyntaxException(errorMessage);
262 }
263
264
265 setValueInScope(facesContext, name, newValue);
266 }
267 else
268 {
269 Object[] baseAndProperty = (Object[]) base_;
270 Object base = baseAndProperty[0];
271 Object property = baseAndProperty[1];
272 PropertyResolver propertyResolver =
273 _application.getPropertyResolver();
274
275 Integer index = ELParserHelper.toIndex(base, property);
276 if (index == null)
277 {
278 propertyResolver.setValue(
279 base, property, newValue);
280 }
281 else
282 {
283 int indexVal = index.intValue();
284 propertyResolver.setValue(
285 base, indexVal, newValue);
286 }
287 }
288 }
289 catch (IndexOutOfBoundsException e)
290 {
291
292 throw new PropertyNotFoundException(
293 "Expression: '" + _expressionString + "'", e);
294 }
295 catch (EvaluationException e)
296 {
297 throw e;
298 }
299 catch (Exception e)
300 {
301 String msg;
302 if (newValue == null)
303 {
304 msg = "Cannot set value for expression '"
305 + _expressionString + "' to null.";
306 }
307 else
308 {
309 msg = "Cannot set value for expression '"
310 + _expressionString + "' to a new value of type "
311 + newValue.getClass().getName();
312 }
313 throw new EvaluationException(msg, e);
314 }
315 }
316
317 private void setValueInScope(
318 FacesContext facesContext, String name, Object newValue)
319 throws ELException
320 {
321 ExternalContext externalContext = facesContext.getExternalContext();
322
323
324 Map scopeMap = externalContext.getRequestMap();
325 Object obj = scopeMap.get(name);
326 if (obj != null)
327 {
328 scopeMap.put(name, newValue);
329 return;
330 }
331
332
333 scopeMap = externalContext.getSessionMap();
334 obj = scopeMap.get(name);
335 if (obj != null)
336 {
337 scopeMap.put(name, newValue);
338 return;
339 }
340
341
342 scopeMap = externalContext.getApplicationMap();
343 obj = scopeMap.get(name);
344 if (obj != null)
345 {
346 scopeMap.put(name, newValue);
347 return;
348 }
349
350
351 ManagedBean mbConfig =
352 getRuntimeConfig(facesContext).getManagedBean(name);
353 if (mbConfig != null)
354 {
355 String scopeName = mbConfig.getManagedBeanScope();
356
357
358
359 Scope scope =
360 (Scope) VariableResolverImpl.s_standardScopes.get(scopeName);
361 if (scope != null)
362 {
363 scope.put(externalContext, name, newValue);
364 return;
365 }
366
367 log.error("Managed bean '" + name + "' has illegal scope: "
368 + scopeName);
369
370 externalContext.getRequestMap().put(name, newValue);
371 return;
372 }
373
374
375 externalContext.getRequestMap().put(name, newValue);
376 }
377
378 public Object getValue(FacesContext facesContext)
379 throws EvaluationException, PropertyNotFoundException
380 {
381 if (facesContext == null) {
382 throw new NullPointerException("facesContext");
383 }
384 try
385 {
386 return _expression instanceof Expression
387 ? ((Expression) _expression).evaluate(
388 new ELVariableResolver(facesContext),
389 s_functionMapper, ELParserHelper.LOGGER)
390 : ((ExpressionString) _expression).evaluate(
391 new ELVariableResolver(facesContext),
392 s_functionMapper, ELParserHelper.LOGGER);
393 }
394 catch (PropertyNotFoundException e) {
395 throw e;
396 }
397 catch (IndexOutOfBoundsException e)
398 {
399
400 throw new PropertyNotFoundException(
401 "Expression: '" + _expressionString + "'", e);
402 }
403 catch (Exception e)
404 {
405 throw new EvaluationException(
406 "Cannot get value for expression '" + _expressionString
407 + "'", e);
408 }
409 }
410
411 protected Object resolveToBaseAndProperty(FacesContext facesContext)
412 throws ELException, NotVariableReferenceException
413 {
414 if (facesContext == null)
415 {
416 throw new NullPointerException("facesContext");
417 }
418
419 VariableResolver variableResolver =
420 new ELVariableResolver(facesContext);
421 Object expression = _expression;
422
423 while (expression instanceof ConditionalExpression)
424 {
425 ConditionalExpression conditionalExpression =
426 ((ConditionalExpression) expression);
427
428
429 boolean condition =
430 Coercions.coerceToBoolean(
431 conditionalExpression.getCondition().evaluate(
432 variableResolver, s_functionMapper,
433 ELParserHelper.LOGGER),
434 ELParserHelper.LOGGER)
435 .booleanValue();
436
437
438 expression = condition ? conditionalExpression.getTrueBranch()
439 : conditionalExpression.getFalseBranch();
440 }
441
442 if (expression instanceof NamedValue)
443 {
444 return ((NamedValue) expression).getName();
445 }
446
447 if (!(expression instanceof ComplexValue)) {
448
449 throw new NotVariableReferenceException(
450 "Parsed Expression of unsupported type for this operation. Expression class: "
451 + _expression.getClass().getName() + ". Expression: '"
452 + _expressionString + "'");
453 }
454
455 ComplexValue complexValue = (ComplexValue) expression;
456
457
458 Object base = complexValue.getPrefix()
459 .evaluate(variableResolver, s_functionMapper,
460 ELParserHelper.LOGGER);
461 if (base == null)
462 {
463 throw new PropertyNotFoundException("Base is null: "
464 + complexValue.getPrefix().getExpressionString());
465 }
466
467
468 List suffixes = complexValue.getSuffixes();
469 int max = suffixes.size() - 1;
470 for (int i = 0; i < max; i++)
471 {
472 ValueSuffix suffix = (ValueSuffix) suffixes.get(i);
473 base = suffix.evaluate(base, variableResolver, s_functionMapper,
474 ELParserHelper.LOGGER);
475 if (base == null)
476 {
477 throw new PropertyNotFoundException("Base is null: "
478 + suffix.getExpressionString());
479 }
480 }
481
482
483 ArraySuffix arraySuffix = (ArraySuffix) suffixes.get(max);
484 Expression arraySuffixIndex = arraySuffix.getIndex();
485
486 Object index;
487 if (arraySuffixIndex != null)
488 {
489 index = arraySuffixIndex.evaluate(
490 variableResolver, s_functionMapper,
491 ELParserHelper.LOGGER);
492 if (index == null)
493 {
494 throw new PropertyNotFoundException("Index is null: "
495 + arraySuffixIndex.getExpressionString());
496 }
497 }
498 else
499 {
500 index = ((PropertySuffix) arraySuffix).getName();
501 }
502
503 return new Object[] {base, index};
504 }
505
506 protected RuntimeConfig getRuntimeConfig(FacesContext facesContext)
507 {
508 if (_runtimeConfig == null)
509 {
510 _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
511 }
512 return _runtimeConfig;
513 }
514
515 public String toString()
516 {
517 return _expressionString;
518 }
519
520
521
522 private boolean _transient = false;
523
524
525
526
527
528 public ValueBindingImpl()
529 {
530 _application = null;
531 _expressionString = null;
532 _expression = null;
533 }
534
535 public Object saveState(FacesContext facesContext)
536 {
537 return _expressionString;
538 }
539
540 public void restoreState(FacesContext facesContext, Object obj)
541 {
542 _application = facesContext.getApplication();
543 _expressionString = (String) obj;
544 _expression = s_expressionCache.get(_expressionString);
545 }
546
547 public boolean isTransient()
548 {
549 return _transient;
550 }
551
552 public void setTransient(boolean flag)
553 {
554 _transient = flag;
555 }
556
557
558
559 public static class ELVariableResolver implements VariableResolver {
560 private final FacesContext _facesContext;
561
562 public ELVariableResolver(FacesContext facesContext)
563 {
564 _facesContext = facesContext;
565 }
566
567 public Object resolveVariable(String pName)
568 throws ELException
569 {
570 return _facesContext.getApplication().getVariableResolver()
571 .resolveVariable(_facesContext, pName);
572 }
573 }
574
575 public static final class NotVariableReferenceException
576 extends ReferenceSyntaxException
577 {
578 private static final long serialVersionUID = 818254526596948605L;
579
580 public NotVariableReferenceException(String message)
581 {
582 super(message);
583 }
584 }
585 }