1 package cz.cuni.amis.utils;
2
3 import java.lang.ref.SoftReference;
4 import java.lang.reflect.Field;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Modifier;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14
15 import cz.cuni.amis.utils.collections.MyCollections;
16 import cz.cuni.amis.utils.maps.HashMapMap;
17
18 public class ClassUtils {
19
20
21
22
23 private static Map<Class, SoftReference<Set<Class>>> subclassesCache =
24 new HashMap<Class, SoftReference<Set<Class>>>();
25
26
27
28
29
30
31
32 @SuppressWarnings("unchecked")
33 private static void probeInterface(Class interf, Set<Class> interfaces) {
34 interfaces.add(interf);
35 for (int i = 0; i < interf.getInterfaces().length; ++i) {
36 probeInterface(interf.getInterfaces()[i], interfaces);
37 }
38 }
39
40
41
42
43
44
45
46
47
48
49
50
51
52 @SuppressWarnings("unchecked")
53 public static synchronized Collection<Class> getSubclasses(Class cls) {
54
55
56 SoftReference<Set<Class>> reference = subclassesCache.get(cls);
57
58 Set<Class> classes = null;
59
60
61 if (reference != null) {
62
63 classes = reference.get();
64 }
65
66
67 if (classes != null) return classes;
68
69
70 classes = new LinkedHashSet<Class>();
71 classes.add(cls);
72 if (cls.getInterfaces() != null) {
73 for (int i = 0; i < cls.getInterfaces().length; ++i) {
74 probeInterface(cls.getInterfaces()[i], classes);
75 }
76 }
77 for (Class superClass = cls.getSuperclass(); superClass != null; superClass = superClass.getSuperclass()) {
78 classes.add(superClass);
79 if (superClass.getInterfaces() != null) {
80 for (int i = 0; i < superClass.getInterfaces().length; ++i) {
81 probeInterface(superClass.getInterfaces()[i], classes);
82 }
83 }
84 }
85 classes.remove(Object.class);
86
87
88 subclassesCache.put(cls, new SoftReference(classes));
89
90 return classes;
91 }
92
93 private static HashMapMap<Class, Boolean, SoftReference<List<Field>>> allFieldsCache = new HashMapMap<Class, Boolean, SoftReference<List<Field>>>();
94
95 public static List<Field> getAllFields(Class cls, boolean includeStatic) {
96 SoftReference<List<Field>> fieldsRef;
97 synchronized(allFieldsCache) {
98 fieldsRef = allFieldsCache.get(cls, includeStatic);
99 }
100 List<Field> fields = null;
101 if (fieldsRef != null) {
102 fields = fieldsRef.get();
103 if (fields != null) return fields;
104 }
105 fields = new ArrayList<Field>();
106 Class clz = cls;
107 if (includeStatic) {
108 while (!clz.equals(Object.class)) {
109 MyCollections.toList(clz.getDeclaredFields(), fields);
110 clz = clz.getSuperclass();
111 }
112 } else {
113 ObjectFilter<Field> filterStatic = new ObjectFilter<Field>() {
114 @Override
115 public boolean accept(Field object) {
116 return !Modifier.isStatic(object.getModifiers());
117 }
118
119 };
120 while (!clz.equals(Object.class)) {
121 MyCollections.toList(clz.getDeclaredFields(), fields, filterStatic);
122 clz = clz.getSuperclass();
123 }
124 }
125 synchronized(allFieldsCache) {
126 allFieldsCache.put(cls, includeStatic, new SoftReference<List<Field>>(fields));
127 }
128 return fields;
129 }
130
131 public static String getMethodSignature(Method method) {
132 StringBuffer sb = new StringBuffer();
133 sb.append(method.getDeclaringClass());
134 sb.append("#");
135 sb.append(method.getReturnType().getSimpleName());
136 sb.append(" ");
137 sb.append(method.getName());
138 sb.append("(");
139 int arg = 0;
140 for (Class type : method.getParameterTypes()) {
141 if (arg > 0) sb.append(", ");
142 sb.append(type.toString());
143 sb.append(" ");
144 sb.append("arg");
145 sb.append(arg++);
146 }
147 sb.append(")");
148 return sb.toString();
149 }
150
151 }