    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018
    019    package org.apache.commons.beanutils;
    020
    021    import java.lang.reflect.InvocationTargetException;
    022    import java.util.Map;
    023
    024
    025
    026    /**
    027     * <p>Utility methods for populating JavaBeans properties via reflection.</p>
    028     *
    029     * <p>The implementations are provided by {@link BeanUtilsBean}.
    030     * These static utility methods use the default instance.
    031     * More sophisticated behaviour can be provided by using a <code>BeanUtilsBean</code> instance.</p>
    032     *
    033     * @author Craig R. McClanahan
    034     * @author Ralph Schaer
    035     * @author Chris Audley
    036     * @author Rey Francois
    037     * @author Gregor Rayman
    038     * @version $Revision: 690380 $ $Date: 2008-08-29 21:04:38 +0100 (Fri, 29 Aug 2008) $
    039     * @see BeanUtilsBean
    040     */
    041
    042    public class BeanUtils {
    043
    044
    045        // ------------------------------------------------------ Private Variables
    046
    047
    048        /**
    049         * The debugging detail level for this component.
    050         *
    051         * Note that this static variable will have unexpected side-effects if
    052         * this class is deployed in a shared classloader within a container.
    053         * However as it is actually completely ignored by this class due to its
    054         * deprecated status, it doesn't do any actual harm.
    055         *
    056         * @deprecated BeanUtils now uses commons-logging for all log messages.
    057         *             Use your favorite logging tool to configure logging for
    058         *             this class.
    059         */
    060        private static int debug = 0;
    061
    062        /**
    063         * The <code>debug</code> static property is no longer used
    064         * @return debug property
    065         * @deprecated BeanUtils now uses commons-logging for all log messages.
    066         *             Use your favorite logging tool to configure logging for
    067         *             this class.
    068         */
    069        public static int getDebug() {
    070            return (debug);
    071        }
    072
    073        /**
    074         * The <code>debug</code> static property is no longer used
    075         * @param newDebug debug property
    076         * @deprecated BeanUtils now uses commons-logging for all log messages.
    077         *             Use your favorite logging tool to configure logging for
    078         *             this class.
    079         */
    080        public static void setDebug(int newDebug) {
    081            debug = newDebug;
    082        }
    083
    084        // --------------------------------------------------------- Class Methods
    085
    086
    087        /**
    088         * <p>Clone a bean based on the available property getters and setters,
    089         * even if the bean class itself does not implement Cloneable.</p>
    090         *
    091         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    092         *
    093         * @param bean Bean to be cloned
    094         * @return the cloned bean
    095         *
    096         * @exception IllegalAccessException if the caller does not have
    097         *  access to the property accessor method
    098         * @exception InstantiationException if a new instance of the bean's
    099         *  class cannot be instantiated
    100         * @exception InvocationTargetException if the property accessor method
    101         *  throws an exception
    102         * @exception NoSuchMethodException if an accessor method for this
    103         *  property cannot be found
    104         * @see BeanUtilsBean#cloneBean
    105         */
    106        public static Object cloneBean(Object bean)
    107                throws IllegalAccessException, InstantiationException,
    108                InvocationTargetException, NoSuchMethodException {
    109
    110            return BeanUtilsBean.getInstance().cloneBean(bean);
    111
    112        }
    113
    114
    115        /**
    116         * <p>Copy property values from the origin bean to the destination bean
    117         * for all cases where the property names are the same.</p>
    118         *
    119         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    120         *
    121         * @param dest Destination bean whose properties are modified
    122         * @param orig Origin bean whose properties are retrieved
    123         *
    124         * @exception IllegalAccessException if the caller does not have
    125         *  access to the property accessor method
    126         * @exception IllegalArgumentException if the <code>dest</code> or
    127         *  <code>orig</code> argument is null or if the <code>dest</code>
    128         *  property type is different from the source type and the relevant
    129         *  converter has not been registered.
    130         * @exception InvocationTargetException if the property accessor method
    131         *  throws an exception
    132         * @see BeanUtilsBean#copyProperties
    133         */
    134        public static void copyProperties(Object dest, Object orig)
    135            throws IllegalAccessException, InvocationTargetException {
    136
    137            BeanUtilsBean.getInstance().copyProperties(dest, orig);
    138        }
    139
    140
    141        /**
    142         * <p>Copy the specified property value to the specified destination bean,
    143         * performing any type conversion that is required.</p>
    144         *
    145         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    146         *
    147         * @param bean Bean on which setting is to be performed
    148         * @param name Property name (can be nested/indexed/mapped/combo)
    149         * @param value Value to be set
    150         *
    151         * @exception IllegalAccessException if the caller does not have
    152         *  access to the property accessor method
    153         * @exception InvocationTargetException if the property accessor method
    154         *  throws an exception
    155         * @see BeanUtilsBean#copyProperty
    156         */
    157        public static void copyProperty(Object bean, String name, Object value)
    158            throws IllegalAccessException, InvocationTargetException {
    159
    160            BeanUtilsBean.getInstance().copyProperty(bean, name, value);
    161        }
    162
    163
    164        /**
    165         * <p>Return the entire set of properties for which the specified bean
    166         * provides a read method.</p>
    167         *
    168         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    169         *
    170         * @param bean Bean whose properties are to be extracted
    171         * @return Map of property descriptors
    172         *
    173         * @exception IllegalAccessException if the caller does not have
    174         *  access to the property accessor method
    175         * @exception InvocationTargetException if the property accessor method
    176         *  throws an exception
    177         * @exception NoSuchMethodException if an accessor method for this
    178         *  property cannot be found
    179         * @see BeanUtilsBean#describe
    180         */
    181        public static Map describe(Object bean)
    182                throws IllegalAccessException, InvocationTargetException,
    183                NoSuchMethodException {
    184
    185            return BeanUtilsBean.getInstance().describe(bean);
    186        }
    187
    188
    189        /**
    190         * <p>Return the value of the specified array property of the specified
    191         * bean, as a String array.</p>
    192         *
    193         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    194         *
    195         * @param bean Bean whose property is to be extracted
    196         * @param name Name of the property to be extracted
    197         * @return The array property value
    198         *
    199         * @exception IllegalAccessException if the caller does not have
    200         *  access to the property accessor method
    201         * @exception InvocationTargetException if the property accessor method
    202         *  throws an exception
    203         * @exception NoSuchMethodException if an accessor method for this
    204         *  property cannot be found
    205         * @see BeanUtilsBean#getArrayProperty
    206         */
    207        public static String[] getArrayProperty(Object bean, String name)
    208                throws IllegalAccessException, InvocationTargetException,
    209                NoSuchMethodException {
    210
    211            return BeanUtilsBean.getInstance().getArrayProperty(bean, name);
    212        }
    213
    214
    215        /**
    216         * <p>Return the value of the specified indexed property of the specified
    217         * bean, as a String.</p>
    218         *
    219         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    220         *
    221         * @param bean Bean whose property is to be extracted
    222         * @param name <code>propertyname[index]</code> of the property value
    223         *  to be extracted
    224         * @return The indexed property's value, converted to a String
    225         *
    226         * @exception IllegalAccessException if the caller does not have
    227         *  access to the property accessor method
    228         * @exception InvocationTargetException if the property accessor method
    229         *  throws an exception
    230         * @exception NoSuchMethodException if an accessor method for this
    231         *  property cannot be found
    232         * @see BeanUtilsBean#getIndexedProperty(Object, String)
    233         */
    234        public static String getIndexedProperty(Object bean, String name)
    235                throws IllegalAccessException, InvocationTargetException,
    236                NoSuchMethodException {
    237
    238            return BeanUtilsBean.getInstance().getIndexedProperty(bean, name);
    239
    240        }
    241
    242
    243        /**
    244         * Return the value of the specified indexed property of the specified
    245         * bean, as a String.  The index is specified as a method parameter and
    246         * must *not* be included in the property name expression
    247         *
    248         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    249         *
    250         * @param bean Bean whose property is to be extracted
    251         * @param name Simple property name of the property value to be extracted
    252         * @param index Index of the property value to be extracted
    253         * @return The indexed property's value, converted to a String
    254         *
    255         * @exception IllegalAccessException if the caller does not have
    256         *  access to the property accessor method
    257         * @exception InvocationTargetException if the property accessor method
    258         *  throws an exception
    259         * @exception NoSuchMethodException if an accessor method for this
    260         *  property cannot be found
    261         * @see BeanUtilsBean#getIndexedProperty(Object, String, int)
    262         */
    263        public static String getIndexedProperty(Object bean,
    264                                                String name, int index)
    265                throws IllegalAccessException, InvocationTargetException,
    266                NoSuchMethodException {
    267
    268            return BeanUtilsBean.getInstance().getIndexedProperty(bean, name, index);
    269
    270        }
    271
    272
    273        /**
    274         * </p>Return the value of the specified indexed property of the specified
    275         * bean, as a String.</p>
    276         *
    277         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    278         *
    279         * @param bean Bean whose property is to be extracted
    280         * @param name <code>propertyname(index)</code> of the property value
    281         *  to be extracted
    282         * @return The mapped property's value, converted to a String
    283         *
    284         * @exception IllegalAccessException if the caller does not have
    285         *  access to the property accessor method
    286         * @exception InvocationTargetException if the property accessor method
    287         *  throws an exception
    288         * @exception NoSuchMethodException if an accessor method for this
    289         *  property cannot be found
    290         * @see BeanUtilsBean#getMappedProperty(Object, String)
    291         */
    292        public static String getMappedProperty(Object bean, String name)
    293                throws IllegalAccessException, InvocationTargetException,
    294                NoSuchMethodException {
    295
    296            return BeanUtilsBean.getInstance().getMappedProperty(bean, name);
    297
    298        }
    299
    300
    301        /**
    302         * </p>Return the value of the specified mapped property of the specified
    303         * bean, as a String.</p>
    304         *
    305         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    306         *
    307         * @param bean Bean whose property is to be extracted
    308         * @param name Simple property name of the property value to be extracted
    309         * @param key Lookup key of the property value to be extracted
    310         * @return The mapped property's value, converted to a String
    311         *
    312         * @exception IllegalAccessException if the caller does not have
    313         *  access to the property accessor method
    314         * @exception InvocationTargetException if the property accessor method
    315         *  throws an exception
    316         * @exception NoSuchMethodException if an accessor method for this
    317         *  property cannot be found
    318         * @see BeanUtilsBean#getMappedProperty(Object, String, String)
    319         */
    320        public static String getMappedProperty(Object bean,
    321                                               String name, String key)
    322                throws IllegalAccessException, InvocationTargetException,
    323                NoSuchMethodException {
    324
    325            return BeanUtilsBean.getInstance().getMappedProperty(bean, name, key);
    326
    327        }
    328
    329
    330        /**
    331         * <p>Return the value of the (possibly nested) property of the specified
    332         * name, for the specified bean, as a String.</p>
    333         *
    334         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    335         *
    336         * @param bean Bean whose property is to be extracted
    337         * @param name Possibly nested name of the property to be extracted
    338         * @return The nested property's value, converted to a String
    339         *
    340         * @exception IllegalAccessException if the caller does not have
    341         *  access to the property accessor method
    342         * @exception IllegalArgumentException if a nested reference to a
    343         *  property returns null
    344         * @exception InvocationTargetException if the property accessor method
    345         *  throws an exception
    346         * @exception NoSuchMethodException if an accessor method for this
    347         *  property cannot be found
    348         * @see BeanUtilsBean#getNestedProperty
    349         */
    350        public static String getNestedProperty(Object bean, String name)
    351                throws IllegalAccessException, InvocationTargetException,
    352                NoSuchMethodException {
    353
    354            return BeanUtilsBean.getInstance().getNestedProperty(bean, name);
    355
    356        }
    357
    358
    359        /**
    360         * <p>Return the value of the specified property of the specified bean,
    361         * no matter which property reference format is used, as a String.</p>
    362         *
    363         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    364         *
    365         * @param bean Bean whose property is to be extracted
    366         * @param name Possibly indexed and/or nested name of the property
    367         *  to be extracted
    368         * @return The property's value, converted to a String
    369         *
    370         * @exception IllegalAccessException if the caller does not have
    371         *  access to the property accessor method
    372         * @exception InvocationTargetException if the property accessor method
    373         *  throws an exception
    374         * @exception NoSuchMethodException if an accessor method for this
    375         *  property cannot be found
    376         * @see BeanUtilsBean#getProperty
    377         */
    378        public static String getProperty(Object bean, String name)
    379                throws IllegalAccessException, InvocationTargetException,
    380                NoSuchMethodException {
    381
    382            return BeanUtilsBean.getInstance().getProperty(bean, name);
    383
    384        }
    385
    386
    387        /**
    388         * <p>Return the value of the specified simple property of the specified
    389         * bean, converted to a String.</p>
    390         *
    391         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    392         *
    393         * @param bean Bean whose property is to be extracted
    394         * @param name Name of the property to be extracted
    395         * @return The property's value, converted to a String
    396         *
    397         * @exception IllegalAccessException if the caller does not have
    398         *  access to the property accessor method
    399         * @exception InvocationTargetException if the property accessor method
    400         *  throws an exception
    401         * @exception NoSuchMethodException if an accessor method for this
    402         *  property cannot be found
    403         * @see BeanUtilsBean#getSimpleProperty
    404         */
    405        public static String getSimpleProperty(Object bean, String name)
    406                throws IllegalAccessException, InvocationTargetException,
    407                NoSuchMethodException {
    408
    409            return BeanUtilsBean.getInstance().getSimpleProperty(bean, name);
    410
    411        }
    412
    413
    414        /**
    415         * <p>Populate the JavaBeans properties of the specified bean, based on
    416         * the specified name/value pairs.</p>
    417         *
    418         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    419         *
    420         * @param bean JavaBean whose properties are being populated
    421         * @param properties Map keyed by property name, with the
    422         *  corresponding (String or String[]) value(s) to be set
    423         *
    424         * @exception IllegalAccessException if the caller does not have
    425         *  access to the property accessor method
    426         * @exception InvocationTargetException if the property accessor method
    427         *  throws an exception
    428         * @see BeanUtilsBean#populate
    429         */
    430        public static void populate(Object bean, Map properties)
    431            throws IllegalAccessException, InvocationTargetException {
    432
    433            BeanUtilsBean.getInstance().populate(bean, properties);
    434        }
    435
    436
    437        /**
    438         * <p>Set the specified property value, performing type conversions as
    439         * required to conform to the type of the destination property.</p>
    440         *
    441         * <p>For more details see <code>BeanUtilsBean</code>.</p>
    442         *
    443         * @param bean Bean on which setting is to be performed
    444         * @param name Property name (can be nested/indexed/mapped/combo)
    445         * @param value Value to be set
    446         *
    447         * @exception IllegalAccessException if the caller does not have
    448         *  access to the property accessor method
    449         * @exception InvocationTargetException if the property accessor method
    450         *  throws an exception
    451         * @see BeanUtilsBean#setProperty
    452         */
    453        public static void setProperty(Object bean, String name, Object value)
    454            throws IllegalAccessException, InvocationTargetException {
    455
    456            BeanUtilsBean.getInstance().setProperty(bean, name, value);
    457        }
    458
    459        /**
    460         * If we're running on JDK 1.4 or later, initialize the cause for the given throwable.
    461         *
    462         * @param  throwable The throwable.
    463         * @param  cause     The cause of the throwable.
    464         * @return  true if the cause was initialized, otherwise false.
    465         * @since 1.8.0
    466         */
    467        public static boolean initCause(Throwable throwable, Throwable cause) {
    468            return BeanUtilsBean.getInstance().initCause(throwable, cause);
    469        }
    470
    471        /**
    472         * Create a cache.
    473         * @return a new cache
    474         * @since 1.8.0
    475         */
    476        public static Map createCache() {
    477            return new WeakFastHashMap();
    478        }
    479
    480        /**
    481         * Return whether a Map is fast
    482         * @param map The map
    483         * @return Whether it is fast or not.
    484         * @since 1.8.0
    485         */
    486        public static boolean getCacheFast(Map map) {
    487            if (map instanceof WeakFastHashMap) {
    488                return ((WeakFastHashMap)map).getFast();
    489            } else {
    490                return false;
    491            }
    492        }
    493
    494        /**
    495         * Set whether fast on a Map
    496         * @param map The map
    497         * @param fast Whether it should be fast or not.
    498         * @since 1.8.0
    499         */
    500        public static void setCacheFast(Map map, boolean fast) {
    501            if (map instanceof WeakFastHashMap) {
    502                ((WeakFastHashMap)map).setFast(fast);
    503            }
    504        }
    505    }