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 Method[] methods = clazz.getMethods();
483 for (int i = 0; i < methods.length; i++)
484 {
485 if (methods[i].getName().equals(name))
486 {
487 if (parameterTypes == null)
488 {
489 return methods[i];
490 }
491 else if (compare(methods[i].getParameterTypes(), parameterTypes, true))
492 {
493 return methods[i];
494 }
495 }
496 }
497 return null;
498 }
499
500 public static Constructor getConstructor(Class clazz, Class[] paramTypes)
501 {
502 return getConstructor(clazz, paramTypes, false);
503 }
504
505
506
507
508
509
510
511
512
513 public static Constructor getConstructor(Class clazz, Class[] paramTypes, boolean exactMatch)
514 {
515 Constructor[] ctors = clazz.getConstructors();
516 for (int i = 0; i < ctors.length; i++)
517 {
518 Class[] types = ctors[i].getParameterTypes();
519 if (types.length == paramTypes.length)
520 {
521 int matchCount = 0;
522 for (int x = 0; x < types.length; x++)
523 {
524 if (paramTypes[x] == null)
525 {
526 matchCount++;
527 }
528 else
529 {
530 if (exactMatch)
531 {
532 if (paramTypes[x].equals(types[x]) || types[x].equals(paramTypes[x]))
533 {
534 matchCount++;
535 }
536 }
537 else
538 {
539 if (paramTypes[x].isAssignableFrom(types[x])
540 || types[x].isAssignableFrom(paramTypes[x]))
541 {
542 matchCount++;
543 }
544 }
545 }
546 }
547 if (matchCount == types.length)
548 {
549 return ctors[i];
550 }
551 }
552 }
553 return null;
554 }
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570 public static List<Method> getSatisfiableMethods(Class<?> implementation,
571 Class<?>[] parameterTypes,
572 boolean voidOk,
573 boolean matchOnObject,
574 Set<String> ignoredMethodNames)
575 {
576 return getSatisfiableMethods(implementation, parameterTypes, voidOk, matchOnObject, ignoredMethodNames, null);
577 }
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594 public static List<Method> getSatisfiableMethods(Class<?> implementation,
595 Class<?>[] parameterTypes,
596 boolean voidOk,
597 boolean matchOnObject,
598 Collection<String> ignoredMethodNames,
599 WildcardFilter filter)
600 {
601 List<Method> result = new ArrayList<Method>();
602
603 if (ignoredMethodNames == null)
604 {
605 ignoredMethodNames = Collections.emptySet();
606 }
607
608 Method[] methods = implementation.getMethods();
609 for (int i = 0; i < methods.length; i++)
610 {
611 Method method = methods[i];
612
613 if (filter != null && filter.accept(method.getName()))
614 {
615 continue;
616 }
617 Class<?>[] methodParams = method.getParameterTypes();
618
619 if (compare(methodParams, parameterTypes, matchOnObject))
620 {
621 if (!ignoredMethodNames.contains(method.getName()))
622 {
623 String returnType = method.getReturnType().getName();
624 if ((returnType.equals("void") && voidOk) || !returnType.equals("void"))
625 {
626 result.add(method);
627 }
628 }
629 }
630 }
631
632 return result;
633 }
634
635
636
637
638
639
640
641
642
643 public static List<Method> getSatisfiableMethodsWithReturnType(Class implementation,
644 Class returnType,
645 boolean matchOnObject,
646 Set<String> ignoredMethodNames)
647 {
648 List<Method> result = new ArrayList<Method>();
649
650 if (ignoredMethodNames == null)
651 {
652 ignoredMethodNames = Collections.emptySet();
653 }
654
655 Method[] methods = implementation.getMethods();
656 for (int i = 0; i < methods.length; i++)
657 {
658 Method method = methods[i];
659 Class returns = method.getReturnType();
660
661 if (compare(new Class[]{returns}, new Class[]{returnType}, matchOnObject))
662 {
663 if (!ignoredMethodNames.contains(method.getName()))
664 {
665 result.add(method);
666 }
667 }
668 }
669
670 return result;
671 }
672
673
674
675
676
677
678
679
680
681 public static boolean isClassOnPath(String className, Class currentClass)
682 {
683 try
684 {
685 return (loadClass(className, currentClass) != null);
686 }
687 catch (ClassNotFoundException e)
688 {
689 return false;
690 }
691 }
692
693
694
695
696
697
698
699
700 public static Class<?>[] getClassTypes(Object object)
701 {
702 if (object == null)
703 {
704 return NO_ARGS_TYPE;
705 }
706
707 Class<?>[] types;
708
709 if (object instanceof Object[])
710 {
711 Object[] objects = (Object[]) object;
712 if (objects.length == 0)
713 {
714 return NO_ARGS_TYPE;
715 }
716 types = new Class[objects.length];
717 for (int i = 0; i < objects.length; i++)
718 {
719 Object o = objects[i];
720 if (o != null)
721 {
722 types[i] = o.getClass();
723 }
724 }
725 }
726 else
727 {
728 types = new Class[]{object.getClass()};
729 }
730
731 return types;
732 }
733
734 public static String getClassName(Class clazz)
735 {
736 if (clazz == null)
737 {
738 return null;
739 }
740 String name = clazz.getName();
741 return name.substring(name.lastIndexOf(".") + 1);
742 }
743
744 public static boolean compare(Class[] c1, Class[] c2, boolean matchOnObject)
745 {
746 if (c1.length != c2.length)
747 {
748 return false;
749 }
750 for (int i = 0; i < c1.length; i++)
751 {
752 if ((c1[i] == null) || (c2[i] == null))
753 {
754 return false;
755 }
756 if (c1[i].equals(Object.class) && !matchOnObject)
757 {
758 return false;
759 }
760 if (!c1[i].isAssignableFrom(c2[i]))
761 {
762 return false;
763 }
764 }
765 return true;
766 }
767
768 public static Class wrapperToPrimitive(Class wrapper)
769 {
770 return (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrapper, wrapper);
771 }
772
773 public static Class[] wrappersToPrimitives(Class[] wrappers)
774 {
775 if (wrappers == null)
776 {
777 return null;
778 }
779
780 if (wrappers.length == 0)
781 {
782 return wrappers;
783 }
784
785 Class[] primitives = new Class[wrappers.length];
786
787 for (int i = 0; i < wrappers.length; i++)
788 {
789 primitives[i] = (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrappers[i], wrappers[i]);
790 }
791
792 return primitives;
793 }
794
795
796
797
798
799
800
801 public static String getSimpleName(Class clazz)
802 {
803 if (null == clazz)
804 {
805 return "null";
806 }
807 else
808 {
809 return classNameHelper(new BufferedReader(new CharArrayReader(clazz.getName().toCharArray())));
810 }
811 }
812
813 private static String classNameHelper(Reader encodedName)
814 {
815
816
817
818
819 try
820 {
821 encodedName.mark(1);
822 switch (encodedName.read())
823 {
824 case -1:
825 return "null";
826 case 'Z':
827 return "boolean";
828 case 'B':
829 return "byte";
830 case 'C':
831 return "char";
832 case 'D':
833 return "double";
834 case 'F':
835 return "float";
836 case 'I':
837 return "int";
838 case 'J':
839 return "long";
840 case 'S':
841 return "short";
842 case '[':
843 return classNameHelper(encodedName) + "[]";
844 case 'L':
845 return shorten(new BufferedReader(encodedName).readLine());
846 default:
847 encodedName.reset();
848 return shorten(new BufferedReader(encodedName).readLine());
849 }
850 }
851 catch (IOException e)
852 {
853 return "unknown type: " + e.getMessage();
854 }
855 }
856
857
858
859
860
861 private static String shorten(String clazz)
862 {
863 if (null != clazz && clazz.endsWith(";"))
864 {
865 clazz = clazz.substring(0, clazz.length() - 1);
866 }
867 if (null != clazz && clazz.lastIndexOf(".") > -1)
868 {
869 clazz = clazz.substring(clazz.lastIndexOf(".") + 1, clazz.length());
870 }
871 return clazz;
872 }
873
874
875
876
877
878
879
880
881
882 public static boolean equal(Object a, Object b)
883 {
884 if (null == a)
885 {
886 return null == b;
887 }
888 else
889 {
890 return null != b && a.equals(b);
891 }
892 }
893
894 public static int hash(Object[] state)
895 {
896 int hash = 0;
897 for (int i = 0; i < state.length; ++i)
898 {
899 hash = hash * 31 + (null == state[i] ? 0 : state[i].hashCode());
900 }
901 return hash;
902 }
903
904 public static void addLibrariesToClasspath(List urls) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
905 {
906 ClassLoader sys = ClassLoader.getSystemClassLoader();
907 if (!(sys instanceof URLClassLoader))
908 {
909 throw new IllegalArgumentException(
910 "PANIC: Mule has been started with an unsupported classloader: " + sys.getClass().getName()
911 + ". " + "Please report this error to user<at>mule<dot>codehaus<dot>org");
912 }
913
914
915
916 URLClassLoader sysCl = (URLClassLoader) sys;
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936 Class refClass = URLClassLoader.class;
937 Method methodAddUrl = refClass.getDeclaredMethod("addURL", new Class[]{URL.class});
938 methodAddUrl.setAccessible(true);
939 for (Iterator it = urls.iterator(); it.hasNext();)
940 {
941 URL url = (URL) it.next();
942 methodAddUrl.invoke(sysCl, url);
943 }
944 }
945
946
947
948
949 public static URL getClassPathRoot(Class clazz)
950 {
951 CodeSource cs = clazz.getProtectionDomain().getCodeSource();
952 return (cs != null ? cs.getLocation() : null);
953 }
954 }