/*
* $Id: ManagedBeanFactoryImpl.java,v 1.19 2007/03/16 13:43:27 rlubke Exp $
*/
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* https://javaserverfaces.dev.java.net/CDDL.html or
* legal/CDDLv1.0.txt.
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* [Name of File] [ver.__] [Date]
*
* Copyright 2005 Sun Microsystems Inc. All Rights Reserved
*/
package com.sun.faces.config;
import com.sun.faces.RIConstants;
import com.sun.faces.application.ApplicationAssociate;
import com.sun.faces.config.beans.DescriptionBean;
import com.sun.faces.config.beans.ListEntriesBean;
import com.sun.faces.config.beans.ManagedBeanBean;
import com.sun.faces.config.beans.ManagedPropertyBean;
import com.sun.faces.config.beans.MapEntriesBean;
import com.sun.faces.config.beans.MapEntryBean;
import com.sun.faces.el.ELUtils;
import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.spi.ManagedBeanFactory;
import com.sun.faces.util.MessageUtils;
import com.sun.faces.util.TypedCollections;
import com.sun.faces.util.Util;
import com.sun.org.apache.commons.beanutils.PropertyUtils;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.ReferenceSyntaxException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* <p>This class creates a managed bean instance. It has a contract with
* the ManagedBeanBean class which is populated from the config file.
* The bean instance is created lazily so a deep copy of the
* ManagedBeanBean is required.</p>
*
* <p>The Application implementation instantiated the beans as required and
* stores them in the appropriate scope.</p>
*/
public class ManagedBeanFactoryImpl extends ManagedBeanFactory {
//
// class variables
//
//
// Protected Constants
//
/**
* Managed bean type is unknown
*/
private static final byte TYPE_IS_UNKNOWN = -1;
/**
* This managed-bean or managed-property is a List
*/
private final static byte TYPE_IS_LIST = 0;
/**
* This managed-bean or managed-property is a Map
*/
private final static byte TYPE_IS_MAP = 1;
/**
* This managed-bean is a bean
*/
private final static byte TYPE_IS_BEAN = 2;
/**
* This managed-bean is a UIComponent
*/
private final static byte TYPE_IS_UICOMPONENT = 3;
/**
* This managed-property is a simple property
*/
private final static byte TYPE_IS_SIMPLE = 3;
private static final String MANAGED_BEAN_CREATED_STACK =
RIConstants.FACES_PREFIX + "managedBeanStack";
/**
* <p>The <code>Log</code> instance for this class.</p>
*/
private static final Logger LOGGER = Util.getLogger(Util.FACES_LOGGER
+ Util.CONFIG_LOGGER);
private boolean injectable;
// Attribute Instance Variables
private ManagedBeanBean managedBean;
private Scope scope = Scope.NONE;
private ApplicationAssociate associate;
// Relationship Instance Variables
/**
* <p>Setting this is part of the initialization contract for this
* class. Not setting this is a vialotation of that contract.</p>
*
*/
private Map<String,ManagedBeanFactory> managedBeanFactoryMap = null;
//
// Constructors and Initializers
//
/**
* Constructor
*/
public ManagedBeanFactoryImpl(ManagedBeanBean managedBean) {
//ManagedBeanBean clone method implemented to return deep copy
this.managedBean = managedBean; // (ManagedBeanBean) managedBean.clone();
//set the scope
scope = getScopeFromString(managedBean.getManagedBeanScope());
injectable = scanForAnnotations();
}
/**
* @return <code>true</code> if the managed bean instance created
* by this factory is a candidate for resource injection otherwise,
* returns <code>false</code>
*/
public boolean isInjectable() {
return injectable;
}
private Scope getScopeFromString(String scopeString) {
Scope result = Scope.NONE;
if (null != scopeString) {
if (scopeString.equalsIgnoreCase(RIConstants.REQUEST)) {
result = Scope.REQUEST;
}
else if (scopeString.equalsIgnoreCase(RIConstants.SESSION)) {
result = Scope.SESSION;
}
else if (scopeString.equalsIgnoreCase(RIConstants.APPLICATION)) {
result = Scope.APPLICATION;
}
}
return result;
}
public void setManagedBeanBean(ManagedBeanBean newBean) {
synchronized (this) {
//ManagedBeanBean clone method implemented to return deep copy
this.managedBean = newBean; // (ManagedBeanBean) newBean.clone();
//set the scope
scope = getScopeFromString(managedBean.getManagedBeanScope());
}
}
public ManagedBeanBean getManagedBeanBean() {
return this.managedBean;
}
public Map<String,ManagedBeanFactory> getManagedBeanFactoryMap() {
if (null == managedBeanFactoryMap) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.info("Contract violation: ManagedBeanFactory must be initialized with managedBeanFactoryMap after instantiation.");
}
}
return managedBeanFactoryMap;
}
public void setManagedBeanFactoryMap(Map<String,ManagedBeanFactory> newManagedBeanFactoryMap) {
managedBeanFactoryMap = newManagedBeanFactoryMap;
}
public String getBeanDescription(String lang) {
DescriptionBean db = managedBean.getDescription(lang);
if (db != null) {
return db.getDescription();
}
return null;
}
public final Class getManagedBeanClass() {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = this.getClass().getClassLoader();
}
return loader.loadClass(managedBean.getManagedBeanClass());
} catch (Exception e) {
}
return null;
}
/**
* Attempt to instantiate the JavaBean and set its properties.
*/
public Object newInstance(FacesContext context) throws FacesException {
Object
bean = null;
int
beanType = TYPE_IS_UNKNOWN;
// before instantiating the bean, make sure there is no cyclic
// references.
Map<String,Object> requestMap =
context.getExternalContext().getRequestMap();
List<String> beanList = TypedCollections.dynamicallyCastList(
(List) requestMap.get(MANAGED_BEAN_CREATED_STACK), String.class);
if (beanList == null) {
beanList = new ArrayList<String>();
requestMap.put(MANAGED_BEAN_CREATED_STACK, beanList);
}
if ( beanList.contains(managedBean.getManagedBeanName())) {
if ( LOGGER.isLoggable(Level.WARNING)) {
LOGGER.warning("Possible cyclic reference to managedBean " +
managedBean.getManagedBeanName() + " ");
}
Object[] obj = new Object[1];
obj[0] = managedBean.getManagedBeanName();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CYCLIC_REFERENCE_ERROR_ID, obj));
}
//
// instantiate the bean
//
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = context.
getClass().getClassLoader();
}
Class mbClass = Class.forName(managedBean.getManagedBeanClass(),
true,
loader);
bean = mbClass.newInstance();
} catch (Exception ex) {
Object[] obj = new Object[2];
obj[0] = managedBean.getManagedBeanClass();
obj[1] = managedBean.getManagedBeanName();
throw new FacesException(
(MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj) + ". " +
ex.getMessage()), ex);
}
// add the bean to the managed bean stack.
beanList.add(managedBean.getManagedBeanName());
// populate the bean with its contents
try {
ApplicationAssociate associate = getAssociate(context);
InjectionProvider injectionProvider =
associate.getInjectionProvider();
// Perform resource injection first
if (injectable) {
injectionProvider.inject(bean);
}
// now setup the managed properties which may
// leverage the injected info from the previous step
switch (beanType = getBeanType(bean)) {
case TYPE_IS_LIST:
copyListEntriesFromConfigToList(
managedBean.getListEntries(),
(List) bean);
break;
case TYPE_IS_MAP:
copyMapEntriesFromConfigToMap(managedBean.getMapEntries(),
(Map) bean);
break;
case TYPE_IS_UICOMPONENT:
// intentional fall-through
case TYPE_IS_BEAN:
setPropertiesIntoBean(bean, beanType, managedBean);
break;
default:
// notreached
assert (false);
break;
}
// now invoke methods marked with @PostConstruct
if (injectable) {
injectionProvider.invokePostConstruct(bean);
}
} catch (FacesException fe) {
throw fe;
} catch (ClassNotFoundException cnfe) {
Object[] obj = new Object[1];
obj[0] = managedBean.getManagedBeanClass();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj),
cnfe);
} catch (InjectionProviderException ipe) {
throw new FacesException(ipe.getCause());
} finally {
beanList.remove(managedBean.getManagedBeanName());
}
return bean;
}
/**
* determine the nature of the bean
*
* @return the appropriate TYPE_IS_* constant
*/
protected int getBeanType(Object bean) {
int result = TYPE_IS_UNKNOWN;
ListEntriesBean listEntries = managedBean.getListEntries();
MapEntriesBean mapEntries = managedBean.getMapEntries();
ManagedPropertyBean[] managedProperties =
managedBean.getManagedProperties();
// is it a List?
if (listEntries != null) {
// managed-bean instances that are Lists, must not have
// properties or map-entries. It is a configuration error
// if they do.
if (mapEntries != null ||
(managedProperties.length > 0)) {
Object[] obj = new Object[1];
obj[0] = managedBean.getManagedBeanClass();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj));
}
result = TYPE_IS_LIST;
}
// is it a Map?
if (mapEntries != null) {
assert (TYPE_IS_UNKNOWN == result);
// managed-bean instances that are Maps, must not have
// properties or list-entries. It is a configuration error
// if they do.
if (managedBean.getManagedProperties().length > 0) {
Object[] obj = new Object[1];
obj[0] = managedBean.getManagedBeanClass();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj));
}
result = TYPE_IS_MAP;
}
if (TYPE_IS_LIST != result && TYPE_IS_MAP != result) {
assert (TYPE_IS_UNKNOWN == result);
// if it's not a List or a Map, it must be a Bean
if (bean instanceof UIComponent) {
result = TYPE_IS_UICOMPONENT;
} else {
result = TYPE_IS_BEAN;
}
}
assert (TYPE_IS_UNKNOWN != result);
return result;
}
/**
* determine the nature of the property
*
* @return the appropriate TYPE_IS_* constant
*/
protected int getPropertyType(ManagedPropertyBean bean) {
int result = TYPE_IS_UNKNOWN;
ListEntriesBean listEntries = bean.getListEntries();
MapEntriesBean mapEntries = bean.getMapEntries();
// is it a List?
if (listEntries != null) {
// managed-property instances that have list-entries must
// not have value or map-entries. It is a configuration
// error if they do.
if (mapEntries != null ||
null != bean.getValue() || bean.isNullValue()) {
Object[] obj = new Object[1];
obj[0] = bean.getPropertyName();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj));
}
result = TYPE_IS_LIST;
}
// is it a Map?
if (mapEntries != null) {
assert (TYPE_IS_UNKNOWN == result);
// managed-property instances that have map-entries, must
// not have value or list-entries. It is a configuration
// error if they do.
if (null != bean.getValue() || bean.isNullValue()) {
Object[] obj = new Object[1];
obj[0] = bean.getPropertyName();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj));
}
result = TYPE_IS_MAP;
}
if (TYPE_IS_LIST != result && TYPE_IS_MAP != result) {
assert (TYPE_IS_UNKNOWN == result);
if (null != bean.getValue() || bean.isNullValue()) {
result = TYPE_IS_SIMPLE;
}
}
// if the managed-property doesn't have list-entries,
// map-entries, value, or null-value contents, this is a
// configuration error. The DTD doesn't allow this anyway.
if (TYPE_IS_UNKNOWN == result && !bean.isNullValue()) {
Object[] obj = new Object[1];
obj[0] = bean.getPropertyName();
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, obj));
}
return result;
}
protected Class copyListEntriesFromConfigToList(ListEntriesBean listEntries,
List<?> valuesForBean)
throws ClassNotFoundException {
String[] valuesFromConfig = listEntries.getValues();
Class valueClass = java.lang.String.class;
Object value = null;
String strValue = null;
int len = 0;
if (0 == (len = valuesFromConfig.length)) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("zero length array");
}
return null;
}
// pull out the value-class
valueClass =
getValueClassConsideringPrimitives(listEntries.getValueClass());
// go through the values from the config and copy them to the
// valuesForBean.
for (int i = 0; i < len; i++) {
strValue = valuesFromConfig[i];
// set our value local variable
if (isVBExpression(strValue)) {
value = evaluateValueExpressionGet(strValue);
} else if (null == strValue) {
value = null;
} else {
value = strValue;
}
// convert the value if necessary
value = getConvertedValueConsideringPrimitives(value, valueClass);
TypedCollections.dynamicallyCastList(valuesForBean, valueClass).add(value);
}
return valueClass;
}
void copyMapEntriesFromConfigToMap(MapEntriesBean mapEntries,
Map<?,?> result)
throws ClassNotFoundException {
Object
key = null,
value = null;
MapEntryBean[] valuesFromConfig = mapEntries.getMapEntries();
MapEntryBean curEntry = null;
Class
keyClass = java.lang.String.class,
valueClass = java.lang.String.class;
String
strKey = null,
strValue = null;
if (valuesFromConfig.length == 0) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("null or zero length array");
}
return;
}
// pull out the key-class and value-class
keyClass =
getValueClassConsideringPrimitives(mapEntries.getKeyClass());
valueClass =
getValueClassConsideringPrimitives(mapEntries.getValueClass());
for (int i = 0, len = valuesFromConfig.length; i < len; i++) {
curEntry = valuesFromConfig[i];
strKey = curEntry.getKey();
strValue = curEntry.getValue();
if (isVBExpression(strKey)) {
key = evaluateValueExpressionGet(strKey);
} else if (null == strKey) {
key = null;
} else {
key = getConvertedValueConsideringPrimitives(strKey,
keyClass);
}
if (isVBExpression(strValue)) {
value = evaluateValueExpressionGet(strValue);
} else if (null == strValue) {
value = null;
} else {
value = getConvertedValueConsideringPrimitives(strValue,
valueClass);
}
TypedCollections.dynamicallyCastMap(result, keyClass, valueClass).put(key, value);
}
}
protected void setPropertiesIntoBean(Object bean,
int beanType,
ManagedBeanBean managedBean) {
Object
value = null;
String
propertyClass = null,
propertyName = null,
strValue = null;
Class valueClass = null;
ManagedPropertyBean[] properties = managedBean.getManagedProperties();
if (null == properties) {
// a bean is allowed to have no properties
return;
}
// iterate over the properties and load each into the bean
for (int i = 0, len = properties.length; i < len; i++) {
// skip null properties or properties without names
if (null == properties[i] ||
null == (propertyName = properties[i].getPropertyName())) {
continue;
}
// determine what kind of property we have
try {
// this switch statement sets the "value" local variable
// and tries to set it into the bean.
switch (getPropertyType(properties[i])) {
case TYPE_IS_LIST:
setArrayOrListPropertiesIntoBean(bean, properties[i]);
break;
case TYPE_IS_MAP:
setMapPropertiesIntoBean(bean, properties[i]);
break;
case TYPE_IS_SIMPLE:
// if the config bean has no managed-property-class
// defined
if (null ==
(propertyClass = properties[i].getPropertyClass())) {
// look at the bean property
if (null ==
(valueClass =
PropertyUtils.getPropertyType(bean,
propertyName))) {
// if the bean property class can't be
// determined, use the fallback.
valueClass = String.class;
}
} else {
// the config has a managed-property-class
// defined
valueClass =
getValueClassConsideringPrimitives(
propertyClass);
}
strValue = properties[i].getValue();
if (isVBExpression(strValue)) {
value = evaluateValueExpressionGet(strValue);
} else if (null == strValue &&
properties[i].isNullValue()) {
value = null;
} else {
value = strValue;
}
// convert the value if necessary
value =
getConvertedValueConsideringPrimitives(value,
valueClass);
PropertyUtils.setSimpleProperty(bean,
propertyName,
value);
break;
default:
assert (false);
}
} catch (FacesException fe) {
throw fe;
} catch (Exception ex) {
// if the property happens to be attribute on
// UIComponent then bean introspection set will fail.
if (TYPE_IS_UICOMPONENT == beanType) {
setComponentAttribute(bean, propertyName, value);
} else {
// then this is a real exception to rethrow
Object[] obj = new Object[1];
obj[0] = propertyName;
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.ERROR_SETTING_BEAN_PROPERTY_ERROR_MESSAGE_ID,
obj),
ex);
}
}
}
}
/**
* <li><p> Call the property getter, if it exists.</p></li>
* <p/>
* <li><p>If the getter returns null or doesn't exist, create a
* java.util.ArrayList(), otherwise use the returned Object (an array or
* a java.util.List).</p></li>
* <p/>
* <li><p>If a List was returned or created in step 2), add all
* elements defined by nested <value> elements in the order
* they are listed, converting values defined by nested
* <value> elements to the type defined by
* <value-class>. If a <value-class> is not defined, use
* the value as-is (i.e., as a java.lang.String). Add null for each
* <null-value> element.</p></li>
* <p/>
* <li><p> If an array was returned in step 2), create a
* java.util.ArrayList and copy all elements from the returned array to
* the new List, auto-boxing elements of a primitive type. Add all
* elements defined by nested <value> elements as described in step
* 3).</p></li>
* <p/>
* <li><p> If a new java.util.List was created in step 2) and the
* property is of type List, set the property by calling the setter
* method, or log an error if there is no setter method.</p></li>
* <p/>
* <li><p> If a new java.util.List was created in step 4), convert
* the * List to array of the same type as the property and set the
* property by * calling the setter method, or log an error if there
* is no setter * method.</p></li>
*/
private void setArrayOrListPropertiesIntoBean(Object bean,
ManagedPropertyBean property)
throws Exception {
Object result = null;
boolean
getterIsNull = true,
getterIsArray = false;
List<?>
valuesForBean = null;
Class
valueType = java.lang.String.class,
propertyType = null;
String propertyName = property.getPropertyName();
try {
// see if there is a getter
result = PropertyUtils.getProperty(bean, propertyName);
getterIsNull = (null == result);
propertyType =
PropertyUtils.getPropertyType(bean, propertyName);
getterIsArray = propertyType.isArray();
} catch (NoSuchMethodException nsme) {
// it's valid to not have a getter.
}
// the property has to be either a List or Array
if (!getterIsArray) {
if (null != propertyType &&
!java.util.List.class.isAssignableFrom(propertyType)) {
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.MANAGED_BEAN_CANNOT_SET_LIST_ARRAY_PROPERTY_ID,
propertyName,
managedBean.getManagedBeanName()));
}
}
//
// Deal with the possibility of the getter returning existing
// values.
//
// if the getter returned non-null
if (!getterIsNull) {
// if what it returned was an array
if (getterIsArray) {
List<Object> existingValuesForBean = new ArrayList<Object>();
for (int i = 0, len = Array.getLength(result); i < len; i++) {
// add the existing values
existingValuesForBean.add(Array.get(result, i));
}
valuesForBean = existingValuesForBean;
} else {
// if what it returned was not a List
if (!(result instanceof List)) {
// throw an exception
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.MANAGED_BEAN_EXISTING_VALUE_NOT_LIST_ID,
propertyName,
managedBean.getManagedBeanName()));
}
valuesForBean = (List) result;
}
} else {
// getter returned null
result = valuesForBean = new ArrayList<Object>();
}
// at this point valuesForBean contains the existing values from
// the bean, or no values if the bean had no values. In any
// case, we can proceed to add values from the config file.
valueType = copyListEntriesFromConfigToList(property.getListEntries(),
valuesForBean);
// at this point valuesForBean has the values to be set into the
// bean.
if (getterIsArray) {
// convert back to Array
result = Array.newInstance(valueType, valuesForBean.size());
for (int i = 0, len = valuesForBean.size(); i < len; i++) {
if (valueType == Boolean.TYPE) {
Array.setBoolean(result, i,
(Boolean) valuesForBean.get(i));
} else if (valueType == Byte.TYPE) {
Array.setByte(result, i,
(Byte) valuesForBean.get(i));
} else if (valueType == Double.TYPE) {
Array.setDouble(result, i,
(Double) valuesForBean.get(i));
} else if (valueType == Float.TYPE) {
Array.setFloat(result, i,
(Float) valuesForBean.get(i));
} else if (valueType == Integer.TYPE) {
Array.setInt(result, i,
(Integer) valuesForBean.get(i));
} else if (valueType == Character.TYPE) {
Array.setChar(result, i,
(Character) valuesForBean.get(i));
} else if (valueType == Short.TYPE) {
Array.setShort(result, i,
(Short) valuesForBean.get(i));
} else if (valueType == Long.TYPE) {
Array.setLong(result, i,
(Long) valuesForBean.get(i));
} else {
Array.set(result, i, valuesForBean.get(i));
}
}
} else {
result = valuesForBean;
}
if (getterIsNull || getterIsArray) {
PropertyUtils.setProperty(bean, propertyName, result);
}
}
/**
* <li><p>Call the property getter, if it exists.</p></li>
* <p/>
* <li><p>If the getter returns null or doesn't exist, create a
* java.util.HashMap(), otherwise use the returned
* java.util.Map.</p></li>
* <p/>
* <li><p>Add all entries defined by nested <map-entry>
* elements in the order they are listed, converting key values
* defined by nested <key> elements to the type defined by
* <key-class> and entry values defined by nested
* <value> elements to the type defined by
* <value-class>. If <key-class> and/or
* <value-class> are not defined, use the value as-is (i.e.,
* as a java.lang.String). Add null for each <null-value>
* element.</p></li>
* <p/>
* <li><p>If a new java.util.Map was created in step 2), set the
* property by calling the setter method, or log an error if there
* is no setter method.</p></li>
*/
private void setMapPropertiesIntoBean(Object bean,
ManagedPropertyBean property)
throws Exception {
Map<?,?> result = null;
boolean getterIsNull = true;
Class propertyType = null;
String propertyName = property.getPropertyName();
try {
// see if there is a getter
result = (Map) PropertyUtils.getProperty(bean, propertyName);
getterIsNull = (null == result);
propertyType = PropertyUtils.getPropertyType(bean, propertyName);
} catch (NoSuchMethodException nsme) {
// it's valid to not have a getter.
}
if (null != propertyType &&
!Map.class.isAssignableFrom(propertyType)) {
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.MANAGED_BEAN_CANNOT_SET_MAP_PROPERTY_ID,
propertyName,
managedBean.getManagedBeanName()));
}
if (getterIsNull) {
result = new HashMap<Object,Object>();
}
// at this point result contains the existing entries from the
// bean, or no entries if the bean had no entries. In any case,
// we can proceed to add values from the config file.
copyMapEntriesFromConfigToMap(property.getMapEntries(), result);
if (getterIsNull) {
PropertyUtils.setProperty(bean, propertyName, result);
}
}
private Class getValueClassConsideringPrimitives(String valueClass)
throws ClassNotFoundException {
Class valueType = java.lang.String.class;
if (null != valueClass && 0 < valueClass.length()) {
if (valueClass.equals(Boolean.TYPE.getName())) {
valueType = Boolean.TYPE;
} else if (valueClass.equals(Byte.TYPE.getName())) {
valueType = Byte.TYPE;
} else if (valueClass.equals(Double.TYPE.getName())) {
valueType = Double.TYPE;
} else if (valueClass.equals(Float.TYPE.getName())) {
valueType = Float.TYPE;
} else if (valueClass.equals(Integer.TYPE.getName())) {
valueType = Integer.TYPE;
} else if (valueClass.equals(Character.TYPE.getName())) {
valueType = Character.TYPE;
} else if (valueClass.equals(Short.TYPE.getName())) {
valueType = Short.TYPE;
} else if (valueClass.equals(Long.TYPE.getName())) {
valueType = Long.TYPE;
} else {
valueType = Util.loadClass(valueClass, this);
}
}
return valueType;
}
private Object getConvertedValueConsideringPrimitives(Object value,
Class<?> valueType)
throws FacesException {
if (null != value && null != valueType) {
String valueString = value.toString();
if (valueType.isEnum()) {
value = Enum.valueOf((Class<? extends Enum>) valueType, valueString);
}
else if (valueType == Boolean.TYPE ||
valueType == java.lang.Boolean.class) {
value = Boolean.valueOf(valueString);
} else if (valueType == Byte.TYPE ||
valueType == java.lang.Byte.class) {
value = (valueString.length() == 0
? 0
: Byte.valueOf(valueString));
} else if (valueType == Double.TYPE ||
valueType == java.lang.Double.class) {
value = (valueString.length() == 0
? 0
: Double.valueOf(valueString));
} else if (valueType == Float.TYPE ||
valueType == java.lang.Float.class) {
value = (valueString.length() == 0
? 0
: Float.valueOf(valueString));
} else if (valueType == Integer.TYPE ||
valueType == java.lang.Integer.class) {
value = (valueString.length() == 0
? 0
: Integer.valueOf(valueString));
} else if (valueType == Character.TYPE ||
valueType == java.lang.Character.class) {
value = (valueString.length() == 0
? 0
: valueString.charAt(0));
} else if (valueType == Short.TYPE ||
valueType == java.lang.Short.class) {
value = (valueString.length() == 0
? 0
: Short.valueOf(valueString));
} else if (valueType == Long.TYPE ||
valueType == java.lang.Long.class) {
value = (valueString.length() == 0
? 0
: Long.valueOf(valueString));
} else if (valueType == String.class) {
} else if (!valueType.isAssignableFrom(value.getClass())) {
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.MANAGED_BEAN_TYPE_CONVERSION_ERROR_ID,
value.toString(),
value.getClass(),
valueType,
managedBean.getManagedBeanName()));
}
}
return value;
}
public Scope getScope() {
return scope;
}
private Object evaluateValueExpressionGet(String value) throws FacesException {
Object result = null;
if (!hasValidLifespan(value)) {
Object[] obj = new Object[1];
obj[0] = value;
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.INVALID_SCOPE_LIFESPAN_ERROR_MESSAGE_ID, obj));
}
ValueExpression ve = ELUtils.getValueExpression(value);
if (ve != null) {
try {
result =
ve.getValue(FacesContext.getCurrentInstance().getELContext());
} catch (PropertyNotFoundException ex) {
Object[] obj = new Object[1];
obj[0] = value;
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.ERROR_GETTING_VALUEREF_VALUE_ERROR_MESSAGE_ID,
obj));
}
} else {
Object[] obj = new Object[1];
obj[0] = value;
throw new FacesException(
MessageUtils.getExceptionMessageString(
MessageUtils.ERROR_GETTING_VALUE_BINDING_ERROR_MESSAGE_ID, obj));
}
return result;
}
@SuppressWarnings("deprecation")
private boolean hasValidLifespan(String value) throws EvaluationException, ReferenceSyntaxException {
Scope valueScope = null;
if (isMixedVBExpression(value)) {
valueScope = getNarrowestScopeFromExpression(value);
}
else {
valueScope = getScopeForSingleExpression(value);
}
//if the managed bean's scope is "none" but the scope of the
//referenced object is not "none", scope is invalid
if (scope == Scope.NONE) {
return valueScope == Scope.NONE;
}
//if the managed bean's scope is "request" it is able to refer
//to objects in any scope
if (scope == Scope.REQUEST) {
return true;
}
//if the managed bean's scope is "session" it is able to refer
//to objects in other "session", "application", or "none" scopes
if (scope == Scope.SESSION) {
return valueScope != Scope.REQUEST;
}
//if the managed bean's scope is "application" it is able to refer
//to objects in other "application", or "none" scopes
if (scope == Scope.APPLICATION) {
return !(valueScope == Scope.REQUEST
|| valueScope == Scope.SESSION);
}
//the managed bean is required to be in either "request", "session",
//"application", or "none" scopes. One of the previous decision
//statements must be true.
assert (false);
return false;
}
@SuppressWarnings("deprecation")
private Scope getScopeForSingleExpression(String value) throws ReferenceSyntaxException, EvaluationException {
String [] firstSegment = new String[1];
Scope valueScope = ELUtils.getScope(value, firstSegment);
if (null == valueScope) {
// Perhaps the bean hasn't been created yet. See what its
// scope would be when it is created.
ManagedBeanFactoryImpl otherFactory = null;
if (null != firstSegment[0] &&
null != (otherFactory = (ManagedBeanFactoryImpl)
getManagedBeanFactoryMap().get(firstSegment[0]))) {
valueScope = otherFactory.getScope();
}
else {
// we are referring to a bean that doesn't exist in the
// configuration file. Give it a wide scope...
valueScope = Scope.APPLICATION;
}
}
return valueScope;
}
@SuppressWarnings("deprecation")
private Scope getNarrowestScopeFromExpression(String expression) throws ReferenceSyntaxException {
// break the argument expression up into its component
// expressions, ignoring literals.
List expressions = ELUtils.getExpressionsFromString(expression);
Iterator iter = expressions.iterator();
int
shortestScope = Scope.NONE.ordinal(),
currentScope = Scope.NONE.ordinal();
Scope
lScope = Scope.NONE,
result = Scope.NONE;
// loop over the expressions
while (iter.hasNext()) {
lScope = getScopeForSingleExpression((String)iter.next());
// don't consider none
if (null == lScope || lScope == Scope.NONE) {
continue;
}
currentScope = lScope.ordinal();
// if we have no basis for comparison
if (Scope.NONE.ordinal() == shortestScope) {
shortestScope = currentScope;
result = lScope;
}
else {
// we have a basis for comparison
if (currentScope < shortestScope) {
shortestScope = currentScope;
result = lScope;
}
}
}
return result;
}
// scan methods and fields for annotations
private boolean scanForAnnotations() {
Class<?> clazz = getManagedBeanClass();
if (clazz != null) {
while (clazz != Object.class) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotations().length > 0) {
return true;
}
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.getDeclaredAnnotations().length > 0) {
return true;
}
}
clazz = clazz.getSuperclass();
}
}
return false;
}
private ApplicationAssociate getAssociate(FacesContext context) {
if (associate == null) {
associate = ApplicationAssociate.getInstance(context.getExternalContext());
}
return associate;
}
/**
* Sets the passed in property name and value as an attribute on
* <ocde>UIComponent</code> instance.
*/
public void setComponentAttribute(Object component, String propName,
Object propValue) {
((UIComponent) component).getAttributes().put(propName, propValue);
}
/*
* Determine whether String is a value binding expression or not.
*/
public static boolean isVBExpression(String expression) {
if (null == expression) {
return false;
}
int start = expression.indexOf("#{");
//check to see if attribute has an expression
if ((expression.indexOf("#{") != -1) &&
(start < expression.indexOf('}'))) {
return true;
}
return false;
}/*
* Determine whether String is a mixed value binding expression or not.
*/
public static boolean isMixedVBExpression(String expression) {
if (null == expression) {
return false;
}
// if it doesn't start and end with delimiters
if (!(expression.startsWith("#{") && expression.endsWith("}"))) {
// see if it has some inside.
return isVBExpression(expression);
}
return false;
}
}