446 lines
16 KiB
Java
446 lines
16 KiB
Java
package org.apache.commons.beanutils;
|
|
|
|
import java.beans.IndexedPropertyDescriptor;
|
|
import java.beans.PropertyDescriptor;
|
|
import java.lang.reflect.Array;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
import org.apache.commons.collections.FastHashMap;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
public class BeanUtils {
|
|
private static FastHashMap dummy = new FastHashMap();
|
|
|
|
private static Log log = LogFactory.getLog(BeanUtils.class);
|
|
|
|
private static int debug = 0;
|
|
|
|
public static int getDebug() {
|
|
return debug;
|
|
}
|
|
|
|
public static void setDebug(int newDebug) {
|
|
debug = newDebug;
|
|
}
|
|
|
|
public static Object cloneBean(Object bean) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Cloning bean: " + bean.getClass().getName());
|
|
Class clazz = bean.getClass();
|
|
Object newBean = clazz.newInstance();
|
|
PropertyUtils.copyProperties(newBean, bean);
|
|
return newBean;
|
|
}
|
|
|
|
public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
|
|
if (dest == null)
|
|
throw new IllegalArgumentException("No destination bean specified");
|
|
if (orig == null)
|
|
throw new IllegalArgumentException("No origin bean specified");
|
|
if (log.isDebugEnabled())
|
|
log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");
|
|
if (orig instanceof DynaBean) {
|
|
DynaProperty[] origDescriptors = ((DynaBean)orig).getDynaClass().getDynaProperties();
|
|
for (int i = 0; i < origDescriptors.length; i++) {
|
|
String name = origDescriptors[i].getName();
|
|
if (PropertyUtils.isWriteable(dest, name)) {
|
|
Object value = ((DynaBean)orig).get(name);
|
|
copyProperty(dest, name, value);
|
|
}
|
|
}
|
|
} else if (orig instanceof Map) {
|
|
Iterator names = ((Map)orig).keySet().iterator();
|
|
while (names.hasNext()) {
|
|
String name = names.next();
|
|
if (PropertyUtils.isWriteable(dest, name)) {
|
|
Object value = ((Map)orig).get(name);
|
|
copyProperty(dest, name, value);
|
|
}
|
|
}
|
|
} else {
|
|
PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(orig);
|
|
for (int i = 0; i < origDescriptors.length; i++) {
|
|
String name = origDescriptors[i].getName();
|
|
if (!"class".equals(name))
|
|
if (PropertyUtils.isReadable(orig, name) && PropertyUtils.isWriteable(dest, name))
|
|
try {
|
|
Object value = PropertyUtils.getSimpleProperty(orig, name);
|
|
copyProperty(dest, name, value);
|
|
} catch (NoSuchMethodException e) {}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException {
|
|
if (log.isTraceEnabled()) {
|
|
StringBuffer sb = new StringBuffer(" copyProperty(");
|
|
sb.append(bean);
|
|
sb.append(", ");
|
|
sb.append(name);
|
|
sb.append(", ");
|
|
if (value == null) {
|
|
sb.append("<NULL>");
|
|
} else if (value instanceof String) {
|
|
sb.append((String)value);
|
|
} else if (value instanceof String[]) {
|
|
String[] values = (String[])value;
|
|
sb.append('[');
|
|
for (int k = 0; k < values.length; k++) {
|
|
if (k > 0)
|
|
sb.append(',');
|
|
sb.append(values[k]);
|
|
}
|
|
sb.append(']');
|
|
} else {
|
|
sb.append(value.toString());
|
|
}
|
|
sb.append(')');
|
|
log.trace(sb.toString());
|
|
}
|
|
Object target = bean;
|
|
int delim = name.lastIndexOf('.');
|
|
if (delim >= 0) {
|
|
try {
|
|
target = PropertyUtils.getProperty(bean, name.substring(0, delim));
|
|
} catch (NoSuchMethodException e) {
|
|
return;
|
|
}
|
|
name = name.substring(delim + 1);
|
|
if (log.isTraceEnabled()) {
|
|
log.trace(" Target bean = " + target);
|
|
log.trace(" Target name = " + name);
|
|
}
|
|
}
|
|
String propName = null;
|
|
Class type = null;
|
|
int index = -1;
|
|
String key = null;
|
|
propName = name;
|
|
int i = propName.indexOf('[');
|
|
if (i >= 0) {
|
|
int k = propName.indexOf(']');
|
|
try {
|
|
index = Integer.parseInt(propName.substring(i + 1, k));
|
|
} catch (NumberFormatException e) {}
|
|
propName = propName.substring(0, i);
|
|
}
|
|
int j = propName.indexOf('(');
|
|
if (j >= 0) {
|
|
int k = propName.indexOf(')');
|
|
try {
|
|
key = propName.substring(j + 1, k);
|
|
} catch (IndexOutOfBoundsException e) {}
|
|
propName = propName.substring(0, j);
|
|
}
|
|
if (target instanceof DynaBean) {
|
|
DynaClass dynaClass = ((DynaBean)target).getDynaClass();
|
|
DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
|
|
if (dynaProperty == null)
|
|
return;
|
|
type = dynaProperty.getType();
|
|
} else {
|
|
PropertyDescriptor descriptor = null;
|
|
try {
|
|
descriptor = PropertyUtils.getPropertyDescriptor(target, name);
|
|
if (descriptor == null)
|
|
return;
|
|
} catch (NoSuchMethodException e) {
|
|
return;
|
|
}
|
|
type = descriptor.getPropertyType();
|
|
if (type == null) {
|
|
if (log.isTraceEnabled())
|
|
log.trace(" target type for property '" + propName + "' is null, so skipping ths setter");
|
|
return;
|
|
}
|
|
}
|
|
if (log.isTraceEnabled())
|
|
log.trace(" target propName=" + propName + ", type=" + type + ", index=" + index + ", key=" + key);
|
|
if (index >= 0) {
|
|
Converter converter = ConvertUtils.lookup(type.getComponentType());
|
|
if (converter != null) {
|
|
log.trace(" USING CONVERTER " + converter);
|
|
value = converter.convert(type, value);
|
|
}
|
|
try {
|
|
PropertyUtils.setIndexedProperty(target, propName, index, value);
|
|
} catch (NoSuchMethodException e) {
|
|
throw new InvocationTargetException(e, "Cannot set " + propName);
|
|
}
|
|
} else if (key != null) {
|
|
try {
|
|
PropertyUtils.setMappedProperty(target, propName, key, value);
|
|
} catch (NoSuchMethodException e) {
|
|
throw new InvocationTargetException(e, "Cannot set " + propName);
|
|
}
|
|
} else {
|
|
Converter converter = ConvertUtils.lookup(type);
|
|
if (converter != null) {
|
|
log.trace(" USING CONVERTER " + converter);
|
|
value = converter.convert(type, value);
|
|
}
|
|
try {
|
|
PropertyUtils.setSimpleProperty(target, propName, value);
|
|
} catch (NoSuchMethodException e) {
|
|
throw new InvocationTargetException(e, "Cannot set " + propName);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Map describe(Object bean) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
if (bean == null)
|
|
return new HashMap();
|
|
if (log.isDebugEnabled())
|
|
log.debug("Describing bean: " + bean.getClass().getName());
|
|
Map description = new HashMap();
|
|
if (bean instanceof DynaBean) {
|
|
DynaProperty[] descriptors = ((DynaBean)bean).getDynaClass().getDynaProperties();
|
|
for (int i = 0; i < descriptors.length; i++) {
|
|
String name = descriptors[i].getName();
|
|
description.put(name, getProperty(bean, name));
|
|
}
|
|
} else {
|
|
PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(bean);
|
|
for (int i = 0; i < descriptors.length; i++) {
|
|
String name = descriptors[i].getName();
|
|
if (descriptors[i].getReadMethod() != null)
|
|
description.put(name, getProperty(bean, name));
|
|
}
|
|
}
|
|
return description;
|
|
}
|
|
|
|
public static String[] getArrayProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getProperty(bean, name);
|
|
if (value == null)
|
|
return null;
|
|
if (value instanceof Collection) {
|
|
ArrayList values = new ArrayList();
|
|
Iterator items = ((Collection)value).iterator();
|
|
while (items.hasNext()) {
|
|
Object item = items.next();
|
|
if (item == null) {
|
|
values.add((String)null);
|
|
continue;
|
|
}
|
|
values.add(item.toString());
|
|
}
|
|
return values.<String>toArray(new String[values.size()]);
|
|
}
|
|
if (value.getClass().isArray()) {
|
|
int n = Array.getLength(value);
|
|
String[] arrayOfString = new String[n];
|
|
for (int i = 0; i < n; i++) {
|
|
Object item = Array.get(value, i);
|
|
if (item == null) {
|
|
arrayOfString[i] = null;
|
|
} else {
|
|
arrayOfString[i] = item.toString();
|
|
}
|
|
}
|
|
return arrayOfString;
|
|
}
|
|
String[] results = new String[1];
|
|
results[0] = value.toString();
|
|
return results;
|
|
}
|
|
|
|
public static String getIndexedProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getIndexedProperty(bean, name);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static String getIndexedProperty(Object bean, String name, int index) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getIndexedProperty(bean, name, index);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static String getMappedProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getMappedProperty(bean, name);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static String getMappedProperty(Object bean, String name, String key) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getMappedProperty(bean, name, key);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static String getNestedProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getNestedProperty(bean, name);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static String getProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
return getNestedProperty(bean, name);
|
|
}
|
|
|
|
public static String getSimpleProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
|
Object value = PropertyUtils.getSimpleProperty(bean, name);
|
|
return ConvertUtils.convert(value);
|
|
}
|
|
|
|
public static void populate(Object bean, Map properties) throws IllegalAccessException, InvocationTargetException {
|
|
if (bean == null || properties == null)
|
|
return;
|
|
if (log.isDebugEnabled())
|
|
log.debug("BeanUtils.populate(" + bean + ", " + properties + ")");
|
|
Iterator names = properties.keySet().iterator();
|
|
while (names.hasNext()) {
|
|
String name = names.next();
|
|
if (name == null)
|
|
continue;
|
|
Object value = properties.get(name);
|
|
setProperty(bean, name, value);
|
|
}
|
|
}
|
|
|
|
public static void setProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException {
|
|
if (log.isTraceEnabled()) {
|
|
StringBuffer sb = new StringBuffer(" setProperty(");
|
|
sb.append(bean);
|
|
sb.append(", ");
|
|
sb.append(name);
|
|
sb.append(", ");
|
|
if (value == null) {
|
|
sb.append("<NULL>");
|
|
} else if (value instanceof String) {
|
|
sb.append((String)value);
|
|
} else if (value instanceof String[]) {
|
|
String[] values = (String[])value;
|
|
sb.append('[');
|
|
for (int k = 0; k < values.length; k++) {
|
|
if (k > 0)
|
|
sb.append(',');
|
|
sb.append(values[k]);
|
|
}
|
|
sb.append(']');
|
|
} else {
|
|
sb.append(value.toString());
|
|
}
|
|
sb.append(')');
|
|
log.trace(sb.toString());
|
|
}
|
|
Object target = bean;
|
|
int delim = name.lastIndexOf('.');
|
|
if (delim >= 0) {
|
|
try {
|
|
target = PropertyUtils.getProperty(bean, name.substring(0, delim));
|
|
} catch (NoSuchMethodException e) {
|
|
return;
|
|
}
|
|
name = name.substring(delim + 1);
|
|
if (log.isTraceEnabled()) {
|
|
log.trace(" Target bean = " + target);
|
|
log.trace(" Target name = " + name);
|
|
}
|
|
}
|
|
String propName = null;
|
|
Class type = null;
|
|
int index = -1;
|
|
String key = null;
|
|
propName = name;
|
|
int i = propName.indexOf('[');
|
|
if (i >= 0) {
|
|
int k = propName.indexOf(']');
|
|
try {
|
|
index = Integer.parseInt(propName.substring(i + 1, k));
|
|
} catch (NumberFormatException e) {}
|
|
propName = propName.substring(0, i);
|
|
}
|
|
int j = propName.indexOf('(');
|
|
if (j >= 0) {
|
|
int k = propName.indexOf(')');
|
|
try {
|
|
key = propName.substring(j + 1, k);
|
|
} catch (IndexOutOfBoundsException e) {}
|
|
propName = propName.substring(0, j);
|
|
}
|
|
if (target instanceof DynaBean) {
|
|
DynaClass dynaClass = ((DynaBean)target).getDynaClass();
|
|
DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
|
|
if (dynaProperty == null)
|
|
return;
|
|
type = dynaProperty.getType();
|
|
} else {
|
|
PropertyDescriptor descriptor = null;
|
|
try {
|
|
descriptor = PropertyUtils.getPropertyDescriptor(target, name);
|
|
if (descriptor == null)
|
|
return;
|
|
} catch (NoSuchMethodException e) {
|
|
return;
|
|
}
|
|
if (descriptor instanceof MappedPropertyDescriptor) {
|
|
if (((MappedPropertyDescriptor)descriptor).getMappedWriteMethod() == null) {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Skipping read-only property");
|
|
return;
|
|
}
|
|
type = ((MappedPropertyDescriptor)descriptor).getMappedPropertyType();
|
|
} else if (descriptor instanceof IndexedPropertyDescriptor) {
|
|
if (((IndexedPropertyDescriptor)descriptor).getIndexedWriteMethod() == null) {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Skipping read-only property");
|
|
return;
|
|
}
|
|
type = ((IndexedPropertyDescriptor)descriptor).getIndexedPropertyType();
|
|
} else {
|
|
if (descriptor.getWriteMethod() == null) {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Skipping read-only property");
|
|
return;
|
|
}
|
|
type = descriptor.getPropertyType();
|
|
}
|
|
}
|
|
Object newValue = null;
|
|
if (type.isArray() && index < 0) {
|
|
if (value == null) {
|
|
String[] values = new String[1];
|
|
values[0] = (String)value;
|
|
newValue = ConvertUtils.convert(values, type);
|
|
} else if (value instanceof String) {
|
|
String[] values = new String[1];
|
|
values[0] = (String)value;
|
|
newValue = ConvertUtils.convert(values, type);
|
|
} else if (value instanceof String[]) {
|
|
newValue = ConvertUtils.convert((String[])value, type);
|
|
} else {
|
|
newValue = value;
|
|
}
|
|
} else if (type.isArray()) {
|
|
if (value instanceof String) {
|
|
newValue = ConvertUtils.convert((String)value, type.getComponentType());
|
|
} else if (value instanceof String[]) {
|
|
newValue = ConvertUtils.convert(((String[])value)[0], type.getComponentType());
|
|
} else {
|
|
newValue = value;
|
|
}
|
|
} else if (value instanceof String || value == null) {
|
|
newValue = ConvertUtils.convert((String)value, type);
|
|
} else if (value instanceof String[]) {
|
|
newValue = ConvertUtils.convert(((String[])value)[0], type);
|
|
} else if (ConvertUtils.lookup(value.getClass()) != null) {
|
|
newValue = ConvertUtils.convert(value.toString(), type);
|
|
} else {
|
|
newValue = value;
|
|
}
|
|
try {
|
|
if (index >= 0) {
|
|
PropertyUtils.setIndexedProperty(target, propName, index, newValue);
|
|
} else if (key != null) {
|
|
PropertyUtils.setMappedProperty(target, propName, key, newValue);
|
|
} else {
|
|
PropertyUtils.setProperty(target, propName, newValue);
|
|
}
|
|
} catch (NoSuchMethodException e) {
|
|
throw new InvocationTargetException(e, "Cannot set " + propName);
|
|
}
|
|
}
|
|
}
|