1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.config;
20
21 import java.lang.reflect.Array;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.el.ELContext;
30 import javax.el.ELException;
31 import javax.el.ELResolver;
32 import javax.el.ExpressionFactory;
33 import javax.el.ValueExpression;
34 import javax.faces.FacesException;
35 import javax.faces.application.Application;
36 import javax.faces.context.ExternalContext;
37 import javax.faces.context.FacesContext;
38 import javax.naming.NamingException;
39
40 import org.apache.commons.beanutils.PropertyUtils;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.apache.myfaces.config.annotation.LifecycleProvider;
44 import org.apache.myfaces.config.annotation.LifecycleProvider2;
45 import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
46 import org.apache.myfaces.config.element.ListEntries;
47 import org.apache.myfaces.config.element.ListEntry;
48 import org.apache.myfaces.config.element.ManagedBean;
49 import org.apache.myfaces.config.element.ManagedProperty;
50 import org.apache.myfaces.config.element.MapEntries;
51 import org.apache.myfaces.config.element.MapEntry;
52 import org.apache.myfaces.shared_impl.util.ClassUtils;
53 import org.apache.myfaces.util.ContainerUtils;
54
55
56
57
58
59
60
61
62 public class ManagedBeanBuilder
63 {
64 private static Log log = LogFactory.getLog(ManagedBeanBuilder.class);
65 private RuntimeConfig _runtimeConfig;
66 public final static String REQUEST = "request";
67 public final static String APPLICATION = "application";
68 public final static String SESSION = "session";
69 public final static String NONE = "none";
70
71 public Object buildManagedBean(FacesContext facesContext, ManagedBean beanConfiguration) throws FacesException
72 {
73
74
75
76
77
78
79
80
81 try
82 {
83 LifecycleProvider lifecycleProvider =
84 LifecycleProviderFactory.getLifecycleProviderFactory().getLifecycleProvider(facesContext.getExternalContext());
85 final Object bean = lifecycleProvider.newInstance(beanConfiguration.getManagedBeanClassName());
86
87 switch (beanConfiguration.getInitMode())
88 {
89 case ManagedBean.INIT_MODE_PROPERTIES:
90 try
91 {
92 initializeProperties(facesContext, beanConfiguration.getManagedProperties(),
93 beanConfiguration.getManagedBeanScope(), bean);
94 }
95 catch (IllegalArgumentException e)
96 {
97 throw new IllegalArgumentException(
98 e.getMessage()
99 + " for bean '"
100 + beanConfiguration.getManagedBeanName()
101 + "' check the configuration to make sure all properties correspond with get/set methods", e);
102 }
103 break;
104
105 case ManagedBean.INIT_MODE_MAP:
106 if (!(bean instanceof Map))
107 {
108 throw new IllegalArgumentException("Class " + bean.getClass().getName()
109 + " of managed bean "
110 + beanConfiguration.getManagedBeanName()
111 + " is not a Map.");
112 }
113 initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map) bean);
114 break;
115
116 case ManagedBean.INIT_MODE_LIST:
117 if (!(bean instanceof List))
118 {
119 throw new IllegalArgumentException("Class " + bean.getClass().getName()
120 + " of managed bean "
121 + beanConfiguration.getManagedBeanName()
122 + " is not a List.");
123 }
124 initializeList(facesContext, beanConfiguration.getListEntries(), (List) bean);
125 break;
126
127 case ManagedBean.INIT_MODE_NO_INIT:
128
129 break;
130
131 default:
132 throw new IllegalStateException("Unknown managed bean type "
133 + bean.getClass().getName() + " for managed bean "
134 + beanConfiguration.getManagedBeanName() + '.');
135 }
136
137
138
139
140 if (lifecycleProvider instanceof LifecycleProvider2)
141 {
142 ((LifecycleProvider2)lifecycleProvider).postConstruct(bean);
143 }
144 return bean;
145 }
146 catch (IllegalAccessException e)
147 {
148 throw new FacesException(e);
149 }
150 catch (InvocationTargetException e)
151 {
152 throw new FacesException(e);
153 }
154 catch (NamingException e)
155 {
156 throw new FacesException(e);
157 }
158 catch (ClassNotFoundException e)
159 {
160 throw new FacesException(e);
161 }
162 catch (InstantiationException e)
163 {
164 throw new FacesException(e);
165 }
166
167 }
168
169
170 private void initializeProperties(FacesContext facesContext, Iterator managedProperties, String targetScope, Object bean)
171 {
172 ELResolver elResolver = facesContext.getApplication().getELResolver();
173 ELContext elContext = facesContext.getELContext();
174
175 while (managedProperties.hasNext())
176 {
177 ManagedProperty property = (ManagedProperty) managedProperties.next();
178 Object value = null;
179
180 switch (property.getType())
181 {
182 case ManagedProperty.TYPE_LIST:
183
184
185
186
187
188 if (PropertyUtils.isReadable(bean, property.getPropertyName()))
189 value = elResolver.getValue(elContext, bean, property.getPropertyName());
190 value = value == null ? new ArrayList() : value;
191
192 if (value instanceof List)
193 {
194 initializeList(facesContext, property.getListEntries(), (List) value);
195
196 }
197 else if (value != null && value.getClass().isArray())
198 {
199 int length = Array.getLength(value);
200 ArrayList temp = new ArrayList(length);
201 for (int i = 0; i < length; i++)
202 {
203 temp.add(Array.get(value, i));
204 }
205 initializeList(facesContext, property.getListEntries(), temp);
206 value = Array.newInstance(value.getClass().getComponentType(), temp.size());
207 length = temp.size();
208
209 for (int i = 0; i < length; i++)
210 {
211 Array.set(value, i, temp.get(i));
212 }
213 }
214 else
215 {
216 value = new ArrayList();
217 initializeList(facesContext, property.getListEntries(), (List) value);
218 }
219
220 break;
221 case ManagedProperty.TYPE_MAP:
222
223
224
225
226
227 if (PropertyUtils.isReadable(bean, property.getPropertyName()))
228 value = elResolver.getValue(elContext, bean, property.getPropertyName());
229 value = value == null ? new HashMap() : value;
230
231 if (!(value instanceof Map))
232 {
233 value = new HashMap();
234 }
235
236 initializeMap(facesContext, property.getMapEntries(), (Map) value);
237 break;
238 case ManagedProperty.TYPE_NULL:
239 value = null;
240 break;
241 case ManagedProperty.TYPE_VALUE:
242
243 if (!isInValidScope(facesContext, property, targetScope))
244 {
245 throw new FacesException("Property " + property.getPropertyName() +
246 " references object in a scope with shorter lifetime than the target scope " + targetScope);
247 }
248 value = property.getRuntimeValue(facesContext);
249 break;
250 }
251 Class propertyClass = null;
252
253 if (property.getPropertyClass() == null)
254 {
255 propertyClass = elResolver
256 .getType(elContext, bean, property.getPropertyName());
257 }
258 else
259 {
260 propertyClass = ClassUtils
261 .simpleJavaTypeToClass(property.getPropertyClass());
262 }
263 if (null == propertyClass)
264 {
265 throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
266 }
267 Object coercedValue = coerceToType(facesContext, value, propertyClass);
268 elResolver.setValue(
269 elContext, bean, property.getPropertyName(), coercedValue);
270 }
271 }
272
273
274
275 public static Object coerceToType(FacesContext facesContext, Object value, Class desiredClass)
276 {
277 if (value == null) return null;
278
279 try
280 {
281 ExpressionFactory expFactory = facesContext.getApplication().getExpressionFactory();
282
283
284 return expFactory.coerceToType(value, desiredClass);
285 }
286 catch (ELException e)
287 {
288 String message = "Cannot coerce " + value.getClass().getName()
289 + " to " + desiredClass.getName();
290 log.error(message, e);
291 throw new FacesException(message, e);
292 }
293 }
294
295
296
297
298
299
300
301
302
303 private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, String targetScope)
304 {
305 if (!property.isValueReference())
306 {
307
308 return true;
309 }
310 String[] expressions = extractExpressions(property.getValueBinding(facesContext).getExpressionString());
311
312 for (int i = 0; i < expressions.length; i++)
313 {
314 String expression = expressions[i];
315 if (expression == null)
316 {
317 continue;
318 }
319
320 String valueScope = getScope(facesContext, expression);
321
322
323 if (targetScope == null || targetScope.equalsIgnoreCase(NONE))
324 {
325 if (valueScope != null && !(valueScope.equalsIgnoreCase(NONE)))
326 {
327 return false;
328 }
329 return true;
330 }
331
332
333 if (targetScope.equalsIgnoreCase(APPLICATION))
334 {
335 if (valueScope != null)
336 {
337 if (valueScope.equalsIgnoreCase(REQUEST) ||
338 valueScope.equalsIgnoreCase(SESSION))
339 {
340 return false;
341 }
342 }
343 return true;
344 }
345
346
347 if (targetScope.equalsIgnoreCase(SESSION))
348 {
349 if (valueScope != null)
350 {
351 if (valueScope.equalsIgnoreCase(REQUEST))
352 {
353 return false;
354 }
355 }
356 return true;
357 }
358
359
360 if (targetScope.equalsIgnoreCase(REQUEST))
361 {
362 return true;
363 }
364 }
365 return false;
366 }
367
368
369 private String getScope(FacesContext facesContext, String expression)
370 {
371 String beanName = getFirstSegment(expression);
372 ExternalContext externalContext = facesContext.getExternalContext();
373
374
375 if (beanName.equalsIgnoreCase("requestScope"))
376 {
377 return REQUEST;
378 }
379 if (beanName.equalsIgnoreCase("sessionScope"))
380 {
381 return SESSION;
382 }
383 if (beanName.equalsIgnoreCase("applicationScope"))
384 {
385 return APPLICATION;
386 }
387
388
389 if (beanName.equalsIgnoreCase("cookie"))
390 {
391 return REQUEST;
392 }
393 if (beanName.equalsIgnoreCase("facesContext"))
394 {
395 return REQUEST;
396 }
397
398 if (beanName.equalsIgnoreCase("header"))
399 {
400 return REQUEST;
401 }
402 if (beanName.equalsIgnoreCase("headerValues"))
403 {
404 return REQUEST;
405 }
406
407 if (beanName.equalsIgnoreCase("initParam"))
408 {
409 return APPLICATION;
410 }
411 if (beanName.equalsIgnoreCase("param"))
412 {
413 return REQUEST;
414 }
415 if (beanName.equalsIgnoreCase("paramValues"))
416 {
417 return REQUEST;
418 }
419 if (beanName.equalsIgnoreCase("view"))
420 {
421 return REQUEST;
422 }
423
424
425 if (externalContext.getRequestMap().get(beanName) != null)
426 {
427 return REQUEST;
428 }
429 if (externalContext.getSessionMap().get(beanName) != null)
430 {
431 return SESSION;
432 }
433 if (externalContext.getApplicationMap().get(beanName) != null)
434 {
435 return APPLICATION;
436 }
437
438
439
440 ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
441
442 if (mbc != null)
443 {
444 return mbc.getManagedBeanScope();
445 }
446
447 return null;
448 }
449
450
451
452
453
454
455
456 private String getFirstSegment(String expression)
457 {
458 int indexDot = expression.indexOf('.');
459 int indexBracket = expression.indexOf('[');
460
461 if (indexBracket < 0)
462 {
463
464 return indexDot < 0 ? expression : expression.substring(0, indexDot);
465
466 }
467
468 if (indexDot < 0)
469 {
470 return expression.substring(0, indexBracket);
471 }
472
473 return expression.substring(0, Math.min(indexDot, indexBracket));
474
475 }
476
477 private String[] extractExpressions(String expressionString)
478 {
479 String[] expressions = expressionString.split("\\#\\{");
480 for (int i = 0; i < expressions.length; i++)
481 {
482 String expression = expressions[i];
483 if (expression.trim().length() == 0)
484 {
485 expressions[i] = null;
486 }
487 else
488 {
489 int index = expression.indexOf('}');
490 expressions[i] = expression.substring(0, index);
491 }
492 }
493 return expressions;
494 }
495
496
497 private void initializeMap(FacesContext facesContext, MapEntries mapEntries, Map map)
498 {
499 Application application = facesContext.getApplication();
500 Class keyClass = (mapEntries.getKeyClass() == null)
501 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
502 Class valueClass = (mapEntries.getValueClass() == null)
503 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
504 ValueExpression valueExpression;
505 ExpressionFactory expFactory = application.getExpressionFactory();
506 ELContext elContext = facesContext.getELContext();
507
508 for (Iterator iterator = mapEntries.getMapEntries(); iterator.hasNext();)
509 {
510 MapEntry entry = (MapEntry) iterator.next();
511 Object key = entry.getKey();
512
513 if (ContainerUtils.isValueReference((String) key))
514 {
515 valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
516 key = valueExpression.getValue(elContext);
517 }
518
519 if (entry.isNullValue())
520 {
521 map.put(coerceToType(facesContext, key, keyClass), null);
522 }
523 else
524 {
525 Object value = entry.getValue();
526 if (ContainerUtils.isValueReference((String) value))
527 {
528 valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
529 value = valueExpression.getValue(elContext);
530 }
531 map.put(coerceToType(facesContext, key, keyClass), coerceToType(facesContext, value, valueClass));
532 }
533 }
534 }
535
536
537 private void initializeList(FacesContext facesContext, ListEntries listEntries, List list)
538 {
539 Application application = facesContext.getApplication();
540 Class valueClass = listEntries.getValueClass() == null ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
541 ExpressionFactory expFactory = application.getExpressionFactory();
542 ELContext elContext = facesContext.getELContext();
543
544 for (Iterator iterator = listEntries.getListEntries(); iterator.hasNext();)
545 {
546 ListEntry entry = (ListEntry) iterator.next();
547 if (entry.isNullValue())
548 {
549 list.add(null);
550 }
551 else
552 {
553 Object value = entry.getValue();
554 if (ContainerUtils.isValueReference((String) value))
555 {
556 ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
557 value = valueExpression.getValue(elContext);
558 }
559 list.add(coerceToType(facesContext, value, valueClass));
560 }
561 }
562 }
563
564 private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
565 {
566 if (_runtimeConfig == null)
567 {
568 _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
569 }
570 return _runtimeConfig;
571 }
572 }