Coverage Report - org.apache.myfaces.config.ManagedBeanBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
ManagedBeanBuilder
0%
0/219
0%
0/152
13.25
ManagedBeanBuilder$1
0%
0/20
0%
0/20
13.25
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 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  
  * Create and initialize managed beans
 60  
  *
 61  
  * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller</a> (latest modification by $Author$)
 62  
  * @author Anton Koinov
 63  
  */
 64  0
 public class ManagedBeanBuilder
 65  
 {
 66  
     //private static Log log = LogFactory.getLog(ManagedBeanBuilder.class);
 67  0
     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  
      * Comparator used to compare Scopes in the following order:
 77  
      * REQUEST VIEW SESSION APPLICATION NONE
 78  
      * @author Jakob Korherr
 79  
      */
 80  0
     private final static Comparator<String> SCOPE_COMPARATOR
 81  
             = new Comparator<String>()
 82  0
     {
 83  
 
 84  
         public int compare(String o1, String o2)
 85  
         {
 86  0
             if (o1.equalsIgnoreCase(o2))
 87  
             {
 88  
                 // the same scope
 89  0
                 return 0;
 90  
             }
 91  0
             if (o1.equalsIgnoreCase(NONE))
 92  
             {
 93  
                 // none is greater than any other scope
 94  0
                 return 1;
 95  
             }
 96  0
             if (o1.equalsIgnoreCase(APPLICATION))
 97  
             {
 98  0
                 if (o2.equalsIgnoreCase(NONE))
 99  
                 {
 100  
                     // application is smaller than none
 101  0
                     return -1;
 102  
                 }
 103  
                 else
 104  
                 {
 105  
                     // ..but greater than any other scope
 106  0
                     return 1;
 107  
                 }
 108  
             }
 109  0
             if (o1.equalsIgnoreCase(SESSION))
 110  
             {
 111  0
                 if (o2.equalsIgnoreCase(REQUEST) || o2.equalsIgnoreCase(VIEW))
 112  
                 {
 113  
                     // session is greater than request and view
 114  0
                     return 1;
 115  
                 }
 116  
                 else
 117  
                 {
 118  
                     // but smaller than any other scope
 119  0
                     return -1;
 120  
                 }
 121  
             }
 122  0
             if (o1.equalsIgnoreCase(VIEW))
 123  
             {
 124  0
                 if (o2.equalsIgnoreCase(REQUEST))
 125  
                 {
 126  
                     // view is greater than request
 127  0
                     return 1;
 128  
                 }
 129  
                 else
 130  
                 {
 131  
                     // ..but smaller than any other scope
 132  0
                     return -1;
 133  
                 }
 134  
             }
 135  0
             if (o1.equalsIgnoreCase(REQUEST))
 136  
             {
 137  
                 // request is smaller than any other scope
 138  0
                 return -1;
 139  
             }
 140  
             
 141  
             // not a valid scope
 142  0
             throw new IllegalArgumentException(o1 + " is not a valid scope");
 143  
         }
 144  
         
 145  
     };
 146  
 
 147  
     @SuppressWarnings("unchecked")
 148  
     public Object buildManagedBean(FacesContext facesContext, ManagedBean beanConfiguration) throws FacesException
 149  
     {
 150  
         try
 151  
         {
 152  0
             ExternalContext externalContext = facesContext.getExternalContext();
 153  0
             LifecycleProvider lifecycleProvider = LifecycleProviderFactory
 154  
                     .getLifecycleProviderFactory( externalContext).getLifecycleProvider(externalContext);
 155  
             
 156  0
             final Object bean = lifecycleProvider.newInstance(beanConfiguration.getManagedBeanClassName());
 157  
 
 158  0
             switch (beanConfiguration.getInitMode())
 159  
             {
 160  
                 case ManagedBean.INIT_MODE_PROPERTIES:
 161  
                     try
 162  
                     {
 163  0
                         initializeProperties(facesContext, beanConfiguration, bean);
 164  
                     }
 165  0
                     catch (IllegalArgumentException e)
 166  
                     {
 167  0
                         throw new IllegalArgumentException(
 168  
                                 e.getMessage()
 169  
                                         + " for bean '"
 170  
                                         + beanConfiguration.getManagedBeanName()
 171  
                                         + "' check the configuration to make sure all properties "
 172  
                                         + "correspond with get/set methods", e);
 173  0
                     }
 174  
                     break;
 175  
 
 176  
                 case ManagedBean.INIT_MODE_MAP:
 177  0
                     if (!(bean instanceof Map))
 178  
                     {
 179  0
                         throw new IllegalArgumentException("Class " + bean.getClass().getName()
 180  
                                 + " of managed bean "
 181  
                                 + beanConfiguration.getManagedBeanName()
 182  
                                 + " is not a Map.");
 183  
                     }
 184  0
                     initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map<Object, Object>) bean);
 185  0
                     break;
 186  
 
 187  
                 case ManagedBean.INIT_MODE_LIST:
 188  0
                     if (!(bean instanceof List))
 189  
                     {
 190  0
                         throw new IllegalArgumentException("Class " + bean.getClass().getName()
 191  
                                 + " of managed bean "
 192  
                                 + beanConfiguration.getManagedBeanName()
 193  
                                 + " is not a List.");
 194  
                     }
 195  0
                     initializeList(facesContext, beanConfiguration.getListEntries(), (List<Object>) bean);
 196  0
                     break;
 197  
 
 198  
                 case ManagedBean.INIT_MODE_NO_INIT:
 199  
                     // no init values
 200  0
                     break;
 201  
 
 202  
                 default:
 203  0
                     throw new IllegalStateException("Unknown managed bean type "
 204  
                             + bean.getClass().getName() + " for managed bean "
 205  
                             + beanConfiguration.getManagedBeanName() + '.');
 206  
             }
 207  
             
 208  
             // MYFACES-1761 if implements LifecycleProvider,
 209  
             //PostConstruct was already called, but if implements
 210  
             //LifecycleProvider2, call it now.
 211  0
             if (lifecycleProvider instanceof LifecycleProvider2)
 212  
             {
 213  0
                 ((LifecycleProvider2)lifecycleProvider).postConstruct(bean);
 214  
             }
 215  0
             return bean;
 216  
         }
 217  0
         catch (IllegalAccessException e)
 218  
         {
 219  0
             throw new FacesException(e);
 220  
         }
 221  0
         catch (InvocationTargetException e)
 222  
         {
 223  0
             throw new FacesException(e);
 224  
         }
 225  0
         catch (NamingException e)
 226  
         {
 227  0
             throw new FacesException(e);
 228  
         }
 229  0
         catch (ClassNotFoundException e)
 230  
         {
 231  0
             throw new FacesException(e);
 232  
         }
 233  0
         catch (InstantiationException e)
 234  
         {
 235  0
             throw new FacesException(e);
 236  
         }
 237  
 
 238  
     }
 239  
 
 240  
 
 241  
     @SuppressWarnings("unchecked")
 242  
     private void initializeProperties(FacesContext facesContext, 
 243  
                                       ManagedBean beanConfiguration, Object bean)
 244  
     {
 245  0
         ELResolver elResolver = facesContext.getApplication().getELResolver();
 246  0
         ELContext elContext = facesContext.getELContext();
 247  
 
 248  0
         for (ManagedProperty property : beanConfiguration.getManagedProperties())
 249  
         {
 250  0
             Object value = null;
 251  
 
 252  0
             switch (property.getType())
 253  
             {
 254  
                 case ManagedProperty.TYPE_LIST:
 255  
 
 256  
                     // JSF 1.1, 5.3.1.3
 257  
                     // Call the property getter, if it exists.
 258  
                     // If the getter returns null or doesn't exist, create a java.util.ArrayList,
 259  
                     // otherwise use the returned Object ...
 260  0
                     if (PropertyUtils.isReadable(bean, property.getPropertyName()))
 261  
                     {
 262  0
                         value = elResolver.getValue(elContext, bean, property.getPropertyName());
 263  
                     }
 264  
                     
 265  0
                     value = value == null ? new ArrayList<Object>() : value;
 266  
 
 267  0
                     if (value instanceof List)
 268  
                     {
 269  0
                         initializeList(facesContext, property.getListEntries(), (List<Object>)value);
 270  
 
 271  
                     }
 272  0
                     else if (value != null && value.getClass().isArray())
 273  
                     {
 274  0
                         int length = Array.getLength(value);
 275  0
                         ArrayList<Object> temp = new ArrayList<Object>(length);
 276  0
                         for (int i = 0; i < length; i++)
 277  
                         {
 278  0
                             temp.add(Array.get(value, i));
 279  
                         }
 280  0
                         initializeList(facesContext, property.getListEntries(), temp);
 281  0
                         value = Array.newInstance(value.getClass().getComponentType(), temp.size());
 282  0
                         length = temp.size();
 283  
 
 284  0
                         for (int i = 0; i < length; i++)
 285  
                         {
 286  0
                             Array.set(value, i, temp.get(i));
 287  
                         }
 288  0
                     }
 289  
                     else
 290  
                     {
 291  0
                         value = new ArrayList<Object>();
 292  0
                         initializeList(facesContext, property.getListEntries(), (List<Object>) value);
 293  
                     }
 294  
 
 295  0
                     break;
 296  
                 case ManagedProperty.TYPE_MAP:
 297  
 
 298  
                     // JSF 1.1, 5.3.1.3
 299  
                     // Call the property getter, if it exists.
 300  
                     // If the getter returns null or doesn't exist, create a java.util.HashMap,
 301  
                     // otherwise use the returned java.util.Map .
 302  0
                     if (PropertyUtils.isReadable(bean, property.getPropertyName()))
 303  
                     {
 304  0
                         value = elResolver.getValue(elContext, bean, property.getPropertyName());
 305  
                     }
 306  0
                     value = value == null ? new HashMap<Object, Object>() : value;
 307  
 
 308  0
                     if (!(value instanceof Map))
 309  
                     {
 310  0
                         value = new HashMap<Object, Object>();
 311  
                     }
 312  
 
 313  0
                     initializeMap(facesContext, property.getMapEntries(), (Map<Object, Object>) value);
 314  0
                     break;
 315  
                 case ManagedProperty.TYPE_NULL:
 316  0
                     break;
 317  
                 case ManagedProperty.TYPE_VALUE:
 318  
                     // check for correct scope of a referenced bean
 319  0
                     if (!isInValidScope(facesContext, property, beanConfiguration))
 320  
                     {
 321  0
                         throw new FacesException("Property " + property.getPropertyName() +
 322  
                                 " references object in a scope with shorter lifetime than the target scope " +
 323  
                                 beanConfiguration.getManagedBeanScope());
 324  
                     }
 325  0
                     value = property.getRuntimeValue(facesContext);
 326  0
                     break;
 327  
                 default:
 328  0
                     throw new FacesException("unknown ManagedProperty type: "+ property.getType());
 329  
             }
 330  
             
 331  0
             Class<?> propertyClass = null;
 332  
 
 333  0
             if (property.getPropertyClass() == null)
 334  
             {
 335  0
                 propertyClass = elResolver.getType(elContext, bean, property.getPropertyName());
 336  
             }
 337  
             else
 338  
             {
 339  0
                 propertyClass = ClassUtils.simpleJavaTypeToClass(property.getPropertyClass());
 340  
             }
 341  
             
 342  0
             if (null == propertyClass)
 343  
             {
 344  0
                 throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
 345  
             }
 346  
             
 347  0
             Object coercedValue = coerceToType(facesContext, value, propertyClass);
 348  0
             elResolver.setValue(elContext, bean, property.getPropertyName(), coercedValue);
 349  0
         }
 350  0
     }
 351  
 
 352  
     // We no longer use the convertToType from shared impl because we switched
 353  
     // to unified EL in JSF 1.2
 354  
     @SuppressWarnings("unchecked")
 355  
     public static <T> T coerceToType(FacesContext facesContext, Object value, Class<? extends T> desiredClass)
 356  
     {
 357  0
         if (value == null)
 358  
         {
 359  0
             return null;
 360  
         }
 361  
 
 362  
         try
 363  
         {
 364  0
             ExpressionFactory expFactory = facesContext.getApplication().getExpressionFactory();
 365  
             // Use coersion implemented by JSP EL for consistency with EL
 366  
             // expressions. Additionally, it caches some of the coersions.
 367  0
             return (T)expFactory.coerceToType(value, desiredClass);
 368  
         }
 369  0
         catch (ELException e)
 370  
         {
 371  0
             String message = "Cannot coerce " + value.getClass().getName()
 372  
                     + " to " + desiredClass.getName();
 373  0
             log.log(Level.SEVERE, message , e);
 374  0
             throw new FacesException(message, e);
 375  
         }
 376  
     }
 377  
 
 378  
 
 379  
     /**
 380  
      * Checks if the scope of the property value is valid for a bean to be stored in targetScope.
 381  
      * If one of the scopes is a custom scope (since jsf 2.0), this method only checks the
 382  
      * references if the current ProjectStage is not Production.
 383  
      * @param facesContext
 384  
      * @param property           the property to be checked
 385  
      * @param beanConfiguration  the ManagedBean, which will be created
 386  
      */
 387  
     private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, ManagedBean beanConfiguration)
 388  
     {
 389  0
         if (!property.isValueReference())
 390  
         {
 391  
             // no value reference but a literal value -> nothing to check
 392  0
             return true;
 393  
         }
 394  
         
 395  
         // get the targetScope (since 2.0 this could be an EL ValueExpression)
 396  0
         String targetScope = null;
 397  0
         if (beanConfiguration.isManagedBeanScopeValueExpression())
 398  
         {
 399  
             // the scope is a custom scope
 400  
             // Spec says, that the developer has to take care about the references
 401  
             // to and from managed-beans in custom scopes.
 402  
             // However, we do check the references, if we are not in Production stage
 403  0
             if (facesContext.isProjectStage(ProjectStage.Production))
 404  
             {
 405  0
                 return true;
 406  
             }
 407  
             else
 408  
             {
 409  0
                 targetScope = getNarrowestScope(facesContext, 
 410  
                                                 beanConfiguration
 411  
                                                     .getManagedBeanScopeValueExpression(facesContext)
 412  
                                                     .getExpressionString());
 413  
                 // if we could not obtain a targetScope, return true
 414  0
                 if (targetScope == null)
 415  
                 {
 416  0
                     return true;
 417  
                 }
 418  
             }
 419  
         }
 420  
         else
 421  
         {
 422  0
             targetScope = beanConfiguration.getManagedBeanScope();
 423  0
             if (targetScope == null)
 424  
             {
 425  0
                 targetScope = NONE;
 426  
             }
 427  
         }
 428  
         
 429  
         // optimization: 'request' scope can reference any value scope
 430  0
         if (targetScope.equalsIgnoreCase(REQUEST))
 431  
         {
 432  0
             return true;
 433  
         }
 434  
         
 435  0
         String valueScope = getNarrowestScope(facesContext, 
 436  
                                               property.getValueBinding(facesContext)
 437  
                                                   .getExpressionString());
 438  
         
 439  
         // if we could not obtain a valueScope, return true
 440  0
         if (valueScope == null)
 441  
         {
 442  0
             return true;
 443  
         }
 444  
         
 445  
         // the target scope needs to have a shorter (or equal) lifetime than the value scope
 446  0
         return (SCOPE_COMPARATOR.compare(targetScope, valueScope) <= 0);
 447  
     }
 448  
 
 449  
     /**
 450  
      * Gets the narrowest scope to which the ValueExpression points.
 451  
      * @param facesContext
 452  
      * @param valueExpression
 453  
      * @return
 454  
      */
 455  
     private String getNarrowestScope(FacesContext facesContext, String valueExpression)
 456  
     {
 457  0
         List<String> expressions = extractExpressions(valueExpression);
 458  
         // exclude NONE scope, if there are more than one ValueExpressions (see Spec for details)
 459  0
         String narrowestScope = expressions.size() == 1 ? NONE : APPLICATION;
 460  0
         boolean scopeFound = false;
 461  
         
 462  0
         for (String expression : expressions)
 463  
         {
 464  0
             String valueScope = getScope(facesContext, expression);
 465  0
             if (valueScope == null)
 466  
             {
 467  0
                 continue;
 468  
             }
 469  
             // we have found at least one valid scope at this point
 470  0
             scopeFound = true;
 471  0
             if (SCOPE_COMPARATOR.compare(valueScope, narrowestScope) < 0)
 472  
             {
 473  0
                 narrowestScope = valueScope;
 474  
             }
 475  0
         }
 476  
         
 477  0
         return scopeFound ? narrowestScope : null;
 478  
     }
 479  
     
 480  
     private String getScope(FacesContext facesContext, String expression)
 481  
     {
 482  0
         String beanName = getFirstSegment(expression);
 483  0
         ExternalContext externalContext = facesContext.getExternalContext();
 484  
 
 485  
         // check scope objects
 486  0
         if (beanName.equalsIgnoreCase("requestScope"))
 487  
         {
 488  0
             return REQUEST;
 489  
         }
 490  0
         if (beanName.equalsIgnoreCase("sessionScope"))
 491  
         {
 492  0
             return SESSION;
 493  
         }
 494  0
         if (beanName.equalsIgnoreCase("applicationScope"))
 495  
         {
 496  0
             return APPLICATION;
 497  
         }
 498  
 
 499  
         // check implicit objects
 500  0
         if (beanName.equalsIgnoreCase("cookie"))
 501  
         {
 502  0
             return REQUEST;
 503  
         }
 504  0
         if (beanName.equalsIgnoreCase("facesContext"))
 505  
         {
 506  0
             return REQUEST;
 507  
         }
 508  0
         if (beanName.equalsIgnoreCase("header"))
 509  
         {
 510  0
             return REQUEST;
 511  
         }
 512  0
         if (beanName.equalsIgnoreCase("headerValues"))
 513  
         {
 514  0
             return REQUEST;
 515  
         }
 516  0
         if (beanName.equalsIgnoreCase("param"))
 517  
         {
 518  0
             return REQUEST;
 519  
         }
 520  0
         if (beanName.equalsIgnoreCase("paramValues"))
 521  
         {
 522  0
             return REQUEST;
 523  
         }
 524  0
         if (beanName.equalsIgnoreCase("request"))
 525  
         {
 526  0
             return REQUEST;
 527  
         }
 528  0
         if (beanName.equalsIgnoreCase("view")) // Spec says that view is considered to be in request scope
 529  
         {
 530  0
             return REQUEST;
 531  
         }
 532  0
         if (beanName.equalsIgnoreCase("application"))
 533  
         {
 534  0
             return APPLICATION;
 535  
         }
 536  0
         if (beanName.equalsIgnoreCase("initParam"))
 537  
         {
 538  0
             return APPLICATION;
 539  
         }
 540  
 
 541  
         // not found so far - check all scopes
 542  0
         final boolean startup = (externalContext instanceof StartupServletExternalContextImpl);
 543  0
         if (!startup)
 544  
         {
 545  
             // request and session maps are only available at runtime - not at startup
 546  
             // (the following code would throw an UnsupportedOperationException).
 547  0
             if (externalContext.getRequestMap().get(beanName) != null)
 548  
             {
 549  0
                 return REQUEST;
 550  
             }
 551  0
             if (externalContext.getSessionMap().get(beanName) != null)
 552  
             {
 553  0
                 return SESSION;
 554  
             }
 555  
         }
 556  0
         if (externalContext.getApplicationMap().get(beanName) != null)
 557  
         {
 558  0
             return APPLICATION;
 559  
         }
 560  0
         if (facesContext.getViewRoot() != null)
 561  
         {
 562  
             // Don't create the view Map during startup
 563  0
             Map<String, Object> viewMap = facesContext.getViewRoot().getViewMap(!startup);
 564  0
             if (viewMap!= null && viewMap.get(beanName) != null)
 565  
             {
 566  0
                 return VIEW;
 567  
             }
 568  
         }
 569  
 
 570  
         //not found - check mangaged bean config
 571  0
         ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
 572  0
         if (mbc != null)
 573  
         {
 574  
             // managed-bean-scope could be a EL ValueExpression (since 2.0)
 575  0
             if (mbc.isManagedBeanScopeValueExpression())
 576  
             {   
 577  
                 // the scope is a custom scope
 578  
                 // Spec says, that the developer has to take care about the references
 579  
                 // to and from managed-beans in custom scopes.
 580  
                 // However, we do check the references, if we are not in Production stage
 581  0
                 if (facesContext.isProjectStage(ProjectStage.Production))
 582  
                 {
 583  0
                     return null;
 584  
                 }
 585  
                 else
 586  
                 {
 587  0
                     String scopeExpression = mbc.getManagedBeanScopeValueExpression(facesContext).getExpressionString();
 588  0
                     return getNarrowestScope(facesContext, scopeExpression);
 589  
                 }
 590  
             }
 591  
             else
 592  
             {
 593  0
                 return mbc.getManagedBeanScope();
 594  
             }
 595  
         }
 596  
 
 597  0
         return null;
 598  
     }
 599  
 
 600  
     /**
 601  
      * Extract the first expression segment, that is the substring up to the first '.' or '['
 602  
      *
 603  
      * @param expression
 604  
      * @return first segment of the expression
 605  
      */
 606  
     private String getFirstSegment(String expression)
 607  
     {
 608  0
         int indexDot = expression.indexOf('.');
 609  0
         int indexBracket = expression.indexOf('[');
 610  
 
 611  0
         if (indexBracket < 0)
 612  
         {
 613  
 
 614  0
             return indexDot < 0 ? expression : expression.substring(0, indexDot);
 615  
 
 616  
         }
 617  
 
 618  0
         if (indexDot < 0)
 619  
         {
 620  0
             return expression.substring(0, indexBracket);
 621  
         }
 622  
 
 623  0
         return expression.substring(0, Math.min(indexDot, indexBracket));
 624  
 
 625  
     }
 626  
 
 627  
     private List<String> extractExpressions(String expressionString)
 628  
     {
 629  0
         List<String> expressions = new ArrayList<String>();
 630  0
         for (String expression : expressionString.split("\\#\\{"))
 631  
         {
 632  0
             int index = expression.indexOf('}');
 633  0
             if (index >= 0)
 634  
             {
 635  0
                 expressions.add(expression.substring(0, index));
 636  
             }
 637  
         }
 638  0
         return expressions;
 639  
     }
 640  
 
 641  
 
 642  
     private void initializeMap(FacesContext facesContext, MapEntries mapEntries, 
 643  
                                Map<? super Object, ? super Object> map)
 644  
     {
 645  0
         Application application = facesContext.getApplication();
 646  
         
 647  0
         Class<?> keyClass = (mapEntries.getKeyClass() == null)
 648  
                 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
 649  
         
 650  0
         Class<?> valueClass = (mapEntries.getValueClass() == null)
 651  
                 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
 652  
         
 653  
         ValueExpression valueExpression;
 654  0
         ExpressionFactory expFactory = application.getExpressionFactory();
 655  0
         ELContext elContext = facesContext.getELContext();
 656  
 
 657  0
         for (Iterator<? extends MapEntry> iterator = mapEntries.getMapEntries(); iterator.hasNext();)
 658  
         {
 659  0
             MapEntry entry = iterator.next();
 660  0
             Object key = entry.getKey();
 661  
 
 662  0
             if (ContainerUtils.isValueReference((String) key))
 663  
             {
 664  0
                 valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
 665  0
                 key = valueExpression.getValue(elContext);
 666  
             }
 667  
 
 668  0
             if (entry.isNullValue())
 669  
             {
 670  0
                 map.put(coerceToType(facesContext, key, keyClass), null);
 671  
             }
 672  
             else
 673  
             {
 674  0
                 Object value = entry.getValue();
 675  0
                 if (ContainerUtils.isValueReference((String) value))
 676  
                 {
 677  0
                     valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
 678  0
                     value = valueExpression.getValue(elContext);
 679  
                 }
 680  
                 
 681  0
                 map.put(coerceToType(facesContext, key, keyClass), coerceToType(facesContext, value, valueClass));
 682  
             }
 683  0
         }
 684  0
     }
 685  
 
 686  
 
 687  
     private void initializeList(FacesContext facesContext, ListEntries listEntries, List<? super Object> list)
 688  
     {
 689  0
         Application application = facesContext.getApplication();
 690  
         
 691  0
         Class<?> valueClass = (listEntries.getValueClass() == null)
 692  
                 ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
 693  
         
 694  0
         ExpressionFactory expFactory = application.getExpressionFactory();
 695  0
         ELContext elContext = facesContext.getELContext();
 696  
 
 697  0
         for (Iterator<? extends ListEntry> iterator = listEntries.getListEntries(); iterator.hasNext();)
 698  
         {
 699  0
             ListEntry entry = iterator.next();
 700  0
             if (entry.isNullValue())
 701  
             {
 702  0
                 list.add(null);
 703  
             }
 704  
             else
 705  
             {
 706  0
                 Object value = entry.getValue();
 707  0
                 if (ContainerUtils.isValueReference((String) value))
 708  
                 {
 709  0
                     ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value,
 710  
                                                                                        Object.class);
 711  0
                     value = valueExpression.getValue(elContext);
 712  
                 }
 713  
                 
 714  0
                 list.add(coerceToType(facesContext, value, valueClass));
 715  
             }
 716  0
         }
 717  0
     }
 718  
 
 719  
     private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
 720  
     {
 721  0
         if (_runtimeConfig == null)
 722  
         {
 723  0
             _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
 724  
         }
 725  
         
 726  0
         return _runtimeConfig;
 727  
     }
 728  
 }