Coverage Report - org.apache.myfaces.config.ManagedBeanBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
ManagedBeanBuilder
0%
0/198
0%
0/138
11.9
 
 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 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  
  * Create and initialize managed beans
 58  
  *
 59  
  * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller</a> (latest modification by $Author: lu4242 $)
 60  
  * @author Anton Koinov
 61  
  */
 62  0
 public class ManagedBeanBuilder
 63  
 {
 64  0
     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  
         /*final AnnotatedManagedBeanHandler handler = new AnnotatedManagedBeanHandler(bean,
 75  
                   beanConfiguration.getManagedBeanScope(), beanConfiguration.getManagedBeanName());
 76  
 
 77  
           final boolean threwUnchecked = handler.invokePostConstruct();
 78  
 
 79  
           if(threwUnchecked)
 80  
               return null;*/
 81  
         try
 82  
         {
 83  0
             LifecycleProvider lifecycleProvider =
 84  
                     LifecycleProviderFactory.getLifecycleProviderFactory().getLifecycleProvider(facesContext.getExternalContext());
 85  0
             final Object bean = lifecycleProvider.newInstance(beanConfiguration.getManagedBeanClassName());
 86  
 
 87  0
             switch (beanConfiguration.getInitMode())
 88  
             {
 89  
                 case ManagedBean.INIT_MODE_PROPERTIES:
 90  
                     try
 91  
                     {
 92  0
                         initializeProperties(facesContext, beanConfiguration.getManagedProperties(),
 93  
                                 beanConfiguration.getManagedBeanScope(), bean);
 94  
                     }
 95  0
                     catch (IllegalArgumentException e)
 96  
                     {
 97  0
                         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  0
                     }
 103  
                     break;
 104  
 
 105  
                 case ManagedBean.INIT_MODE_MAP:
 106  0
                     if (!(bean instanceof Map))
 107  
                     {
 108  0
                         throw new IllegalArgumentException("Class " + bean.getClass().getName()
 109  
                                 + " of managed bean "
 110  
                                 + beanConfiguration.getManagedBeanName()
 111  
                                 + " is not a Map.");
 112  
                     }
 113  0
                     initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map) bean);
 114  0
                     break;
 115  
 
 116  
                 case ManagedBean.INIT_MODE_LIST:
 117  0
                     if (!(bean instanceof List))
 118  
                     {
 119  0
                         throw new IllegalArgumentException("Class " + bean.getClass().getName()
 120  
                                 + " of managed bean "
 121  
                                 + beanConfiguration.getManagedBeanName()
 122  
                                 + " is not a List.");
 123  
                     }
 124  0
                     initializeList(facesContext, beanConfiguration.getListEntries(), (List) bean);
 125  0
                     break;
 126  
 
 127  
                 case ManagedBean.INIT_MODE_NO_INIT:
 128  
                     // no init values
 129  0
                     break;
 130  
 
 131  
                 default:
 132  0
                     throw new IllegalStateException("Unknown managed bean type "
 133  
                             + bean.getClass().getName() + " for managed bean "
 134  
                             + beanConfiguration.getManagedBeanName() + '.');
 135  
             }
 136  
             
 137  
             // MYFACES-1761 if implements LifecycleProvider,
 138  
             //PostConstruct was already called, but if implements
 139  
             //LifecycleProvider2, call it now.
 140  0
             if (lifecycleProvider instanceof LifecycleProvider2)
 141  
             {
 142  0
                 ((LifecycleProvider2)lifecycleProvider).postConstruct(bean);
 143  
             }
 144  0
             return bean;
 145  
         }
 146  0
         catch (IllegalAccessException e)
 147  
         {
 148  0
             throw new FacesException(e);
 149  
         }
 150  0
         catch (InvocationTargetException e)
 151  
         {
 152  0
             throw new FacesException(e);
 153  
         }
 154  0
         catch (NamingException e)
 155  
         {
 156  0
             throw new FacesException(e);
 157  
         }
 158  0
         catch (ClassNotFoundException e)
 159  
         {
 160  0
             throw new FacesException(e);
 161  
         }
 162  0
         catch (InstantiationException e)
 163  
         {
 164  0
             throw new FacesException(e);
 165  
         }
 166  
 
 167  
     }
 168  
 
 169  
 
 170  
     private void initializeProperties(FacesContext facesContext, Iterator managedProperties, String targetScope, Object bean)
 171  
     {
 172  0
         ELResolver elResolver = facesContext.getApplication().getELResolver();
 173  0
         ELContext elContext = facesContext.getELContext();
 174  
 
 175  0
         while (managedProperties.hasNext())
 176  
         {
 177  0
             ManagedProperty property = (ManagedProperty) managedProperties.next();
 178  0
             Object value = null;
 179  
 
 180  0
             switch (property.getType())
 181  
             {
 182  
                 case ManagedProperty.TYPE_LIST:
 183  
 
 184  
                     // JSF 1.1, 5.3.1.3
 185  
                     // Call the property getter, if it exists.
 186  
                     // If the getter returns null or doesn't exist, create a java.util.ArrayList,
 187  
                     // otherwise use the returned Object ...
 188  0
                     if (PropertyUtils.isReadable(bean, property.getPropertyName()))
 189  0
                         value = elResolver.getValue(elContext, bean, property.getPropertyName());
 190  0
                     value = value == null ? new ArrayList() : value;
 191  
 
 192  0
                     if (value instanceof List)
 193  
                     {
 194  0
                         initializeList(facesContext, property.getListEntries(), (List) value);
 195  
 
 196  
                     }
 197  0
                     else if (value != null && value.getClass().isArray())
 198  
                     {
 199  0
                         int length = Array.getLength(value);
 200  0
                         ArrayList temp = new ArrayList(length);
 201  0
                         for (int i = 0; i < length; i++)
 202  
                         {
 203  0
                             temp.add(Array.get(value, i));
 204  
                         }
 205  0
                         initializeList(facesContext, property.getListEntries(), temp);
 206  0
                         value = Array.newInstance(value.getClass().getComponentType(), temp.size());
 207  0
                         length = temp.size();
 208  
 
 209  0
                         for (int i = 0; i < length; i++)
 210  
                         {
 211  0
                             Array.set(value, i, temp.get(i));
 212  
                         }
 213  0
                     }
 214  
                     else
 215  
                     {
 216  0
                         value = new ArrayList();
 217  0
                         initializeList(facesContext, property.getListEntries(), (List) value);
 218  
                     }
 219  
 
 220  0
                     break;
 221  
                 case ManagedProperty.TYPE_MAP:
 222  
 
 223  
                     // JSF 1.1, 5.3.1.3
 224  
                     // Call the property getter, if it exists.
 225  
                     // If the getter returns null or doesn't exist, create a java.util.HashMap,
 226  
                     // otherwise use the returned java.util.Map .
 227  0
                     if (PropertyUtils.isReadable(bean, property.getPropertyName()))
 228  0
                         value = elResolver.getValue(elContext, bean, property.getPropertyName());
 229  0
                     value = value == null ? new HashMap() : value;
 230  
 
 231  0
                     if (!(value instanceof Map))
 232  
                     {
 233  0
                         value = new HashMap();
 234  
                     }
 235  
 
 236  0
                     initializeMap(facesContext, property.getMapEntries(), (Map) value);
 237  0
                     break;
 238  
                 case ManagedProperty.TYPE_NULL:
 239  0
                     value = null;
 240  0
                     break;
 241  
                 case ManagedProperty.TYPE_VALUE:
 242  
                     // check for correct scope of a referenced bean
 243  0
                     if (!isInValidScope(facesContext, property, targetScope))
 244  
                     {
 245  0
                         throw new FacesException("Property " + property.getPropertyName() +
 246  
                                 " references object in a scope with shorter lifetime than the target scope " + targetScope);
 247  
                     }
 248  0
                     value = property.getRuntimeValue(facesContext);
 249  
                     break;
 250  
             }
 251  0
             Class propertyClass = null;
 252  
 
 253  0
             if (property.getPropertyClass() == null)
 254  
             {
 255  0
                 propertyClass = elResolver
 256  
                         .getType(elContext, bean, property.getPropertyName());
 257  
             }
 258  
             else
 259  
             {
 260  0
                 propertyClass = ClassUtils
 261  
                         .simpleJavaTypeToClass(property.getPropertyClass());
 262  
             }
 263  0
             if (null == propertyClass)
 264  
             {
 265  0
                 throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
 266  
             }
 267  0
             Object coercedValue = coerceToType(facesContext, value, propertyClass);
 268  0
             elResolver.setValue(
 269  
                     elContext, bean, property.getPropertyName(), coercedValue);
 270  0
         }
 271  0
     }
 272  
 
 273  
     // We no longer use the convertToType from shared impl because we switched
 274  
     // to unified EL in JSF 1.2
 275  
     public static Object coerceToType(FacesContext facesContext, Object value, Class desiredClass)
 276  
     {
 277  0
         if (value == null) return null;
 278  
 
 279  
         try
 280  
         {
 281  0
             ExpressionFactory expFactory = facesContext.getApplication().getExpressionFactory();
 282  
             // Use coersion implemented by JSP EL for consistency with EL
 283  
             // expressions. Additionally, it caches some of the coersions.
 284  0
             return expFactory.coerceToType(value, desiredClass);
 285  
         }
 286  0
         catch (ELException e)
 287  
         {
 288  0
             String message = "Cannot coerce " + value.getClass().getName()
 289  
                     + " to " + desiredClass.getName();
 290  0
             log.error(message, e);
 291  0
             throw new FacesException(message, e);
 292  
         }
 293  
     }
 294  
 
 295  
 
 296  
     /**
 297  
      * Check if the scope of the property value is valid for a bean to be stored in targetScope.
 298  
      *
 299  
      * @param facesContext
 300  
      * @param property     the property to be checked
 301  
      * @param targetScope  name of the target scope of the bean under construction
 302  
      */
 303  
     private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, String targetScope)
 304  
     {
 305  0
         if (!property.isValueReference())
 306  
         {
 307  
             // no value reference but a literal value -> nothing to check
 308  0
             return true;
 309  
         }
 310  0
         String[] expressions = extractExpressions(property.getValueBinding(facesContext).getExpressionString());
 311  
 
 312  0
         for (int i = 0; i < expressions.length; i++)
 313  
         {
 314  0
             String expression = expressions[i];
 315  0
             if (expression == null)
 316  
             {
 317  0
                 continue;
 318  
             }
 319  
 
 320  0
             String valueScope = getScope(facesContext, expression);
 321  
 
 322  
             // if the target scope is 'none' value scope has to be 'none', too
 323  0
             if (targetScope == null || targetScope.equalsIgnoreCase(NONE))
 324  
             {
 325  0
                 if (valueScope != null && !(valueScope.equalsIgnoreCase(NONE)))
 326  
                 {
 327  0
                     return false;
 328  
                 }
 329  0
                 return true;
 330  
             }
 331  
 
 332  
             // 'application' scope can reference 'application' and 'none'
 333  0
             if (targetScope.equalsIgnoreCase(APPLICATION))
 334  
             {
 335  0
                 if (valueScope != null)
 336  
                 {
 337  0
                     if (valueScope.equalsIgnoreCase(REQUEST) ||
 338  
                             valueScope.equalsIgnoreCase(SESSION))
 339  
                     {
 340  0
                         return false;
 341  
                     }
 342  
                 }
 343  0
                 return true;
 344  
             }
 345  
 
 346  
             // 'session' scope can reference 'session', 'application', and 'none' but not 'request'
 347  0
             if (targetScope.equalsIgnoreCase(SESSION))
 348  
             {
 349  0
                 if (valueScope != null)
 350  
                 {
 351  0
                     if (valueScope.equalsIgnoreCase(REQUEST))
 352  
                     {
 353  0
                         return false;
 354  
                     }
 355  
                 }
 356  0
                 return true;
 357  
             }
 358  
 
 359  
             // 'request' scope can reference any value scope
 360  0
             if (targetScope.equalsIgnoreCase(REQUEST))
 361  
             {
 362  0
                 return true;
 363  
             }
 364  
         }
 365  0
         return false;
 366  
     }
 367  
 
 368  
 
 369  
     private String getScope(FacesContext facesContext, String expression)
 370  
     {
 371  0
         String beanName = getFirstSegment(expression);
 372  0
         ExternalContext externalContext = facesContext.getExternalContext();
 373  
 
 374  
         // check scope objects
 375  0
         if (beanName.equalsIgnoreCase("requestScope"))
 376  
         {
 377  0
             return REQUEST;
 378  
         }
 379  0
         if (beanName.equalsIgnoreCase("sessionScope"))
 380  
         {
 381  0
             return SESSION;
 382  
         }
 383  0
         if (beanName.equalsIgnoreCase("applicationScope"))
 384  
         {
 385  0
             return APPLICATION;
 386  
         }
 387  
 
 388  
         // check implicit objects
 389  0
         if (beanName.equalsIgnoreCase("cookie"))
 390  
         {
 391  0
             return REQUEST;
 392  
         }
 393  0
         if (beanName.equalsIgnoreCase("facesContext"))
 394  
         {
 395  0
             return REQUEST;
 396  
         }
 397  
 
 398  0
         if (beanName.equalsIgnoreCase("header"))
 399  
         {
 400  0
             return REQUEST;
 401  
         }
 402  0
         if (beanName.equalsIgnoreCase("headerValues"))
 403  
         {
 404  0
             return REQUEST;
 405  
         }
 406  
 
 407  0
         if (beanName.equalsIgnoreCase("initParam"))
 408  
         {
 409  0
             return APPLICATION;
 410  
         }
 411  0
         if (beanName.equalsIgnoreCase("param"))
 412  
         {
 413  0
             return REQUEST;
 414  
         }
 415  0
         if (beanName.equalsIgnoreCase("paramValues"))
 416  
         {
 417  0
             return REQUEST;
 418  
         }
 419  0
         if (beanName.equalsIgnoreCase("view"))
 420  
         {
 421  0
             return REQUEST;
 422  
         }
 423  
 
 424  
         // not found so far - check all scopes
 425  0
         if (externalContext.getRequestMap().get(beanName) != null)
 426  
         {
 427  0
             return REQUEST;
 428  
         }
 429  0
         if (externalContext.getSessionMap().get(beanName) != null)
 430  
         {
 431  0
             return SESSION;
 432  
         }
 433  0
         if (externalContext.getApplicationMap().get(beanName) != null)
 434  
         {
 435  0
             return APPLICATION;
 436  
         }
 437  
 
 438  
         //not found - check mangaged bean config
 439  
 
 440  0
         ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
 441  
 
 442  0
         if (mbc != null)
 443  
         {
 444  0
             return mbc.getManagedBeanScope();
 445  
         }
 446  
 
 447  0
         return null;
 448  
     }
 449  
 
 450  
     /**
 451  
      * Extract the first expression segment, that is the substring up to the first '.' or '['
 452  
      *
 453  
      * @param expression
 454  
      * @return first segment of the expression
 455  
      */
 456  
     private String getFirstSegment(String expression)
 457  
     {
 458  0
         int indexDot = expression.indexOf('.');
 459  0
         int indexBracket = expression.indexOf('[');
 460  
 
 461  0
         if (indexBracket < 0)
 462  
         {
 463  
 
 464  0
             return indexDot < 0 ? expression : expression.substring(0, indexDot);
 465  
 
 466  
         }
 467  
 
 468  0
         if (indexDot < 0)
 469  
         {
 470  0
             return expression.substring(0, indexBracket);
 471  
         }
 472  
 
 473  0
         return expression.substring(0, Math.min(indexDot, indexBracket));
 474  
 
 475  
     }
 476  
 
 477  
     private String[] extractExpressions(String expressionString)
 478  
     {
 479  0
         String[] expressions = expressionString.split("\\#\\{");
 480  0
         for (int i = 0; i < expressions.length; i++)
 481  
         {
 482  0
             String expression = expressions[i];
 483  0
             if (expression.trim().length() == 0)
 484  
             {
 485  0
                 expressions[i] = null;
 486  
             }
 487  
             else
 488  
             {
 489  0
                 int index = expression.indexOf('}');
 490  0
                 expressions[i] = expression.substring(0, index);
 491  
             }
 492  
         }
 493  0
         return expressions;
 494  
     }
 495  
 
 496  
 
 497  
     private void initializeMap(FacesContext facesContext, MapEntries mapEntries, Map map)
 498  
     {
 499  0
         Application application = facesContext.getApplication();
 500  0
         Class keyClass = (mapEntries.getKeyClass() == null)
 501  
                 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
 502  0
         Class valueClass = (mapEntries.getValueClass() == null)
 503  
                 ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
 504  
         ValueExpression valueExpression;
 505  0
         ExpressionFactory expFactory = application.getExpressionFactory();
 506  0
         ELContext elContext = facesContext.getELContext();
 507  
 
 508  0
         for (Iterator iterator = mapEntries.getMapEntries(); iterator.hasNext();)
 509  
         {
 510  0
             MapEntry entry = (MapEntry) iterator.next();
 511  0
             Object key = entry.getKey();
 512  
 
 513  0
             if (ContainerUtils.isValueReference((String) key))
 514  
             {
 515  0
                 valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
 516  0
                 key = valueExpression.getValue(elContext);
 517  
             }
 518  
 
 519  0
             if (entry.isNullValue())
 520  
             {
 521  0
                 map.put(coerceToType(facesContext, key, keyClass), null);
 522  
             }
 523  
             else
 524  
             {
 525  0
                 Object value = entry.getValue();
 526  0
                 if (ContainerUtils.isValueReference((String) value))
 527  
                 {
 528  0
                     valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
 529  0
                     value = valueExpression.getValue(elContext);
 530  
                 }
 531  0
                 map.put(coerceToType(facesContext, key, keyClass), coerceToType(facesContext, value, valueClass));
 532  
             }
 533  0
         }
 534  0
     }
 535  
 
 536  
 
 537  
     private void initializeList(FacesContext facesContext, ListEntries listEntries, List list)
 538  
     {
 539  0
         Application application = facesContext.getApplication();
 540  0
         Class valueClass = listEntries.getValueClass() == null ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
 541  0
         ExpressionFactory expFactory = application.getExpressionFactory();
 542  0
         ELContext elContext = facesContext.getELContext();
 543  
 
 544  0
         for (Iterator iterator = listEntries.getListEntries(); iterator.hasNext();)
 545  
         {
 546  0
             ListEntry entry = (ListEntry) iterator.next();
 547  0
             if (entry.isNullValue())
 548  
             {
 549  0
                 list.add(null);
 550  
             }
 551  
             else
 552  
             {
 553  0
                 Object value = entry.getValue();
 554  0
                 if (ContainerUtils.isValueReference((String) value))
 555  
                 {
 556  0
                     ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
 557  0
                     value = valueExpression.getValue(elContext);
 558  
                 }
 559  0
                 list.add(coerceToType(facesContext, value, valueClass));
 560  
             }
 561  0
         }
 562  0
     }
 563  
 
 564  
     private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
 565  
     {
 566  0
         if (_runtimeConfig == null)
 567  
         {
 568  0
             _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
 569  
         }
 570  0
         return _runtimeConfig;
 571  
     }
 572  
 }