?? beanutilsbean.java
字號:
/*
* 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
*
* http://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.beanutils;
import java.beans.IndexedPropertyDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.beanutils.expression.Resolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* <p>JavaBean property population methods.</p>
*
* <p>This class provides implementations for the utility methods in
* {@link BeanUtils}.
* Different instances can be used to isolate caches between classloaders
* and to vary the value converters registered.</p>
*
* @author Craig R. McClanahan
* @author Ralph Schaer
* @author Chris Audley
* @author Rey Francois
* @author Gregor Rayman
* @version $Revision: 687117 $ $Date: 2008-08-19 19:19:36 +0100 (Tue, 19 Aug 2008) $
* @see BeanUtils
* @since 1.7
*/
public class BeanUtilsBean {
// ------------------------------------------------------ Private Class Variables
/**
* Contains <code>BeanUtilsBean</code> instances indexed by context classloader.
*/
private static final ContextClassLoaderLocal
BEANS_BY_CLASSLOADER = new ContextClassLoaderLocal() {
// Creates the default instance used when the context classloader is unavailable
protected Object initialValue() {
return new BeanUtilsBean();
}
};
/**
* Gets the instance which provides the functionality for {@link BeanUtils}.
* This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
* This mechanism provides isolation for web apps deployed in the same container.
*
* @return The (pseudo-singleton) BeanUtils bean instance
*/
public static BeanUtilsBean getInstance() {
return (BeanUtilsBean) BEANS_BY_CLASSLOADER.get();
}
/**
* Sets the instance which provides the functionality for {@link BeanUtils}.
* This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
* This mechanism provides isolation for web apps deployed in the same container.
*
* @param newInstance The (pseudo-singleton) BeanUtils bean instance
*/
public static void setInstance(BeanUtilsBean newInstance) {
BEANS_BY_CLASSLOADER.set(newInstance);
}
// --------------------------------------------------------- Attributes
/**
* Logging for this instance
*/
private Log log = LogFactory.getLog(BeanUtils.class);
/** Used to perform conversions between object types when setting properties */
private ConvertUtilsBean convertUtilsBean;
/** Used to access properties*/
private PropertyUtilsBean propertyUtilsBean;
/** A reference to Throwable's initCause method, or null if it's not there in this JVM */
private static final Method INIT_CAUSE_METHOD = getInitCauseMethod();
// --------------------------------------------------------- Constuctors
/**
* <p>Constructs an instance using new property
* and conversion instances.</p>
*/
public BeanUtilsBean() {
this(new ConvertUtilsBean(), new PropertyUtilsBean());
}
/**
* <p>Constructs an instance using given conversion instances
* and new {@link PropertyUtilsBean} instance.</p>
*
* @param convertUtilsBean use this <code>ConvertUtilsBean</code>
* to perform conversions from one object to another
*
* @since 1.8.0
*/
public BeanUtilsBean(ConvertUtilsBean convertUtilsBean) {
this(convertUtilsBean, new PropertyUtilsBean());
}
/**
* <p>Constructs an instance using given property and conversion instances.</p>
*
* @param convertUtilsBean use this <code>ConvertUtilsBean</code>
* to perform conversions from one object to another
* @param propertyUtilsBean use this <code>PropertyUtilsBean</code>
* to access properties
*/
public BeanUtilsBean(
ConvertUtilsBean convertUtilsBean,
PropertyUtilsBean propertyUtilsBean) {
this.convertUtilsBean = convertUtilsBean;
this.propertyUtilsBean = propertyUtilsBean;
}
// --------------------------------------------------------- Public Methods
/**
* <p>Clone a bean based on the available property getters and setters,
* even if the bean class itself does not implement Cloneable.</p>
*
* <p>
* <strong>Note:</strong> this method creates a <strong>shallow</strong> clone.
* In other words, any objects referred to by the bean are shared with the clone
* rather than being cloned in turn.
* </p>
*
* @param bean Bean to be cloned
* @return the cloned bean
*
* @exception IllegalAccessException if the caller does not have
* access to the property accessor method
* @exception InstantiationException if a new instance of the bean's
* class cannot be instantiated
* @exception InvocationTargetException if the property accessor method
* throws an exception
* @exception NoSuchMethodException if an accessor method for this
* property cannot be found
*/
public Object cloneBean(Object bean)
throws IllegalAccessException, InstantiationException,
InvocationTargetException, NoSuchMethodException {
if (log.isDebugEnabled()) {
log.debug("Cloning bean: " + bean.getClass().getName());
}
Object newBean = null;
if (bean instanceof DynaBean) {
newBean = ((DynaBean) bean).getDynaClass().newInstance();
} else {
newBean = bean.getClass().newInstance();
}
getPropertyUtils().copyProperties(newBean, bean);
return (newBean);
}
/**
* <p>Copy property values from the origin bean to the destination bean
* for all cases where the property names are the same. For each
* property, a conversion is attempted as necessary. All combinations of
* standard JavaBeans and DynaBeans as origin and destination are
* supported. Properties that exist in the origin bean, but do not exist
* in the destination bean (or are read-only in the destination bean) are
* silently ignored.</p>
*
* <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
* to contain String-valued <strong>simple</strong> property names as the keys, pointing at
* the corresponding property values that will be converted (if necessary)
* and set in the destination bean. <strong>Note</strong> that this method
* is intended to perform a "shallow copy" of the properties and so complex
* properties (for example, nested ones) will not be copied.</p>
*
* <p>This method differs from <code>populate()</code>, which
* was primarily designed for populating JavaBeans from the map of request
* parameters retrieved on an HTTP request, is that no scalar->indexed
* or indexed->scalar manipulations are performed. If the origin property
* is indexed, the destination property must be also.</p>
*
* <p>If you know that no type conversions are required, the
* <code>copyProperties()</code> method in {@link PropertyUtils} will
* execute faster than this method.</p>
*
* <p><strong>FIXME</strong> - Indexed and mapped properties that do not
* have getter and setter methods for the underlying array or Map are not
* copied by this method.</p>
*
* @param dest Destination bean whose properties are modified
* @param orig Origin bean whose properties are retrieved
*
* @exception IllegalAccessException if the caller does not have
* access to the property accessor method
* @exception IllegalArgumentException if the <code>dest</code> or
* <code>orig</code> argument is null or if the <code>dest</code>
* property type is different from the source type and the relevant
* converter has not been registered.
* @exception InvocationTargetException if the property accessor method
* throws an exception
*/
public void copyProperties(Object dest, Object orig)
throws IllegalAccessException, InvocationTargetException {
// Validate existence of the specified beans
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 + ")");
}
// Copy the properties, converting as necessary
if (orig instanceof DynaBean) {
DynaProperty[] origDescriptors =
((DynaBean) orig).getDynaClass().getDynaProperties();
for (int i = 0; i < origDescriptors.length; i++) {
String name = origDescriptors[i].getName();
// Need to check isReadable() for WrapDynaBean
// (see Jira issue# BEANUTILS-61)
if (getPropertyUtils().isReadable(orig, name) &&
getPropertyUtils().isWriteable(dest, name)) {
Object value = ((DynaBean) orig).get(name);
copyProperty(dest, name, value);
}
}
} else if (orig instanceof Map) {
Iterator entries = ((Map) orig).entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
String name = (String)entry.getKey();
if (getPropertyUtils().isWriteable(dest, name)) {
copyProperty(dest, name, entry.getValue());
}
}
} else /* if (orig is a standard JavaBean) */ {
PropertyDescriptor[] origDescriptors =
getPropertyUtils().getPropertyDescriptors(orig);
for (int i = 0; i < origDescriptors.length; i++) {
String name = origDescriptors[i].getName();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -