Source Code Cross Referenced for MethodUtils.java in  » Workflow-Engines » OSWorkflow » com » opensymphony » workflow » designer » beanutils » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » OSWorkflow » com.opensymphony.workflow.designer.beanutils 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * The Apache Software License, Version 1.1
003:         *
004:         * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
005:         * reserved.
006:         *
007:         * Redistribution and use in source and binary forms, with or without
008:         * modification, are permitted provided that the following conditions
009:         * are met:
010:         *
011:         * 1. Redistributions of source code must retain the above copyright
012:         *    notice, this list of conditions and the following disclaimer.
013:         *
014:         * 2. Redistributions in binary form must reproduce the above copyright
015:         *    notice, this list of conditions and the following disclaimer in
016:         *    the documentation and/or other materials provided with the
017:         *    distribution.
018:         *
019:         * 3. The end-user documentation included with the redistribution,
020:         *    if any, must include the following acknowledgement:
021:         *       "This product includes software developed by the
022:         *        Apache Software Foundation (http://www.apache.org/)."
023:         *    Alternately, this acknowledgement may appear in the software itself,
024:         *    if and wherever such third-party acknowledgements normally appear.
025:         *
026:         * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software
027:         *    Foundation" must not be used to endorse or promote products derived
028:         *    from this software without prior written permission. For written
029:         *    permission, please contact apache@apache.org.
030:         *
031:         * 5. Products derived from this software may not be called "Apache",
032:         *    "Apache" nor may "Apache" appear in their names without prior
033:         *    written permission of the Apache Software Foundation.
034:         *
035:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046:         * SUCH DAMAGE.
047:         * ====================================================================
048:         *
049:         * This software consists of voluntary contributions made by many
050:         * individuals on behalf of the Apache Software Foundation.  For more
051:         * information on the Apache Software Foundation, please see
052:         * <http://www.apache.org/>.
053:         *
054:         */
055:
056:        package com.opensymphony.workflow.designer.beanutils;
057:
058:        import java.lang.reflect.InvocationTargetException;
059:        import java.lang.reflect.Method;
060:        import java.lang.reflect.Modifier;
061:
062:        import java.util.WeakHashMap;
063:
064:        /**
065:         * <p> Utility reflection methods focussed on methods in general rather than properties in particular. </p>
066:         *
067:         * <h3>Known Limitations</h3>
068:         * <h4>Accessing Public Methods In A Default Access Superclass</h4>
069:         * <p>There is an issue when invoking public methods contained in a default access superclass.
070:         * Reflection locates these methods fine and correctly assigns them as public.
071:         * However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
072:         *
073:         * <p><code>MethodUtils</code> contains a workaround for this situation.
074:         * It will attempt to call <code>setAccessible</code> on this method.
075:         * If this call succeeds, then the method can be invoked as normal.
076:         * This call will only succeed when the application has sufficient security privilages.
077:         * If this call fails then a warning will be logged and the method may fail.</p>
078:         *
079:         * @author Craig R. McClanahan
080:         * @author Ralph Schaer
081:         * @author Chris Audley
082:         * @author Rey Fran�ois
083:         * @author Gregor Ra�man
084:         * @author Jan Sorensen
085:         * @author Robert Burrell Donkin
086:         */
087:
088:        public class MethodUtils {
089:
090:            // --------------------------------------------------------- Private Methods
091:
092:            /** Only log warning about accessibility work around once */
093:            private static boolean loggedAccessibleWarning = false;
094:
095:            /** An empty class array */
096:            private static final Class[] emptyClassArray = new Class[0];
097:            /** An empty object array */
098:            private static final Object[] emptyObjectArray = new Object[0];
099:
100:            /**
101:             * Stores a cache of Methods against MethodDescriptors, in a WeakHashMap.
102:             */
103:            private static WeakHashMap cache = new WeakHashMap();
104:
105:            // --------------------------------------------------------- Public Methods
106:
107:            /**
108:             * <p>Invoke a named method whose parameter type matches the object type.</p>
109:             *
110:             * <p>The behaviour of this method is less deterministic
111:             * than {@link #invokeExactMethod}.
112:             * It loops through all methods with names that match
113:             * and then executes the first it finds with compatable parameters.</p>
114:             *
115:             * <p>This method supports calls to methods taking primitive parameters
116:             * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
117:             * would match a <code>boolean</code> primitive.</p>
118:             *
119:             * <p> This is a convenient wrapper for
120:             * {@link #invokeMethod(Object object,String methodName,Object [] args)}.
121:             * </p>
122:             *
123:             * @param object invoke method on this object
124:             * @param methodName get method with this name
125:             * @param arg use this argument
126:             *
127:             * @throws NoSuchMethodException if there is no such accessible method
128:             * @throws InvocationTargetException wraps an exception thrown by the
129:             *  method invoked
130:             * @throws IllegalAccessException if the requested method is not accessible
131:             *  via reflection
132:             */
133:            public static Object invokeMethod(Object object, String methodName,
134:                    Object arg) throws NoSuchMethodException,
135:                    IllegalAccessException, InvocationTargetException {
136:
137:                Object[] args = { arg };
138:                return invokeMethod(object, methodName, args);
139:
140:            }
141:
142:            /**
143:             * <p>Invoke a named method whose parameter type matches the object type.</p>
144:             *
145:             * <p>The behaviour of this method is less deterministic
146:             * than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
147:             * It loops through all methods with names that match
148:             * and then executes the first it finds with compatable parameters.</p>
149:             *
150:             * <p>This method supports calls to methods taking primitive parameters
151:             * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
152:             * would match a <code>boolean</code> primitive.</p>
153:             *
154:             * <p> This is a convenient wrapper for
155:             * {@link #invokeMethod(Object, String, Object[], Class[])} } }.
156:             * </p>
157:             *
158:             * @param object invoke method on this object
159:             * @param methodName get method with this name
160:             * @param args use these arguments - treat null as empty array
161:             *
162:             * @throws NoSuchMethodException if there is no such accessible method
163:             * @throws InvocationTargetException wraps an exception thrown by the
164:             *  method invoked
165:             * @throws IllegalAccessException if the requested method is not accessible
166:             *  via reflection
167:             */
168:            public static Object invokeMethod(Object object, String methodName,
169:                    Object[] args) throws NoSuchMethodException,
170:                    IllegalAccessException, InvocationTargetException {
171:
172:                if (args == null) {
173:                    args = emptyObjectArray;
174:                }
175:                int arguments = args.length;
176:                Class parameterTypes[] = new Class[arguments];
177:                for (int i = 0; i < arguments; i++) {
178:                    parameterTypes[i] = args[i].getClass();
179:                }
180:                return invokeMethod(object, methodName, args, parameterTypes);
181:
182:            }
183:
184:            /**
185:             * <p>Invoke a named method whose parameter type matches the object type.</p>
186:             *
187:             * <p>The behaviour of this method is less deterministic
188:             * than {@link
189:             * #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
190:             * It loops through all methods with names that match
191:             * and then executes the first it finds with compatable parameters.</p>
192:             *
193:             * <p>This method supports calls to methods taking primitive parameters
194:             * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
195:             * would match a <code>boolean</code> primitive.</p>
196:             *
197:             *
198:             * @param object invoke method on this object
199:             * @param methodName get method with this name
200:             * @param args use these arguments - treat null as empty array
201:             * @param parameterTypes match these parameters - treat null as empty array
202:             *
203:             * @throws NoSuchMethodException if there is no such accessible method
204:             * @throws InvocationTargetException wraps an exception thrown by the
205:             *  method invoked
206:             * @throws IllegalAccessException if the requested method is not accessible
207:             *  via reflection
208:             */
209:            public static Object invokeMethod(Object object, String methodName,
210:                    Object[] args, Class[] parameterTypes)
211:                    throws NoSuchMethodException, IllegalAccessException,
212:                    InvocationTargetException {
213:
214:                if (parameterTypes == null) {
215:                    parameterTypes = emptyClassArray;
216:                }
217:                if (args == null) {
218:                    args = emptyObjectArray;
219:                }
220:
221:                Method method = getMatchingAccessibleMethod(object.getClass(),
222:                        methodName, parameterTypes);
223:                if (method == null)
224:                    throw new NoSuchMethodException(
225:                            "No such accessible method: " + methodName
226:                                    + "() on object: "
227:                                    + object.getClass().getName());
228:                return method.invoke(object, args);
229:            }
230:
231:            /**
232:             * <p>Invoke a method whose parameter type matches exactly the object
233:             * type.</p>
234:             *
235:             * <p> This is a convenient wrapper for
236:             * {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
237:             * </p>
238:             *
239:             * @param object invoke method on this object
240:             * @param methodName get method with this name
241:             * @param arg use this argument
242:             *
243:             * @throws NoSuchMethodException if there is no such accessible method
244:             * @throws InvocationTargetException wraps an exception thrown by the
245:             *  method invoked
246:             * @throws IllegalAccessException if the requested method is not accessible
247:             *  via reflection
248:             */
249:            public static Object invokeExactMethod(Object object,
250:                    String methodName, Object arg)
251:                    throws NoSuchMethodException, IllegalAccessException,
252:                    InvocationTargetException {
253:
254:                Object[] args = { arg };
255:                return invokeExactMethod(object, methodName, args);
256:
257:            }
258:
259:            /**
260:             * <p>Invoke a method whose parameter types match exactly the object
261:             * types.</p>
262:             *
263:             * <p> This uses reflection to invoke the method obtained from a call to
264:             * {@link #getAccessibleMethod}.</p>
265:             *
266:             * @param object invoke method on this object
267:             * @param methodName get method with this name
268:             * @param args use these arguments - treat null as empty array
269:             *
270:             * @throws NoSuchMethodException if there is no such accessible method
271:             * @throws InvocationTargetException wraps an exception thrown by the
272:             *  method invoked
273:             * @throws IllegalAccessException if the requested method is not accessible
274:             *  via reflection
275:             */
276:            public static Object invokeExactMethod(Object object,
277:                    String methodName, Object[] args)
278:                    throws NoSuchMethodException, IllegalAccessException,
279:                    InvocationTargetException {
280:                if (args == null) {
281:                    args = emptyObjectArray;
282:                }
283:                int arguments = args.length;
284:                Class parameterTypes[] = new Class[arguments];
285:                for (int i = 0; i < arguments; i++) {
286:                    parameterTypes[i] = args[i].getClass();
287:                }
288:                return invokeExactMethod(object, methodName, args,
289:                        parameterTypes);
290:
291:            }
292:
293:            /**
294:             * <p>Invoke a method whose parameter types match exactly the parameter
295:             * types given.</p>
296:             *
297:             * <p>This uses reflection to invoke the method obtained from a call to
298:             * {@link #getAccessibleMethod}.</p>
299:             *
300:             * @param object invoke method on this object
301:             * @param methodName get method with this name
302:             * @param args use these arguments - treat null as empty array
303:             * @param parameterTypes match these parameters - treat null as empty array
304:             *
305:             * @throws NoSuchMethodException if there is no such accessible method
306:             * @throws InvocationTargetException wraps an exception thrown by the
307:             *  method invoked
308:             * @throws IllegalAccessException if the requested method is not accessible
309:             *  via reflection
310:             */
311:            public static Object invokeExactMethod(Object object,
312:                    String methodName, Object[] args, Class[] parameterTypes)
313:                    throws NoSuchMethodException, IllegalAccessException,
314:                    InvocationTargetException {
315:
316:                if (args == null) {
317:                    args = emptyObjectArray;
318:                }
319:
320:                if (parameterTypes == null) {
321:                    parameterTypes = emptyClassArray;
322:                }
323:
324:                Method method = getAccessibleMethod(object.getClass(),
325:                        methodName, parameterTypes);
326:                if (method == null)
327:                    throw new NoSuchMethodException(
328:                            "No such accessible method: " + methodName
329:                                    + "() on object: "
330:                                    + object.getClass().getName());
331:                return method.invoke(object, args);
332:
333:            }
334:
335:            /**
336:             * <p>Return an accessible method (that is, one that can be invoked via
337:             * reflection) with given name and a single parameter.  If no such method
338:             * can be found, return <code>null</code>.
339:             * Basically, a convenience wrapper that constructs a <code>Class</code>
340:             * array for you.</p>
341:             *
342:             * @param clazz get method from this class
343:             * @param methodName get method with this name
344:             * @param parameterType taking this type of parameter
345:             */
346:            public static Method getAccessibleMethod(Class clazz,
347:                    String methodName, Class parameterType) {
348:
349:                Class[] parameterTypes = { parameterType };
350:                return getAccessibleMethod(clazz, methodName, parameterTypes);
351:
352:            }
353:
354:            /**
355:             * <p>Return an accessible method (that is, one that can be invoked via
356:             * reflection) with given name and parameters.  If no such method
357:             * can be found, return <code>null</code>.
358:             * This is just a convenient wrapper for
359:             * {@link #getAccessibleMethod(Method method)}.</p>
360:             *
361:             * @param clazz get method from this class
362:             * @param methodName get method with this name
363:             * @param parameterTypes with these parameters types
364:             */
365:            public static Method getAccessibleMethod(Class clazz,
366:                    String methodName, Class[] parameterTypes) {
367:
368:                try {
369:                    MethodDescriptor md = new MethodDescriptor(clazz,
370:                            methodName, parameterTypes, true);
371:                    // Check the cache first
372:                    Method method = (Method) cache.get(md);
373:                    if (method != null) {
374:                        return method;
375:                    }
376:
377:                    method = getAccessibleMethod(clazz.getMethod(methodName,
378:                            parameterTypes));
379:                    cache.put(md, method);
380:                    return method;
381:                } catch (NoSuchMethodException e) {
382:                    return (null);
383:                }
384:
385:            }
386:
387:            /**
388:             * <p>Return an accessible method (that is, one that can be invoked via
389:             * reflection) that implements the specified Method.  If no such method
390:             * can be found, return <code>null</code>.</p>
391:             *
392:             * @param method The method that we wish to call
393:             */
394:            public static Method getAccessibleMethod(Method method) {
395:
396:                // Make sure we have a method to check
397:                if (method == null) {
398:                    return (null);
399:                }
400:
401:                // If the requested method is not public we cannot call it
402:                if (!Modifier.isPublic(method.getModifiers())) {
403:                    return (null);
404:                }
405:
406:                // If the declaring class is public, we are done
407:                Class clazz = method.getDeclaringClass();
408:                if (Modifier.isPublic(clazz.getModifiers())) {
409:                    return (method);
410:                }
411:
412:                // Check the implemented interfaces and subinterfaces
413:                method = getAccessibleMethodFromInterfaceNest(clazz, method
414:                        .getName(), method.getParameterTypes());
415:                return (method);
416:
417:            }
418:
419:            // -------------------------------------------------------- Private Methods
420:
421:            /**
422:             * <p>Return an accessible method (that is, one that can be invoked via
423:             * reflection) that implements the specified method, by scanning through
424:             * all implemented interfaces and subinterfaces.  If no such method
425:             * can be found, return <code>null</code>.</p>
426:             *
427:             * <p> There isn't any good reason why this method must be private.
428:             * It is because there doesn't seem any reason why other classes should
429:             * call this rather than the higher level methods.</p>
430:             *
431:             * @param clazz Parent class for the interfaces to be checked
432:             * @param methodName Method name of the method we wish to call
433:             * @param parameterTypes The parameter type signatures
434:             */
435:            private static Method getAccessibleMethodFromInterfaceNest(
436:                    Class clazz, String methodName, Class parameterTypes[]) {
437:
438:                Method method = null;
439:
440:                // Search up the superclass chain
441:                for (; clazz != null; clazz = clazz.getSuperclass()) {
442:
443:                    // Check the implemented interfaces of the parent class
444:                    Class interfaces[] = clazz.getInterfaces();
445:                    for (int i = 0; i < interfaces.length; i++) {
446:
447:                        // Is this interface public?
448:                        if (!Modifier.isPublic(interfaces[i].getModifiers()))
449:                            continue;
450:
451:                        // Does the method exist on this interface?
452:                        try {
453:                            method = interfaces[i].getDeclaredMethod(
454:                                    methodName, parameterTypes);
455:                        } catch (NoSuchMethodException e) {
456:                        }
457:                        if (method != null)
458:                            break;
459:
460:                        // Recursively check our parent interfaces
461:                        method = getAccessibleMethodFromInterfaceNest(
462:                                interfaces[i], methodName, parameterTypes);
463:                        if (method != null)
464:                            break;
465:
466:                    }
467:
468:                }
469:
470:                // If we found a method return it
471:                if (method != null)
472:                    return (method);
473:
474:                // We did not find anything
475:                return (null);
476:
477:            }
478:
479:            /**
480:             * <p>Find an accessible method that matches the given name and has compatible parameters.
481:             * Compatible parameters mean that every method parameter is assignable from
482:             * the given parameters.
483:             * In other words, it finds a method with the given name
484:             * that will take the parameters given.<p>
485:             *
486:             * <p>This method is slightly undeterminstic since it loops
487:             * through methods names and return the first matching method.</p>
488:             *
489:             * <p>This method is used by
490:             * {@link
491:             * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
492:             *
493:             * <p>This method can match primitive parameter by passing in wrapper classes.
494:             * For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
495:             * parameter.
496:             *
497:             * @param clazz find method in this class
498:             * @param methodName find method with this name
499:             * @param parameterTypes find method with compatible parameters
500:             */
501:            public static Method getMatchingAccessibleMethod(Class clazz,
502:                    String methodName, Class[] parameterTypes) {
503:                MethodDescriptor md = new MethodDescriptor(clazz, methodName,
504:                        parameterTypes, false);
505:
506:                // see if we can find the method directly
507:                // most of the time this works and it's much faster
508:                try {
509:                    // Check the cache first
510:                    Method method = (Method) cache.get(md);
511:                    if (method != null) {
512:                        return method;
513:                    }
514:
515:                    method = clazz.getMethod(methodName, parameterTypes);
516:
517:                    try {
518:                        //
519:                        // XXX Default access superclass workaround
520:                        //
521:                        // When a public class has a default access superclass
522:                        // with public methods, these methods are accessible.
523:                        // Calling them from compiled code works fine.
524:                        //
525:                        // Unfortunately, using reflection to invoke these methods
526:                        // seems to (wrongly) to prevent access even when the method
527:                        // modifer is public.
528:                        //
529:                        // The following workaround solves the problem but will only
530:                        // work from sufficiently privilages code.
531:                        //
532:                        // Better workarounds would be greatfully accepted.
533:                        //
534:                        method.setAccessible(true);
535:
536:                    } catch (SecurityException se) {
537:                        // log but continue just in case the method.invoke works anyway
538:                        if (!loggedAccessibleWarning) {
539:                            boolean vunerableJVM = false;
540:                            try {
541:                                String specVersion = System
542:                                        .getProperty("java.specification.version");
543:                                if (specVersion.charAt(0) == '1'
544:                                        && (specVersion.charAt(0) == '0'
545:                                                || specVersion.charAt(0) == '1'
546:                                                || specVersion.charAt(0) == '2' || specVersion
547:                                                .charAt(0) == '3')) {
548:
549:                                    vunerableJVM = true;
550:                                }
551:                            } catch (SecurityException e) {
552:                                // don't know - so display warning
553:                                vunerableJVM = true;
554:                            }
555:                            loggedAccessibleWarning = true;
556:                        }
557:                    }
558:                    cache.put(md, method);
559:                    return method;
560:
561:                } catch (NoSuchMethodException e) { /* SWALLOW */
562:                }
563:
564:                // search through all methods
565:                int paramSize = parameterTypes.length;
566:                Method[] methods = clazz.getMethods();
567:                for (int i = 0, size = methods.length; i < size; i++) {
568:                    if (methods[i].getName().equals(methodName)) {
569:
570:                        // compare parameters
571:                        Class[] methodsParams = methods[i].getParameterTypes();
572:                        int methodParamSize = methodsParams.length;
573:                        if (methodParamSize == paramSize) {
574:                            boolean match = true;
575:                            for (int n = 0; n < methodParamSize; n++) {
576:                                if (!isAssignmentCompatible(methodsParams[n],
577:                                        parameterTypes[n])) {
578:                                    match = false;
579:                                    break;
580:                                }
581:                            }
582:
583:                            if (match) {
584:                                // get accessible version of method
585:                                Method method = getAccessibleMethod(methods[i]);
586:                                if (method != null) {
587:                                    try {
588:                                        //
589:                                        // XXX Default access superclass workaround
590:                                        // (See above for more details.)
591:                                        //
592:                                        method.setAccessible(true);
593:
594:                                    } catch (SecurityException se) {
595:                                        // log but continue just in case the method.invoke works anyway
596:                                    }
597:                                    cache.put(md, method);
598:                                    return method;
599:                                }
600:
601:                            }
602:                        }
603:                    }
604:                }
605:
606:                // didn't find a match
607:                return null;
608:            }
609:
610:            /**
611:             * <p>Determine whether a type can be used as a parameter in a method invocation.
612:             * This method handles primitive conversions correctly.</p>
613:             *
614:             * <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
615:             * a <code>Long</code> to a <code>long</code>,
616:             * a <code>Float</code> to a <code>float</code>,
617:             * a <code>Integer</code> to a <code>int</code>,
618:             * and a <code>Double</code> to a <code>double</code>.
619:             * Now logic widening matches are allowed.
620:             * For example, a <code>Long</code> will not match a <code>int</code>.
621:             *
622:             * @param parameterType the type of parameter accepted by the method
623:             * @param parameterization the type of parameter being tested
624:             *
625:             * @return true if the assignement is compatible.
626:             */
627:            public static final boolean isAssignmentCompatible(
628:                    Class parameterType, Class parameterization) {
629:                // try plain assignment
630:                if (parameterType.isAssignableFrom(parameterization)) {
631:                    return true;
632:                }
633:
634:                if (parameterType.isPrimitive()) {
635:                    // this method does *not* do widening - you must specify exactly
636:                    // is this the right behaviour?
637:                    Class parameterWrapperClazz = getPrimitiveWrapper(parameterType);
638:                    if (parameterWrapperClazz != null) {
639:                        return parameterWrapperClazz.equals(parameterization);
640:                    }
641:                }
642:
643:                return false;
644:            }
645:
646:            /**
647:             * Gets the wrapper object class for the given primitive type class.
648:             * For example, passing <code>boolean.class</code> returns <code>Boolean.class</code>
649:             * @param primitiveType the primitive type class for which a match is to be found
650:             * @return the wrapper type associated with the given primitive
651:             * or null if no match is found
652:             */
653:            public static Class getPrimitiveWrapper(Class primitiveType) {
654:                // does anyone know a better strategy than comparing names?
655:                if (boolean.class.equals(primitiveType)) {
656:                    return Boolean.class;
657:                } else if (float.class.equals(primitiveType)) {
658:                    return Float.class;
659:                } else if (long.class.equals(primitiveType)) {
660:                    return Long.class;
661:                } else if (int.class.equals(primitiveType)) {
662:                    return Integer.class;
663:                } else if (short.class.equals(primitiveType)) {
664:                    return Short.class;
665:                } else if (byte.class.equals(primitiveType)) {
666:                    return Byte.class;
667:                } else if (double.class.equals(primitiveType)) {
668:                    return Double.class;
669:                } else if (char.class.equals(primitiveType)) {
670:                    return Character.class;
671:                } else {
672:
673:                    return null;
674:                }
675:            }
676:
677:            /**
678:             * Gets the class for the primitive type corresponding to the primitive wrapper class given.
679:             * For example, an instance of <code>Boolean.class</code> returns a <code>boolean.class</code>.
680:             * @param wrapperType the
681:             * @return the primitive type class corresponding to the given wrapper class,
682:             * null if no match is found
683:             */
684:            public static Class getPrimitiveType(Class wrapperType) {
685:                // does anyone know a better strategy than comparing names?
686:                if (Boolean.class.equals(wrapperType)) {
687:                    return boolean.class;
688:                } else if (Float.class.equals(wrapperType)) {
689:                    return float.class;
690:                } else if (Long.class.equals(wrapperType)) {
691:                    return long.class;
692:                } else if (Integer.class.equals(wrapperType)) {
693:                    return int.class;
694:                } else if (Short.class.equals(wrapperType)) {
695:                    return short.class;
696:                } else if (Byte.class.equals(wrapperType)) {
697:                    return byte.class;
698:                } else if (Double.class.equals(wrapperType)) {
699:                    return double.class;
700:                } else if (Character.class.equals(wrapperType)) {
701:                    return char.class;
702:                } else {
703:                    return null;
704:                }
705:            }
706:
707:            /**
708:             * Find a non primitive representation for given primitive class.
709:             *
710:             * @param clazz the class to find a representation for, not null
711:             * @return the original class if it not a primitive. Otherwise the wrapper class. Not null
712:             */
713:            public static Class toNonPrimitiveClass(Class clazz) {
714:                if (clazz.isPrimitive()) {
715:                    Class primitiveClazz = MethodUtils
716:                            .getPrimitiveWrapper(clazz);
717:                    // the above method returns
718:                    if (primitiveClazz != null) {
719:                        return primitiveClazz;
720:                    } else {
721:                        return clazz;
722:                    }
723:                } else {
724:                    return clazz;
725:                }
726:            }
727:
728:            /**
729:             * Represents the key to looking up a Method by reflection.
730:             */
731:            private static class MethodDescriptor {
732:                private Class cls;
733:                private String methodName;
734:                private Class[] paramTypes;
735:                private boolean exact;
736:                private int hashCode;
737:
738:                /**
739:                 * The sole constructor.
740:                 *
741:                 * @param cls  the class to reflect, must not be null
742:                 * @param methodName  the method name to obtain
743:                 * @param paramTypes the array of classes representing the paramater types
744:                 * @param exact whether the match has to be exact.
745:                 */
746:                public MethodDescriptor(Class cls, String methodName,
747:                        Class[] paramTypes, boolean exact) {
748:                    if (cls == null) {
749:                        throw new IllegalArgumentException(
750:                                "Class cannot be null");
751:                    }
752:                    if (methodName == null) {
753:                        throw new IllegalArgumentException(
754:                                "Method Name cannot be null");
755:                    }
756:                    if (paramTypes == null) {
757:                        paramTypes = emptyClassArray;
758:                    }
759:
760:                    this .cls = cls;
761:                    this .methodName = methodName;
762:                    this .paramTypes = paramTypes;
763:                    this .exact = exact;
764:
765:                    this .hashCode = methodName.length();
766:                }
767:
768:                /**
769:                 * Checks for equality.
770:                 * @param obj object to be tested for equality
771:                 * @return true, if the object describes the same Method.
772:                 */
773:                public boolean equals(Object obj) {
774:                    if (!(obj instanceof  MethodDescriptor)) {
775:                        return false;
776:                    }
777:                    MethodDescriptor md = (MethodDescriptor) obj;
778:
779:                    return (exact == md.exact
780:                            && methodName.equals(md.methodName)
781:                            && cls.equals(md.cls) && java.util.Arrays.equals(
782:                            paramTypes, md.paramTypes));
783:                }
784:
785:                /**
786:                 * Returns the string length of method name. I.e. if the
787:                 * hashcodes are different, the objects are different. If the
788:                 * hashcodes are the same, need to use the equals method to
789:                 * determine equality.
790:                 * @return the string length of method name.
791:                 */
792:                public int hashCode() {
793:                    return hashCode;
794:                }
795:            }
796:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.