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