• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.annotationvisitor;
18 
19 import org.apache.bcel.classfile.AnnotationEntry;
20 import org.apache.bcel.classfile.DescendingVisitor;
21 import org.apache.bcel.classfile.EmptyVisitor;
22 import org.apache.bcel.classfile.Field;
23 import org.apache.bcel.classfile.FieldOrMethod;
24 import org.apache.bcel.classfile.JavaClass;
25 import org.apache.bcel.classfile.Method;
26 
27 import java.util.Map;
28 
29 /**
30  * Visits a JavaClass instance and passes any annotated members to a {@link AnnotationHandler}
31  * according to the map provided.
32  */
33 public class AnnotationVisitor extends EmptyVisitor {
34 
35     private final JavaClass mClass;
36     private final Status mStatus;
37     private final DescendingVisitor mDescendingVisitor;
38     private final Map<String, AnnotationHandler> mAnnotationHandlers;
39 
40     /**
41      * Creates a visitor for a class.
42      *
43      * @param clazz Class to visit
44      * @param status For reporting debug information
45      * @param handlers Map of {@link AnnotationHandler}. The keys should be annotation names, as
46      *                 class descriptors.
47      */
AnnotationVisitor(JavaClass clazz, Status status, Map<String, AnnotationHandler> handlers)48     public AnnotationVisitor(JavaClass clazz, Status status,
49             Map<String, AnnotationHandler> handlers) {
50         mClass = clazz;
51         mStatus = status;
52         mAnnotationHandlers = handlers;
53         mDescendingVisitor = new DescendingVisitor(clazz, this);
54     }
55 
visit()56     public void visit() {
57         mStatus.debug("Visit class %s", mClass.getClassName());
58         AnnotationContext context = new AnnotatedClassContext(mStatus, mClass, "L%s;");
59         AnnotationEntry[] annotationEntries = mClass.getAnnotationEntries();
60         handleAnnotations(context, annotationEntries);
61 
62         mDescendingVisitor.visit();
63     }
64 
65     @Override
visitMethod(Method method)66     public void visitMethod(Method method) {
67         visitMember(method, "L%s;->%s%s");
68     }
69 
70     @Override
visitField(Field field)71     public void visitField(Field field) {
72         visitMember(field, "L%s;->%s:%s");
73     }
74 
visitMember(FieldOrMethod member, String signatureFormatString)75     private void visitMember(FieldOrMethod member, String signatureFormatString) {
76         mStatus.debug("Visit member %s : %s", member.getName(), member.getSignature());
77         AnnotationContext context = new AnnotatedMemberContext(mStatus,
78             (JavaClass) mDescendingVisitor.predecessor(), member,
79             signatureFormatString);
80         AnnotationEntry[] annotationEntries = member.getAnnotationEntries();
81         handleAnnotations(context, annotationEntries);
82     }
83 
handleAnnotations(AnnotationContext context, AnnotationEntry[] annotationEntries)84     private void handleAnnotations(AnnotationContext context, AnnotationEntry[] annotationEntries) {
85         for (AnnotationEntry a : annotationEntries) {
86             if (mAnnotationHandlers.containsKey(a.getAnnotationType())) {
87                 mStatus.debug("Member has annotation %s for which we have a handler",
88                         a.getAnnotationType());
89                 mAnnotationHandlers.get(a.getAnnotationType()).handleAnnotation(a, context);
90             } else {
91                 mStatus.debug("Member has annotation %s for which we do not have a handler",
92                     a.getAnnotationType());
93             }
94         }
95     }
96 }
97