| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.class2greylist; |
| |
| import org.apache.bcel.classfile.AnnotationEntry; |
| import org.apache.bcel.classfile.DescendingVisitor; |
| import org.apache.bcel.classfile.EmptyVisitor; |
| import org.apache.bcel.classfile.Field; |
| import org.apache.bcel.classfile.FieldOrMethod; |
| import org.apache.bcel.classfile.JavaClass; |
| import org.apache.bcel.classfile.Method; |
| |
| import java.util.Map; |
| |
| /** |
| * Visits a JavaClass instance and passes any annotated members to a {@link AnnotationHandler} |
| * according to the map provided. |
| */ |
| public class AnnotationVisitor extends EmptyVisitor { |
| |
| private final JavaClass mClass; |
| private final Status mStatus; |
| private final DescendingVisitor mDescendingVisitor; |
| private final Map<String, AnnotationHandler> mAnnotationHandlers; |
| |
| /** |
| * Creates a visitor for a class. |
| * |
| * @param clazz Class to visit |
| * @param status For reporting debug information |
| * @param handlers Map of {@link AnnotationHandler}. The keys should be annotation names, as |
| * class descriptors. |
| */ |
| public AnnotationVisitor(JavaClass clazz, Status status, |
| Map<String, AnnotationHandler> handlers) { |
| mClass = clazz; |
| mStatus = status; |
| mAnnotationHandlers = handlers; |
| mDescendingVisitor = new DescendingVisitor(clazz, this); |
| } |
| |
| public void visit() { |
| mStatus.debug("Visit class %s", mClass.getClassName()); |
| mDescendingVisitor.visit(); |
| } |
| |
| @Override |
| public void visitMethod(Method method) { |
| visitMember(method, "L%s;->%s%s"); |
| } |
| |
| @Override |
| public void visitField(Field field) { |
| visitMember(field, "L%s;->%s:%s"); |
| } |
| |
| private void visitMember(FieldOrMethod member, String signatureFormatString) { |
| mStatus.debug("Visit member %s : %s", member.getName(), member.getSignature()); |
| AnnotationContext context = new AnnotationContext(mStatus, member, |
| (JavaClass) mDescendingVisitor.predecessor(), signatureFormatString); |
| for (AnnotationEntry a : member.getAnnotationEntries()) { |
| if (mAnnotationHandlers.containsKey(a.getAnnotationType())) { |
| mStatus.debug("Member has annotation %s for which we have a handler", |
| a.getAnnotationType()); |
| mAnnotationHandlers.get(a.getAnnotationType()).handleAnnotation(a, context); |
| } else { |
| mStatus.debug("Member has annotation %s for which we do not have a handler", |
| a.getAnnotationType()); |
| } |
| } |
| } |
| } |