Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.beanutils2;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.beanutils2.expression.DefaultResolver;
import org.apache.commons.beanutils2.expression.Resolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Utility methods for using Java Reflection APIs to facilitate generic property getter and setter operations on Java objects. Much of this code was originally
* included in {@code BeanUtils}, but has been separated because of the volume of code involved.
*
* In general, the objects that are examined and modified using these methods are expected to conform to the property getter and setter method naming
* conventions described in the JavaBeans Specification (Version 1.0.1). No data type conversions are performed, and there are no usage of any
* {@code PropertyEditor} classes that have been registered, although a convenient way to access the registered classes themselves is included.
*
* For the purposes of this class, five formats for referencing a particular property value of a bean are defined, with the default layout of an
* identifying String in parentheses. However the notation for these formats and how they are resolved is now (since BeanUtils 1.8.0) controlled by the
* configured {@link Resolver} implementation:
*
*
Simple ({@code name}) - The specified {@code name} identifies an individual property of a particular JavaBean. The name of the actual
* getter or setter method to be used is determined using standard JavaBeans introspection, so that (unless overridden by a {@code BeanInfo} class, a property
* named "xyz" will have a getter method named {@code getXyz()} or (for boolean properties only) {@code isXyz()}, and a setter method named
* {@code setXyz()}.
*
Nested ({@code name1.name2.name3}) The first name element is used to select a property getter, as for simple references above. The
* object returned for this property is then consulted, using the same approach, for a property getter for a property named {@code name2}, and so on. The
* property value that is ultimately retrieved or modified is the one identified by the last name element.
*
Indexed ({@code name[index]}) - The underlying property value is assumed to be an array, or this JavaBean is assumed to have indexed
* property getter and setter methods. The appropriate (zero-relative) entry in the array is selected. {@code List} objects are now also supported for
* read/write. You simply need to define a getter that returns the {@code List}
*
Mapped ({@code name(key)}) - The JavaBean is assumed to have an property getter and setter methods with an additional attribute of type
* {@link String}.
*
Combined ({@code name1.name2[index].name3(key)}) - Combining mapped, nested, and indexed references is also supported.
*
*
* @see Resolver
* @see PropertyUtils
* @since 1.7
*/
public class PropertyUtilsBean {
/** Log instance */
private static final Log LOG = LogFactory.getLog(PropertyUtilsBean.class);
/**
* Gets the PropertyUtils bean instance.
*
* @return The PropertyUtils bean instance
*/
protected static PropertyUtilsBean getInstance() {
return BeanUtilsBean.getInstance().getPropertyUtils();
}
/**
* Converts an object to a list of objects. This method is used when dealing with indexed properties. It assumes that indexed properties are stored as lists
* of objects.
*
* @param obj the object to be converted
* @return the resulting list of objects
*/
@SuppressWarnings("unchecked")
private static List is null}
* @since 1.6
*/
public boolean isReadable(Object bean, String name) {
// Validate method parameters
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
// Resolve nested references
while (resolver.hasNested(name)) {
final String next = resolver.next(name);
Object nestedBean = null;
try {
nestedBean = getProperty(bean, next);
} catch (final IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
return false;
}
if (nestedBean == null) {
throw new NestedNullException("Null property value for '" + next + "' on bean class '" + bean.getClass() + "'");
}
bean = nestedBean;
name = resolver.remove(name);
}
// Remove any subscript from the final name value
name = resolver.getProperty(name);
// Treat WrapDynaBean as special case - may be a write-only property
// (see Jira issue# BEANUTILS-61)
if (bean instanceof WrapDynaBean) {
bean = ((WrapDynaBean) bean).getInstance();
}
// Return the requested result
if (bean instanceof DynaBean) {
// All DynaBean properties are readable
return ((DynaBean) bean).getDynaClass().getDynaProperty(name) != null;
}
try {
final PropertyDescriptor desc = getPropertyDescriptor(bean, name);
if (desc != null) {
Method readMethod = getReadMethod(bean.getClass(), desc);
if (readMethod == null) {
if (desc instanceof IndexedPropertyDescriptor) {
readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod();
} else if (desc instanceof MappedPropertyDescriptor) {
readMethod = ((MappedPropertyDescriptor) desc).getMappedReadMethod();
}
readMethod = MethodUtils.getAccessibleMethod(bean.getClass(), readMethod);
}
return readMethod != null;
}
return false;
} catch (final IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
return false;
}
}
/**
* Return {@code true} if the specified property name identifies a writable property on the specified bean; otherwise, return {@code false}.
*
* @param bean Bean to be examined (may be a {@link DynaBean}
* @param name Property name to be evaluated
* @return {@code true} if the property is writable, otherwise {@code false}
* @throws IllegalArgumentException if {@code bean} or {@code name is null}
* @since 1.6
*/
public boolean isWriteable(Object bean, String name) {
// Validate method parameters
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
// Resolve nested references
while (resolver.hasNested(name)) {
final String next = resolver.next(name);
Object nestedBean = null;
try {
nestedBean = getProperty(bean, next);
} catch (final IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
return false;
}
if (nestedBean == null) {
throw new NestedNullException("Null property value for '" + next + "' on bean class '" + bean.getClass() + "'");
}
bean = nestedBean;
name = resolver.remove(name);
}
// Remove any subscript from the final name value
name = resolver.getProperty(name);
// Treat WrapDynaBean as special case - may be a read-only property
// (see Jira issue# BEANUTILS-61)
if (bean instanceof WrapDynaBean) {
bean = ((WrapDynaBean) bean).getInstance();
}
// Return the requested result
if (bean instanceof DynaBean) {
// All DynaBean properties are writable
return ((DynaBean) bean).getDynaClass().getDynaProperty(name) != null;
}
try {
final PropertyDescriptor desc = getPropertyDescriptor(bean, name);
if (desc != null) {
Method writeMethod = getWriteMethod(bean.getClass(), desc);
if (writeMethod == null) {
if (desc instanceof IndexedPropertyDescriptor) {
writeMethod = ((IndexedPropertyDescriptor) desc).getIndexedWriteMethod();
} else if (desc instanceof MappedPropertyDescriptor) {
writeMethod = ((MappedPropertyDescriptor) desc).getMappedWriteMethod();
}
writeMethod = MethodUtils.getAccessibleMethod(bean.getClass(), writeMethod);
}
return writeMethod != null;
}
return false;
} catch (final IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
return false;
}
}
/**
* Removes the specified {@code BeanIntrospector}.
*
* @param introspector the {@code BeanIntrospector} to be removed
* @return true if the {@code BeanIntrospector} existed and could be removed, false otherwise
* @since 1.9
*/
public boolean removeBeanIntrospector(final BeanIntrospector introspector) {
return introspectors.remove(introspector);
}
/**
* Resets the {@link BeanIntrospector} objects registered at this instance. After this method was called, only the default {@code BeanIntrospector} is
* registered.
*
* @since 1.9
*/
public final void resetBeanIntrospectors() {
introspectors.clear();
introspectors.add(DefaultBeanIntrospector.INSTANCE);
introspectors.add(SuppressPropertiesBeanIntrospector.SUPPRESS_CLASS);
introspectors.add(SuppressPropertiesBeanIntrospector.SUPPRESS_DECLARING_CLASS);
}
/**
* Sets the value of the specified indexed property of the specified bean, with no type conversions. In addition to supporting the JavaBeans specification,
* this method has been extended to support {@code List} objects as well.
*
* @param bean Bean whose property is to be set
* @param name Simple property name of the property value to be set
* @param index Index of the property value to be set
* @param value Value to which the indexed property element is to be set
* @throws IndexOutOfBoundsException if the specified index is outside the valid range for the underlying property
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws IllegalArgumentException if {@code bean} or {@code name} is null
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setIndexedProperty(final Object bean, final String name, final int index, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
if (name == null || name.isEmpty()) {
if (bean.getClass().isArray()) {
Array.set(bean, index, value);
return;
}
if (bean instanceof List) {
final List list = toObjectList(bean);
list.set(index, value);
return;
}
}
Objects.requireNonNull(name, "name");
// Handle DynaBean instances specially
if (bean instanceof DynaBean) {
final DynaProperty descriptor = ((DynaBean) bean).getDynaClass().getDynaProperty(name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on bean class '" + bean.getClass() + "'");
}
((DynaBean) bean).set(name, index, value);
return;
}
// Retrieve the property descriptor for the specified property
final PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on bean class '" + bean.getClass() + "'");
}
// Call the indexed setter method if there is one
if (descriptor instanceof IndexedPropertyDescriptor) {
Method writeMethod = ((IndexedPropertyDescriptor) descriptor).getIndexedWriteMethod();
writeMethod = MethodUtils.getAccessibleMethod(bean.getClass(), writeMethod);
if (writeMethod != null) {
try {
if (LOG.isTraceEnabled()) {
final String valueClassName = value == null ? "" : value.getClass().getName();
LOG.trace("setSimpleProperty: Invoking method " + writeMethod + " with index=" + index + ", value=" + value + " (class "
+ valueClassName + ")");
}
invokeMethod(writeMethod, bean, Integer.valueOf(index), value);
} catch (final InvocationTargetException e) {
if (e.getTargetException() instanceof IndexOutOfBoundsException) {
throw (IndexOutOfBoundsException) e.getTargetException();
}
throw e;
}
return;
}
}
// Otherwise, the underlying property must be an array or a list
final Method readMethod = getReadMethod(bean.getClass(), descriptor);
if (readMethod == null) {
throw new NoSuchMethodException("Property '" + name + "' has no getter method on bean class '" + bean.getClass() + "'");
}
// Call the property getter to get the array or list
final Object array = invokeMethod(readMethod, bean, BeanUtils.EMPTY_OBJECT_ARRAY);
if (!array.getClass().isArray()) {
if (!(array instanceof List)) {
throw new IllegalArgumentException("Property '" + name + "' is not indexed on bean class '" + bean.getClass() + "'");
}
// Modify the specified value in the List
final List list = toObjectList(array);
list.set(index, value);
} else {
// Modify the specified value in the array
Array.set(array, index, value);
}
}
/**
* Sets the value of the specified indexed property of the specified bean, with no type conversions. The zero-relative index of the required value must be
* included (in square brackets) as a suffix to the property name, or {@code IllegalArgumentException} will be thrown. In addition to supporting the
* JavaBeans specification, this method has been extended to support {@code List} objects as well.
*
* @param bean Bean whose property is to be modified
* @param name {@code propertyname[index]} of the property value to be modified
* @param value Value to which the specified property element should be set
* @throws IndexOutOfBoundsException if the specified index is outside the valid range for the underlying property
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws IllegalArgumentException if {@code bean} or {@code name} is null
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setIndexedProperty(final Object bean, String name, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
// Identify the index of the requested individual property
int index = -1;
try {
index = resolver.getIndex(name);
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid indexed property '" + name + "' on bean class '" + bean.getClass() + "'");
}
if (index < 0) {
throw new IllegalArgumentException("Invalid indexed property '" + name + "' on bean class '" + bean.getClass() + "'");
}
// Isolate the name
name = resolver.getProperty(name);
// Set the specified indexed property value
setIndexedProperty(bean, name, index, value);
}
/**
* Sets the value of the specified mapped property of the specified bean, with no type conversions. The key of the value to set must be included (in
* brackets) as a suffix to the property name, or {@code IllegalArgumentException} will be thrown.
*
* @param bean Bean whose property is to be set
* @param name {@code propertyname(key)} of the property value to be set
* @param value The property value to be set
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setMappedProperty(final Object bean, String name, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
// Identify the key of the requested individual property
String key = null;
try {
key = resolver.getKey(name);
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid mapped property '" + name + "' on bean class '" + bean.getClass() + "'");
}
if (key == null) {
throw new IllegalArgumentException("Invalid mapped property '" + name + "' on bean class '" + bean.getClass() + "'");
}
// Isolate the name
name = resolver.getProperty(name);
// Request the specified indexed property value
setMappedProperty(bean, name, key, value);
}
/**
* Sets the value of the specified mapped property of the specified bean, with no type conversions.
*
* @param bean Bean whose property is to be set
* @param name Mapped property name of the property value to be set
* @param key Key of the property value to be set
* @param value The property value to be set
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setMappedProperty(final Object bean, final String name, final String key, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
Objects.requireNonNull(key, "key");
// Handle DynaBean instances specially
if (bean instanceof DynaBean) {
final DynaProperty descriptor = ((DynaBean) bean).getDynaClass().getDynaProperty(name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on bean class '" + bean.getClass() + "'");
}
((DynaBean) bean).set(name, key, value);
return;
}
// Retrieve the property descriptor for the specified property
final PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on bean class '" + bean.getClass() + "'");
}
if (descriptor instanceof MappedPropertyDescriptor) {
// Call the keyed setter method if there is one
Method mappedWriteMethod = ((MappedPropertyDescriptor) descriptor).getMappedWriteMethod();
mappedWriteMethod = MethodUtils.getAccessibleMethod(bean.getClass(), mappedWriteMethod);
if (mappedWriteMethod == null) {
throw new NoSuchMethodException("Property '" + name + "' has no mapped setter method" + "on bean class '" + bean.getClass() + "'");
}
if (LOG.isTraceEnabled()) {
final String valueClassName = value == null ? "" : value.getClass().getName();
LOG.trace("setSimpleProperty: Invoking method " + mappedWriteMethod + " with key=" + key + ", value=" + value + " (class " + valueClassName
+ ")");
}
invokeMethod(mappedWriteMethod, bean, key, value);
} else {
/* means that the result has to be retrieved from a map */
final Method readMethod = getReadMethod(bean.getClass(), descriptor);
if (readMethod == null) {
throw new NoSuchMethodException("Property '" + name + "' has no mapped getter method on bean class '" + bean.getClass() + "'");
}
final Object invokeResult = invokeMethod(readMethod, bean, BeanUtils.EMPTY_OBJECT_ARRAY);
/* test and fetch from the map */
if (invokeResult instanceof Map) {
toPropertyMap(invokeResult).put(key, value);
}
}
}
/**
* Sets the value of the (possibly nested) property of the specified name, for the specified bean, with no type conversions.
*
* Example values for parameter "name" are:
*
*
"a" -- sets the value of property a of the specified bean
*
"a.b" -- gets the value of property a of the specified bean, then on that object sets the value of property b.
*
"a(key)" -- sets a value of mapped-property a on the specified bean. This effectively means bean.setA("key").
*
"a[3]" -- sets a value of indexed-property a on the specified bean. This effectively means bean.setA(3).
*
*
* @param bean Bean whose property is to be modified
* @param name Possibly nested name of the property to be modified
* @param value Value to which the property is to be set
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws IllegalArgumentException if {@code bean} or {@code name} is null
* @throws IllegalArgumentException if a nested reference to a property returns null
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setNestedProperty(Object bean, String name, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
// Resolve nested references
while (resolver.hasNested(name)) {
final String next = resolver.next(name);
Object nestedBean = null;
if (bean instanceof Map) {
nestedBean = getPropertyOfMapBean((Map, ?>) bean, next);
} else if (resolver.isMapped(next)) {
nestedBean = getMappedProperty(bean, next);
} else if (resolver.isIndexed(next)) {
nestedBean = getIndexedProperty(bean, next);
} else {
nestedBean = getSimpleProperty(bean, next);
}
if (nestedBean == null) {
throw new NestedNullException("Null property value for '" + name + "' on bean class '" + bean.getClass() + "'");
}
bean = nestedBean;
name = resolver.remove(name);
}
if (bean instanceof Map) {
setPropertyOfMapBean(toPropertyMap(bean), name, value);
} else if (resolver.isMapped(name)) {
setMappedProperty(bean, name, value);
} else if (resolver.isIndexed(name)) {
setIndexedProperty(bean, name, value);
} else {
setSimpleProperty(bean, name, value);
}
}
/**
* Sets the value of the specified property of the specified bean, no matter which property reference format is used, with no type conversions.
*
* @param bean Bean whose property is to be modified
* @param name Possibly indexed and/or nested name of the property to be modified
* @param value Value to which this property is to be set
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws IllegalArgumentException if {@code bean} or {@code name} is null
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setProperty(final Object bean, final String name, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
setNestedProperty(bean, name, value);
}
/**
* This method is called by method setNestedProperty when the current bean is found to be a Map object, and defines how to deal with setting a property on a
* Map.
*
* The standard implementation here is to:
*
*
call bean.set(propertyName) for all propertyName values.
*
throw an IllegalArgumentException if the property specifier contains MAPPED_DELIM or INDEXED_DELIM, as Map entries are essentially simple properties;
* mapping and indexing operations do not make sense when accessing a map (even thought the returned object may be a Map or an Array).
*
*
* The default behavior of BeanUtils 1.7.1 or later is for assigning to "a.b" to mean a.put(b, obj) always. However the behavior of BeanUtils version 1.6.0,
* 1.6.1, 1.7.0 was for "a.b" to mean a.setB(obj) if such a method existed, and a.put(b, obj) otherwise. In version 1.5 it meant a.put(b, obj) always (ie
* the same as the behavior in the current version). In versions prior to 1.5 it meant a.setB(obj) always. [yes, this is all very unfortunate]
*
* Users who would like to customize the meaning of "a.b" in method setNestedProperty when a is a Map can create a custom subclass of this class and
* override this method to implement the behavior of their choice, such as restoring the pre-1.4 behavior of this class if they wish. When overriding this
* method, do not forget to deal with MAPPED_DELIM and INDEXED_DELIM characters in the propertyName.
*
* Note, however, that the recommended solution for objects that implement Map but want their simple properties to come first is for those objects
* to override their get/put methods to implement that behavior, and not to solve the problem by modifying the default behavior of the
* PropertyUtilsBean class by overriding this method.
*
* @param bean Map bean
* @param propertyName The property name
* @param value the property value
* @throws IllegalArgumentException when the propertyName is regarded as being invalid.
* @throws IllegalAccessException just in case subclasses override this method to try to access real setter methods and find permission is denied.
* @throws InvocationTargetException just in case subclasses override this method to try to access real setter methods, and find it throws an exception when
* invoked.
*
* @throws NoSuchMethodException just in case subclasses override this method to try to access real setter methods, and want to fail if no simple method
* is available.
* @since 1.8.0
*/
protected void setPropertyOfMapBean(final Map bean, String propertyName, final Object value)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
if (resolver.isMapped(propertyName)) {
final String name = resolver.getProperty(propertyName);
if (name == null || name.isEmpty()) {
propertyName = resolver.getKey(propertyName);
}
}
if (resolver.isIndexed(propertyName) || resolver.isMapped(propertyName)) {
throw new IllegalArgumentException("Indexed or mapped properties are not supported on" + " objects of type Map: " + propertyName);
}
bean.put(propertyName, value);
}
/**
* Configure the {@link Resolver} implementation used by BeanUtils.
*
* The {@link Resolver} handles the property name expressions and the implementation in use effectively controls the dialect of the expression
* language that BeanUtils recognizes.
*
* {@link DefaultResolver} is the default implementation used.
*
* @param resolver The property expression resolver.
* @since 1.8.0
*/
public void setResolver(final Resolver resolver) {
if (resolver == null) {
this.resolver = new DefaultResolver();
} else {
this.resolver = resolver;
}
}
/**
* Sets the value of the specified simple property of the specified bean, with no type conversions.
*
* @param bean Bean whose property is to be modified
* @param name Name of the property to be modified
* @param value Value to which the property should be set
* @throws IllegalAccessException if the caller does not have access to the property accessor method
* @throws IllegalArgumentException if {@code bean} or {@code name} is null
* @throws IllegalArgumentException if the property name is nested or indexed
* @throws InvocationTargetException if the property accessor method throws an exception
* @throws NoSuchMethodException if an accessor method for this property cannot be found
*/
public void setSimpleProperty(final Object bean, final String name, final Object value)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Objects.requireNonNull(bean, "bean");
Objects.requireNonNull(name, "name");
final Class> beanClass = bean.getClass();
// Validate the syntax of the property name
if (resolver.hasNested(name)) {
throw new IllegalArgumentException("Nested property names are not allowed: Property '" + name + "' on bean class '" + beanClass + "'");
}
if (resolver.isIndexed(name)) {
throw new IllegalArgumentException("Indexed property names are not allowed: Property '" + name + "' on bean class '" + beanClass + "'");
}
if (resolver.isMapped(name)) {
throw new IllegalArgumentException("Mapped property names are not allowed: Property '" + name + "' on bean class '" + beanClass + "'");
}
// Handle DynaBean instances specially
if (bean instanceof DynaBean) {
final DynaProperty descriptor = ((DynaBean) bean).getDynaClass().getDynaProperty(name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on dynaclass '" + ((DynaBean) bean).getDynaClass() + "'");
}
((DynaBean) bean).set(name, value);
return;
}
// Retrieve the property setter method for the specified property
final PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" + name + "' on class '" + beanClass + "'");
}
final Method writeMethod = getWriteMethod(beanClass, descriptor);
if (writeMethod == null) {
throw new NoSuchMethodException("Property '" + name + "' has no setter method in class '" + beanClass + "'");
}
// Call the property setter method
if (LOG.isTraceEnabled()) {
final String valueClassName = value == null ? "" : value.getClass().getName();
LOG.trace("setSimpleProperty: Invoking method " + writeMethod + " with value " + value + " (class " + valueClassName + ")");
}
invokeMethod(writeMethod, bean, value);
}
}