KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > workflow > designer > beanutils > MethodUtils


1 /*
2  * $Header: /cvs/osworkflow/src/designer/com/opensymphony/workflow/designer/beanutils/MethodUtils.java,v 1.2 2004/04/16 10:36:29 hani Exp $
3  * $Revision: 1.2 $
4  * $Date: 2004/04/16 10:36:29 $
5  *
6  * ====================================================================
7  *
8  * The Apache Software License, Version 1.1
9  *
10  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
11  * reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. The end-user documentation included with the redistribution,
26  * if any, must include the following acknowledgement:
27  * "This product includes software developed by the
28  * Apache Software Foundation (http://www.apache.org/)."
29  * Alternately, this acknowledgement may appear in the software itself,
30  * if and wherever such third-party acknowledgements normally appear.
31  *
32  * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software
33  * Foundation" must not be used to endorse or promote products derived
34  * from this software without prior written permission. For written
35  * permission, please contact apache@apache.org.
36  *
37  * 5. Products derived from this software may not be called "Apache",
38  * "Apache" nor may "Apache" appear in their names without prior
39  * written permission of the Apache Software Foundation.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  * ====================================================================
54  *
55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation. For more
57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>.
59  *
60  */

61
62 package com.opensymphony.workflow.designer.beanutils;
63
64
65 import java.lang.reflect.InvocationTargetException JavaDoc;
66 import java.lang.reflect.Method JavaDoc;
67 import java.lang.reflect.Modifier JavaDoc;
68
69 import java.util.WeakHashMap JavaDoc;
70
71 /**
72  * <p> Utility reflection methods focussed on methods in general rather than properties in particular. </p>
73  *
74  * <h3>Known Limitations</h3>
75  * <h4>Accessing Public Methods In A Default Access Superclass</h4>
76  * <p>There is an issue when invoking public methods contained in a default access superclass.
77  * Reflection locates these methods fine and correctly assigns them as public.
78  * However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
79  *
80  * <p><code>MethodUtils</code> contains a workaround for this situation.
81  * It will attempt to call <code>setAccessible</code> on this method.
82  * If this call succeeds, then the method can be invoked as normal.
83  * This call will only succeed when the application has sufficient security privilages.
84  * If this call fails then a warning will be logged and the method may fail.</p>
85  *
86  * @author Craig R. McClanahan
87  * @author Ralph Schaer
88  * @author Chris Audley
89  * @author Rey François
90  * @author Gregor Raıman
91  * @author Jan Sorensen
92  * @author Robert Burrell Donkin
93  */

