KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > beans > BeansUtils


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

22
23
24 package com.mchange.v2.beans;
25
26 import java.beans.*;
27 import java.lang.reflect.*;
28 import java.util.*;
29 import com.mchange.v2.log.*;
30
31 import com.mchange.v2.lang.Coerce;
32
33 public final class BeansUtils
34 {
35     final static MLogger logger = MLog.getLogger( BeansUtils.class );
36
37     final static Object JavaDoc[] EMPTY_ARGS = new Object JavaDoc[0];
38
39     public static PropertyEditor findPropertyEditor( PropertyDescriptor pd )
40     {
41         PropertyEditor out = null;
42         Class JavaDoc editorClass = null;
43         try
44         {
45             editorClass = pd.getPropertyEditorClass();
46             if (editorClass != null)
47                 out = (PropertyEditor) editorClass.newInstance();
48         }
49         catch (Exception JavaDoc e)
50         {
51 // e.printStackTrace();
52
// System.err.println("WARNING: Bad property editor class " + editorClass.getName() +
53
// " registered for property " + pd.getName());
54
if (logger.isLoggable( MLevel.WARNING ) )
55                 logger.log(MLevel.WARNING, "Bad property editor class " + editorClass.getName() + " registered for property " + pd.getName(), e);
56         }
57
58         if ( out == null )
59             out = PropertyEditorManager.findEditor( pd.getPropertyType() );
60         return out;
61     }
62
63     public static boolean equalsByAccessibleProperties( Object JavaDoc bean0, Object JavaDoc bean1 )
64     throws IntrospectionException
65     { return equalsByAccessibleProperties( bean0, bean1, Collections.EMPTY_SET ); }
66
67     public static boolean equalsByAccessibleProperties( Object JavaDoc bean0, Object JavaDoc bean1, Collection ignoreProps )
68     throws IntrospectionException
69     {
70         Map m0 = new HashMap();
71         Map m1 = new HashMap();
72         extractAccessiblePropertiesToMap( m0, bean0, ignoreProps );
73         extractAccessiblePropertiesToMap( m1, bean1, ignoreProps );
74         //System.err.println("Map0 -> " + m0);
75
//System.err.println("Map1 -> " + m1);
76
return m0.equals(m1);
77     }
78
79     public static void overwriteAccessibleProperties( Object JavaDoc sourceBean, Object JavaDoc destBean )
80     throws IntrospectionException
81     { overwriteAccessibleProperties( sourceBean, destBean, Collections.EMPTY_SET ); }
82
83     public static void overwriteAccessibleProperties( Object JavaDoc sourceBean, Object JavaDoc destBean, Collection ignoreProps )
84     throws IntrospectionException
85     {
86         try
87         {
88             BeanInfo beanInfo = Introspector.getBeanInfo( sourceBean.getClass(), Object JavaDoc.class ); //so we don't see message about getClass()
89
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
90             for( int i = 0, len = pds.length; i < len; ++i)
91             {
92                 PropertyDescriptor pd = pds[i];
93                 if ( ignoreProps.contains( pd.getName() ) )
94                     continue;
95
96                 Method getter = pd.getReadMethod();
97                 Method setter = pd.getWriteMethod();
98
99                 if ( getter == null || setter == null )
100                 {
101                     if ( pd instanceof IndexedPropertyDescriptor )
102                     {
103 // System.err.println("WARNING: BeansUtils.overwriteAccessibleProperties() does not");
104
// System.err.println("support indexed properties that do not provide single-valued");
105
// System.err.println("array getters and setters! [The indexed methods provide no means");
106
// System.err.println("of modifying the size of the array in the destination bean if");
107
// System.err.println("it does not match the source.]");
108

109                         if ( logger.isLoggable( MLevel.WARNING ) )
110                             logger.warning("BeansUtils.overwriteAccessibleProperties() does not" +
111                                             " support indexed properties that do not provide single-valued" +
112                                             " array getters and setters! [The indexed methods provide no means" +
113                                             " of modifying the size of the array in the destination bean if" +
114                             " it does not match the source.]");
115                     }
116
117                     //System.err.println("Property inaccessible for overwriting: " + pd.getName());
118
if (logger.isLoggable( MLevel.INFO ))
119                         logger.info("Property inaccessible for overwriting: " + pd.getName());
120                 }
121                 else
122                 {
123                     Object JavaDoc value = getter.invoke( sourceBean, EMPTY_ARGS );
124                     setter.invoke( destBean, new Object JavaDoc[] { value } );
125                 }
126             }
127         }
128         catch ( IntrospectionException e )
129         { throw e; }
130         catch ( Exception JavaDoc e )
131         {
132             //e.printStackTrace();
133
if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ))
134                 logger.log( MLevel.FINE, "Converting exception to throwable IntrospectionException" );
135
136             throw new IntrospectionException( e.getMessage() );
137         }
138     }
139
140     public static void overwriteAccessiblePropertiesFromMap( Map sourceMap, Object JavaDoc destBean, boolean skip_nulls )
141     throws IntrospectionException
142     { overwriteAccessiblePropertiesFromMap( sourceMap, destBean, skip_nulls, Collections.EMPTY_SET ); }
143
144     public static void overwriteAccessiblePropertiesFromMap( Map sourceMap, Object JavaDoc destBean, boolean skip_nulls, Collection ignoreProps )
145     throws IntrospectionException
146     {
147         overwriteAccessiblePropertiesFromMap( sourceMap,
148                         destBean,
149                         skip_nulls,
150                         ignoreProps,
151                         false,
152                         MLevel.WARNING,
153                         MLevel.WARNING,
154                         true);
155     }
156
157     public static void overwriteAccessiblePropertiesFromMap( Map sourceMap,
158                     Object JavaDoc destBean,
159                     boolean skip_nulls,
160                     Collection ignoreProps,
161                     boolean coerce_strings,
162                     MLevel cantWriteLevel,
163                     MLevel cantCoerceLevel,
164                     boolean die_on_one_prop_failure)
165     throws IntrospectionException
166     {
167         if (cantWriteLevel == null)
168             cantWriteLevel = MLevel.WARNING;
169         if (cantCoerceLevel == null)
170             cantCoerceLevel = MLevel.WARNING;
171
172         Set sourceMapProps = sourceMap.keySet();
173
174         String JavaDoc propName = null;
175         BeanInfo beanInfo = Introspector.getBeanInfo( destBean.getClass(), Object JavaDoc.class ); //so we don't see message about getClass()
176
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
177         //System.err.println("ignoreProps: " + ignoreProps );
178
for( int i = 0, len = pds.length; i < len; ++i)
179         {
180             PropertyDescriptor pd = pds[i];
181             propName = pd.getName();
182
183             if (! sourceMapProps.contains( propName ))
184                 continue;
185
186             if ( ignoreProps != null && ignoreProps.contains( propName ) )
187             {
188                 //System.err.println("ignoring: " + propName);
189
continue;
190             }
191             //else
192
// System.err.println("not ignoring: " + propName);
193

194             Object JavaDoc propVal = sourceMap.get( propName );
195             if (propVal == null)
196             {
197                 if (skip_nulls) continue;
198                 //do we need to worry about primitives here?
199
}
200
201             Method setter = pd.getWriteMethod();
202             boolean rethrow = false;
203
204             Class JavaDoc propType = pd.getPropertyType();;
205
206 // try
207
// {
208

209             if ( setter == null )
210             {
211                 if ( pd instanceof IndexedPropertyDescriptor )
212                 {
213                     if ( logger.isLoggable( MLevel.FINER ) )
214                         logger.finer("BeansUtils.overwriteAccessiblePropertiesFromMap() does not" +
215                                         " support indexed properties that do not provide single-valued" +
216                                         " array getters and setters! [The indexed methods provide no means" +
217                                         " of modifying the size of the array in the destination bean if" +
218                         " it does not match the source.]");
219
220                 }
221
222                 if ( logger.isLoggable( cantWriteLevel ))
223                 {
224                     String JavaDoc msg = "Property inaccessible for overwriting: " + propName;
225                     logger.log( cantWriteLevel, msg );
226                     if (die_on_one_prop_failure)
227                     {
228                         rethrow = true;
229                         throw new IntrospectionException( msg );
230                     }
231                 }
232
233             }
234             else
235             {
236                 if (coerce_strings &&
237                                 propVal != null &&
238                                 propVal.getClass() == String JavaDoc.class &&
239                                 (propType = pd.getPropertyType()) != String JavaDoc.class &&
240                                 Coerce.canCoerce( propType ))
241                 {
242                     Object JavaDoc coercedPropVal;
243                     try
244                     {
245                         coercedPropVal = Coerce.toObject( (String JavaDoc) propVal, propType );
246                         //System.err.println(propName + "-> coercedPropVal: " + coercedPropVal);
247
setter.invoke( destBean, new Object JavaDoc[] { coercedPropVal } );
248                     }
249                     catch (IllegalArgumentException JavaDoc e)
250                     {
251                         // thrown by Coerce.toObject()
252
// recall that NumberFormatException inherits from IllegalArgumentException
253
String JavaDoc msg =
254                             "Failed to coerce property: " + propName +
255                             " [propVal: " + propVal + "; propType: " + propType + "]";
256                         if ( logger.isLoggable( cantCoerceLevel ) )
257                             logger.log( cantCoerceLevel, msg, e );
258                         if (die_on_one_prop_failure)
259                         {
260                             rethrow = true;
261                             throw new IntrospectionException( msg );
262                         }
263                     }
264                     catch (Exception JavaDoc e)
265                     {
266                         String JavaDoc msg =
267                             "Failed to set property: " + propName +
268                             " [propVal: " + propVal + "; propType: " + propType + "]";
269                         if ( logger.isLoggable( cantWriteLevel ) )
270                             logger.log( cantWriteLevel, msg, e );
271                         if (die_on_one_prop_failure)
272                         {
273                             rethrow = true;
274                             throw new IntrospectionException( msg );
275                         }
276                     }
277                 }
278                 else
279                 {
280                     try
281                     {
282                         //System.err.println("invoking method: " + setter);
283
setter.invoke( destBean, new Object JavaDoc[] { propVal } );
284                     }
285                     catch (Exception JavaDoc e)
286                     {
287                         String JavaDoc msg =
288                             "Failed to set property: " + propName +
289                             " [propVal: " + propVal + "; propType: " + propType + "]";
290                         if ( logger.isLoggable( cantWriteLevel ) )
291                             logger.log( cantWriteLevel, msg, e );
292                         if (die_on_one_prop_failure)
293                         {
294                             rethrow = true;
295                             throw new IntrospectionException( msg );
296                         }
297                     }
298                 }
299             }
300 // }
301
// catch (Exception e)
302
// {
303
// if (e instanceof IntrospectionException && rethrow)
304
// throw (IntrospectionException) e;
305
// else
306
// {
307
// String msg =
308
// "An exception occurred while trying to set property '" + propName +
309
// "' to value '" + propVal + "'. ";
310
// logger.log(MLevel.WARNING, msg, e);
311
// if (die_on_one_prop_failure)
312
// {
313
// rethrow = true;
314
// throw new IntrospectionException( msg + e.toString());
315
// }
316
// }
317
// }
318
}
319     }
320
321     public static void appendPropNamesAndValues(StringBuffer JavaDoc appendIntoMe, Object JavaDoc bean, Collection ignoreProps) throws IntrospectionException
322     {
323         Map tmp = new TreeMap( String.CASE_INSENSITIVE_ORDER );
324         extractAccessiblePropertiesToMap( tmp, bean, ignoreProps );
325         boolean first = true;
326         for (Iterator ii = tmp.keySet().iterator(); ii.hasNext(); )
327         {
328             String JavaDoc key = (String JavaDoc) ii.next();
329             Object JavaDoc val = tmp.get( key );
330             if (first)
331                 first = false;
332             else
333                 appendIntoMe.append( ", " );
334             appendIntoMe.append( key );
335             appendIntoMe.append( " -> ");
336             appendIntoMe.append( val );
337         }
338     }
339
340
341     public static void extractAccessiblePropertiesToMap( Map fillMe, Object JavaDoc bean ) throws IntrospectionException
342     { extractAccessiblePropertiesToMap( fillMe, bean, Collections.EMPTY_SET ); }
343
344     public static void extractAccessiblePropertiesToMap( Map fillMe, Object JavaDoc bean, Collection ignoreProps ) throws IntrospectionException
345     {
346         String JavaDoc propName = null;
347         try
348         {
349             BeanInfo bi = Introspector.getBeanInfo( bean.getClass(), Object JavaDoc.class );
350             PropertyDescriptor[] pds = bi.getPropertyDescriptors();
351             for (int i = 0, len = pds.length; i < len; ++i)
352             {
353                 PropertyDescriptor pd = pds[i];
354                 propName = pd.getName();
355                 if (ignoreProps.contains( propName ))
356                     continue;
357
358                 Method readMethod = pd.getReadMethod();
359                 Object JavaDoc propVal = readMethod.invoke( bean, EMPTY_ARGS );
360                 fillMe.put( propName, propVal );
361             }
362         }
363         catch ( IntrospectionException e )
364         {
365 // if (propName != null)
366
// System.err.println("Problem occurred while overwriting property: " + propName);
367
if ( logger.isLoggable( MLevel.WARNING ) )
368                 logger.warning("Problem occurred while overwriting property: " + propName);
369             if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ))
370                 logger.logp( MLevel.FINE,
371                                 BeansUtils.class.getName(),
372                                 "extractAccessiblePropertiesToMap( Map fillMe, Object bean, Collection ignoreProps )",
373                                 (propName != null ? "Problem occurred while overwriting property: " + propName : "") + " throwing...",
374                                 e );
375             throw e;
376         }
377         catch ( Exception JavaDoc e )
378         {
379             //e.printStackTrace();
380
if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ))
381                 logger.logp( MLevel.FINE,
382                                 BeansUtils.class.getName(),
383                                 "extractAccessiblePropertiesToMap( Map fillMe, Object bean, Collection ignoreProps )",
384                                 "Caught unexpected Exception; Converting to IntrospectionException.",
385                                 e );
386             throw new IntrospectionException( e.toString() + (propName == null ? "" : " [" + propName + ']') );
387         }
388     }
389
390     private static void overwriteProperty( String JavaDoc propName, Object JavaDoc value, Method putativeSetter, Object JavaDoc target )
391     throws Exception JavaDoc
392     {
393         if ( putativeSetter.getDeclaringClass().isAssignableFrom( target.getClass() ) )
394             putativeSetter.invoke( target, new Object JavaDoc[] { value } );
395         else
396         {
397             BeanInfo beanInfo = Introspector.getBeanInfo( target.getClass(), Object JavaDoc.class );
398             PropertyDescriptor pd = null;
399
400             PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
401             for( int i = 0, len = pds.length; i < len; ++i)
402                 if (propName.equals( pds[i].getName() ))
403                 {
404                     pd = pds[i];
405                     break;
406                 }
407
408             Method targetSetter = pd.getWriteMethod();
409             targetSetter.invoke( target, new Object JavaDoc[] { value } );
410         }
411     }
412
413
414     public static void overwriteSpecificAccessibleProperties( Object JavaDoc sourceBean, Object JavaDoc destBean, Collection props )
415     throws IntrospectionException
416     {
417         try
418         {
419             Set _props = new HashSet(props);
420
421             BeanInfo beanInfo = Introspector.getBeanInfo( sourceBean.getClass(), Object JavaDoc.class ); //so we don't see message about getClass()
422
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
423             for( int i = 0, len = pds.length; i < len; ++i)
424             {
425                 PropertyDescriptor pd = pds[i];
426                 String JavaDoc name = pd.getName();
427                 if (! _props.remove( name ) )
428                     continue;
429
430                 Method getter = pd.getReadMethod();
431                 Method setter = pd.getWriteMethod();
432
433                 if ( getter == null || setter == null )
434                 {
435                     if ( pd instanceof IndexedPropertyDescriptor )
436                     {
437 // System.err.println("WARNING: BeansUtils.overwriteAccessibleProperties() does not");
438
// System.err.println("support indexed properties that do not provide single-valued");
439
// System.err.println("array getters and setters! [The indexed methods provide no means");
440
// System.err.println("of modifying the size of the array in the destination bean if");
441
// System.err.println("it does not match the source.]");
442

443                         if ( logger.isLoggable( MLevel.WARNING ) )
444                             logger.warning("BeansUtils.overwriteAccessibleProperties() does not" +
445                                             " support indexed properties that do not provide single-valued" +
446                                             " array getters and setters! [The indexed methods provide no means" +
447                                             " of modifying the size of the array in the destination bean if" +
448                             " it does not match the source.]");
449                     }
450
451                     if ( logger.isLoggable( MLevel.INFO ) )
452                         logger.info("Property inaccessible for overwriting: " + pd.getName());
453                 }
454                 else
455                 {
456                     Object JavaDoc value = getter.invoke( sourceBean, EMPTY_ARGS );
457                     overwriteProperty( name, value, setter, destBean );
458                     //setter.invoke( destBean, new Object[] { value } );
459
}
460             }
461             if ( logger.isLoggable( MLevel.WARNING ) )
462             {
463                 for (Iterator ii = _props.iterator(); ii.hasNext(); )
464                     logger.warning("failed to find expected property: " + ii.next());
465                 //System.err.println("failed to find expected property: " + ii.next());
466
}
467         }
468         catch ( IntrospectionException e )
469         { throw e; }
470         catch ( Exception JavaDoc e )
471         {
472             //e.printStackTrace();
473
if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ))
474                 logger.logp( MLevel.FINE,
475                                 BeansUtils.class.getName(),
476                                 "overwriteSpecificAccessibleProperties( Object sourceBean, Object destBean, Collection props )",
477                                 "Caught unexpected Exception; Converting to IntrospectionException.",
478                                 e );
479             throw new IntrospectionException( e.getMessage() );
480         }
481     }
482
483     public static void debugShowPropertyChange( PropertyChangeEvent evt )
484     {
485         System.err.println("PropertyChangeEvent: [ propertyName -> " + evt.getPropertyName() +
486                         ", oldValue -> " + evt.getOldValue() +
487                         ", newValue -> " + evt.getNewValue() +
488         " ]");
489     }
490
491     private BeansUtils()
492     {}
493 }
494
Popular Tags