1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.bedstead.harrier.annotations
17 
18 import com.android.bedstead.harrier.AnnotationExecutor
19 
20 /**
21  * Annotation to apply to an annotation outside of Harrier to indicate it should be processed
22  * with a particular [AnnotationExecutor].
23  */
24 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
25 @Retention(AnnotationRetention.RUNTIME)
26 annotation class UsesAnnotationExecutor(
27 
28     /**
29      * The fully qualified name of the [AnnotationExecutor] to use when parsing this annotation.
30      *
31      * This works even for cases where the annotation needs to be defined in a separate target
32      * to the executor, for example where the annotation cannot be defined in an Android target.
33      */
34     val value: String
35 ) {
36     companion object {
37         const val PERMISSIONS = "com.android.bedstead.permissions.PermissionsAnnotationExecutor"
38         const val ROOT = "com.android.xts.root.RootAnnotationExecutor"
39         const val INTERACTIVE = "com.android.interactive.InteractiveAnnotationExecutor"
40         const val FLAGS = "com.android.bedstead.flags.FlagsAnnotationExecutor"
41         const val MULTI_USER = "com.android.bedstead.multiuser.MultiUserAnnotationExecutor"
42         const val ENTERPRISE = "com.android.bedstead.enterprise.EnterpriseAnnotationExecutor"
43         const val MAIN = "com.android.bedstead.harrier.MainAnnotationExecutor"
44     }
45 }
46 
47 /**
48  * Create class from the fully qualified name in [UsesAnnotationExecutor.value] parameter
49  */
getAnnotationExecutorClassnull50 fun UsesAnnotationExecutor.getAnnotationExecutorClass(): Class<out AnnotationExecutor?> {
51     if (value.isEmpty()) {
52         throw IllegalStateException("@UsesAnnotationExecutor value is empty")
53     } else {
54         try {
55             @Suppress("UNCHECKED_CAST")
56             return Class.forName(value) as Class<out AnnotationExecutor?>
57         } catch (ignored: ClassNotFoundException) {
58             throw IllegalStateException(
59                 "Could not find annotation executor " +
60                         value +
61                         ". Probably a dependency issue. If you are depending on a " +
62                         "-annotations target (e.g. bedstead-root-annotations) instead " +
63                         "depend on the non-annotations target (e.g. bedstead-root)"
64             )
65         }
66     }
67 }
68