1
2
3
4
5
6
7
8
9
10
11 package org.mule.util;
12
13 import org.mule.routing.filters.WildcardFilter;
14
15 import java.io.BufferedReader;
16 import java.io.CharArrayReader;
17 import java.io.IOException;
18 import java.io.Reader;
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Modifier;
23 import java.net.URL;
24 import java.net.URLClassLoader;
25 import java.security.AccessController;
26 import java.security.CodeSource;
27 import java.security.PrivilegedAction;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Enumeration;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38
39
40
41
42
43
44
45
46
47 public class ClassUtils extends org.apache.commons.lang.ClassUtils
48 {
49 public static final Object[] NO_ARGS = new Object[]{};
50 public static final Class<?>[] NO_ARGS_TYPE = new Class<?>[]{};
51
52 private static final Map<Class<?>, Class<?>> wrapperToPrimitiveMap = new HashMap<Class<?>, Class<?>>();
53 private static final Map<String, Class<?>> primitiveTypeNameMap = new HashMap<String, Class<?>>(32);
54
55 static
56 {
57 wrapperToPrimitiveMap.put(Boolean.class, Boolean.TYPE);
58 wrapperToPrimitiveMap.put(Byte.class, Byte.TYPE);
59 wrapperToPrimitiveMap.put(Character.class, Character.TYPE);
60 wrapperToPrimitiveMap.put(Short.class, Short.TYPE);
61 wrapperToPrimitiveMap.put(Integer.class, Integer.TYPE);
62 wrapperToPrimitiveMap.put(Long.class, Long.TYPE);
63 wrapperToPrimitiveMap.put(Double.class, Double.TYPE);
64 wrapperToPrimitiveMap.put(Float.class, Float.TYPE);
65 wrapperToPrimitiveMap.put(Void.TYPE, Void.TYPE);
66
67 Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(32);
68 primitiveTypes.addAll(wrapperToPrimitiveMap.values());
69 for (Class<?> primitiveType : primitiveTypes)
70 {
71 primitiveTypeNameMap.put(primitiveType.getName(), primitiveType);
72 }
73 }
74
75 public static boolean isConcrete(Class<?> clazz)
76 {
77 if (clazz == null)
78 {
79 throw new IllegalArgumentException("clazz may not be null");
80 }
81 return !(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()));
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 public static URL getResource(final String resourceName, final Class<?> callingClass)
101 {
102 URL url = AccessController.doPrivileged(new PrivilegedAction<URL>()
103 {
104 public URL run()
105 {
106 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
107 return cl != null ? cl.getResource(resourceName) : null;
108 }
109 });
110
111 if (url == null)
112 {
113 url = AccessController.doPrivileged(new PrivilegedAction<URL>()
114 {
115 public URL run()
116 {
117 return ClassUtils.class.getClassLoader().getResource(resourceName);
118 }
119 });
120 }
121
122 if (url == null)
123 {
124 url = AccessController.doPrivileged(new PrivilegedAction<URL>()
125 {
126 public URL run()
127 {
128 return callingClass.getClassLoader().getResource(resourceName);
129 }
130 });
131 }
132
133 return url;
134 }
135
136 public static Enumeration<URL> getResources(final String resourceName, final Class<?> callingClass)
137 {
138 Enumeration<URL> enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
139 {
140 public Enumeration<URL> run()
141 {
142 try
143 {
144 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
145 return cl != null ? cl.getResources(resourceName) : null;
146 }
147 catch (IOException e)
148 {
149 return null;
150 }
151 }
152 });
153
154 if (enumeration == null)
155 {
156 enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
157 {
158 public Enumeration<URL> run()
159 {
160 try
161 {
162 return ClassUtils.class.getClassLoader().getResources(resourceName);
163 }
164 catch (IOException e)
165 {
166 return null;
167 }
168 }
169 });
170 }
171
172 if (enumeration == null)
173 {
174 enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
175 {
176 public Enumeration<URL> run()
177 {
178 try
179 {
180 return callingClass.getClassLoader().getResources(resourceName);
181 }
182 catch (IOException e)
183 {
184 return null;
185 }
186 }
187 });
188 }
189
190 return enumeration;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 public static Class loadClass(final String className, final Class<?> callingClass) throws ClassNotFoundException
211 {
212 return loadClass(className, callingClass, Object.class);
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public static <T extends Class> T loadClass(final String className, final Class<?> callingClass, T type) throws ClassNotFoundException
233 {
234 if (className.length() <= 8)
235 {
236
237 if (primitiveTypeNameMap.containsKey(className))
238 {
239 return (T) primitiveTypeNameMap.get(className);
240 }
241 }
242
243 Class<?> clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
244 {
245 public Class<?> run()
246 {
247 try
248 {
249 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
250 return cl != null ? cl.loadClass(className) : null;
251
252 }
253 catch (ClassNotFoundException e)
254 {
255 return null;
256 }
257 }
258 });
259
260 if (clazz == null)
261 {
262 clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
263 {
264 public Class<?> run()
265 {
266 try
267 {
268 return Class.forName(className);
269 }
270 catch (ClassNotFoundException e)
271 {
272 return null;
273 }
274 }
275 });
276 }
277
278 if (clazz == null)
279 {
280 clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
281 {
282 public Class<?> run()
283 {
284 try
285 {
286 return ClassUtils.class.getClassLoader().loadClass(className);
287 }
288 catch (ClassNotFoundException e)
289 {
290 return null;
291 }
292 }
293 });
294 }
295
296 if (clazz == null)
297 {
298 clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
299 {
300 public Class<?> run()
301 {
302 try
303 {
304 return callingClass.getClassLoader().loadClass(className);
305 }
306 catch (ClassNotFoundException e)
307 {
308 return null;
309 }
310 }
311 });
312 }
313
314 if (clazz == null)
315 {
316 throw new ClassNotFoundException(className);
317 }
318
319 if(type.isAssignableFrom(clazz))
320 {
321 return (T)clazz;
322 }
323 else
324 {
325 throw new IllegalArgumentException(String.format("Loaded class '%s' is not assignable from type '%s'", clazz.getName(), type.getName()));
326 }
327 }
328
329
330
331
332
333
334
335
336
337 public static Class loadClass(final String className, final ClassLoader classLoader)
338 throws ClassNotFoundException
339 {
340 return classLoader.loadClass(className);
341 }
342
343
344
345
346
347
348
349
350
351
352 public static Class<?> initializeClass(Class<?> clazz)
353 {
354 try
355 {
356 return getClass(clazz.getName(), true);
357 }
358 catch (ClassNotFoundException e)
359 {
360 IllegalStateException ise = new IllegalStateException();
361 ise.initCause(e);
362 throw ise;
363 }
364 }
365
366 public static <T> T instanciateClass(Class<? extends T> clazz, Object... constructorArgs)
367 throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException,
368 IllegalAccessException, InvocationTargetException
369 {
370 Class<?>[] args;
371 if (constructorArgs != null)
372 {
373 args = new Class[constructorArgs.length];
374 for (int i = 0; i < constructorArgs.length; i++)
375 {
376 if (constructorArgs[i] == null)
377 {
378 args[i] = null;
379 }
380 else
381 {
382 args[i] = constructorArgs[i].getClass();
383 }
384 }
385 }
386 else
387 {
388 args = new Class[0];
389 }
390
391
392
393 Constructor<?> ctor = getConstructor(clazz, args);
394
395 if (ctor == null)
396 {
397
398 ctor = getConstructor(clazz, wrappersToPrimitives(args));
399 }
400
401 if (ctor == null)
402 {
403 StringBuffer argsString = new StringBuffer(100);
404 for (Class<?> arg : args)
405 {
406 argsString.append(arg.getName()).append(", ");
407 }
408 throw new NoSuchMethodException("could not find constructor on class: " + clazz + ", with matching arg params: "
409 + argsString);
410 }
411
412 return (T)ctor.newInstance(constructorArgs);
413 }
414
415 public static Object instanciateClass(String name, Object... constructorArgs)
416 throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
417 InstantiationException, IllegalAccessException, InvocationTargetException
418 {
419 return instanciateClass(name, constructorArgs, (ClassLoader) null);
420 }
421
422 public static Object instanciateClass(String name, Object[] constructorArgs, Class<?> callingClass)
423 throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
424 InstantiationException, IllegalAccessException, InvocationTargetException
425 {
426 Class<?> clazz = loadClass(name, callingClass);
427 return instanciateClass(clazz, constructorArgs);
428 }
429
430 public static Object instanciateClass(String name, Object[] constructorArgs, ClassLoader classLoader)
431 throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
432 InstantiationException, IllegalAccessException, InvocationTargetException
433 {
434 Class<?> clazz;
435 if (classLoader != null)
436 {
437 clazz = loadClass(name, classLoader);
438 }
439 else
440 {
441 clazz = loadClass(name, ClassUtils.class);
442 }
443 if (clazz == null)
444 {
445 throw new ClassNotFoundException(name);
446 }
447 return instanciateClass(clazz, constructorArgs);
448 }
449
450 public static Class<?>[] getParameterTypes(Object bean, String methodName)
451 {
452 if (!methodName.startsWith("set"))
453 {
454 methodName = "set" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
455 }
456
457 Method methods[] = bean.getClass().getMethods();
458
459 for (int i = 0; i < methods.length; i++)
460 {
461 if (methods[i].getName().equals(methodName))
462 {
463 return methods[i].getParameterTypes();
464 }
465 }
466
467 return new Class[]{};
468 }
469
470
471
472
473
474
475
476
477
478
479
480 public static Method getMethod(Class<?> clazz, String name, Class<?>[] parameterTypes)
481 {
482 return getMethod(clazz, name, parameterTypes, false);
483 }
484
485 public static Method getMethod(Class clazz, String name, Class[] parameterTypes, boolean acceptNulls)
486 {
487 Method[] methods = clazz.getMethods();
488 for (int i = 0; i < methods.length; i++)
489 {
490 if (methods[i].getName().equals(name))
491 {
492 if (parameterTypes == null)
493 {
494 return methods[i];
495 }
496 else if (compare(methods[i].getParameterTypes(), parameterTypes, true, acceptNulls))
497 {
498 return methods[i];
499 }
500 }
501 }
502 return null;
503 }
504
505 public static Constructor getConstructor(Class clazz, Class[] paramTypes)
506 {
507 return getConstructor(clazz, paramTypes, false);
508 }
509
510
511
512
513
514
515
516
517
518 public static Constructor getConstructor(Class clazz, Class[] paramTypes, boolean exactMatch)
519 {
520 Constructor[] ctors = clazz.getConstructors();
521 for (int i = 0; i < ctors.length; i++)
522 {
523 Class[] types = ctors[i].getParameterTypes();
524 if (types.length == paramTypes.length)
525 {
526 int matchCount = 0;
527 for (int x = 0; x < types.length; x++)
528 {
529 if (paramTypes[x] == null)
530 {
531 matchCount++;
532 }
533 else
534 {
535 if (exactMatch)
536 {
537 if (paramTypes[x].equals(types[x]) || types[x].equals(paramTypes[x]))
538 {
539 matchCount++;
540 }
541 }
542 else
543 {
544 if (paramTypes[x].isAssignableFrom(types[x])
545 || types[x].isAssignableFrom(paramTypes[x]))
546 {
547 matchCount++;
548 }
549 }
550 }
551 }
552 if (matchCount == types.length)
553 {
554 return ctors[i];
555 }
556 }
557 }
558 return null;
559 }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575 public static List<Method> getSatisfiableMethods(Class<?> implementation,
576 Class<?>[] parameterTypes,
577 boolean voidOk,
578 boolean matchOnObject,
579 Set<String> ignoredMethodNames)
580 {
581 return getSatisfiableMethods(implementation, parameterTypes, voidOk, matchOnObject, ignoredMethodNames, null);
582 }
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599 public static List<Method> getSatisfiableMethods(Class<?> implementation,
600 Class<?>[] parameterTypes,
601 boolean voidOk,
602 boolean matchOnObject,
603 Collection<String> ignoredMethodNames,
604 WildcardFilter filter)
605 {
606 List<Method> result = new ArrayList<Method>();
607
608 if (ignoredMethodNames == null)
609 {
610 ignoredMethodNames = Collections.emptySet();
611 }
612
613 Method[] methods = implementation.getMethods();
614 for (int i = 0; i < methods.length; i++)
615 {
616 Method method = methods[i];
617
618 if (filter != null && filter.accept(method.getName()))
619 {
620 continue;
621 }
622 Class<?>[] methodParams = method.getParameterTypes();
623
624 if (compare(methodParams, parameterTypes, matchOnObject))
625 {
626 if (!ignoredMethodNames.contains(method.getName()))
627 {
628 String returnType = method.getReturnType().getName();
629 if ((returnType.equals("void") && voidOk) || !returnType.equals("void"))
630 {
631 result.add(method);
632 }
633 }
634 }
635 }
636
637 return result;
638 }
639
640
641
642
643
644
645
646
647
648 public static List<Method> getSatisfiableMethodsWithReturnType(Class implementation,
649 Class returnType,
650 boolean matchOnObject,
651 Set<String> ignoredMethodNames)
652 {
653 List<Method> result = new ArrayList<Method>();
654
655 if (ignoredMethodNames == null)
656 {
657 ignoredMethodNames = Collections.emptySet();
658 }
659
660 Method[] methods = implementation.getMethods();
661 for (int i = 0; i < methods.length; i++)
662 {
663 Method method = methods[i];
664 Class returns = method.getReturnType();
665
666 if (compare(new Class[]{returns}, new Class[]{returnType}, matchOnObject))
667 {
668 if (!ignoredMethodNames.contains(method.getName()))
669 {
670 result.add(method);
671 }
672 }
673 }
674
675 return result;
676 }
677
678
679
680
681
682
683
684
685
686 public static boolean isClassOnPath(String className, Class currentClass)
687 {
688 try
689 {
690 return (loadClass(className, currentClass) != null);
691 }
692 catch (ClassNotFoundException e)
693 {
694 return false;
695 }
696 }
697
698
699
700
701
702
703
704
705 public static Class<?>[] getClassTypes(Object object)
706 {
707 if (object == null)
708 {
709 return NO_ARGS_TYPE;
710 }
711
712 Class<?>[] types;
713
714 if (object instanceof Object[])
715 {
716 Object[] objects = (Object[]) object;
717 if (objects.length == 0)
718 {
719 return NO_ARGS_TYPE;
720 }
721 types = new Class[objects.length];
722 for (int i = 0; i < objects.length; i++)
723 {
724 Object o = objects[i];
725 if (o != null)
726 {
727 types[i] = o.getClass();
728 }
729 }
730 }
731 else
732 {
733 types = new Class[]{object.getClass()};
734 }
735
736 return types;
737 }
738
739 public static String getClassName(Class clazz)
740 {
741 if (clazz == null)
742 {
743 return null;
744 }
745 String name = clazz.getName();
746 return name.substring(name.lastIndexOf(".") + 1);
747 }
748
749 public static boolean compare(Class[] c1, Class[] c2, boolean matchOnObject)
750 {
751 return compare(c1, c2, matchOnObject, false);
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767 public static boolean compare(Class[] c1, Class[] c2, boolean matchOnObject, boolean acceptNulls)
768 {
769 if (c1.length != c2.length)
770 {
771 return false;
772 }
773 for (int i = 0; i < c1.length; i++)
774 {
775 if (!acceptNulls)
776 {
777 if ((c1[i] == null) || (c2[i] == null))
778 {
779 return false;
780 }
781 }
782 else
783 {
784 if (c1[i] == null)
785 {
786 return false;
787 }
788 if ((c2[i] == null) && (c1[i].isPrimitive()))
789 {
790 return false;
791 }
792 if (c2[i] == null)
793 {
794 return true;
795 }
796 }
797 if (c1[i].equals(Object.class) && !matchOnObject)
798 {
799 return false;
800 }
801 if (!c1[i].isAssignableFrom(c2[i]))
802 {
803 return false;
804 }
805 }
806 return true;
807 }
808
809 public static Class wrapperToPrimitive(Class wrapper)
810 {
811 return (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrapper, wrapper);
812 }
813
814 public static Class[] wrappersToPrimitives(Class[] wrappers)
815 {
816 if (wrappers == null)
817 {
818 return null;
819 }
820
821 if (wrappers.length == 0)
822 {
823 return wrappers;
824 }
825
826 Class[] primitives = new Class[wrappers.length];
827
828 for (int i = 0; i < wrappers.length; i++)
829 {
830 primitives[i] = (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrappers[i], wrappers[i]);
831 }
832
833 return primitives;
834 }
835
836
837
838
839
840
841
842 public static String getSimpleName(Class clazz)
843 {
844 if (null == clazz)
845 {
846 return "null";
847 }
848 else
849 {
850 return classNameHelper(new BufferedReader(new CharArrayReader(clazz.getName().toCharArray())));
851 }
852 }
853
854 private static String classNameHelper(Reader encodedName)
855 {
856
857
858
859
860 try
861 {
862 encodedName.mark(1);
863 switch (encodedName.read())
864 {
865 case -1:
866 return "null";
867 case 'Z':
868 return "boolean";
869 case 'B':
870 return "byte";
871 case 'C':
872 return "char";
873 case 'D':
874 return "double";
875 case 'F':
876 return "float";
877 case 'I':
878 return "int";
879 case 'J':
880 return "long";
881 case 'S':
882 return "short";
883 case '[':
884 return classNameHelper(encodedName) + "[]";
885 case 'L':
886 return shorten(new BufferedReader(encodedName).readLine());
887 default:
888 encodedName.reset();
889 return shorten(new BufferedReader(encodedName).readLine());
890 }
891 }
892 catch (IOException e)
893 {
894 return "unknown type: " + e.getMessage();
895 }
896 }
897
898
899
900
901
902 private static String shorten(String clazz)
903 {
904 if (null != clazz && clazz.endsWith(";"))
905 {
906 clazz = clazz.substring(0, clazz.length() - 1);
907 }
908 if (null != clazz && clazz.lastIndexOf(".") > -1)
909 {
910 clazz = clazz.substring(clazz.lastIndexOf(".") + 1, clazz.length());
911 }
912 return clazz;
913 }
914
915
916
917
918
919
920
921
922
923 public static boolean equal(Object a, Object b)
924 {
925 if (null == a)
926 {
927 return null == b;
928 }
929 else
930 {
931 return null != b && a.equals(b);
932 }
933 }
934
935 public static int hash(Object[] state)
936 {
937 int hash = 0;
938 for (int i = 0; i < state.length; ++i)
939 {
940 hash = hash * 31 + (null == state[i] ? 0 : state[i].hashCode());
941 }
942 return hash;
943 }
944
945 public static void addLibrariesToClasspath(List urls) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
946 {
947 ClassLoader sys = ClassLoader.getSystemClassLoader();
948 if (!(sys instanceof URLClassLoader))
949 {
950 throw new IllegalArgumentException(
951 "PANIC: Mule has been started with an unsupported classloader: " + sys.getClass().getName()
952 + ". " + "Please report this error to user<at>mule<dot>codehaus<dot>org");
953 }
954
955
956
957 URLClassLoader sysCl = (URLClassLoader) sys;
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977 Class refClass = URLClassLoader.class;
978 Method methodAddUrl = refClass.getDeclaredMethod("addURL", new Class[]{URL.class});
979 methodAddUrl.setAccessible(true);
980 for (Iterator it = urls.iterator(); it.hasNext();)
981 {
982 URL url = (URL) it.next();
983 methodAddUrl.invoke(sysCl, url);
984 }
985 }
986
987
988
989
990 public static URL getClassPathRoot(Class clazz)
991 {
992 CodeSource cs = clazz.getProtectionDomain().getCodeSource();
993 return (cs != null ? cs.getLocation() : null);
994 }
995 }