1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.callbackparams.internal;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Modifier;
21 import java.util.ArrayList;
22 import java.util.List;
23 import org.apache.bcel.generic.Type;
24 import org.callbackparams.internal.template.TestrunCallbacks;
25 import org.callbackparams.support.ClassBytecodeBuilder;
26
27 class TestrunCallbacksConstructors {
28
29 private final Class topClassInRebytedPackage;
30 private final List constructorParamTypes;
31
32 TestrunCallbacksConstructors(Class topClassInRebytedPackage) {
33 this.topClassInRebytedPackage = topClassInRebytedPackage;
34 this.constructorParamTypes = initConstructorParamTypes();
35 }
36
37 private List initConstructorParamTypes() {
38 Class superClass = topClassInRebytedPackage.getSuperclass();
39 final Constructor[] superClassConstructors =
40 superClass.getDeclaredConstructors();
41 List constructorParamTypes0 =
42 new ArrayList(superClassConstructors.length);
43 for (int i = 0 ; i < superClassConstructors.length ; ++i) {
44 final Constructor c = superClassConstructors[i];
45 if (false == isAccessible(c)) {
46 continue;
47 }
48 final Class[] paramTypes = c.getParameterTypes();
49 if (areParamterTypesAccessible(paramTypes)) {
50 constructorParamTypes0.add(Type.getTypes(paramTypes));
51 }
52 }
53 return constructorParamTypes0;
54 }
55
56 private boolean isAccessible(Constructor c) {
57 int modifier = c.getModifiers();
58 return Modifier.isPublic(modifier) || Modifier.isProtected(modifier);
59 }
60
61 private boolean areParamterTypesAccessible(final Class[] paramTypes) {
62 for (int i = 0 ; i < paramTypes.length ; ++i) {
63 if (false == isParameterTypeAccessible(paramTypes[i])) {
64 return false;
65 }
66 }
67 return true;
68 }
69
70 private boolean isParameterTypeAccessible(Class param) {
71 if (param.isPrimitive()) {
72 return true;
73 } else if (param.isArray()) {
74 return isParameterTypeAccessible(param.getComponentType());
75 } else {
76 return isClassAccessible(param);
77 }
78 }
79
80 private boolean isClassAccessible(Class classOrInterf) {
81 final int modifiers = classOrInterf.getModifiers();
82 if (Modifier.isProtected(modifiers)) {
83 return classOrInterf.isAssignableFrom(topClassInRebytedPackage)
84 || classOrInterf.getDeclaringClass()
85 .isAssignableFrom(topClassInRebytedPackage);
86 } else if (false == Modifier.isPublic(modifiers)) {
87 return false;
88 } else if (classOrInterf.isAssignableFrom(topClassInRebytedPackage)) {
89 return true;
90 } else {
91 Class enclosingClass = classOrInterf.getDeclaringClass();
92 return null == enclosingClass || isClassAccessible(enclosingClass);
93 }
94 }
95
96 boolean needsConstructorModifications(String className) {
97 return topClassInRebytedPackage.getName().equals(className)
98 || TestrunCallbacks.class.getName().equals(className);
99 }
100
101 void modifyConstructors(String className, ClassBytecodeBuilder cbb) {
102 if (topClassInRebytedPackage.getName().equals(className)) {
103 cbb.setNewSuperClass(TestrunCallbacks.class.getName());
104
105 } else if (TestrunCallbacks.class.getName().equals(className)) {
106 cbb.setupTransparentConstructors(constructorParamTypes,
107 topClassInRebytedPackage.getSuperclass().getName());
108
109 } else {
110
111 }
112 }
113 }