Source Code Cross Referenced for ClassUtils.java in  » J2EE » spring-framework-2.5 » org » springframework » util » 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 » J2EE » spring framework 2.5 » org.springframework.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.util;
018:
019:        import java.beans.Introspector;
020:        import java.lang.reflect.Array;
021:        import java.lang.reflect.Constructor;
022:        import java.lang.reflect.Method;
023:        import java.lang.reflect.Modifier;
024:        import java.lang.reflect.Proxy;
025:        import java.util.ArrayList;
026:        import java.util.Arrays;
027:        import java.util.Collection;
028:        import java.util.Collections;
029:        import java.util.HashMap;
030:        import java.util.HashSet;
031:        import java.util.Iterator;
032:        import java.util.LinkedHashSet;
033:        import java.util.List;
034:        import java.util.Map;
035:        import java.util.Set;
036:
037:        import org.apache.commons.logging.Log;
038:        import org.apache.commons.logging.LogFactory;
039:
040:        /**
041:         * Miscellaneous class utility methods. Mainly for internal use within the
042:         * framework; consider Jakarta's Commons Lang for a more comprehensive suite
043:         * of class utilities.
044:         *
045:         * @author Keith Donald
046:         * @author Rob Harrop
047:         * @author Juergen Hoeller
048:         * @since 1.1
049:         * @see TypeUtils
050:         * @see ReflectionUtils
051:         */
052:        public abstract class ClassUtils {
053:
054:            /** Suffix for array class names: "[]" */
055:            public static final String ARRAY_SUFFIX = "[]";
056:
057:            /** Prefix for internal array class names: "[L" */
058:            private static final String INTERNAL_ARRAY_PREFIX = "[L";
059:
060:            /** The package separator character '.' */
061:            private static final char PACKAGE_SEPARATOR = '.';
062:
063:            /** The inner class separator character '$' */
064:            private static final char INNER_CLASS_SEPARATOR = '$';
065:
066:            /** The CGLIB class separator character "$$" */
067:            public static final String CGLIB_CLASS_SEPARATOR = "$$";
068:
069:            /** The ".class" file suffix */
070:            public static final String CLASS_FILE_SUFFIX = ".class";
071:
072:            private static final Log logger = LogFactory
073:                    .getLog(ClassUtils.class);
074:
075:            /**
076:             * Map with primitive wrapper type as key and corresponding primitive
077:             * type as value, for example: Integer.class -> int.class.
078:             */
079:            private static final Map primitiveWrapperTypeMap = new HashMap(8);
080:
081:            /**
082:             * Map with primitive type name as key and corresponding primitive
083:             * type as value, for example: "int" -> "int.class".
084:             */
085:            private static final Map primitiveTypeNameMap = new HashMap(16);
086:
087:            static {
088:                primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
089:                primitiveWrapperTypeMap.put(Byte.class, byte.class);
090:                primitiveWrapperTypeMap.put(Character.class, char.class);
091:                primitiveWrapperTypeMap.put(Double.class, double.class);
092:                primitiveWrapperTypeMap.put(Float.class, float.class);
093:                primitiveWrapperTypeMap.put(Integer.class, int.class);
094:                primitiveWrapperTypeMap.put(Long.class, long.class);
095:                primitiveWrapperTypeMap.put(Short.class, short.class);
096:
097:                Set primitiveTypeNames = new HashSet(16);
098:                primitiveTypeNames.addAll(primitiveWrapperTypeMap.values());
099:                primitiveTypeNames.addAll(Arrays.asList(new Class[] {
100:                        boolean[].class, byte[].class, char[].class,
101:                        double[].class, float[].class, int[].class,
102:                        long[].class, short[].class }));
103:                for (Iterator it = primitiveTypeNames.iterator(); it.hasNext();) {
104:                    Class primitiveClass = (Class) it.next();
105:                    primitiveTypeNameMap.put(primitiveClass.getName(),
106:                            primitiveClass);
107:                }
108:            }
109:
110:            /**
111:             * Return the default ClassLoader to use: typically the thread context
112:             * ClassLoader, if available; the ClassLoader that loaded the ClassUtils
113:             * class will be used as fallback.
114:             * <p>Call this method if you intend to use the thread context ClassLoader
115:             * in a scenario where you absolutely need a non-null ClassLoader reference:
116:             * for example, for class path resource loading (but not necessarily for
117:             * <code>Class.forName</code>, which accepts a <code>null</code> ClassLoader
118:             * reference as well).
119:             * @return the default ClassLoader (never <code>null</code>)
120:             * @see java.lang.Thread#getContextClassLoader()
121:             */
122:            public static ClassLoader getDefaultClassLoader() {
123:                ClassLoader cl = null;
124:                try {
125:                    cl = Thread.currentThread().getContextClassLoader();
126:                } catch (Throwable ex) {
127:                    logger
128:                            .debug(
129:                                    "Cannot access thread context ClassLoader - falling back to system class loader",
130:                                    ex);
131:                }
132:                if (cl == null) {
133:                    // No thread context class loader -> use class loader of this class.
134:                    cl = ClassUtils.class.getClassLoader();
135:                }
136:                return cl;
137:            }
138:
139:            /**
140:             * Determine whether the {@link Class} identified by the supplied name is present
141:             * and can be loaded. Will return <code>false</code> if either the class or
142:             * one of its dependencies is not present or cannot be loaded.
143:             * @param className the name of the class to check
144:             * @return whether the specified class is present
145:             */
146:            public static boolean isPresent(String className) {
147:                return isPresent(className, getDefaultClassLoader());
148:            }
149:
150:            /**
151:             * Determine whether the {@link Class} identified by the supplied name is present
152:             * and can be loaded. Will return <code>false</code> if either the class or
153:             * one of its dependencies is not present or cannot be loaded.
154:             * @param className the name of the class to check
155:             * @param classLoader the class loader to use
156:             * (may be <code>null</code>, which indicates the default class loader)
157:             * @return whether the specified class is present
158:             */
159:            public static boolean isPresent(String className,
160:                    ClassLoader classLoader) {
161:                try {
162:                    forName(className, classLoader);
163:                    return true;
164:                } catch (Throwable ex) {
165:                    if (logger.isDebugEnabled()) {
166:                        logger
167:                                .debug("Class ["
168:                                        + className
169:                                        + "] or one of its dependencies is not present: "
170:                                        + ex);
171:                    }
172:                    return false;
173:                }
174:            }
175:
176:            /**
177:             * Replacement for <code>Class.forName()</code> that also returns Class instances
178:             * for primitives (like "int") and array class names (like "String[]").
179:             * <p>Always uses the default class loader: that is, preferably the thread context
180:             * class loader, or the ClassLoader that loaded the ClassUtils class as fallback.
181:             * @param name the name of the Class
182:             * @return Class instance for the supplied name
183:             * @throws ClassNotFoundException if the class was not found
184:             * @throws LinkageError if the class file could not be loaded
185:             * @see Class#forName(String, boolean, ClassLoader)
186:             * @see #getDefaultClassLoader()
187:             */
188:            public static Class forName(String name)
189:                    throws ClassNotFoundException, LinkageError {
190:                return forName(name, getDefaultClassLoader());
191:            }
192:
193:            /**
194:             * Replacement for <code>Class.forName()</code> that also returns Class instances
195:             * for primitives (like "int") and array class names (like "String[]").
196:             * @param name the name of the Class
197:             * @param classLoader the class loader to use
198:             * (may be <code>null</code>, which indicates the default class loader)
199:             * @return Class instance for the supplied name
200:             * @throws ClassNotFoundException if the class was not found
201:             * @throws LinkageError if the class file could not be loaded
202:             * @see Class#forName(String, boolean, ClassLoader)
203:             */
204:            public static Class forName(String name, ClassLoader classLoader)
205:                    throws ClassNotFoundException, LinkageError {
206:                Assert.notNull(name, "Name must not be null");
207:
208:                Class clazz = resolvePrimitiveClassName(name);
209:                if (clazz != null) {
210:                    return clazz;
211:                }
212:
213:                // "java.lang.String[]" style arrays
214:                if (name.endsWith(ARRAY_SUFFIX)) {
215:                    String elementClassName = name.substring(0, name.length()
216:                            - ARRAY_SUFFIX.length());
217:                    Class elementClass = forName(elementClassName, classLoader);
218:                    return Array.newInstance(elementClass, 0).getClass();
219:                }
220:
221:                // "[Ljava.lang.String;" style arrays
222:                int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX);
223:                if (internalArrayMarker != -1 && name.endsWith(";")) {
224:                    String elementClassName = null;
225:                    if (internalArrayMarker == 0) {
226:                        elementClassName = name.substring(INTERNAL_ARRAY_PREFIX
227:                                .length(), name.length() - 1);
228:                    } else if (name.startsWith("[")) {
229:                        elementClassName = name.substring(1);
230:                    }
231:                    Class elementClass = forName(elementClassName, classLoader);
232:                    return Array.newInstance(elementClass, 0).getClass();
233:                }
234:
235:                ClassLoader classLoaderToUse = classLoader;
236:                if (classLoaderToUse == null) {
237:                    classLoaderToUse = getDefaultClassLoader();
238:                }
239:                return classLoaderToUse.loadClass(name);
240:            }
241:
242:            /**
243:             * Resolve the given class name into a Class instance. Supports
244:             * primitives (like "int") and array class names (like "String[]").
245:             * <p>This is effectively equivalent to the <code>forName</code>
246:             * method with the same arguments, with the only difference being
247:             * the exceptions thrown in case of class loading failure.
248:             * @param className the name of the Class
249:             * @param classLoader the class loader to use
250:             * (may be <code>null</code>, which indicates the default class loader)
251:             * @return Class instance for the supplied name
252:             * @throws IllegalArgumentException if the class name was not resolvable
253:             * (that is, the class could not be found or the class file could not be loaded)
254:             * @see #forName(String, ClassLoader)
255:             */
256:            public static Class resolveClassName(String className,
257:                    ClassLoader classLoader) throws IllegalArgumentException {
258:                try {
259:                    return forName(className, classLoader);
260:                } catch (ClassNotFoundException ex) {
261:                    throw new IllegalArgumentException("Cannot find class ["
262:                            + className + "]. Root cause: " + ex);
263:                } catch (LinkageError ex) {
264:                    throw new IllegalArgumentException(
265:                            "Error loading class ["
266:                                    + className
267:                                    + "]: problem with class file or dependent class. Root cause: "
268:                                    + ex);
269:                }
270:            }
271:
272:            /**
273:             * Resolve the given class name as primitive class, if appropriate,
274:             * according to the JVM's naming rules for primitive classes.
275:             * <p>Also supports the JVM's internal class names for primitive arrays.
276:             * Does <i>not</i> support the "[]" suffix notation for primitive arrays;
277:             * this is only supported by {@link #forName}.
278:             * @param name the name of the potentially primitive class
279:             * @return the primitive class, or <code>null</code> if the name does not denote
280:             * a primitive class or primitive array class
281:             */
282:            public static Class resolvePrimitiveClassName(String name) {
283:                Class result = null;
284:                // Most class names will be quite long, considering that they
285:                // SHOULD sit in a package, so a length check is worthwhile.
286:                if (name != null && name.length() <= 8) {
287:                    // Could be a primitive - likely.
288:                    result = (Class) primitiveTypeNameMap.get(name);
289:                }
290:                return result;
291:            }
292:
293:            /**
294:             * Return the user-defined class for the given instance: usually simply
295:             * the class of the given instance, but the original class in case of a
296:             * CGLIB-generated subclass.
297:             * @param instance the instance to check
298:             * @return the user-defined class
299:             */
300:            public static Class getUserClass(Object instance) {
301:                Assert.notNull(instance, "Instance must not be null");
302:                return getUserClass(instance.getClass());
303:            }
304:
305:            /**
306:             * Return the user-defined class for the given class: usually simply the given
307:             * class, but the original class in case of a CGLIB-generated subclass.
308:             * @param clazz the class to check
309:             * @return the user-defined class
310:             */
311:            public static Class getUserClass(Class clazz) {
312:                return (clazz != null
313:                        && clazz.getName().indexOf(CGLIB_CLASS_SEPARATOR) != -1 ? clazz
314:                        .getSuperclass()
315:                        : clazz);
316:            }
317:
318:            /**
319:             * Get the class name without the qualified package name.
320:             * @param className the className to get the short name for
321:             * @return the class name of the class without the package name
322:             * @throws IllegalArgumentException if the className is empty
323:             */
324:            public static String getShortName(String className) {
325:                Assert.hasLength(className, "Class name must not be empty");
326:                int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
327:                int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR);
328:                if (nameEndIndex == -1) {
329:                    nameEndIndex = className.length();
330:                }
331:                String shortName = className.substring(lastDotIndex + 1,
332:                        nameEndIndex);
333:                shortName = shortName.replace(INNER_CLASS_SEPARATOR,
334:                        PACKAGE_SEPARATOR);
335:                return shortName;
336:            }
337:
338:            /**
339:             * Get the class name without the qualified package name.
340:             * @param clazz the class to get the short name for
341:             * @return the class name of the class without the package name
342:             */
343:            public static String getShortName(Class clazz) {
344:                return getShortName(getQualifiedName(clazz));
345:            }
346:
347:            /**
348:             * Return the short string name of a Java class in decapitalized JavaBeans
349:             * property format. Strips the outer class name in case of an inner class.
350:             * @param clazz the class
351:             * @return the short name rendered in a standard JavaBeans property format
352:             * @see java.beans.Introspector#decapitalize(String)
353:             */
354:            public static String getShortNameAsProperty(Class clazz) {
355:                String shortName = ClassUtils.getShortName(clazz);
356:                int dotIndex = shortName.lastIndexOf('.');
357:                shortName = (dotIndex != -1 ? shortName.substring(dotIndex + 1)
358:                        : shortName);
359:                return Introspector.decapitalize(shortName);
360:            }
361:
362:            /**
363:             * Determine the name of the class file, relative to the containing
364:             * package: e.g. "String.class"
365:             * @param clazz the class
366:             * @return the file name of the ".class" file
367:             */
368:            public static String getClassFileName(Class clazz) {
369:                Assert.notNull(clazz, "Class must not be null");
370:                String className = clazz.getName();
371:                int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
372:                return className.substring(lastDotIndex + 1)
373:                        + CLASS_FILE_SUFFIX;
374:            }
375:
376:            /**
377:             * Determine the name of the package of the given class:
378:             * e.g. "java.lang" for the <code>java.lang.String</code> class.
379:             * @param clazz the class
380:             * @return the package name, or the empty String if the class
381:             * is defined in the default package
382:             */
383:            public static String getPackageName(Class clazz) {
384:                Assert.notNull(clazz, "Class must not be null");
385:                String className = clazz.getName();
386:                int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
387:                return (lastDotIndex != -1 ? className.substring(0,
388:                        lastDotIndex) : "");
389:            }
390:
391:            /**
392:             * Return the qualified name of the given class: usually simply
393:             * the class name, but component type class name + "[]" for arrays.
394:             * @param clazz the class
395:             * @return the qualified name of the class
396:             */
397:            public static String getQualifiedName(Class clazz) {
398:                Assert.notNull(clazz, "Class must not be null");
399:                if (clazz.isArray()) {
400:                    return getQualifiedNameForArray(clazz);
401:                } else {
402:                    return clazz.getName();
403:                }
404:            }
405:
406:            /**
407:             * Build a nice qualified name for an array:
408:             * component type class name + "[]".
409:             * @param clazz the array class
410:             * @return a qualified name for the array class
411:             */
412:            private static String getQualifiedNameForArray(Class clazz) {
413:                StringBuffer buffer = new StringBuffer();
414:                while (clazz.isArray()) {
415:                    clazz = clazz.getComponentType();
416:                    buffer.append(ClassUtils.ARRAY_SUFFIX);
417:                }
418:                buffer.insert(0, clazz.getName());
419:                return buffer.toString();
420:            }
421:
422:            /**
423:             * Return the qualified name of the given method, consisting of
424:             * fully qualified interface/class name + "." + method name.
425:             * @param method the method
426:             * @return the qualified name of the method
427:             */
428:            public static String getQualifiedMethodName(Method method) {
429:                Assert.notNull(method, "Method must not be null");
430:                return method.getDeclaringClass().getName() + "."
431:                        + method.getName();
432:            }
433:
434:            /**
435:             * Determine whether the given class has a constructor with the given signature.
436:             * <p>Essentially translates <code>NoSuchMethodException</code> to "false".
437:             * @param clazz	the clazz to analyze
438:             * @param paramTypes the parameter types of the method
439:             * @return whether the class has a corresponding constructor
440:             * @see java.lang.Class#getMethod
441:             */
442:            public static boolean hasConstructor(Class clazz, Class[] paramTypes) {
443:                return (getConstructorIfAvailable(clazz, paramTypes) != null);
444:            }
445:
446:            /**
447:             * Determine whether the given class has a constructor with the given signature,
448:             * and return it if available (else return <code>null</code>).
449:             * <p>Essentially translates <code>NoSuchMethodException</code> to <code>null</code>.
450:             * @param clazz	the clazz to analyze
451:             * @param paramTypes the parameter types of the method
452:             * @return the constructor, or <code>null</code> if not found
453:             * @see java.lang.Class#getConstructor
454:             */
455:            public static Constructor getConstructorIfAvailable(Class clazz,
456:                    Class[] paramTypes) {
457:                Assert.notNull(clazz, "Class must not be null");
458:                try {
459:                    return clazz.getConstructor(paramTypes);
460:                } catch (NoSuchMethodException ex) {
461:                    return null;
462:                }
463:            }
464:
465:            /**
466:             * Determine whether the given class has a method with the given signature.
467:             * <p>Essentially translates <code>NoSuchMethodException</code> to "false".
468:             * @param clazz	the clazz to analyze
469:             * @param methodName the name of the method
470:             * @param paramTypes the parameter types of the method
471:             * @return whether the class has a corresponding method
472:             * @see java.lang.Class#getMethod
473:             */
474:            public static boolean hasMethod(Class clazz, String methodName,
475:                    Class[] paramTypes) {
476:                return (getMethodIfAvailable(clazz, methodName, paramTypes) != null);
477:            }
478:
479:            /**
480:             * Determine whether the given class has a method with the given signature,
481:             * and return it if available (else return <code>null</code>).
482:             * <p>Essentially translates <code>NoSuchMethodException</code> to <code>null</code>.
483:             * @param clazz	the clazz to analyze
484:             * @param methodName the name of the method
485:             * @param paramTypes the parameter types of the method
486:             * @return the method, or <code>null</code> if not found
487:             * @see java.lang.Class#getMethod
488:             */
489:            public static Method getMethodIfAvailable(Class clazz,
490:                    String methodName, Class[] paramTypes) {
491:                Assert.notNull(clazz, "Class must not be null");
492:                Assert.notNull(methodName, "Method name must not be null");
493:                try {
494:                    return clazz.getMethod(methodName, paramTypes);
495:                } catch (NoSuchMethodException ex) {
496:                    return null;
497:                }
498:            }
499:
500:            /**
501:             * Return the number of methods with a given name (with any argument types),
502:             * for the given class and/or its superclasses. Includes non-public methods.
503:             * @param clazz	the clazz to check
504:             * @param methodName the name of the method
505:             * @return the number of methods with the given name
506:             */
507:            public static int getMethodCountForName(final Class clazz,
508:                    final String methodName) {
509:                Assert.notNull(clazz, "Class must not be null");
510:                Assert.notNull(methodName, "Method name must not be null");
511:                int count = 0;
512:                final Method[] declaredMethods = clazz.getDeclaredMethods();
513:                for (int i = 0; i < declaredMethods.length; i++) {
514:                    Method method = declaredMethods[i];
515:                    if (methodName.equals(method.getName())) {
516:                        count++;
517:                    }
518:                }
519:                Class[] ifcs = clazz.getInterfaces();
520:                for (int i = 0; i < ifcs.length; i++) {
521:                    count += getMethodCountForName(ifcs[i], methodName);
522:                }
523:                if (clazz.getSuperclass() != null) {
524:                    count += getMethodCountForName(clazz.getSuperclass(),
525:                            methodName);
526:                }
527:                return count;
528:            }
529:
530:            /**
531:             * Does the given class and/or its superclasses at least have one or more
532:             * methods (with any argument types)? Includes non-public methods.
533:             * @param clazz	the clazz to check
534:             * @param methodName the name of the method
535:             * @return whether there is at least one method with the given name
536:             */
537:            public static boolean hasAtLeastOneMethodWithName(
538:                    final Class clazz, final String methodName) {
539:                Assert.notNull(clazz, "Class must not be null");
540:                Assert.notNull(methodName, "Method name must not be null");
541:                final Method[] declaredMethods = clazz.getDeclaredMethods();
542:                for (int i = 0; i < declaredMethods.length; i++) {
543:                    Method method = declaredMethods[i];
544:                    if (method.getName().equals(methodName)) {
545:                        return true;
546:                    }
547:                }
548:                Class[] ifcs = clazz.getInterfaces();
549:                for (int i = 0; i < ifcs.length; i++) {
550:                    if (hasAtLeastOneMethodWithName(ifcs[i], methodName)) {
551:                        return true;
552:                    }
553:                }
554:                return (clazz.getSuperclass() != null && hasAtLeastOneMethodWithName(
555:                        clazz.getSuperclass(), methodName));
556:            }
557:
558:            /**
559:             * Given a method, which may come from an interface, and a target class used
560:             * in the current reflective invocation, find the corresponding target method
561:             * if there is one. E.g. the method may be <code>IFoo.bar()</code> and the
562:             * target class may be <code>DefaultFoo</code>. In this case, the method may be
563:             * <code>DefaultFoo.bar()</code>. This enables attributes on that method to be found.
564:             * <p><b>NOTE:</b> In contrast to {@link org.springframework.aop.support.AopUtils#getMostSpecificMethod},
565:             * this method does <i>not</i> resolve Java 5 bridge methods automatically.
566:             * Call {@link org.springframework.core.BridgeMethodResolver#findBridgedMethod}
567:             * if bridge method resolution is desirable (e.g. for obtaining metadata from
568:             * the original method definition).
569:             * @param method the method to be invoked, which may come from an interface
570:             * @param targetClass the target class for the current invocation.
571:             * May be <code>null</code> or may not even implement the method.
572:             * @return the specific target method, or the original method if the
573:             * <code>targetClass</code> doesn't implement it or is <code>null</code>
574:             * @see org.springframework.aop.support.AopUtils#getMostSpecificMethod
575:             */
576:            public static Method getMostSpecificMethod(Method method,
577:                    Class targetClass) {
578:                if (method != null && targetClass != null) {
579:                    try {
580:                        method = targetClass.getMethod(method.getName(), method
581:                                .getParameterTypes());
582:                    } catch (NoSuchMethodException ex) {
583:                        // Perhaps the target class doesn't implement this method:
584:                        // that's fine, just use the original method.
585:                    }
586:                }
587:                return method;
588:            }
589:
590:            /**
591:             * Return a static method of a class.
592:             * @param methodName the static method name
593:             * @param clazz	the class which defines the method
594:             * @param args the parameter types to the method
595:             * @return the static method, or <code>null</code> if no static method was found
596:             * @throws IllegalArgumentException if the method name is blank or the clazz is null
597:             */
598:            public static Method getStaticMethod(Class clazz,
599:                    String methodName, Class[] args) {
600:                Assert.notNull(clazz, "Class must not be null");
601:                Assert.notNull(methodName, "Method name must not be null");
602:                try {
603:                    Method method = clazz.getDeclaredMethod(methodName, args);
604:                    if ((method.getModifiers() & Modifier.STATIC) != 0) {
605:                        return method;
606:                    }
607:                } catch (NoSuchMethodException ex) {
608:                }
609:                return null;
610:            }
611:
612:            /**
613:             * Check if the given class represents a primitive wrapper,
614:             * i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double.
615:             * @param clazz the class to check
616:             * @return whether the given class is a primitive wrapper class
617:             */
618:            public static boolean isPrimitiveWrapper(Class clazz) {
619:                Assert.notNull(clazz, "Class must not be null");
620:                return primitiveWrapperTypeMap.containsKey(clazz);
621:            }
622:
623:            /**
624:             * Check if the given class represents a primitive (i.e. boolean, byte,
625:             * char, short, int, long, float, or double) or a primitive wrapper
626:             * (i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double).
627:             * @param clazz the class to check
628:             * @return whether the given class is a primitive or primitive wrapper class
629:             */
630:            public static boolean isPrimitiveOrWrapper(Class clazz) {
631:                Assert.notNull(clazz, "Class must not be null");
632:                return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
633:            }
634:
635:            /**
636:             * Check if the given class represents an array of primitives,
637:             * i.e. boolean, byte, char, short, int, long, float, or double.
638:             * @param clazz the class to check
639:             * @return whether the given class is a primitive array class
640:             */
641:            public static boolean isPrimitiveArray(Class clazz) {
642:                Assert.notNull(clazz, "Class must not be null");
643:                return (clazz.isArray() && clazz.getComponentType()
644:                        .isPrimitive());
645:            }
646:
647:            /**
648:             * Check if the given class represents an array of primitive wrappers,
649:             * i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double.
650:             * @param clazz the class to check
651:             * @return whether the given class is a primitive wrapper array class
652:             */
653:            public static boolean isPrimitiveWrapperArray(Class clazz) {
654:                Assert.notNull(clazz, "Class must not be null");
655:                return (clazz.isArray() && isPrimitiveWrapper(clazz
656:                        .getComponentType()));
657:            }
658:
659:            /**
660:             * Check if the right-hand side type may be assigned to the left-hand side
661:             * type, assuming setting by reflection. Considers primitive wrapper
662:             * classes as assignable to the corresponding primitive types.
663:             * @param lhsType the target type
664:             * @param rhsType	the value type that should be assigned to the target type
665:             * @return if the target type is assignable from the value type
666:             * @see TypeUtils#isAssignable
667:             */
668:            public static boolean isAssignable(Class lhsType, Class rhsType) {
669:                Assert.notNull(lhsType, "Left-hand side type must not be null");
670:                Assert
671:                        .notNull(rhsType,
672:                                "Right-hand side type must not be null");
673:                return (lhsType.isAssignableFrom(rhsType) || lhsType
674:                        .equals(primitiveWrapperTypeMap.get(rhsType)));
675:            }
676:
677:            /**
678:             * Determine if the given type is assignable from the given value,
679:             * assuming setting by reflection. Considers primitive wrapper classes
680:             * as assignable to the corresponding primitive types.
681:             * @param type	the target type
682:             * @param value the value that should be assigned to the type
683:             * @return if the type is assignable from the value
684:             */
685:            public static boolean isAssignableValue(Class type, Object value) {
686:                Assert.notNull(type, "Type must not be null");
687:                return (value != null ? isAssignable(type, value.getClass())
688:                        : !type.isPrimitive());
689:            }
690:
691:            /**
692:             * Convert a "/"-based resource path to a "."-based fully qualified class name.
693:             * @param resourcePath the resource path pointing to a class
694:             * @return the corresponding fully qualified class name
695:             */
696:            public static String convertResourcePathToClassName(
697:                    String resourcePath) {
698:                return resourcePath.replace('/', '.');
699:            }
700:
701:            /**
702:             * Convert a "."-based fully qualified class name to a "/"-based resource path.
703:             * @param className the fully qualified class name
704:             * @return the corresponding resource path, pointing to the class
705:             */
706:            public static String convertClassNameToResourcePath(String className) {
707:                return className.replace('.', '/');
708:            }
709:
710:            /**
711:             * Return a path suitable for use with <code>ClassLoader.getResource</code>
712:             * (also suitable for use with <code>Class.getResource</code> by prepending a
713:             * slash ('/') to the return value. Built by taking the package of the specified
714:             * class file, converting all dots ('.') to slashes ('/'), adding a trailing slash
715:             * if necesssary, and concatenating the specified resource name to this.
716:             * <br/>As such, this function may be used to build a path suitable for
717:             * loading a resource file that is in the same package as a class file,
718:             * although {@link org.springframework.core.io.ClassPathResource} is usually
719:             * even more convenient.
720:             * @param clazz	the Class whose package will be used as the base
721:             * @param resourceName the resource name to append. A leading slash is optional.
722:             * @return the built-up resource path
723:             * @see java.lang.ClassLoader#getResource
724:             * @see java.lang.Class#getResource
725:             */
726:            public static String addResourcePathToPackagePath(Class clazz,
727:                    String resourceName) {
728:                Assert.notNull(resourceName, "Resource name must not be null");
729:                if (!resourceName.startsWith("/")) {
730:                    return classPackageAsResourcePath(clazz) + "/"
731:                            + resourceName;
732:                }
733:                return classPackageAsResourcePath(clazz) + resourceName;
734:            }
735:
736:            /**
737:             * Given an input class object, return a string which consists of the
738:             * class's package name as a pathname, i.e., all dots ('.') are replaced by
739:             * slashes ('/'). Neither a leading nor trailing slash is added. The result
740:             * could be concatenated with a slash and the name of a resource, and fed
741:             * directly to <code>ClassLoader.getResource()</code>. For it to be fed to
742:             * <code>Class.getResource</code> instead, a leading slash would also have
743:             * to be prepended to the returned value.
744:             * @param clazz the input class. A <code>null</code> value or the default
745:             * (empty) package will result in an empty string ("") being returned.
746:             * @return a path which represents the package name
747:             * @see ClassLoader#getResource
748:             * @see Class#getResource
749:             */
750:            public static String classPackageAsResourcePath(Class clazz) {
751:                if (clazz == null) {
752:                    return "";
753:                }
754:                String className = clazz.getName();
755:                int packageEndIndex = className.lastIndexOf('.');
756:                if (packageEndIndex == -1) {
757:                    return "";
758:                }
759:                String packageName = className.substring(0, packageEndIndex);
760:                return packageName.replace('.', '/');
761:            }
762:
763:            /**
764:             * Build a String that consists of the names of the classes/interfaces
765:             * in the given array.
766:             * <p>Basically like <code>AbstractCollection.toString()</code>, but stripping
767:             * the "class "/"interface " prefix before every class name.
768:             * @param classes a Collection of Class objects (may be <code>null</code>)
769:             * @return a String of form "[com.foo.Bar, com.foo.Baz]"
770:             * @see java.util.AbstractCollection#toString()
771:             */
772:            public static String classNamesToString(Class[] classes) {
773:                return classNamesToString(Arrays.asList(classes));
774:            }
775:
776:            /**
777:             * Build a String that consists of the names of the classes/interfaces
778:             * in the given collection.
779:             * <p>Basically like <code>AbstractCollection.toString()</code>, but stripping
780:             * the "class "/"interface " prefix before every class name.
781:             * @param classes a Collection of Class objects (may be <code>null</code>)
782:             * @return a String of form "[com.foo.Bar, com.foo.Baz]"
783:             * @see java.util.AbstractCollection#toString()
784:             */
785:            public static String classNamesToString(Collection classes) {
786:                if (CollectionUtils.isEmpty(classes)) {
787:                    return "[]";
788:                }
789:                StringBuffer sb = new StringBuffer("[");
790:                for (Iterator it = classes.iterator(); it.hasNext();) {
791:                    Class clazz = (Class) it.next();
792:                    sb.append(clazz.getName());
793:                    if (it.hasNext()) {
794:                        sb.append(", ");
795:                    }
796:                }
797:                sb.append("]");
798:                return sb.toString();
799:            }
800:
801:            /**
802:             * Return all interfaces that the given instance implements as array,
803:             * including ones implemented by superclasses.
804:             * @param instance the instance to analyse for interfaces
805:             * @return all interfaces that the given instance implements as array
806:             */
807:            public static Class[] getAllInterfaces(Object instance) {
808:                Assert.notNull(instance, "Instance must not be null");
809:                return getAllInterfacesForClass(instance.getClass());
810:            }
811:
812:            /**
813:             * Return all interfaces that the given class implements as array,
814:             * including ones implemented by superclasses.
815:             * <p>If the class itself is an interface, it gets returned as sole interface.
816:             * @param clazz the class to analyse for interfaces
817:             * @return all interfaces that the given object implements as array
818:             */
819:            public static Class[] getAllInterfacesForClass(Class clazz) {
820:                Assert.notNull(clazz, "Class must not be null");
821:                if (clazz.isInterface()) {
822:                    return new Class[] { clazz };
823:                }
824:                List interfaces = new ArrayList();
825:                while (clazz != null) {
826:                    for (int i = 0; i < clazz.getInterfaces().length; i++) {
827:                        Class ifc = clazz.getInterfaces()[i];
828:                        if (!interfaces.contains(ifc)) {
829:                            interfaces.add(ifc);
830:                        }
831:                    }
832:                    clazz = clazz.getSuperclass();
833:                }
834:                return (Class[]) interfaces
835:                        .toArray(new Class[interfaces.size()]);
836:            }
837:
838:            /**
839:             * Return all interfaces that the given instance implements as Set,
840:             * including ones implemented by superclasses.
841:             * @param instance the instance to analyse for interfaces
842:             * @return all interfaces that the given instance implements as Set
843:             */
844:            public static Set getAllInterfacesAsSet(Object instance) {
845:                Assert.notNull(instance, "Instance must not be null");
846:                return getAllInterfacesForClassAsSet(instance.getClass());
847:            }
848:
849:            /**
850:             * Return all interfaces that the given class implements as Set,
851:             * including ones implemented by superclasses.
852:             * <p>If the class itself is an interface, it gets returned as sole interface.
853:             * @param clazz the class to analyse for interfaces
854:             * @return all interfaces that the given object implements as Set
855:             */
856:            public static Set getAllInterfacesForClassAsSet(Class clazz) {
857:                Assert.notNull(clazz, "Class must not be null");
858:                if (clazz.isInterface()) {
859:                    return Collections.singleton(clazz);
860:                }
861:                Set interfaces = new LinkedHashSet();
862:                while (clazz != null) {
863:                    for (int i = 0; i < clazz.getInterfaces().length; i++) {
864:                        Class ifc = clazz.getInterfaces()[i];
865:                        interfaces.add(ifc);
866:                    }
867:                    clazz = clazz.getSuperclass();
868:                }
869:                return interfaces;
870:            }
871:
872:            /**
873:             * Create a composite interface Class for the given interfaces,
874:             * implementing the given interfaces in one single Class.
875:             * <p>This implementation builds a JDK proxy class for the given interfaces.
876:             * @param interfaces the interfaces to merge
877:             * @param classLoader the ClassLoader to create the composite Class in
878:             * @return the merged interface as Class
879:             * @see java.lang.reflect.Proxy#getProxyClass
880:             */
881:            public static Class createCompositeInterface(Class[] interfaces,
882:                    ClassLoader classLoader) {
883:                Assert.notEmpty(interfaces, "Interfaces must not be empty");
884:                Assert.notNull(classLoader, "ClassLoader must not be null");
885:                return Proxy.getProxyClass(classLoader, interfaces);
886:            }
887:
888:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.