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