📄 beanwrapperimpl.java
字号:
if (logger.isDebugEnabled())
logger.debug("About to invoke read method [" + pd.getReadMethod() + "] on object of class [" +
this.object.getClass().getName() + "]");
try {
Object value = pd.getReadMethod().invoke(this.object, (Object[]) null);
if (tokens.keys != null) {
// apply indexes and map keys
for (int i = 0; i < tokens.keys.length; i++) {
String key = tokens.keys[i];
if (value == null) {
throw new NullValueInNestedPathException(
getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value of property referenced in indexed " +
"property path '" + propertyName + "': returned null");
}
else if (value.getClass().isArray()) {
value = Array.get(value, Integer.parseInt(key));
}
else if (value instanceof List) {
List list = (List) value;
value = list.get(Integer.parseInt(key));
}
else if (value instanceof Set) {
// apply index to Iterator in case of a Set
Set set = (Set) value;
int index = Integer.parseInt(key);
if (index < 0 || index >= set.size()) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Cannot get element with index " + index + " from Set of size " +
set.size() + ", accessed using property path '" + propertyName + "'");
}
Iterator it = set.iterator();
for (int j = 0; it.hasNext(); j++) {
Object elem = it.next();
if (j == index) {
value = elem;
break;
}
}
}
else if (value instanceof Map) {
Map map = (Map) value;
value = map.get(key);
}
else {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]");
}
}
}
return value;
}
catch (InvocationTargetException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Getter for property '" + actualName + "' threw exception", ex);
}
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Index of out of bounds in property path '" + propertyName + "'", ex);
}
catch (NumberFormatException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
}
public void setPropertyValue(String propertyName, Object value) throws BeansException {
BeanWrapperImpl nestedBw = null;
try {
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(
getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
nestedBw.setPropertyValue(tokens, value);
}
protected void setPropertyValue(PropertyTokenHolder tokens, Object value)
throws BeansException {
String propertyName = tokens.canonicalName;
if (tokens.keys != null) {
// apply indexes and map keys: fetch value for all keys but the last one
PropertyTokenHolder getterTokens = new PropertyTokenHolder();
getterTokens.canonicalName = tokens.canonicalName;
getterTokens.actualName = tokens.actualName;
getterTokens.keys = new String[tokens.keys.length - 1];
System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
Object propValue = null;
try {
propValue = getPropertyValue(getterTokens);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(
getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "'", ex);
}
// set value for last key
String key = tokens.keys[tokens.keys.length - 1];
if (propValue == null) {
throw new NullValueInNestedPathException(
getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
else if (propValue.getClass().isArray()) {
Class requiredType = propValue.getClass().getComponentType();
Object newValue = doTypeConversionIfNecessary(propertyName, propertyName, null, value, requiredType);
try {
Array.set(propValue, Integer.parseInt(key), newValue);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(
this.rootObject, this.nestedPath + propertyName, null, newValue);
throw new TypeMismatchException(pce, requiredType, ex);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Invalid array index in property path '" + propertyName + "'", ex);
}
}
else if (propValue instanceof List) {
Object newValue = doTypeConversionIfNecessary(propertyName, propertyName, null, value, null);
List list = (List) propValue;
int index = Integer.parseInt(key);
if (index < list.size()) {
list.set(index, newValue);
}
else if (index >= list.size()) {
for (int i = list.size(); i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
list.size() + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(newValue);
}
}
else if (propValue instanceof Map) {
Object newValue = doTypeConversionIfNecessary(propertyName, propertyName, null, value, null);
Map map = (Map) propValue;
map.put(key, newValue);
}
else {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + value + "]");
}
}
else {
if (!isWritableProperty(propertyName)) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName);
}
PropertyDescriptor pd = getPropertyDescriptor(propertyName);
Method writeMethod = pd.getWriteMethod();
Object newValue = null;
try {
// old value may still be null
newValue = doTypeConversionIfNecessary(propertyName, propertyName, null, value, pd.getPropertyType());
if (pd.getPropertyType().isPrimitive() && (newValue == null || "".equals(newValue))) {
throw new IllegalArgumentException("Invalid value [" + value + "] for property '" +
pd.getName() + "' of primitive type [" + pd.getPropertyType() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("About to invoke write method [" + writeMethod + "] on object of class [" +
this.object.getClass().getName() + "]");
}
writeMethod.invoke(this.object, new Object[] { newValue });
if (logger.isDebugEnabled()) {
String msg = "Invoked write method [" + writeMethod + "] with value ";
// only cause toString invocation of new value in case of simple property
if (newValue == null || BeanUtils.isSimpleProperty(pd.getPropertyType())) {
logger.debug(msg + PROPERTY_KEY_PREFIX + newValue + PROPERTY_KEY_SUFFIX);
}
else {
logger.debug(msg + "of type [" + pd.getPropertyType().getName() + "]");
}
}
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
}
else {
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
}
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
}
catch (IllegalAccessException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
throw new MethodInvocationException(pce, ex);
}
}
}
public void setPropertyValue(PropertyValue pv) throws BeansException {
setPropertyValue(pv.getName(), pv.getValue());
}
/**
* Bulk update from a Map.
* Bulk updates from PropertyValues are more powerful: this method is
* provided for convenience.
* @param map map containing properties to set, as name-value pairs.
* The map may include nested properties.
* @throws BeansException if there's a fatal, low-level exception
*/
public void setPropertyValues(Map map) throws BeansException {
setPropertyValues(new MutablePropertyValues(map));
}
public void setPropertyValues(PropertyValues pvs) throws BeansException {
setPropertyValues(pvs, false);
}
public void setPropertyValues(PropertyValues propertyValues, boolean ignoreUnknown) throws BeansException {
List propertyAccessExceptions = new ArrayList();
PropertyValue[] pvs = propertyValues.getPropertyValues();
for (int i = 0; i < pvs.length; i++) {
try {
// This method may throw any BeansException, which won't be caught
// here, if there is a critical failure such as no matching field.
// We can attempt to deal only with less serious exceptions.
setPropertyValue(pvs[i]);
}
catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
}
// otherwise, just ignore it and continue...
}
catch (PropertyAccessException ex) {
propertyAccessExceptions.add(ex);
}
}
// If we encountered individual exceptions, throw the composite exception.
if (!propertyAccessExceptions.isEmpty()) {
Object[] paeArray = propertyAccessExceptions.toArray(
new PropertyAccessException[propertyAccessExceptions.size()]);
throw new PropertyAccessExceptionsException(this, (PropertyAccessException[]) paeArray);
}
}
private PropertyChangeEvent createPropertyChangeEvent(String propertyName, Object oldValue, Object newValue) {
return new PropertyChangeEvent(
(this.rootObject != null ? this.rootObject : "constructor"),
(propertyName != null ? this.nestedPath + propertyName : null),
oldValue, newValue);
}
/**
* Convert the value to the required type (if necessary from a String).
* Conversions from String to any type use the setAsText method of
* the PropertyEditor class. Note that a PropertyEditor must be registered
* for this class for this to work. This is a standard Java Beans API.
* A number of property editors are automatically registered by this class.
* @param newValue proposed change value.
* @param requiredType type we must convert to
* @throws BeansException if there is an internal error
* @return new value, possibly the result of type convertion
*/
public Object doTypeConversionIfNecessary(Object newValue, Class requiredType) throws BeansException {
return doTypeConversionIfNecessary(null, null, null, newValue, requiredType);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -