KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > MethodUtils


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.beanutils;
18
19
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Modifier JavaDoc;
23
24 import java.util.WeakHashMap JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29
30
31 /**
32  * <p> Utility reflection methods focussed on methods in general rather than properties in particular. </p>
33  *
34  * <h3>Known Limitations</h3>
35  * <h4>Accessing Public Methods In A Default Access Superclass</h4>
36  * <p>There is an issue when invoking public methods contained in a default access superclass.
37  * Reflection locates these methods fine and correctly assigns them as public.
38  * However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
39  *
40  * <p><code>MethodUtils</code> contains a workaround for this situation.
41  * It will attempt to call <code>setAccessible</code> on this method.
42  * If this call succeeds, then the method can be invoked as normal.
43  * This call will only succeed when the application has sufficient security privilages.
44  * If this call fails then a warning will be logged and the method may fail.</p>
45  *
46  * @author Craig R. McClanahan
47  * @author Ralph Schaer
48  * @author Chris Audley
49  * @author Rey François
50  * @author Gregor Raıman
51  * @author Jan Sorensen
52  * @author Robert Burrell Donkin
53  */

54
55 public class MethodUtils {
56
57     // --------------------------------------------------------- Private Methods
58

59     /**
60      * All logging goes through this logger
61      */

62     private static Log log = LogFactory.getLog(MethodUtils.class);
63     /** Only log warning about accessibility work around once */
64     private static boolean loggedAccessibleWarning = false;
65
66     /** An empty class array */
67     private static final Class JavaDoc[] emptyClassArray = new Class JavaDoc[0];
68     /** An empty object array */
69     private static final Object JavaDoc[] emptyObjectArray = new Object JavaDoc[0];
70
71     /**
72      * Stores a cache of Methods against MethodDescriptors, in a WeakHashMap.
73      */

74     private static WeakHashMap JavaDoc cache = new WeakHashMap JavaDoc();
75     
76     // --------------------------------------------------------- Public Methods
77

78     /**
79      * <p>Invoke a named method whose parameter type matches the object type.</p>
80      *
81      * <p>The behaviour of this method is less deterministic
82      * than {@link #invokeExactMethod}.
83      * It loops through all methods with names that match
84      * and then executes the first it finds with compatable parameters.</p>
85      *
86      * <p>This method supports calls to methods taking primitive parameters
87      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
88      * would match a <code>boolean</code> primitive.</p>
89      *
90      * <p> This is a convenient wrapper for
91      * {@link #invokeMethod(Object object,String methodName,Object [] args)}.
92      * </p>
93      *
94      * @param object invoke method on this object
95      * @param methodName get method with this name
96      * @param arg use this argument
97      *
98      * @throws NoSuchMethodException if there is no such accessible method
99      * @throws InvocationTargetException wraps an exception thrown by the
100      * method invoked
101      * @throws IllegalAccessException if the requested method is not accessible
102      * via reflection
103      */

104     public static Object JavaDoc invokeMethod(
105             Object JavaDoc object,
106             String JavaDoc methodName,
107             Object JavaDoc arg)
108             throws
109             NoSuchMethodException JavaDoc,
110             IllegalAccessException JavaDoc,
111             InvocationTargetException JavaDoc {
112
113         Object JavaDoc[] args = {arg};
114         return invokeMethod(object, methodName, args);
115
116     }
117
118
119     /**
120      * <p>Invoke a named method whose parameter type matches the object type.</p>
121      *
122      * <p>The behaviour of this method is less deterministic
123      * than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
124      * It loops through all methods with names that match
125      * and then executes the first it finds with compatable parameters.</p>
126      *
127      * <p>This method supports calls to methods taking primitive parameters
128      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
129      * would match a <code>boolean</code> primitive.</p>
130      *
131      * <p> This is a convenient wrapper for
132      * {@link #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
133      * </p>
134      *
135      * @param object invoke method on this object
136      * @param methodName get method with this name
137      * @param args use these arguments - treat null as empty array
138      *
139      * @throws NoSuchMethodException if there is no such accessible method
140      * @throws InvocationTargetException wraps an exception thrown by the
141      * method invoked
142      * @throws IllegalAccessException if the requested method is not accessible
143      * via reflection
144      */

145     public static Object JavaDoc invokeMethod(
146             Object JavaDoc object,
147             String JavaDoc methodName,
148             Object JavaDoc[] args)
149             throws
150             NoSuchMethodException JavaDoc,
151             IllegalAccessException JavaDoc,
152             InvocationTargetException JavaDoc {
153         
154         if (args == null) {
155             args = emptyObjectArray;
156         }
157         int arguments = args.length;
158         Class JavaDoc parameterTypes [] = new Class JavaDoc[arguments];
159         for (int i = 0; i < arguments; i++) {
160             parameterTypes[i] = args[i].getClass();
161         }
162         return invokeMethod(object, methodName, args, parameterTypes);
163
164     }
165
166
167     /**
168      * <p>Invoke a named method whose parameter type matches the object type.</p>
169      *
170      * <p>The behaviour of this method is less deterministic
171      * than {@link
172      * #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
173      * It loops through all methods with names that match
174      * and then executes the first it finds with compatable parameters.</p>
175      *
176      * <p>This method supports calls to methods taking primitive parameters
177      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
178      * would match a <code>boolean</code> primitive.</p>
179      *
180      *
181      * @param object invoke method on this object
182      * @param methodName get method with this name
183      * @param args use these arguments - treat null as empty array
184      * @param parameterTypes match these parameters - treat null as empty array
185      *
186      * @throws NoSuchMethodException if there is no such accessible method
187      * @throws InvocationTargetException wraps an exception thrown by the
188      * method invoked
189      * @throws IllegalAccessException if the requested method is not accessible
190      * via reflection
191      */

192     public static Object JavaDoc invokeMethod(
193             Object JavaDoc object,
194             String JavaDoc methodName,
195             Object JavaDoc[] args,
196             Class JavaDoc[] parameterTypes)
197                 throws
198                     NoSuchMethodException JavaDoc,
199                     IllegalAccessException JavaDoc,
200                     InvocationTargetException JavaDoc {
201                     
202         if (parameterTypes == null) {
203             parameterTypes = emptyClassArray;
204         }
205         if (args == null) {
206             args = emptyObjectArray;
207         }
208
209         Method JavaDoc method = getMatchingAccessibleMethod(
210                 object.getClass(),
211                 methodName,
212                 parameterTypes);
213         if (method == null)
214             throw new NoSuchMethodException JavaDoc("No such accessible method: " +
215                     methodName + "() on object: " + object.getClass().getName());
216         return method.invoke(object, args);
217     }
218
219
220     /**
221      * <p>Invoke a method whose parameter type matches exactly the object
222      * type.</p>
223      *
224      * <p> This is a convenient wrapper for
225      * {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
226      * </p>
227      *
228      * @param object invoke method on this object
229      * @param methodName get method with this name
230      * @param arg use this argument
231      *
232      * @throws NoSuchMethodException if there is no such accessible method
233      * @throws InvocationTargetException wraps an exception thrown by the
234      * method invoked
235      * @throws IllegalAccessException if the requested method is not accessible
236      * via reflection
237      */

238     public static Object JavaDoc invokeExactMethod(
239             Object JavaDoc object,
240             String JavaDoc methodName,
241             Object JavaDoc arg)
242             throws
243             NoSuchMethodException JavaDoc,
244             IllegalAccessException JavaDoc,
245             InvocationTargetException JavaDoc {
246
247         Object JavaDoc[] args = {arg};
248         return invokeExactMethod(object, methodName, args);
249
250     }
251
252
253     /**
254      * <p>Invoke a method whose parameter types match exactly the object
255      * types.</p>
256      *
257      * <p> This uses reflection to invoke the method obtained from a call to
258      * {@link #getAccessibleMethod}.</p>
259      *
260      * @param object invoke method on this object
261      * @param methodName get method with this name
262      * @param args use these arguments - treat null as empty array
263      *
264      * @throws NoSuchMethodException if there is no such accessible method
265      * @throws InvocationTargetException wraps an exception thrown by the
266      * method invoked
267      * @throws IllegalAccessException if the requested method is not accessible
268      * via reflection
269      */

270     public static Object JavaDoc invokeExactMethod(
271             Object JavaDoc object,
272             String JavaDoc methodName,
273             Object JavaDoc[] args)
274             throws
275             NoSuchMethodException JavaDoc,
276             IllegalAccessException JavaDoc,
277             InvocationTargetException JavaDoc {
278         if (args == null) {
279             args = emptyObjectArray;
280         }
281         int arguments = args.length;
282         Class JavaDoc parameterTypes [] = new Class JavaDoc[arguments];
283         for (int i = 0; i < arguments; i++) {
284             parameterTypes[i] = args[i].getClass();
285         }
286         return invokeExactMethod(object, methodName, args, parameterTypes);
287
288     }
289
290
291     /**
292      * <p>Invoke a method whose parameter types match exactly the parameter
293      * types given.</p>
294      *
295      * <p>This uses reflection to invoke the method obtained from a call to
296      * {@link #getAccessibleMethod}.</p>
297      *
298      * @param object invoke method on this object
299      * @param methodName get method with this name
300      * @param args use these arguments - treat null as empty array
301      * @param parameterTypes match these parameters - treat null as empty array
302      *
303      * @throws NoSuchMethodException if there is no such accessible method
304      * @throws InvocationTargetException wraps an exception thrown by the
305      * method invoked
306      * @throws IllegalAccessException if the requested method is not accessible
307      * via reflection
308      */

309     public static Object JavaDoc invokeExactMethod(
310             Object JavaDoc object,
311             String JavaDoc methodName,
312             Object JavaDoc[] args,
313             Class JavaDoc[] parameterTypes)
314             throws
315             NoSuchMethodException JavaDoc,
316             IllegalAccessException JavaDoc,
317             InvocationTargetException JavaDoc {
318         
319         if (args == null) {
320             args = emptyObjectArray;
321         }
322                 
323         if (parameterTypes == null) {
324             parameterTypes = emptyClassArray;
325         }
326
327         Method JavaDoc method = getAccessibleMethod(
328                 object.getClass(),
329                 methodName,
330                 parameterTypes);
331         if (method == null)
332             throw new NoSuchMethodException JavaDoc("No such accessible method: " +
333                     methodName + "() on object: " + object.getClass().getName());
334         return method.invoke(object, args);
335
336     }
337
338
339     /**
340      * <p>Return an accessible method (that is, one that can be invoked via
341      * reflection) with given name and a single parameter. If no such method
342      * can be found, return <code>null</code>.
343      * Basically, a convenience wrapper that constructs a <code>Class</code>
344      * array for you.</p>
345      *
346      * @param clazz get method from this class
347      * @param methodName get method with this name
348      * @param parameterType taking this type of parameter
349      */

350     public static Method JavaDoc getAccessibleMethod(
351             Class JavaDoc clazz,
352             String JavaDoc methodName,
353             Class JavaDoc parameterType) {
354
355         Class JavaDoc[] parameterTypes = {parameterType};
356         return getAccessibleMethod(clazz, methodName, parameterTypes);
357
358     }
359
360
361     /**
362      * <p>Return an accessible method (that is, one that can be invoked via
363      * reflection) with given name and parameters. If no such method
364      * can be found, return <code>null</code>.
365      * This is just a convenient wrapper for
366      * {@link #getAccessibleMethod(Method method)}.</p>
367      *
368      * @param clazz get method from this class
369      * @param methodName get method with this name
370      * @param parameterTypes with these parameters types
371      */

372     public static Method JavaDoc getAccessibleMethod(
373             Class JavaDoc clazz,
374             String JavaDoc methodName,
375             Class JavaDoc[] parameterTypes) {
376
377         try {
378             MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
379             // Check the cache first
380
Method JavaDoc method = (Method JavaDoc)cache.get(md);
381             if (method != null) {
382                 return method;
383             }
384             
385             method = getAccessibleMethod
386                     (clazz.getMethod(methodName, parameterTypes));
387             cache.put(md, method);
388             return method;
389         } catch (NoSuchMethodException JavaDoc e) {
390             return (null);
391         }
392
393     }
394
395
396     /**
397      * <p>Return an accessible method (that is, one that can be invoked via
398      * reflection) that implements the specified Method. If no such method
399      * can be found, return <code>null</code>.</p>
400      *
401      * @param method The method that we wish to call
402      */

403     public static Method JavaDoc getAccessibleMethod(Method JavaDoc method) {
404
405         // Make sure we have a method to check
406
if (method == null) {
407             return (null);
408         }
409
410         // If the requested method is not public we cannot call it
411
if (!Modifier.isPublic(method.getModifiers())) {
412             return (null);
413         }
414
415         // If the declaring class is public, we are done
416
Class JavaDoc clazz = method.getDeclaringClass();
417         if (Modifier.isPublic(clazz.getModifiers())) {
418             return (method);
419         }
420
421         // Check the implemented interfaces and subinterfaces
422
method =
423                 getAccessibleMethodFromInterfaceNest(clazz,
424                         method.getName(),
425                         method.getParameterTypes());
426         return (method);
427
428     }
429
430
431     // -------------------------------------------------------- Private Methods
432

433     /**
434      * <p>Return an accessible method (that is, one that can be invoked via
435      * reflection) that implements the specified method, by scanning through
436      * all implemented interfaces and subinterfaces. If no such method
437      * can be found, return <code>null</code>.</p>
438      *
439      * <p> There isn't any good reason why this method must be private.
440      * It is because there doesn't seem any reason why other classes should
441      * call this rather than the higher level methods.</p>
442      *
443      * @param clazz Parent class for the interfaces to be checked
444      * @param methodName Method name of the method we wish to call
445      * @param parameterTypes The parameter type signatures
446      */

447     private static Method JavaDoc getAccessibleMethodFromInterfaceNest
448             (Class JavaDoc clazz, String JavaDoc methodName, Class JavaDoc parameterTypes[]) {
449
450         Method JavaDoc method = null;
451
452         // Search up the superclass chain
453
for (; clazz != null; clazz = clazz.getSuperclass()) {
454
455             // Check the implemented interfaces of the parent class
456
Class JavaDoc interfaces[] = clazz.getInterfaces();
457             for (int i = 0; i < interfaces.length; i++) {
458
459                 // Is this interface public?
460
if (!Modifier.isPublic(interfaces[i].getModifiers()))
461                     continue;
462
463                 // Does the method exist on this interface?
464
try {
465                     method = interfaces[i].getDeclaredMethod(methodName,
466                             parameterTypes);
467                 } catch (NoSuchMethodException JavaDoc e) {
468                     ;
469                 }
470                 if (method != null)
471                     break;
472
473                 // Recursively check our parent interfaces
474
method =
475                         getAccessibleMethodFromInterfaceNest(interfaces[i],
476                                 methodName,
477                                 parameterTypes);
478                 if (method != null)
479                     break;
480
481             }
482
483         }
484
485         // If we found a method return it
486
if (method != null)
487             return (method);
488
489         // We did not find anything
490
return (null);
491
492     }
493
494     /**
495      * <p>Find an accessible method that matches the given name and has compatible parameters.
496      * Compatible parameters mean that every method parameter is assignable from
497      * the given parameters.
498      * In other words, it finds a method with the given name
499      * that will take the parameters given.<p>
500      *
501      * <p>This method is slightly undeterminstic since it loops
502      * through methods names and return the first matching method.</p>
503      *
504      * <p>This method is used by
505      * {@link
506      * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
507      *
508      * <p>This method can match primitive parameter by passing in wrapper classes.
509      * For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
510      * parameter.
511      *
512      * @param clazz find method in this class
513      * @param methodName find method with this name
514      * @param parameterTypes find method with compatible parameters
515      */

516     public static Method JavaDoc getMatchingAccessibleMethod(
517                                                 Class JavaDoc clazz,
518                                                 String JavaDoc methodName,
519                                                 Class JavaDoc[] parameterTypes) {
520         // trace logging
521
if (log.isTraceEnabled()) {
522             log.trace("Matching name=" + methodName + " on " + clazz);
523         }
524         MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
525         
526         // see if we can find the method directly
527
// most of the time this works and it's much faster
528
try {
529             // Check the cache first
530
Method JavaDoc method = (Method JavaDoc)cache.get(md);
531             if (method != null) {
532                 return method;
533             }
534
535             method = clazz.getMethod(methodName, parameterTypes);
536             if (log.isTraceEnabled()) {
537                 log.trace("Found straight match: " + method);
538                 log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
539             }
540             
541             try {
542                 //
543
// XXX Default access superclass workaround
544
//
545
// When a public class has a default access superclass
546
// with public methods, these methods are accessible.
547
// Calling them from compiled code works fine.
548
//
549
// Unfortunately, using reflection to invoke these methods
550
// seems to (wrongly) to prevent access even when the method
551
// modifer is public.
552
//
553
// The following workaround solves the problem but will only
554
// work from sufficiently privilages code.
555
//
556
// Better workarounds would be greatfully accepted.
557
//
558
method.setAccessible(true);
559                 
560             } catch (SecurityException JavaDoc se) {
561                 // log but continue just in case the method.invoke works anyway
562
if (!loggedAccessibleWarning) {
563                     boolean vunerableJVM = false;
564                     try {
565                         String JavaDoc specVersion = System.getProperty("java.specification.version");
566                         if (specVersion.charAt(0) == '1' &&
567                                 (specVersion.charAt(0) == '0' ||
568                                  specVersion.charAt(0) == '1' ||
569                                  specVersion.charAt(0) == '2' ||
570                                  specVersion.charAt(0) == '3')) {
571                                  
572                             vunerableJVM = true;
573                         }
574                     } catch (SecurityException JavaDoc e) {
575                         // don't know - so display warning
576
vunerableJVM = true;
577                     }
578                     if (vunerableJVM) {
579                         log.warn(
580                             "Current Security Manager restricts use of workarounds for reflection bugs "
581                             + " in pre-1.4 JVMs.");
582                     }
583                     loggedAccessibleWarning = true;
584                 }
585                 log.debug(
586                         "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
587                         se);
588             }
589             cache.put(md, method);
590             return method;
591             
592         } catch (NoSuchMethodException JavaDoc e) { /* SWALLOW */ }
593         
594         // search through all methods
595
int paramSize = parameterTypes.length;
596         Method JavaDoc[] methods = clazz.getMethods();
597         for (int i = 0, size = methods.length; i < size ; i++) {
598             if (methods[i].getName().equals(methodName)) {
599                 // log some trace information
600
if (log.isTraceEnabled()) {
601                     log.trace("Found matching name:");
602                     log.trace(methods[i]);
603                 }
604                 
605                 // compare parameters
606
Class JavaDoc[] methodsParams = methods[i].getParameterTypes();
607                 int methodParamSize = methodsParams.length;
608                 if (methodParamSize == paramSize) {
609                     boolean match = true;
610                     for (int n = 0 ; n < methodParamSize; n++) {
611                         if (log.isTraceEnabled()) {
612                             log.trace("Param=" + parameterTypes[n].getName());
613                             log.trace("Method=" + methodsParams[n].getName());
614                         }
615                         if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
616                             if (log.isTraceEnabled()) {
617                                 log.trace(methodsParams[n] + " is not assignable from "
618                                             + parameterTypes[n]);
619                             }
620                             match = false;
621                             break;
622                         }
623                     }
624                     
625                     if (match) {
626                         // get accessible version of method
627
Method JavaDoc method = getAccessibleMethod(methods[i]);
628                         if (method != null) {
629                             if (log.isTraceEnabled()) {
630                                 log.trace(method + " accessible version of "
631                                             + methods[i]);
632                             }
633                             try {
634                                 //
635
// XXX Default access superclass workaround
636
// (See above for more details.)
637
//
638
method.setAccessible(true);
639                                 
640                             } catch (SecurityException JavaDoc se) {
641                                 // log but continue just in case the method.invoke works anyway
642
if (!loggedAccessibleWarning) {
643                                     log.warn(
644             "Cannot use JVM pre-1.4 access bug workaround due to restrictive security manager.");
645                                     loggedAccessibleWarning = true;
646                                 }
647                                 log.debug(
648             "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
649                                         se);
650                             }
651                             cache.put(md, method);
652                             return method;
653                         }
654                         
655                         log.trace("Couldn't find accessible method.");
656                     }
657                 }
658             }
659         }
660         
661         // didn't find a match
662
log.trace("No match found.");
663         return null;
664     }
665
666     /**
667      * <p>Determine whether a type can be used as a parameter in a method invocation.
668      * This method handles primitive conversions correctly.</p>
669      *
670      * <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
671      * a <code>Long</code> to a <code>long</code>,
672      * a <code>Float</code> to a <code>float</code>,
673      * a <code>Integer</code> to a <code>int</code>,
674      * and a <code>Double</code> to a <code>double</code>.
675      * Now logic widening matches are allowed.
676      * For example, a <code>Long</code> will not match a <code>int</code>.
677      *
678      * @param parameterType the type of parameter accepted by the method
679      * @param parameterization the type of parameter being tested
680      *
681      * @return true if the assignement is compatible.
682      */

683     public static final boolean isAssignmentCompatible(Class JavaDoc parameterType, Class JavaDoc parameterization) {
684         // try plain assignment
685
if (parameterType.isAssignableFrom(parameterization)) {
686             return true;
687         }
688         
689         if (parameterType.isPrimitive()) {
690             // this method does *not* do widening - you must specify exactly
691
// is this the right behaviour?
692
Class JavaDoc parameterWrapperClazz = getPrimitiveWrapper(parameterType);
693             if (parameterWrapperClazz != null) {
694                 return parameterWrapperClazz.equals(parameterization);
695             }
696         }
697         
698         return false;
699     }
700     
701     /**
702      * Gets the wrapper object class for the given primitive type class.
703      * For example, passing <code>boolean.class</code> returns <code>Boolean.class</code>
704      * @param primitiveType the primitive type class for which a match is to be found
705      * @return the wrapper type associated with the given primitive
706      * or null if no match is found
707      */

708     public static Class JavaDoc getPrimitiveWrapper(Class JavaDoc primitiveType) {
709         // does anyone know a better strategy than comparing names?
710
if (boolean.class.equals(primitiveType)) {
711             return Boolean JavaDoc.class;
712         } else if (float.class.equals(primitiveType)) {
713             return Float JavaDoc.class;
714         } else if (long.class.equals(primitiveType)) {
715             return Long JavaDoc.class;
716         } else if (int.class.equals(primitiveType)) {
717             return Integer JavaDoc.class;
718         } else if (short.class.equals(primitiveType)) {
719             return Short JavaDoc.class;
720         } else if (byte.class.equals(primitiveType)) {
721             return Byte JavaDoc.class;
722         } else if (double.class.equals(primitiveType)) {
723             return Double JavaDoc.class;
724         } else if (char.class.equals(primitiveType)) {
725             return Character JavaDoc.class;
726         } else {
727             
728             return null;
729         }
730     }
731
732     /**
733      * Gets the class for the primitive type corresponding to the primitive wrapper class given.
734      * For example, an instance of <code>Boolean.class</code> returns a <code>boolean.class</code>.
735      * @param wrapperType the
736      * @return the primitive type class corresponding to the given wrapper class,
737      * null if no match is found
738      */

739     public static Class JavaDoc getPrimitiveType(Class JavaDoc wrapperType) {
740         // does anyone know a better strategy than comparing names?
741
if (Boolean JavaDoc.class.equals(wrapperType)) {
742             return boolean.class;
743         } else if (Float JavaDoc.class.equals(wrapperType)) {
744             return float.class;
745         } else if (Long JavaDoc.class.equals(wrapperType)) {
746             return long.class;
747         } else if (Integer JavaDoc.class.equals(wrapperType)) {
748             return int.class;
749         } else if (Short JavaDoc.class.equals(wrapperType)) {
750             return short.class;
751         } else if (Byte JavaDoc.class.equals(wrapperType)) {
752             return byte.class;
753         } else if (Double JavaDoc.class.equals(wrapperType)) {
754             return double.class;
755         } else if (Character JavaDoc.class.equals(wrapperType)) {
756             return char.class;
757         } else {
758             if (log.isDebugEnabled()) {
759                 log.debug("Not a known primitive wrapper class: " + wrapperType);
760             }
761             return null;
762         }
763     }
764     
765     /**
766      * Find a non primitive representation for given primitive class.
767      *
768      * @param clazz the class to find a representation for, not null
769      * @return the original class if it not a primitive. Otherwise the wrapper class. Not null
770      */

