1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.ep.db4o.javassist;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Modifier;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import javassist.ClassPool;
27 import javassist.LoaderClassPath;
28 import net.ep.db4o.activator.TransparentActivation;
29
30 import com.db4o.internal.Platform4;
31 import com.db4o.reflect.ReflectArray;
32 import com.db4o.reflect.ReflectClass;
33 import com.db4o.reflect.Reflector;
34 import com.db4o.reflect.ReflectorConfiguration;
35 import com.db4o.reflect.jdk.ClassLoaderJdkLoader;
36 import com.db4o.reflect.jdk.JdkClass;
37 import com.db4o.reflect.jdk.JdkLoader;
38 import com.db4o.reflect.jdk.JdkReflector;
39 import com.db4o.ta.Activatable;
40
41 @SuppressWarnings("unchecked")
42 public class JVSTReflector implements Reflector {
43
44 private static final boolean debug = false;
45
46
47 private static final Map<Class, List<ClassData>> _classCache = new HashMap<Class, List<ClassData>>();
48
49 public static class ClassData {
50 ReflectClass _reflectClass;
51 boolean ignoreNullActivator;
52 boolean threadLocal;
53 @Override
54 public String toString() {
55 return _reflectClass + " ignoreNullActivator:" + ignoreNullActivator + " threadLocal:" + threadLocal;
56 }
57 }
58
59 public static final <T> Class<? super T> getRealClass(Class<? super T> clazz) {
60 if (isEnhanced(clazz)) {
61 clazz = clazz.getSuperclass();
62 }
63 return clazz;
64 }
65
66 public static final boolean hasPublicConstructor(Class clazz) {
67 boolean hasPublic = true;
68 for (Constructor constr : clazz.getDeclaredConstructors()) {
69 if (Modifier.isPublic(constr.getModifiers()))
70 return true;
71 hasPublic = false;
72 }
73 return hasPublic;
74 }
75
76 public static final boolean isEnhanced(Class clazz) {
77 if (clazz.equals(TransparentActivation.class))
78 return false;
79 return TransparentActivation.class.isAssignableFrom(clazz);
80 }
81
82 public static final boolean shouldBeEnhanced(Class clazz) {
83 return canBeEnhanced(clazz)
84 && hasPublicConstructor(clazz)
85 && (clazz.getPackage().getName() == null || !clazz.getPackage()
86 .getName().startsWith("java")
87 && !clazz.getPackage().getName().startsWith("com.db4o"));
88 }
89
90 public static final boolean canBeEnhanced(Class clazz) {
91 return !Modifier.isFinal(clazz.getModifiers())
92 && !clazz.isInterface()
93 && !clazz.isAnnotation()
94 && !clazz.isPrimitive()
95 && !clazz.isArray()
96 && !clazz.isAnonymousClass()
97 && !Activatable.class.isAssignableFrom(clazz);
98 }
99
100 public static String explainWhyNotEnhanced(Class clazz) {
101 List<String> reasons = new ArrayList<String>();
102 StringBuilder sb = new StringBuilder();
103 if (Modifier.isFinal(clazz.getModifiers()))
104 reasons.add("modifiers are final");
105 if (clazz.isInterface())
106 reasons.add("class is an interface");
107 if (clazz.isAnnotation())
108 reasons.add("class is an annotation");
109 if (clazz.isPrimitive())
110 reasons.add("the class represents a primitive type");
111 if (clazz.isArray())
112 reasons.add("the class represents an array");
113 if (clazz.isAnonymousClass())
114 reasons.add("the class represents an anonymous class");
115 if (Activatable.class.isAssignableFrom(clazz))
116 reasons.add("the class already implements " + Activatable.class.getName());
117
118
119
120
121
122
123
124
125
126 boolean first = true;
127 for (String reason:reasons) {
128 if (!first)
129 sb.append("\n");
130 sb.append(reason);
131 first = false;
132 }
133 return sb.toString();
134 }
135
136
137
138
139
140
141
142
143 static Class[] toNative(ReflectClass[] claxx) {
144 Class[] clazz = null;
145 if (claxx != null) {
146 clazz = new Class[claxx.length];
147 for (int i = 0; i < claxx.length; i++) {
148 clazz[i] = JdkReflector.toNative(claxx[i]);
149 }
150 }
151 return clazz;
152 }
153
154 private ReflectArray _array;
155
156 private final JdkLoader _classLoader;
157
158 private ClassPool _classPool;
159
160 private ReflectorConfiguration _config;
161
162 private JdkReflector _jdkReflect;
163
164 private Reflector _parent;
165
166 private boolean _threadLocal;
167
168 private PersistOnMethodPolicy _persistPolicy;
169
170 private ActivateOnMethodPolicy _activationPolicy;
171
172 private boolean _ignoreNullActivator;
173
174
175
176
177
178
179
180 public JVSTReflector(ClassLoader classLoader) {
181 this(new ClassLoaderJdkLoader(classLoader));
182 }
183
184
185
186
187
188
189
190 public JVSTReflector(JdkLoader classLoader) {
191 _classLoader = classLoader;
192 _classPool = new ClassPool();
193 _classPool.appendClassPath(new LoaderClassPath(Thread.currentThread()
194 .getContextClassLoader()));
195 _jdkReflect = new JdkReflector(classLoader);
196
197 }
198
199 private JVSTReflector(JdkLoader classLoader, ReflectorConfiguration config){
200 _classLoader = classLoader;
201 _config = config;
202 }
203
204
205
206
207
208
209 public ReflectArray array() {
210 if (_array == null) {
211 _array = new JVSTArray(parent());
212 }
213 return _array;
214 }
215
216 public ReflectorConfiguration configuration() {
217 return _config;
218 }
219
220 public void configuration(ReflectorConfiguration config) {
221 _config = config;
222 _jdkReflect.configuration(config);
223 }
224
225 private ReflectClass findInCache(Class clazz) {
226 List<ClassData> clList = _classCache.get(clazz);
227 if (clList == null)
228 return null;
229 if (debug)
230 System.out.println(clazz.getName() + " - cache contains " + clList.size() + " items " + clList.toString());
231 for (ClassData clData:clList) {
232 if (clData.ignoreNullActivator == _ignoreNullActivator && clData.threadLocal == _threadLocal)
233 return clData._reflectClass;
234 }
235 return null;
236 }
237
238 protected ReflectClass createClass(Class clazz) {
239 ReflectClass res = findInCache(clazz);
240 if (res != null)
241 return res;
242 if (shouldBeEnhanced(clazz)) {
243 if (debug)
244 System.out.println("enhancing:" + clazz + " threadLocal:" + _threadLocal);
245 res = enhanceClass(clazz);
246 } else {
247 res = new JdkClass(parent(), _jdkReflect, getRealClass(clazz));
248 addToCache(clazz, res);
249 }
250 return res;
251 }
252
253 private void addToCache(Class clazz, ReflectClass res) {
254 ClassData clData = new ClassData();
255 clData._reflectClass = res;
256 clData.ignoreNullActivator = _ignoreNullActivator;
257 clData.threadLocal = _threadLocal;
258 List<ClassData> list = new ArrayList<ClassData>();
259 list.add(clData);
260 _classCache.put(clazz, list);
261 }
262
263 public JVSTClass enhanceClass(Class clazz) {
264 ReflectClass res = findInCache(clazz);
265 if (res != null && res instanceof JVSTClass)
266 return (JVSTClass) res;
267 JVSTClass jclazz = new JVSTClass(parent(), this, _classPool, clazz, _threadLocal, _ignoreNullActivator, _persistPolicy,_activationPolicy);
268 addToCache(clazz, jclazz);
269 return jclazz;
270 }
271
272
273
274
275
276
277
278
279 public Object deepClone(Object obj) {
280 JVSTReflector clone = new JVSTReflector(_classLoader, _config);
281 return clone;
282 }
283
284
285
286
287
288
289
290
291 public ReflectClass forClass(Class clazz) {
292 return createClass(clazz);
293 }
294
295
296
297
298
299
300
301
302 public ReflectClass forName(String className) {
303 Class clazz = _classLoader.loadClass(className);
304 if (clazz == null)
305 return null;
306 return createClass(clazz);
307 }
308
309
310
311
312
313
314
315
316 public ReflectClass forObject(Object a_object) {
317 if (a_object == null)
318 return null;
319 return parent().forClass(a_object.getClass());
320 }
321
322 public ActivateOnMethodPolicy getActivationPolicy() {
323 return _activationPolicy;
324 }
325
326 public PersistOnMethodPolicy getPersistPolicy() {
327 return _persistPolicy;
328 }
329
330
331
332
333 public boolean isCollection(ReflectClass candidate) {
334 return false;
335 }
336
337
338
339
340 public boolean methodCallsSupported() {
341 return true;
342 }
343
344 Object nullValue(ReflectClass clazz) {
345 return Platform4.nullValue(JdkReflector.toNative(clazz));
346 }
347
348 private Reflector parent() {
349 if(_parent == null){
350 return this;
351 }
352 return _parent;
353 }
354
355 public void setActivationPolicy(ActivateOnMethodPolicy activationPolicy) {
356 _activationPolicy = activationPolicy;
357 }
358
359
360
361
362
363
364
365 public void setParent(Reflector reflector) {
366 _parent = reflector;
367 }
368
369 public void setPersistPolicy(PersistOnMethodPolicy persistPolicy) {
370 _persistPolicy = persistPolicy;
371 }
372
373 public void setThreadLocal(boolean threadLocal) {
374 _threadLocal = threadLocal;
375 }
376
377 public void setIgnoreNullActivator(boolean ignore) {
378 _ignoreNullActivator = ignore;
379 }
380
381 }