94
95 public class MethodUtils {
96
97     // --------------------------------------------------------- Private Methods
98

99     /** Only log warning about accessibility work around once */
100     private static boolean loggedAccessibleWarning = false;
101
102     /** An empty class array */
103     private static final Class JavaDoc[] emptyClassArray = new Class JavaDoc[0];
104     /** An empty object array */
105     private static final Object JavaDoc[] emptyObjectArray = new Object JavaDoc[0];
106
107     /**
108      * Stores a cache of Methods against MethodDescriptors, in a WeakHashMap.
109      */

110     private static WeakHashMap JavaDoc cache = new WeakHashMap JavaDoc();
111
112     // --------------------------------------------------------- Public Methods
113

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

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

181     public static Object JavaDoc invokeMethod(
182             Object JavaDoc object,
183             String JavaDoc methodName,
184             Object JavaDoc[] args)
185             throws
186             NoSuchMethodException JavaDoc,
187             IllegalAccessException JavaDoc,
188             InvocationTargetException JavaDoc {
189
190         if (args == null) {
191             args = emptyObjectArray;
192         }
193         int arguments = args.length;
194         Class JavaDoc parameterTypes [] = new Class JavaDoc[arguments];
195         for (int i = 0; i < arguments; i++) {
196             parameterTypes[i] = args[i].getClass();
197         }
198         return invokeMethod(object, methodName, args, parameterTypes);
199
200     }
201
202
203     /**
204      * <p>Invoke a named method whose parameter type matches the object type.</p>
205      *
206      * <p>The behaviour of this method is less deterministic
207      * than {@link
208      * #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
209      * It loops through all methods with names that match
210      * and then executes the first it finds with compatable parameters.</p>
211      *
212      * <p>This method supports calls to methods taking primitive parameters
213      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
214      * would match a <code>boolean</code> primitive.</p>
215      *
216      *
217      * @param object invoke method on this object
218      * @param methodName get method with this name
219      * @param args use these arguments - treat null as empty array
220      * @param parameterTypes match these parameters - treat null as empty array
221      *
222      * @throws NoSuchMethodException if there is no such accessible method
223      * @throws InvocationTargetException wraps an exception thrown by the
224      * method invoked
225      * @throws IllegalAccessException if the requested method is not accessible
226      * via reflection
227      */

228     public static Object JavaDoc invokeMethod(
229             Object JavaDoc object,
230             String JavaDoc methodName,
231             Object JavaDoc[] args,
232             Class JavaDoc[] parameterTypes)
233                 throws
234                     NoSuchMethodException JavaDoc,
235                     IllegalAccessException JavaDoc,
236                     InvocationTargetException JavaDoc {
237
238         if (parameterTypes == null) {
239             parameterTypes = emptyClassArray;
240         }
241         if (args == null) {
242             args = emptyObjectArray;
243         }
244
245         Method JavaDoc method = getMatchingAccessibleMethod(
246                 object.getClass(),
247                 methodName,
248                 parameterTypes);
249         if (method == null)
250             throw new NoSuchMethodException JavaDoc("No such accessible method: " +
251                     methodName + "() on object: " + object.getClass().getName());
252         return method.invoke(object, args);
253     }
254
255
256     /**
257      * <p>Invoke a method whose parameter type matches exactly the object
258      * type.</p>
259      *
260      * <p> This is a convenient wrapper for
261      * {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
262      * </p>
263      *
264      * @param object invoke method on this object
265      * @param methodName get method with this name
266      * @param arg use this argument
267      *
268      * @throws NoSuchMethodException if there is no such accessible method
269      * @throws InvocationTargetException wraps an exception thrown by the
270      * method invoked
271      * @throws IllegalAccessException if the requested method is not accessible
272      * via reflection
273      */

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

306     public static Object JavaDoc invokeExactMethod(
307             Object JavaDoc object,
308             String JavaDoc methodName,
309             Object JavaDoc[] args)
310             throws
311             NoSuchMethodException JavaDoc,
312             IllegalAccessException JavaDoc,
313             InvocationTargetException JavaDoc {
314         if (args == null) {
315             args = emptyObjectArray;
316         }
317         int arguments = args.length;
318         Class JavaDoc parameterTypes [] = new Class JavaDoc[arguments];
319         for (int i = 0; i < arguments; i++) {
320             parameterTypes[i] = args[i].getClass();
321         }
322         return invokeExactMethod(object, methodName, args, parameterTypes);
323
324     }
325
326
327     /**
328      * <p>Invoke a method whose parameter types match exactly the parameter
329      * types given.</p>
330      *
331      * <p>This uses reflection to invoke the method obtained from a call to
332      * {@link #getAccessibleMethod}.</p>
333      *
334      * @param object invoke method on this object
335      * @param methodName get method with this name
336      * @param args use these arguments - treat null as empty array
337      * @param parameterTypes match these parameters - treat null as empty array
338      *
339      * @throws NoSuchMethodException if there is no such accessible method
340      * @throws InvocationTargetException wraps an exception thrown by the
341      * method invoked
342      * @throws IllegalAccessException if the requested method is not accessible
343      * via reflection
344      */

345     public static Object JavaDoc invokeExactMethod(
346             Object JavaDoc object,
347             String JavaDoc methodName,
348             Object JavaDoc[] args,
349             Class JavaDoc[] parameterTypes)
350             throws
351             NoSuchMethodException JavaDoc,
352             IllegalAccessException JavaDoc,
353             InvocationTargetException JavaDoc {
354
355         if (args == null) {
356             args = emptyObjectArray;
357         }
358
359         if (parameterTypes == null) {
360             parameterTypes = emptyClassArray;
361         }
362
363         Method JavaDoc method = getAccessibleMethod(
364                 object.getClass(),
365                 methodName,
366                 parameterTypes);
367         if (method == null)
368             throw new NoSuchMethodException JavaDoc("No such accessible method: " +
369                     methodName + "() on object: " + object.getClass().getName());
370         return method.invoke(object, args);
371
372     }
373
374
375     /**
376      * <p>Return an accessible method (that is, one that can be invoked via
377      * reflection) with given name and a single parameter. If no such method
378      * can be found, return <code>null</code>.
379      * Basically, a convenience wrapper that constructs a <code>Class</code>
380      * array for you.</p>
381      *
382      * @param clazz get method from this class
383      * @param methodName get method with this name
384      * @param parameterType taking this type of parameter
385      */

386     public static Method JavaDoc getAccessibleMethod(
387             Class JavaDoc clazz,
388             String JavaDoc methodName,
389             Class JavaDoc parameterType) {
390
391         Class JavaDoc[] parameterTypes = {parameterType};
392         return getAccessibleMethod(clazz, methodName, parameterTypes);
393
394     }
395
396
397     /**
398      * <p>Return an accessible method (that is, one that can be invoked via
399      * reflection) with given name and parameters. If no such method
400      * can be found, return <code>null</code>.
401      * This is just a convenient wrapper for
402      * {@link #getAccessibleMethod(Method method)}.</p>
403      *
404      * @param clazz get method from this class
405      * @param methodName get method with this name
406      * @param parameterTypes with these parameters types
407      */

408     public static Method JavaDoc getAccessibleMethod(
409             Class JavaDoc clazz,
410             String JavaDoc methodName,
411             Class JavaDoc[] parameterTypes) {
412
413         try {
414             MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
415             // Check the cache first
416
Method JavaDoc method = (Method JavaDoc)cache.get(md);
417             if (method != null) {
418                 return method;
419             }
420
421             method = getAccessibleMethod
422                     (clazz.getMethod(methodName, parameterTypes));
423             cache.put(md, method);
424             return method;
425         } catch (NoSuchMethodException JavaDoc e) {
426             return (null);
427         }
428
429     }
430
431
432     /**
433      * <p>Return an accessible method (that is, one that can be invoked via
434      * reflection) that implements the specified Method. If no such method
435      * can be found, return <code>null</code>.</p>
436      *
437      * @param method The method that we wish to call
438      */

439     public static Method JavaDoc getAccessibleMethod(Method JavaDoc method) {
440
441         // Make sure we have a method to check
442
if (method == null) {
443             return (null);
444         }
445
446         // If the requested method is not public we cannot call it
447
if (!Modifier.isPublic(method.getModifiers())) {
448             return (null);
449         }
450
451         // If the declaring class is public, we are done
452
Class JavaDoc clazz = method.getDeclaringClass();
453         if (Modifier.isPublic(clazz.getModifiers())) {
454             return (method);
455         }
456
457         // Check the implemented interfaces and subinterfaces
458
method =
459                 getAccessibleMethodFromInterfaceNest(clazz,
460                         method.getName(),
461                         method.getParameterTypes());
462         return (method);
463
464     }
465
466
467     // -------------------------------------------------------- Private Methods
468

469     /**
470      * <p>Return an accessible method (that is, one that can be invoked via
471      * reflection) that implements the specified method, by scanning through
472      * all implemented interfaces and subinterfaces. If no such method
473      * can be found, return <code>null</code>.</p>
474      *
475      * <p> There isn't any good reason why this method must be private.
476      * It is because there doesn't seem any reason why other classes should
477      * call this rather than the higher level methods.</p>
478      *
479      * @param clazz Parent class for the interfaces to be checked
480      * @param methodName Method name of the method we wish to call
481      * @param parameterTypes The parameter type signatures
482      */

483     private static Method JavaDoc getAccessibleMethodFromInterfaceNest
484             (Class JavaDoc clazz, String JavaDoc methodName, Class JavaDoc parameterTypes[]) {
485
486         Method JavaDoc method = null;
487
488         // Search up the superclass chain
489
for (; clazz != null; clazz = clazz.getSuperclass()) {
490
491             // Check the implemented interfaces of the parent class
492
Class JavaDoc interfaces[] = clazz.getInterfaces();
493             for (int i = 0; i < interfaces.length; i++) {
494
495                 // Is this interface public?
496
if (!Modifier.isPublic(interfaces[i].getModifiers()))
497                     continue;
498
499                 // Does the method exist on this interface?
500
try {
501                     method = interfaces[i].getDeclaredMethod(methodName,
502                             parameterTypes);
503                 } catch (NoSuchMethodException JavaDoc e) {
504                     ;
505                 }
506                 if (method != null)
507                     break;
508
509                 // Recursively check our parent interfaces
510
method =
511                         getAccessibleMethodFromInterfaceNest(interfaces[i],
512                                 methodName,
513                                 parameterTypes);
514                 if (method != null)
515                     break;
516
517             }
518
519         }
520
521         // If we found a method return it
522
if (method != null)
523             return (method);
524
525         // We did not find anything
526
return (null);
527
528     }
529
530     /**
531      * <p>Find an accessible method that matches the given name and has compatible parameters.
532      * Compatible parameters mean that every method parameter is assignable from
533      * the given parameters.
534      * In other words, it finds a method with the given name
535      * that will take the parameters given.<p>
536      *
537      * <p>This method is slightly undeterminstic since it loops
538      * through methods names and return the first matching method.</p>
539      *
540      * <p>This method is used by
541      * {@link
542      * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
543      *
544      * <p>This method can match primitive parameter by passing in wrapper classes.
545      * For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
546      * parameter.
547      *
548      * @param clazz find method in this class
549      * @param methodName find method with this name
550      * @param parameterTypes find method with compatible parameters
551      */

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

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

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

732     public static Class JavaDoc getPrimitiveType(Class JavaDoc wrapperType) {
733         // does anyone know a better strategy than comparing names?
734
if (Boolean JavaDoc.class.equals(wrapperType)) {
735             return boolean.class;
736         } else if (Float JavaDoc.class.equals(wrapperType)) {
737             return float.class;
738         } else if (Long JavaDoc.class.equals(wrapperType)) {
739             return long.class;
740         } else if (Integer JavaDoc.class.equals(wrapperType)) {
741             return int.class;
742         } else if (Short JavaDoc.class.equals(wrapperType)) {
743             return short.class;
744         } else if (Byte JavaDoc.class.equals(wrapperType)) {
745             return byte.class;
746         } else if (Double JavaDoc.class.equals(wrapperType)) {
747             return double.class;
748         } else if (Character JavaDoc.class.equals(wrapperType)) {
749             return char.class;
750         } else {
751             return null;
752         }
753     }
754
755     /**
756      * Find a non primitive representation for given primitive class.
757      *
758      * @param clazz the class to find a representation for, not null
759      * @return the original class if it not a primitive. Otherwise the wrapper class. Not null
760      */

761     public static Class JavaDoc toNonPrimitiveClass(Class JavaDoc clazz) {
762         if (clazz.isPrimitive()) {
763             Class JavaDoc primitiveClazz = MethodUtils.getPrimitiveWrapper(clazz);
764             // the above method returns
765
if (primitiveClazz != null) {
766                 return primitiveClazz;
767             } else {
768                 return clazz;
769             }
770         } else {
771             return clazz;
772         }
773     }
774
775
776     /**
777      * Represents the key to looking up a Method by reflection.
778      */

779     private static class MethodDescriptor {
780         private Class JavaDoc cls;
781         private String JavaDoc methodName;
782         private Class JavaDoc[] paramTypes;
783         private boolean exact;
784         private int hashCode;
785
786         /**
787          * The sole constructor.
788          *
789          * @param cls the class to reflect, must not be null
790          * @param methodName the method name to obtain
791          * @param paramTypes the array of classes representing the paramater types
792          * @param exact whether the match has to be exact.
793          */

794         public MethodDescriptor(Class JavaDoc cls, String JavaDoc methodName, Class JavaDoc[] paramTypes, boolean exact) {
795             if (cls == null) {
796                 throw new IllegalArgumentException JavaDoc("Class cannot be null");
797             }
798             if (methodName == null) {
799                 throw new IllegalArgumentException JavaDoc("Method Name cannot be null");
800             }
801             if (paramTypes == null) {
802                 paramTypes = emptyClassArray;
803             }
804
805             this.cls = cls;
806             this.methodName = methodName;
807             this.paramTypes = paramTypes;
808             this.exact= exact;
809
810             this.hashCode = methodName.length();
811         }
812         /**
813          * Checks for equality.
814          * @param obj object to be tested for equality
815          * @return true, if the object describes the same Method.
816          */

817         public boolean equals(Object JavaDoc obj) {
818             if (!(obj instanceof MethodDescriptor)) {
819                 return false;
820             }
821             MethodDescriptor md = (MethodDescriptor)obj;
822
823             return (
824                 exact == md.exact &&
825                 methodName.equals(md.methodName) &&
826                 cls.equals(md.cls) &&
827                 java.util.Arrays.equals(paramTypes, md.paramTypes)
828             );
829         }
830         /**
831          * Returns the string length of method name. I.e. if the
832          * hashcodes are different, the objects are different. If the
833          * hashcodes are the same, need to use the equals method to
834          * determine equality.
835          * @return the string length of method name.
836          */

837         public int hashCode() {
838             return hashCode;
839         }
840     }
841 }
842
Popular Tags