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 org.apache.commons.beanutils.PropertyUtils;
22 import org.apache.myfaces.config.annotation.LifecycleProvider;
23 import org.apache.myfaces.config.annotation.LifecycleProvider2;
24 import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
25 import org.apache.myfaces.config.element.ListEntries;
26 import org.apache.myfaces.config.element.ListEntry;
27 import org.apache.myfaces.config.element.ManagedBean;
28 import org.apache.myfaces.config.element.ManagedProperty;
29 import org.apache.myfaces.config.element.MapEntries;
30 import org.apache.myfaces.config.element.MapEntry;
31 import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
32 import org.apache.myfaces.shared.util.ClassUtils;
33 import org.apache.myfaces.util.ContainerUtils;
34
35 import javax.el.ELContext;
36 import javax.el.ELException;
37 import javax.el.ELResolver;
38 import javax.el.ExpressionFactory;
39 import javax.el.ValueExpression;
40 import javax.faces.FacesException;
41 import javax.faces.application.Application;
42 import javax.faces.application.ProjectStage;
43 import javax.faces.context.ExternalContext;
44 import javax.faces.context.FacesContext;
45 import javax.naming.NamingException;
46 import java.lang.reflect.Array;
47 import java.lang.reflect.InvocationTargetException;
48 import java.util.ArrayList;
49 import java.util.Comparator;
50 import java.util.HashMap;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.logging.Level;
55 import java.util.logging.Logger;
56
57
58
59
60
61
62
63
64 public class ManagedBeanBuilder
65 {
66
67 private static Logger log = Logger.getLogger(ManagedBeanBuilder.class.getName());
68 private RuntimeConfig _runtimeConfig;
69 public final static String REQUEST = "request";
70 public final static String VIEW = "view";
71 public final static String APPLICATION = "application";
72 public final static String SESSION = "session";
73 public final static String NONE = "none";
74
75
76
77
78
79
80 private final static Comparator<String> scopeComparator = new Comparator<String>()
81 {
82
83 public int compare(String o1, String o2)
84 {
85 if (o1.equalsIgnoreCase(o2))
86 {
87
88 return 0;
89 }
90 if (o1.equalsIgnoreCase(NONE))
91 {
92
93 return 1;
94 }
95 if (o1.equalsIgnoreCase(APPLICATION))
96 {
97 if (o2.equalsIgnoreCase(NONE))
98 {
99
100 return -1;
101 }
102 else
103 {
104
105 return 1;
106 }
107 }
108 if (o1.equalsIgnoreCase(SESSION))
109 {
110 if (o2.equalsIgnoreCase(REQUEST) || o2.equalsIgnoreCase(VIEW))
111 {
112
113 return 1;
114 }
115 else
116 {
117
118 return -1;
119 }
120 }
121 if (o1.equalsIgnoreCase(VIEW))
122 {
123 if (o2.equalsIgnoreCase(REQUEST))
124 {
125
126 return 1;
127 }
128 else
129 {
130
131 return -1;
132 }
133 }
134 if (o1.equalsIgnoreCase(REQUEST))
135 {
136
137 return -1;
138 }
139
140
141 throw new IllegalArgumentException(o1 + " is not a valid scope");
142 }
143
144 };
145
146 @SuppressWarnings("unchecked")
147 public Object buildManagedBean(FacesContext facesContext, ManagedBean beanConfiguration) throws FacesException
148 {
149 try
150 {
151 ExternalContext externalContext = facesContext.getExternalContext();
152 LifecycleProvider lifecycleProvider = LifecycleProviderFactory
153 .getLifecycleProviderFactory( externalContext).getLifecycleProvider(externalContext);
154
155 final Object bean = lifecycleProvider.newInstance(beanConfiguration.getManagedBeanClassName());
156
157 switch (beanConfiguration.getInitMode())
158 {
159 case ManagedBean.INIT_MODE_PROPERTIES:
160 try
161 {
162 initializeProperties(facesContext, beanConfiguration, bean);
163 }
164 catch (IllegalArgumentException e)
165 {
166 throw new IllegalArgumentException(
167 e.getMessage()
168 + " for bean '"
169 + beanConfiguration.getManagedBeanName()
170 + "' check the configuration to make sure all properties correspond with get/set methods", e);
171 }
172 break;
173
174 case ManagedBean.INIT_MODE_MAP:
175 if (!(bean instanceof Map))
176 {
177 throw new IllegalArgumentException("Class " + bean.getClass().getName()
178 + " of managed bean "
179 + beanConfiguration.getManagedBeanName()
180 + " is not a Map.");
181 }
182 initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map<Object, Object>) bean);
183 break;
184
185 case ManagedBean.INIT_MODE_LIST:
186 if (!(bean instanceof List))
187 {
188 throw new IllegalArgumentException("Class " + bean.getClass().getName()
189 + " of managed bean "
190 + beanConfiguration.getManagedBeanName()
191 + " is not a List.");
192 }
193 initializeList(facesContext, beanConfiguration.getListEntries(), (List<Object>) bean);
194 break;
195
196 case ManagedBean.INIT_MODE_NO_INIT:
197
198 break;
199
200 default:
201 throw new IllegalStateException("Unknown managed bean type "
202 + bean.getClass().getName() + " for managed bean "
203 + beanConfiguration.getManagedBeanName() + '.');
204 }
205
206
207
208
209 if (lifecycleProvider instanceof LifecycleProvider2)
210 {
211 ((LifecycleProvider2)lifecycleProvider).postConstruct(bean);
212 }
213 return bean;
214 }
215 catch (IllegalAccessException e)
216 {
217 throw new FacesException(e);
218 }
219 catch (InvocationTargetException e)
220 {
221 throw new FacesException(e);
222 }
223 catch (NamingException e)
224 {
225 throw new FacesException(e);
226 }
227 catch (ClassNotFoundException e)
228 {
229 throw new FacesException(e);
230 }
231 catch (InstantiationException e)
232 {
233 throw new FacesException(e);
234 }
235
236 }
237
238
239 @SuppressWarnings("unchecked")
240 private void initializeProperties(FacesContext facesContext,
241 ManagedBean beanConfiguration, Object bean)
242 {
243 ELResolver elResolver = facesContext.getApplication().getELResolver();
244 ELContext elContext = facesContext.getELContext();
245
246 for (ManagedProperty property : beanConfiguration.getManagedProperties())
247 {
248 Object value = null;
249
250 switch (property.getType())
251 {
252 case ManagedProperty.TYPE_LIST:
253
254
255
256
257
258 if (PropertyUtils.isReadable(bean, property.getPropertyName()))
259 {
260 value = elResolver.getValue(elContext, bean, property.getPropertyName());
261 }
262
263 value = value == null ? new ArrayList<Object>() : value;
264
265 if (value instanceof List)
266 {
267 initializeList(facesContext, property.getListEntries(), (List<Object>)value);
268
269 }
270 else if (value != null && value.getClass().isArray())
271 {
272 int length = Array.getLength(value);
273 ArrayList<Object> temp = new ArrayList<Object>(length);
274 for (int i = 0; i < length; i++)
275 {
276 temp.add(Array.get(value, i));
277 }
278 initializeList(facesContext, property.getListEntries(), temp);
279 value = Array.newInstance(value.getClass().getComponentType(), temp.size());
280 length = temp.size();
281
282 for (int i = 0; i < length; i++)
283 {
284 Array.set(value, i, temp.get(i));
285 }
286 }
287 else
288 {
289 value = new ArrayList<Object>();
290 initializeList(facesContext, property.getListEntries(), (List<Object>) value);
291 }
292
293 break;
294 case ManagedProperty.TYPE_MAP:
295
296
297
298
299
300 if (PropertyUtils.isReadable(bean, property.getPropertyName()))
301 value = elResolver.getValue(elContext, bean, property.getPropertyName());
302 value = value == null ? new HashMap<Object, Object>() : value;
303
304 if (!(value instanceof Map))
305 {
306 value = new HashMap<Object, Object>();
307 }
308
309 initializeMap(facesContext, property.getMapEntries(), (Map<Object, Object>) value);
310 break;
311 case ManagedProperty.TYPE_NULL:
312 break;
313 case ManagedProperty.TYPE_VALUE:
314
315 if (!isInValidScope(facesContext, property, beanConfiguration))
316 {
317 throw new FacesException("Property " + property.getPropertyName() +
318 " references object in a scope with shorter lifetime than the target scope " +
319 beanConfiguration.getManagedBeanScope());
320 }
321 value = property.getRuntimeValue(facesContext);
322 break;
323 }
324
325 Class<?> propertyClass = null;
326
327 if (property.getPropertyClass() == null)
328 {
329 propertyClass = elResolver.getType(elContext, bean, property.getPropertyName());
330 }
331 else
332 {
333 propertyClass = ClassUtils.simpleJavaTypeToClass(property.getPropertyClass());
334 }
335
336 if (null == propertyClass)
337 {
338 throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
339 }
340
341 Object coercedValue = coerceToType(facesContext, value, propertyClass);
342 elResolver.setValue(elContext, bean, property.getPropertyName(), coercedValue);
343 }
344 }
345
346
347
348 @SuppressWarnings("unchecked")
349 public static <T> T coerceToType(FacesContext facesContext, Object value, Class<? extends T> desiredClass)
350 {
351 if (value == null) return null;
352
353 try
354 {
355 ExpressionFactory expFactory = facesContext.getApplication().getExpressionFactory();
356
357
358 return (T)expFactory.coerceToType(value, desiredClass);
359 }
360 catch (ELException e)
361 {
362 String message = "Cannot coerce " + value.getClass().getName()
363 + " to " + desiredClass.getName();
364 log.log(Level.SEVERE, message , e);
365 throw new FacesException(message, e);
366 }
367 }
368
369
370
371
372
373
374
375
376
377
378 private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, ManagedBean beanConfiguration)
379 {
380 if (!property.isValueReference())
381 {
382
383 return true;
384 }
385
386
387 String targetScope = null;
388 if (beanConfiguration.isManagedBeanScopeValueExpression())
389 {
390
391
392
393
394 if (facesContext.isProjectStage(ProjectStage.Production))
395 {
396 return true;
397 }
398 else
399 {
400 targetScope = getNarrowestScope(facesContext,
401 beanConfiguration
402 .getManagedBeanScopeValueExpression(facesContext)
403 .getExpressionString());
404
405 if (targetScope == null)
406 {
407 return true;
408 }
409 }
410 }
411 else
412 {
413 targetScope = beanConfiguration.getManagedBeanScope();
414 if (targetScope == null)
415 {
416 targetScope = NONE;
417 }
418 }
419
420
421 if (targetScope.equalsIgnoreCase(REQUEST))
422 {
423 return true;
424 }
425
426 String valueScope = getNarrowestScope(facesContext,
427 property.getValueBinding(facesContext)
428 .getExpressionString());
429
430
431 if (valueScope == null)
432 {
433 return true;
434 }
435
436
437 return (scopeComparator.compare(targetScope, valueScope) <= 0);
438 }
439
440
441
442
443
444
445
446 private String getNarrowestScope(FacesContext facesContext, String valueExpression)
447 {
448 List<String> expressions = extractExpressions(valueExpression);
449
450 String narrowestScope = expressions.size() == 1 ? NONE : APPLICATION;
451 boolean scopeFound = false;
452
453 for (String expression : expressions)
454 {
455 String valueScope = getScope(facesContext, expression);
456 if (valueScope == null)
457 {
458 continue;
459 }
460
461 scopeFound = true;
462 if (scopeComparator.compare(valueScope, narrowestScope) < 0)
463 {
464 narrowestScope = valueScope;
465 }
466 }
467
468 return scopeFound ? narrowestScope : null;
469 }
470
471 private String getScope(FacesContext facesContext, String expression)
472 {
473 String beanName = getFirstSegment(expression);
474 ExternalContext externalContext = facesContext.getExternalContext();
475
476
477 if (beanName.equalsIgnoreCase("requestScope"))
478 {
479 return REQUEST;
480 }
481 if (beanName.equalsIgnoreCase("sessionScope"))
482 {
483 return SESSION;
484 }
485 if (beanName.equalsIgnoreCase("applicationScope"))
486 {
487 return APPLICATION;
488 }
489
490
491 if (beanName.equalsIgnoreCase("cookie"))
492 {
493 return REQUEST;
494 }
495 if (beanName.equalsIgnoreCase("facesContext"))
496 {
497 return REQUEST;
498 }
499 if (beanName.equalsIgnoreCase("header"))
500 {
501 return REQUEST;
502 }
503 if (beanName.equalsIgnoreCase("headerValues"))
504 {
505 return REQUEST;
506 }
507 if (beanName.equalsIgnoreCase("param"))
508 {
509 return REQUEST;
510 }
511 if (beanName.equalsIgnoreCase("paramValues"))
512 {
513 return REQUEST;
514 }
515 if (beanName.equalsIgnoreCase("request"))
516 {
517 return REQUEST;
518 }
519 if (beanName.equalsIgnoreCase("view"))
520 {
521 return REQUEST;
522 }
523 if (beanName.equalsIgnoreCase("application"))
524 {
525 return APPLICATION;
526 }
527 if (beanName.equalsIgnoreCase("initParam"))
528 {
529 return APPLICATION;
530 }
531
532
533 final boolean startup = (externalContext instanceof StartupServletExternalContextImpl);
534 if (!startup)
535 {
536
537
538 if (externalContext.getRequestMap().get(beanName) != null)
539 {
540 return REQUEST;
541 }
542 if (externalContext.getSessionMap().get(beanName) != null)
543 {
544 return SESSION;
545 }
546 }
547 if (externalContext.getApplicationMap().get(beanName) != null)
548 {
549 return APPLICATION;
550 }
551 if (facesContext.getViewRoot().getViewMap().get(beanName) != null)
552 {
553 return VIEW;
554 }
555
556
557 ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
558 if (mbc != null)
559 {
560
561 if (mbc.isManagedBeanScopeValueExpression())
562 {
563
564
565
566
567 if (facesContext.isProjectStage(ProjectStage.Production))
568 {
569 return null;
570 }
571 else
572 {
573 String scopeExpression = mbc.getManagedBeanScopeValueExpression(facesContext).getExpressionString();
574 return getNarrowestScope(facesContext, scopeExpression);
575 }
576 }
577 else
578 {
579 return mbc.getManagedBeanScope();
580 }
581 }
582
583 return null;
584 }
585
586
587
588
589
590
591
592 private String getFirstSegment(String expression)
593 {
594 int indexDot = expression.indexOf('.');
595 int indexBracket = expression.indexOf('[');
596
597 if (indexBracket < 0)
598 {
599
600 return indexDot < 0 ? expression : expression.substring(0, indexDot);
601
602 }
603
604 if (indexDot < 0)
605 {
606 return expression.substring(0, indexBracket);
607 }
608
609 return expression.substring(0, Math.min(indexDot, indexBracket));
610
611 }
612
613 private List<String> extractExpressions(String expressionString)
614 {
615 List<String> expressions = new ArrayList<String>();
616 for (String expression : expressionString.split("\\#\\{"))
617 {
618 int index = expression.indexOf('}');
619 if (index >= 0)
620 {
621 expressions.add(expression.substring(0, index));
622 }
623 }
624 return expressions;
625 }
626
627
628 private void initializeMap(FacesContext facesContext, MapEntries mapEntries,
629 Map<? super Object, ? super Object> map)
630 {
631 Application application = facesContext.getApplication();
632
633 Class<?> keyClass = (mapEntries.getKeyClass() == null)
634 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
635
636 Class<?> valueClass = (mapEntries.getValueClass() == null)
637 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
638
639 ValueExpression valueExpression;
640 ExpressionFactory expFactory = application.getExpressionFactory();
641 ELContext elContext = facesContext.getELContext();
642
643 for (Iterator<? extends MapEntry> iterator = mapEntries.getMapEntries(); iterator.hasNext();)
644 {
645 MapEntry entry = iterator.next();
646 Object key = entry.getKey();
647
648 if (ContainerUtils.isValueReference((String) key))
649 {
650 valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
651 key = valueExpression.getValue(elContext);
652 }
653
654 if (entry.isNullValue())
655 {
656 map.put(coerceToType(facesContext, key, keyClass), null);
657 }
658 else
659 {
660 Object value = entry.getValue();
661 if (ContainerUtils.isValueReference((String) value))
662 {
663 valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
664 value = valueExpression.getValue(elContext);
665 }
666
667 map.put(coerceToType(facesContext, key, keyClass), coerceToType(facesContext, value, valueClass));
668 }
669 }
670 }
671
672
673 private void initializeList(FacesContext facesContext, ListEntries listEntries, List<? super Object> list)
674 {
675 Application application = facesContext.getApplication();
676
677 Class<?> valueClass = (listEntries.getValueClass() == null)
678 ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
679
680 ExpressionFactory expFactory = application.getExpressionFactory();
681 ELContext elContext = facesContext.getELContext();
682
683 for (Iterator<? extends ListEntry> iterator = listEntries.getListEntries(); iterator.hasNext();)
684 {
685 ListEntry entry = iterator.next();
686 if (entry.isNullValue())
687 {
688 list.add(null);
689 }
690 else
691 {
692 Object value = entry.getValue();
693 if (ContainerUtils.isValueReference((String) value))
694 {
695 ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
696 value = valueExpression.getValue(elContext);
697 }
698
699 list.add(coerceToType(facesContext, value, valueClass));
700 }
701 }
702 }
703
704 private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
705 {
706 if (_runtimeConfig == null)
707 {
708 _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
709 }
710
711 return _runtimeConfig;
712 }
713 }