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    }