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