Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/myfaces/config/ManagedBeanBuilder.java


1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.myfaces.config;
17  
18  import org.apache.myfaces.config.element.*;
19  import org.apache.myfaces.util.ClassUtils;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import javax.faces.FacesException;
24  import javax.faces.application.Application;
25  import javax.faces.context.FacesContext;
26  import javax.faces.context.ExternalContext;
27  import javax.faces.el.PropertyResolver;
28  import javax.faces.el.ValueBinding;
29  import javax.faces.el.EvaluationException;
30  import javax.faces.webapp.UIComponentTag;
31  import java.util.*;
32  import java.lang.reflect.Array;
33  
34  
35  /**
36   * Create and initialize managed beans
37   *
38   * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller</a> (latest modification by $Author: oros $)
39   * @author Anton Koinov
40   */
41  public class ManagedBeanBuilder
42  {
43      private static Log log = LogFactory.getLog(ManagedBeanBuilder.class);
44      private RuntimeConfig _runtimeConfig;
45  
46  
47      public Object buildManagedBean(FacesContext facesContext, ManagedBean beanConfiguration) throws FacesException
48      {
49          Object bean = ClassUtils.newInstance(beanConfiguration.getManagedBeanClassName());
50  
51          switch (beanConfiguration.getInitMode())
52          {
53              case ManagedBean.INIT_MODE_PROPERTIES:
54                  try {
55                    initializeProperties(facesContext, beanConfiguration.getManagedProperties(),
56                        beanConfiguration.getManagedBeanScope(), bean);
57                  } catch (IllegalArgumentException e) {
58                    throw new IllegalArgumentException(
59                            e.getMessage()
60                                + " for bean '"
61                                + beanConfiguration.getManagedBeanName()
62                                + "' check the configuration to make sure all properties correspond with get/set methods");
63                  }
64                  break;
65  
66              case ManagedBean.INIT_MODE_MAP:
67                  if (!(bean instanceof Map))
68                  {
69                      throw new IllegalArgumentException("Class " + bean.getClass().getName()
70                          + " of managed bean "
71                          + beanConfiguration.getManagedBeanName()
72                          + " is not a Map.");
73                  }
74                  initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map) bean);
75                  break;
76  
77              case ManagedBean.INIT_MODE_LIST:
78                  if (!(bean instanceof List))
79                  {
80                      throw new IllegalArgumentException("Class " + bean.getClass().getName()
81                          + " of managed bean "
82                          + beanConfiguration.getManagedBeanName()
83                          + " is not a List.");
84                  }
85                  initializeList(facesContext, beanConfiguration.getListEntries(), (List) bean);
86                  break;
87  
88              case ManagedBean.INIT_MODE_NO_INIT:
89                  // no init values
90                  break;
91  
92              default:
93                  throw new IllegalStateException("Unknown managed bean type "
94                      + bean.getClass().getName() + " for managed bean "
95                      + beanConfiguration.getManagedBeanName() + '.');
96          }
97          return bean;
98      }
99  
100 
101     private void initializeProperties(FacesContext facesContext, Iterator managedProperties, String targetScope, Object bean)
102     {
103         PropertyResolver propertyResolver =
104             facesContext.getApplication().getPropertyResolver();
105 
106         while (managedProperties.hasNext())
107         {
108             ManagedProperty property = (ManagedProperty) managedProperties.next();
109             Object value = null;
110 
111             switch (property.getType())
112             {
113                 case ManagedProperty.TYPE_LIST:
114                     value = propertyResolver.getValue(bean, property.getPropertyName());
115 
116                     if (value instanceof List) {
117                         initializeList(facesContext, property.getListEntries(), (List) value);
118 
119                     } else if (value != null && value.getClass().isArray()) {
120                         int length = Array.getLength(value);
121                         ArrayList temp = new ArrayList(length);
122                         for (int i = 0; i < length; i++) {
123                             temp.add(Array.get(value, i));
124                         }
125                         initializeList(facesContext, property.getListEntries(), temp);
126                         value = Array.newInstance(value.getClass().getComponentType(), temp.size());
127                         length = temp.size();
128 
129                         for (int i = 0; i < length; i++) {
130                             Array.set(value, i, temp.get(i));
131                         }
132                     } else {
133                           value = new ArrayList();
134                         initializeList(facesContext, property.getListEntries(), (List) value);
135                     }
136 
137                     break;
138                 case ManagedProperty.TYPE_MAP:
139 
140                     value = propertyResolver.getValue(bean, property.getPropertyName());
141 
142                     if (! (value instanceof Map)) {
143                         value = new HashMap();
144                     }
145 
146                     initializeMap(facesContext, property.getMapEntries(), (Map) value);
147                     break;
148                 case ManagedProperty.TYPE_NULL:
149                     value = null;
150                     break;
151                 case ManagedProperty.TYPE_VALUE:
152                     // check for correct scope of a referenced bean
153                     if (! isInValidScope(facesContext, property, targetScope)) {
154                         throw new FacesException("Property " + property.getPropertyName() +
155                             " references object in a scope with shorter lifetime than the target scope " + targetScope);
156                     }
157                     value = property.getRuntimeValue(facesContext);
158                     break;
159             }
160             Class propertyClass = null;
161 
162             if (property.getPropertyClass() == null)
163             {
164                 propertyClass = propertyResolver
165                     .getType(bean, property.getPropertyName());
166             }
167             else
168             {
169                 propertyClass = ClassUtils
170                     .simpleJavaTypeToClass(property.getPropertyClass());
171             }
172             if(null == propertyClass) {
173               throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
174             }
175             Object coercedValue = ClassUtils.convertToType(value, propertyClass);
176             propertyResolver.setValue(
177                 bean, property.getPropertyName(), coercedValue);
178         }
179     }
180 
181 
182     /**
183      * Check if the scope of the property value is valid for a bean to be stored in targetScope.
184      * @param facesContext
185      * @param property          the property to be checked
186      * @param targetScope       name of the target scope of the bean under construction
187      */
188     private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, String targetScope)
189     {
190         if (! property.isValueReference()) {
191             // no value reference but a literal value -> nothing to check
192             return true;
193         }
194         String[] expressions = extractExpressions(property.getValueBinding(facesContext).getExpressionString());
195 
196         for (int i = 0; i < expressions.length; i++) {
197             String expression = expressions[i];
198             if (expression == null) {
199                 continue;
200             }
201 
202             String valueScope = getScope(facesContext, expression);
203 
204             // if the target scope is 'none' value scope has to be 'none', too
205             if (targetScope == null || targetScope.equalsIgnoreCase("none")) {
206                 if (valueScope != null && !(valueScope.equalsIgnoreCase("none"))) {
207                     return false;
208                 }
209                 return true;
210             }
211 
212             // 'application' scope can reference 'application' and 'none'
213             if (targetScope.equalsIgnoreCase("application")) {
214                 if (valueScope != null) {
215                     if (valueScope.equalsIgnoreCase("request") ||
216                         valueScope.equalsIgnoreCase("session")) {
217                         return false;
218                     }
219                 }
220                 return true;
221             }
222 
223             // 'session' scope can reference 'session', 'application', and 'none' but not 'request'
224             if (targetScope.equalsIgnoreCase("session")) {
225                 if (valueScope != null) {
226                     if (valueScope.equalsIgnoreCase("request")) {
227                         return false;
228                     }
229                 }
230                 return true;
231             }
232 
233             // 'request' scope can reference any value scope
234             if (targetScope.equalsIgnoreCase("request")) {
235                 return true;
236             }
237         }
238         return false;
239     }
240 
241 
242     private String getScope(FacesContext facesContext, String expression)
243     {
244         String beanName = getFirstSegment(expression);
245         ExternalContext externalContext = facesContext.getExternalContext();
246 
247         // check scope objects
248         if (beanName.equalsIgnoreCase("requestScope")) {
249             return "request";
250         }
251         if (beanName.equalsIgnoreCase("sessionScope")) {
252             return "session";
253         }
254         if (beanName.equalsIgnoreCase("applicationScope")) {
255             return "application";
256         }
257 
258       // check implicit objects
259         if (beanName.equalsIgnoreCase("cookie")) {
260       return "request";
261         }
262         if (beanName.equalsIgnoreCase("facesContext")) {
263             return "request";
264         }
265 
266         if (beanName.equalsIgnoreCase("header")) {
267             return "request";
268         }
269         if (beanName.equalsIgnoreCase("headerValues")) {
270             return "request";
271         }
272 
273         if (beanName.equalsIgnoreCase("initParam")) {
274       return "application";
275         }
276         if (beanName.equalsIgnoreCase("param")) {
277             return "request";
278         }
279         if (beanName.equalsIgnoreCase("paramValues")) {
280             return "request";
281         }
282         if (beanName.equalsIgnoreCase("view")) {
283             return "request";
284         }
285 
286 
287         // not found so far - check all scopes
288         if (externalContext.getRequestMap().get(beanName) != null) {
289             return "request";
290         }
291         if (externalContext.getSessionMap().get(beanName) != null) {
292             return "session";
293         }
294         if (externalContext.getApplicationMap().get(beanName) != null) {
295             return "application";
296         }
297 
298         //not found - check mangaged bean config
299 
300 
301         ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
302 
303         if (mbc != null) {
304             return mbc.getManagedBeanScope();
305         }
306 
307         return null;
308     }
309 
310 
311 
312 
313     /**
314      * Extract the first expression segment, that is the substring up to the first '.' or '['
315      * @param expression
316      * @return first segment of the expression
317      */
318     private String getFirstSegment(String expression)
319     {
320         int indexDot = expression.indexOf('.');
321         int indexBracket = expression.indexOf('[');
322 
323         if (indexBracket < 0) {
324                 if (indexDot < 0) {
325                     return expression;
326                 } else {
327                     return expression.substring(0, indexDot);
328                 }
329         } else {
330             if (indexDot < 0) {
331                 return expression.substring(0, indexBracket);
332             } else {
333                 return expression.substring(0, Math.min(indexDot, indexBracket));
334             }
335         }
336     }
337 
338     private String getSecondSegment(String expression, String firstSegment)
339     {
340         String tmp = expression.substring(firstSegment.length());
341 
342         if (tmp.length() == 0) {
343             return null;
344         }
345         if (tmp.charAt(0) == '.') {
346             return getFirstSegment(tmp.substring(1));
347         }
348         // starts with [
349         tmp = tmp.substring(1).trim();
350         int index;
351 
352         if (tmp.charAt(0) == '"') {
353             index = tmp.indexOf('"', 1);
354 
355             if (index < 0) {
356                 throw new EvaluationException(tmp);
357             }
358             return tmp.substring(1, index);
359         }
360         if (tmp.charAt(0) == '\'') {
361             index = tmp.indexOf('\'', 1);
362 
363             if (index < 0) {
364                 throw new EvaluationException(tmp);
365             }
366             return tmp.substring(1, index);
367         }
368 
369         index = tmp.indexOf(']');
370 
371         if (index < 0) {
372             throw new EvaluationException(tmp);
373         }
374 
375         return tmp.substring(1, index);
376     }
377 
378 
379     private String[] extractExpressions(String expressionString)
380     {
381         String[] expressions = expressionString.split("\\#\\{");
382         for (int i = 0; i < expressions.length; i++) {
383             String expression = expressions[i];
384             if (expression.trim().length() == 0) {
385                 expressions[i] = null;
386             } else {
387                 int index = expression.indexOf('}');
388                 expressions[i] = expression.substring(0, index);
389             }
390         }
391         return expressions;
392     }
393 
394 
395     private void initializeMap(FacesContext facesContext, MapEntries mapEntries, Map map)
396     {
397         Application application = facesContext.getApplication();
398         Class keyClass = (mapEntries.getKeyClass() == null)
399             ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
400         Class valueClass = (mapEntries.getValueClass() == null)
401             ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
402         ValueBinding valueBinding;
403 
404         for (Iterator iterator = mapEntries.getMapEntries(); iterator.hasNext();)
405         {
406             MapEntry entry = (MapEntry) iterator.next();
407             Object key = entry.getKey();
408 
409             if (UIComponentTag.isValueReference((String) key))
410             {
411                 valueBinding = application.createValueBinding((String) key);
412                 key = valueBinding.getValue(facesContext);
413             }
414 
415             if (entry.isNullValue())
416             {
417                 map.put(ClassUtils.convertToType(key, keyClass), null);
418             }
419             else
420             {
421                 Object value = entry.getValue();
422                 if (UIComponentTag.isValueReference((String) value))
423                 {
424                     valueBinding = application.createValueBinding((String) value);
425                     value = valueBinding.getValue(facesContext);
426                 }
427                 map.put(ClassUtils.convertToType(key, keyClass), ClassUtils.convertToType(value, valueClass));
428             }
429         }
430     }
431 
432 
433     private void initializeList(FacesContext facesContext, ListEntries listEntries, List list)
434     {
435         Application application = facesContext.getApplication();
436         Class valueClass = listEntries.getValueClass() == null ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
437         ValueBinding valueBinding;
438 
439         for (Iterator iterator = listEntries.getListEntries(); iterator.hasNext();)
440         {
441             ListEntry entry = (ListEntry) iterator.next();
442             if (entry.isNullValue())
443             {
444                 list.add(null);
445             }
446             else
447             {
448                 Object value = entry.getValue();
449                 if (UIComponentTag.isValueReference((String) value))
450                 {
451                     valueBinding = application.createValueBinding((String) value);
452                     value = valueBinding.getValue(facesContext);
453                 }
454                 list.add(ClassUtils.convertToType(value, valueClass));
455             }
456         }
457     }
458 
459     private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
460     {
461         if (_runtimeConfig == null)
462         {
463             _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
464         }
465         return _runtimeConfig;
466     }
467 }