1 package junitx.ddtunit.util;
2
3 import java.lang.reflect.Array;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.Field;
6 import java.lang.reflect.Method;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.Set;
10 import java.util.Vector;
11
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15
16
17
18
19
20
21
22 public class ClassAnalyser {
23
24
25
26
27 public final static String CLASS_CONSTRUCTOR = "class$";
28
29 private final static String usage = "usage: \n"
30 + "ShowMethods qualified.class.name\n"
31 + "To show all methods in class or: \n"
32 + "ShowMethods qualified.class.name word\n"
33 + "To search for methods involving 'word'";
34
35 private static Logger log = LoggerFactory.getLogger(ClassAnalyser.class);
36
37
38
39
40 private ClassAnalyser() {
41
42 }
43
44
45
46
47
48
49 public static void main(String[] args) {
50 if (args.length < 1) {
51 System.out.println(ClassAnalyser.usage);
52 System.exit(0);
53 }
54
55 System.out.println("ClassAnalyser started with class " + args[0]);
56
57 if (args.length == 1) {
58 ClassAnalyser.showAllMethods(args[0]);
59 ClassAnalyser.showAllFields(args[0]);
60 } else {
61 ClassAnalyser.showSelectedMethods(args[0], args[1]);
62 }
63
64 System.out.println("ClassAnalyser end.");
65 }
66
67
68
69
70
71
72
73
74 public static String getShortName(Object obj) {
75 String className = obj.getClass().getName();
76
77 return getShortName(className);
78 }
79
80
81
82
83
84
85
86
87 public static String getShortName(Class className) {
88 String localName = className.getName();
89
90 return getShortName(localName);
91 }
92
93
94
95
96
97
98
99
100 public static String getShortName(String className) {
101 String shortName = className.substring(className.lastIndexOf(".") + 1,
102 className.length());
103
104 return shortName;
105 }
106
107
108
109
110
111
112
113
114
115 public static void showAllFields(String qualifiedClassName) {
116 try {
117 Class c = Class.forName(qualifiedClassName);
118 Field[] fields = c.getDeclaredFields();
119 log.debug("===Class " + qualifiedClassName + " fields:");
120
121 for (int i = 0; i < fields.length; i++) {
122 log.debug(fields[i].toString());
123 }
124 } catch (ClassNotFoundException ex) {
125 log.error("No such class: " + qualifiedClassName, ex);
126 throw new ClassAnalyserException("No class found of type "
127 + qualifiedClassName, ex);
128 }
129 }
130
131
132
133
134
135
136
137
138
139
140 public static void showSelectedFields(String qualifiedClassName,
141 String searchTerm) {
142 try {
143 Class c = Class.forName(qualifiedClassName);
144 Field[] fields = c.getDeclaredFields();
145 log.debug("===Class " + qualifiedClassName
146 + " fields selected by '" + searchTerm + "':");
147
148 for (int i = 0; i < fields.length; i++) {
149 if (fields[i].toString().indexOf(searchTerm) != -1) {
150 log.debug(fields[i].toString());
151 }
152 }
153 } catch (ClassNotFoundException ex) {
154 log.error("No such class: " + qualifiedClassName, ex);
155 throw new ClassAnalyserException("No class found of type "
156 + qualifiedClassName, ex);
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171 public static Field getSelectedField(String qualifiedClassName,
172 String searchTerm) {
173 Field localField = null;
174 if (qualifiedClassName != null && searchTerm != null) {
175 try {
176 Class c = Class.forName(qualifiedClassName);
177
178 while (c != null) {
179
180
181
182 Field[] fields = c.getDeclaredFields();
183 String className = c.getName();
184 log.debug("===Class " + className + " fields selected by '"
185 + searchTerm + "':");
186
187 boolean found = false;
188
189 for (int i = 0; i < fields.length; i++) {
190
191
192
193
194 String fieldName = fields[i].getName();
195 log.debug("check search term <" + searchTerm
196 + "> in field <" + fieldName + ">");
197
198 if (!fieldName.startsWith("class$")
199 && fieldName.equals(searchTerm)) {
200
201 if (!found) {
202 localField = fields[i];
203 found = true;
204 log.debug("First hit.");
205
206 break;
207 } else {
208 throw new IllegalArgumentException(
209 "double count of field " + searchTerm);
210 }
211 }
212 }
213
214 if (!found) {
215 c = c.getSuperclass();
216 log.debug("=== No Hit");
217 } else {
218 c = null;
219 log.debug("=== End of Check");
220 }
221 }
222 } catch (ClassNotFoundException ex) {
223 log.error("No such class: " + qualifiedClassName, ex);
224 throw new ClassAnalyserException("No class found of type "
225 + qualifiedClassName, ex);
226 }
227 }
228 return localField;
229 }
230
231
232
233
234
235
236
237
238
239 public static void showAllMethods(String qualifiedClassName) {
240 try {
241 Class c = Class.forName(qualifiedClassName);
242 Method[] m = c.getMethods();
243 Constructor[] ctor = c.getConstructors();
244 log.debug("===Class " + qualifiedClassName + " methods:");
245
246 for (int i = 0; i < m.length; i++) {
247 log.debug(m[i].toString());
248 }
249
250 log.debug("===Class " + qualifiedClassName + " constructors:");
251
252 for (int i = 0; i < ctor.length; i++) {
253 log.debug(ctor[i].toString());
254 }
255 } catch (ClassNotFoundException ex) {
256 log.error("No such class: " + qualifiedClassName, ex);
257 throw new ClassAnalyserException("No class found of type "
258 + qualifiedClassName, ex);
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271
272 public static String[] getAllMethods(String qualifiedClassName) {
273 Class c;
274 Method[] m;
275
276 try {
277 c = Class.forName(qualifiedClassName);
278 m = c.getMethods();
279 log.debug("===Class " + qualifiedClassName + " methods:");
280
281 String[] methods = new String[m.length];
282
283 for (int i = 0; i < m.length; i++) {
284 log.debug(m[i].toString());
285 methods[i] = m[i].getName();
286 }
287
288 return methods;
289 } catch (ClassNotFoundException ex) {
290 log.error("No such class: " + qualifiedClassName, ex);
291 throw new ClassAnalyserException("No class found of type "
292 + qualifiedClassName, ex);
293 }
294 }
295
296
297
298
299
300
301
302
303
304
305
306 public static void showSelectedMethods(String qualifiedClassName,
307 String searchTerm) {
308 try {
309 Class c = Class.forName(qualifiedClassName);
310 Method[] m = c.getMethods();
311 Constructor[] ctor = c.getConstructors();
312
313 for (int i = 0; i < m.length; i++) {
314 if (m[i].toString().indexOf(searchTerm) != -1) {
315 log.info(m[i].toString());
316 }
317 }
318
319 for (int i = 0; i < ctor.length; i++) {
320 if (ctor[i].toString().indexOf(searchTerm) != -1) {
321 log.info(ctor[i].toString());
322 }
323 }
324 } catch (ClassNotFoundException ex) {
325 log.error("No such class: " + qualifiedClassName, ex);
326 throw new ClassAnalyserException("No class found of type "
327 + qualifiedClassName, ex);
328 }
329 }
330
331
332
333
334
335
336
337
338
339
340
341 public static Object findMethodByParams(String className,
342 String methodName, Class[] args) {
343 Object method = null;
344
345 try {
346 Object[] methods;
347 Class myClass = Class.forName(className);
348 if (CLASS_CONSTRUCTOR.compareTo(methodName) == 0) {
349 methods = myClass.getDeclaredConstructors();
350 } else {
351 methods = myClass.getDeclaredMethods();
352 }
353
354 Vector searchMethods = filterByNameAndParamCount(methods,
355 methodName, args.length);
356 boolean found = false;
357 for (Iterator iter = searchMethods.iterator(); iter.hasNext();) {
358 Object myMethod = iter.next();
359
360 found = filterByParam(myMethod, args, 0);
361
362 if (found) {
363
364 method = myMethod;
365
366 break;
367 }
368 }
369
370 if (!found) {
371 Set superClazzes = getSuperElements(myClass);
372 for (Iterator iter = superClazzes.iterator(); iter.hasNext();) {
373 Class clazz = (Class) iter.next();
374 method = findMethodByParams(clazz.getName(), methodName,
375 args);
376 if (method != null) {
377 found = true;
378 break;
379 }
380 }
381 }
382 } catch (Exception e) {
383 throw new ClassAnalyserException(
384 "Could not find constructor of class " + className, e);
385 }
386
387 return method;
388 }
389
390
391
392
393
394
395
396
397
398 public static Method findMethodByName(String qualifiedClassName, String methodName) {
399 try {
400 Class c = Class.forName(qualifiedClassName);
401 Method[] m = c.getMethods();
402 Method firstMethod = null;
403 log.debug("===Class " + qualifiedClassName + " methods:");
404
405 for (int i = 0; i < m.length; i++) {
406 if (m[i].getName().endsWith(methodName)){
407 firstMethod = m[i];
408 break;
409 }
410 }
411 return firstMethod;
412 } catch (ClassNotFoundException ex) {
413 log.error("No such class: " + qualifiedClassName, ex);
414 throw new ClassAnalyserException("No class found of type "
415 + qualifiedClassName, ex);
416 }
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430 private static boolean filterByParam(Object method, Class[] args, int pos) {
431 boolean valid = false;
432 Class arg;
433 Class argOnPos;
434
435
436 if (pos >= args.length) {
437 valid = true;
438 } else {
439 arg = args[pos];
440
441 if (java.lang.reflect.Constructor.class.isInstance(method)) {
442 argOnPos = ((Constructor) method).getParameterTypes()[pos];
443 } else {
444 argOnPos = ((Method) method).getParameterTypes()[pos];
445 }
446
447
448
449
450
451 if (arg.equals(argOnPos)
452 || getSuperElements(arg).contains(argOnPos)) {
453 valid = filterByParam(method, args, pos + 1);
454
455
456 if (!valid) {
457 valid = filterByPrimitiveParam(method, args, pos + 1);
458 }
459 } else {
460 valid = filterByPrimitiveParam(method, args, pos);
461 }
462 }
463
464 return valid;
465 }
466
467 public static Set getSuperElements(Class clazz) {
468 Set clazzList = new HashSet();
469 Class[] interfaces = clazz.getInterfaces();
470 for (int count = 0; count < interfaces.length; count++) {
471 clazzList.addAll(getSuperElements(interfaces[count]));
472 clazzList.add(interfaces[count]);
473 }
474 Class superClazz = clazz.getSuperclass();
475 if (superClazz == null) {
476 return clazzList;
477 } else {
478 Set result = getSuperElements(superClazz);
479 result.add(superClazz);
480 result.addAll(clazzList);
481 return result;
482 }
483 }
484
485 private static boolean filterByPrimitiveParam(Object method, Class[] args,
486 int pos) {
487 boolean valid = false;
488 Class arg;
489 Class argOnPos;
490
491
492 if (pos >= args.length) {
493 valid = true;
494 } else {
495 arg = args[pos];
496
497 if (java.lang.reflect.Constructor.class.isInstance(method)) {
498 argOnPos = ((Constructor) method).getParameterTypes()[pos];
499 } else {
500 argOnPos = ((Method) method).getParameterTypes()[pos];
501 }
502
503
504 if (hasPrimitive(arg) && argOnPos.equals(getPrimitiveClass(arg))) {
505 valid = filterByParam(method, args, pos + 1);
506 }
507 }
508
509 return valid;
510 }
511
512
513
514
515
516
517
518
519 public static Class getPrimitiveClass(Class checkClass) {
520 Class primitive = null;
521 boolean arrayFound = false;
522 Class verifyClazz = checkClass;
523 if (hasPrimitive(checkClass)) {
524
525 String name = checkClass.getName();
526 if (name.startsWith("[L")) {
527 arrayFound = true;
528 try {
529 verifyClazz = Class.forName(name.substring(2,
530 name.length() - 1));
531 } catch (ClassNotFoundException ex) {
532 throw new ClassAnalyserException(
533 "Could not construct base class from array");
534 }
535 }
536 if (verifyClazz.equals(java.lang.Integer.class)) {
537 if (arrayFound) {
538 primitive = getPrimitiveArrayClass("[I");
539 } else {
540 primitive = Integer.TYPE;
541 }
542 } else if (verifyClazz.equals(java.lang.Long.class)) {
543 if (arrayFound) {
544 primitive = getPrimitiveArrayClass("[J");
545 } else {
546 primitive = Long.TYPE;
547 }
548 } else if (verifyClazz.equals(java.lang.Short.class)) {
549 if (arrayFound) {
550 primitive = getPrimitiveArrayClass("[S");
551 } else {
552 primitive = Short.TYPE;
553 }
554 } else if (verifyClazz.equals(java.lang.Double.class)) {
555 if (arrayFound) {
556 primitive = getPrimitiveArrayClass("[D");
557 } else {
558 primitive = Double.TYPE;
559 }
560 } else if (verifyClazz.equals(java.lang.Float.class)) {
561 if (arrayFound) {
562 primitive = getPrimitiveArrayClass("[F");
563 } else {
564 primitive = Float.TYPE;
565 }
566 } else if (verifyClazz.equals(Character.class)) {
567 if (arrayFound) {
568 primitive = getPrimitiveArrayClass("[C");
569 } else {
570 primitive = Character.TYPE;
571 }
572 } else if (verifyClazz.equals(Byte.class)) {
573 if (arrayFound) {
574 primitive = getPrimitiveArrayClass("[B");
575 } else {
576 primitive = Byte.TYPE;
577 }
578 } else if (verifyClazz.equals(Boolean.class)) {
579 if (arrayFound) {
580 primitive = getPrimitiveArrayClass("[Z");
581 } else {
582 primitive = Boolean.TYPE;
583 }
584 }
585 }
586
587 return primitive;
588 }
589
590
591
592
593
594
595
596
597 public static Object createPrimitiveArray(Object value) {
598 int valueLength = Array.getLength(value);
599 Object valueArray;
600 valueArray = Array.newInstance(ClassAnalyser
601 .getPrimitiveArrayBaseType(value.getClass()), valueLength);
602 Object obj = null;
603 for (int count = 0; count < valueLength; count++) {
604 obj = Array.get(value, count);
605 if (obj != null) {
606 Array.set(valueArray, count, obj);
607 }
608 }
609 return valueArray;
610 }
611
612
613
614
615
616
617 static public Class getPrimitiveArrayBaseType(Class clazz) {
618 String clazzName = clazz.getName();
619 Class baseClazz = null;
620 if (clazzName != null && clazzName.startsWith("[L")) {
621 clazzName = clazzName.substring(2, clazzName.length() - 1);
622 try {
623 baseClazz = Class.forName(clazzName);
624 } catch (ClassNotFoundException ex) {
625 throw new ClassAnalyserException(
626 "Could not create base class of array");
627 }
628 }
629 Class primitiveClazz = getPrimitiveClass(baseClazz);
630 return primitiveClazz;
631 }
632
633
634
635
636
637 static private Class getPrimitiveArrayClass(String primitive) {
638 Class primitiveArrayClazz = null;
639 try {
640 primitiveArrayClazz = Class.forName(primitive);
641 } catch (ClassNotFoundException ex) {
642 throw new ClassAnalyserException("Could not create " + primitive
643 + " array");
644 }
645 return primitiveArrayClazz;
646 }
647
648
649
650
651
652
653
654
655 public static boolean hasPrimitive(Class checkClass) {
656 boolean check = false;
657 Class verifyClazz = checkClass;
658
659 String name = checkClass.getName();
660 if (name.startsWith("[L")) {
661 try {
662 verifyClazz = Class.forName(name
663 .substring(2, name.length() - 1));
664 } catch (ClassNotFoundException ex) {
665 throw new ClassAnalyserException(
666 "Could not construct base class from array");
667 }
668 }
669 if (verifyClazz.equals(java.lang.Integer.class)
670 || verifyClazz.equals(java.lang.Short.class)
671 || verifyClazz.equals(java.lang.Long.class)
672 || verifyClazz.equals(java.lang.Float.class)
673 || verifyClazz.equals(java.lang.Double.class)
674 || verifyClazz.equals(java.lang.Character.class)
675 || verifyClazz.equals(java.lang.Byte.class)
676 || verifyClazz.equals(java.lang.Boolean.class)) {
677 check = true;
678 }
679
680 return check;
681 }
682
683
684
685
686
687
688
689
690
691
692 private static Vector filterByNameAndParamCount(Object[] methods,
693 String methodName, int count) {
694 Vector selected = new Vector();
695
696 for (int i = 0; i < methods.length; i++) {
697 int paramCount;
698 String myName;
699
700 if (java.lang.reflect.Constructor.class.isInstance(methods[i])) {
701 Constructor myConstr = (Constructor) methods[i];
702 myName = CLASS_CONSTRUCTOR;
703 paramCount = myConstr.getParameterTypes().length;
704 } else {
705 Method myMethod = (Method) methods[i];
706 myName = myMethod.getName();
707 paramCount = myMethod.getParameterTypes().length;
708 }
709
710 if ((methodName.compareTo(myName) == 0) && (paramCount == count)) {
711 selected.add(methods[i]);
712 }
713 }
714
715 return selected;
716 }
717
718
719
720
721
722
723 public static String classPackage(Object obj) {
724 String packageName = "";
725 String pathSeparator = "/";
726 if (obj != null) {
727 if (obj.getClass().getPackage() != null) {
728 packageName = obj.getClass().getPackage().getName().replaceAll(
729 "\\.", pathSeparator);
730 }
731 }
732 return packageName;
733 }
734
735
736
737
738
739
740 public static String classPackage(Class<?> clazz) {
741 String packageName = "";
742 String pathSeparator = "/";
743 if (clazz != null) {
744 if (clazz.getPackage() != null) {
745 packageName = clazz.getPackage().getName().replaceAll(
746 "\\.", pathSeparator);
747 }
748 }
749 return packageName;
750 }
751
752
753 }