2
2
3
3
import com .github .containersolutions .operator .api .Controller ;
4
4
import com .github .containersolutions .operator .api .ResourceController ;
5
+ import io .fabric8 .kubernetes .api .builder .Function ;
5
6
import io .fabric8 .kubernetes .client .CustomResource ;
6
7
import io .fabric8 .kubernetes .client .CustomResourceDoneable ;
7
8
import javassist .*;
8
- import org .apache .commons .lang3 .StringUtils ;
9
9
import org .slf4j .Logger ;
10
10
import org .slf4j .LoggerFactory ;
11
11
12
+ import java .util .HashMap ;
13
+ import java .util .Map ;
14
+
12
15
13
16
class ControllerUtils {
14
17
15
18
private final static Logger log = LoggerFactory .getLogger (Operator .class );
16
- private static ClassPool pool ;
17
- private static Class generatedCustomResourceDoneable ;
19
+
20
+ // this is just to support testing, this way we don't try to create class multiple times in memory with same name.
21
+ // note that other solution is to add a random string to doneable class name
22
+ private static Map <Class <? extends CustomResource >, Class <? extends CustomResourceDoneable <? extends CustomResource >>>
23
+ doneableClassCache = new HashMap <>();
18
24
19
25
static String getDefaultFinalizer (ResourceController controller ) {
20
26
return getAnnotation (controller ).finalizerName ();
@@ -29,71 +35,36 @@ static String getCrdName(ResourceController controller) {
29
35
}
30
36
31
37
32
- public static <R extends CustomResource > Class <? extends CustomResourceDoneable <R >> getCustomResourceDoneableClass (ResourceController <R > controller ) {
33
- return createCustomResourceDoneableClass (controller );
34
- }
38
+ public static <T extends CustomResource > Class <? extends CustomResourceDoneable <T >>
39
+ getCustomResourceDoneableClass (ResourceController <T > controller ) {
40
+ try {
41
+ Class <? extends CustomResource > customResourceClass = getAnnotation (controller ).customResourceClass ();
42
+ String className = customResourceClass .getPackage ().getName () + "." + customResourceClass .getSimpleName () + "CustomResourceDoneable" ;
35
43
36
- private static < R extends CustomResource > Class <? extends CustomResourceDoneable < R >> createCustomResourceDoneableClass ( ResourceController < R > controller ) {
37
- pool = ClassPool . getDefault ( );
38
- pool . appendClassPath ( new ClassClassPath ( ControllerUtils . class ));
44
+ if ( doneableClassCache . containsKey ( customResourceClass ) ) {
45
+ return ( Class <? extends CustomResourceDoneable < T >>) doneableClassCache . get ( customResourceClass );
46
+ }
39
47
40
- String controllerName = StringUtils . substringAfterLast ( controller . getClass (). toString (), "." );
41
- Class < R > customResourceClass = ( Class < R >) getAnnotation ( controller ). customResourceClass ( );
48
+ ClassPool pool = ClassPool . getDefault ( );
49
+ pool . appendClassPath ( new LoaderClassPath ( Thread . currentThread (). getContextClassLoader ()) );
42
50
43
- String className = getPackageName (customResourceClass .getName (), controllerName + "CustomResourceDoneable" );
44
- if (isClassInPool (className )) {
45
- return generatedCustomResourceDoneable ;
46
- }
47
- CtClass customDoneable = null ;
48
- try {
49
- CtClass superClass = pool .get ("io.fabric8.kubernetes.client.CustomResourceDoneable" );
50
- CtClass function = pool .get ("io.fabric8.kubernetes.api.builder.Function" );
51
+ CtClass superClass = pool .get (CustomResourceDoneable .class .getName ());
52
+ CtClass function = pool .get (Function .class .getName ());
51
53
CtClass customResource = pool .get (customResourceClass .getName ());
52
54
CtClass [] argTypes = {customResource , function };
53
- customDoneable = pool .makeClass (className , superClass );
55
+ CtClass customDoneable = pool .makeClass (className , superClass );
54
56
CtConstructor ctConstructor = CtNewConstructor .make (argTypes , null , "super($1, $2);" , customDoneable );
55
57
customDoneable .addConstructor (ctConstructor );
56
58
59
+ Class <? extends CustomResourceDoneable <T >> doneableClass = customDoneable .toClass ();
60
+ doneableClassCache .put (customResourceClass , doneableClass );
61
+ return doneableClass ;
57
62
} catch (CannotCompileException | NotFoundException e ) {
58
- log .error ("Error creating CustomResourceDoneable CtClass: {}" , e );
59
- }
60
- Class <? extends CustomResourceDoneable <R >> doneableClass = getClassFromCtClass (customDoneable );
61
- generatedCustomResourceDoneable = doneableClass ;
62
- return doneableClass ;
63
- }
64
-
65
- private static boolean isClassInPool (String className ) {
66
- try {
67
- pool .get (className );
68
- return true ;
69
- } catch (NotFoundException e ) {
70
- log .debug ("Class {} not in pool" , className );
71
- return false ;
63
+ throw new IllegalStateException (e );
72
64
}
73
65
}
74
66
75
67
private static Controller getAnnotation (ResourceController controller ) {
76
68
return controller .getClass ().getAnnotation (Controller .class );
77
69
}
78
-
79
- private static String getPackageName (String customResourceName , String newClassName ) {
80
- CtClass customResource = null ;
81
- try {
82
- customResource = pool .get (customResourceName );
83
- } catch (NotFoundException e ) {
84
- log .error ("Error getting class: {}" , e );
85
- }
86
- String packageName = customResource != null ? customResource .getPackageName () : "" ;
87
- return packageName + "." + newClassName ;
88
- }
89
-
90
- private static Class getClassFromCtClass (CtClass customCtClass ) {
91
- Class customClass = null ;
92
- try {
93
- customClass = customCtClass .toClass ();
94
- } catch (CannotCompileException e ) {
95
- log .error ("Error transforming CtClass to Class: {}" , e );
96
- }
97
- return customClass ;
98
- }
99
- }
70
+ }
0 commit comments