771     public static Class JavaDoc toNonPrimitiveClass(Class JavaDoc clazz) {
772         if (clazz.isPrimitive()) {
773             Class JavaDoc primitiveClazz = MethodUtils.getPrimitiveWrapper(clazz);
774             // the above method returns
775
if (primitiveClazz != null) {
776                 return primitiveClazz;
777             } else {
778                 return clazz;
779             }
780         } else {
781             return clazz;
782         }
783     }
784     
785
786     /**
787      * Represents the key to looking up a Method by reflection.
788      */

789     private static class MethodDescriptor {
790         private Class JavaDoc cls;
791         private String JavaDoc methodName;
792         private Class JavaDoc[] paramTypes;
793         private boolean exact;
794         private int hashCode;
795
796         /**
797          * The sole constructor.
798          *
799          * @param cls the class to reflect, must not be null
800          * @param methodName the method name to obtain
801          * @param paramTypes the array of classes representing the paramater types
802          * @param exact whether the match has to be exact.
803          */

804         public MethodDescriptor(Class JavaDoc cls, String JavaDoc methodName, Class JavaDoc[] paramTypes, boolean exact) {
805             if (cls == null) {
806                 throw new IllegalArgumentException JavaDoc("Class cannot be null");
807             }
808             if (methodName == null) {
809                 throw new IllegalArgumentException JavaDoc("Method Name cannot be null");
810             }
811             if (paramTypes == null) {
812                 paramTypes = emptyClassArray;
813             }
814
815             this.cls = cls;
816             this.methodName = methodName;
817             this.paramTypes = paramTypes;
818             this.exact= exact;
819
820             this.hashCode = methodName.length();
821         }
822         /**
823          * Checks for equality.
824          * @param obj object to be tested for equality
825          * @return true, if the object describes the same Method.
826          */

827         public boolean equals(Object JavaDoc obj) {
828             if (!(obj instanceof MethodDescriptor)) {
829                 return false;
830             }
831             MethodDescriptor md = (MethodDescriptor)obj;
832
833             return (
834                 exact == md.exact &&
835                 methodName.equals(md.methodName) &&
836                 cls.equals(md.cls) &&
837                 java.util.Arrays.equals(paramTypes, md.paramTypes)
838             );
839         }
840         /**
841          * Returns the string length of method name. I.e. if the
842          * hashcodes are different, the objects are different. If the
843          * hashcodes are the same, need to use the equals method to
844          * determine equality.
845          * @return the string length of method name.
846          */

847         public int hashCode() {
848             return hashCode;
849         }
850     }
851 }
852
Popular Tags