Home | History | Annotate | Download | only in mkstubs
      1 /*
      2  * Copyright (C) 2009 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.mkstubs;
     18 
     19 import com.android.mkstubs.Main.Logger;
     20 
     21 import org.objectweb.asm.AnnotationVisitor;
     22 import org.objectweb.asm.Attribute;
     23 import org.objectweb.asm.ClassVisitor;
     24 import org.objectweb.asm.FieldVisitor;
     25 import org.objectweb.asm.MethodVisitor;
     26 import org.objectweb.asm.Opcodes;
     27 
     28 /**
     29  * A class visitor that filters out all members (fields, methods and inner classes) that are
     30  * either private, default-access or rejected by the {@link Filter}.
     31  */
     32 class FilterClassAdapter extends ClassVisitor {
     33 
     34     private final Logger mLog;
     35     private final Filter mFilter;
     36     private String mClassName;
     37 
     38     public FilterClassAdapter(ClassVisitor writer, Filter filter, Logger log) {
     39         super(Opcodes.ASM4, writer);
     40         mFilter = filter;
     41         mLog = log;
     42     }
     43 
     44     @Override
     45     public void visit(int version, int access, String name, String signature,
     46             String superName, String[] interfaces) {
     47 
     48         mClassName = name;
     49         super.visit(version, access, name, signature, superName, interfaces);
     50     }
     51 
     52     @Override
     53     public void visitEnd() {
     54         super.visitEnd();
     55     }
     56 
     57     /**
     58      * Visits a field.
     59      *
     60      * {@inheritDoc}
     61      *
     62      * Examples:
     63      * name = mArg
     64      * desc = Ljava/Lang/String;
     65      * signature = null (not a template) or template type
     66      */
     67     @Override
     68     public FieldVisitor visitField(int access, String name, String desc,
     69             String signature, Object value) {
     70         // only accept public/protected fields
     71         if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
     72             return null;
     73         }
     74 
     75         // filter on field name
     76         String filterName = String.format("%s#%s", mClassName, name);
     77 
     78         if (!mFilter.accept(filterName)) {
     79             mLog.debug("- Remove field " + filterName);
     80             return null;
     81         }
     82 
     83         // TODO we should produce an error if a filtered desc/signature is being used.
     84 
     85         return super.visitField(access, name, desc, signature, value);
     86     }
     87 
     88     /**
     89      * Visits a method.
     90      *
     91      * {@inheritDoc}
     92      *
     93      * Examples:
     94      * name = <init>
     95      * desc = ()V
     96      * signature = null (not a template) or template type
     97      */
     98     @Override
     99     public MethodVisitor visitMethod(int access, String name, String desc,
    100             String signature, String[] exceptions) {
    101 
    102         // only accept public/protected methods
    103         if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
    104             return null;
    105         }
    106 
    107         // filter on method name using the non-generic descriptor
    108         String filterName = String.format("%s#%s%s", mClassName, name, desc);
    109 
    110         if (!mFilter.accept(filterName)) {
    111             mLog.debug("- Remove method " + filterName);
    112             return null;
    113         }
    114 
    115         // filter on method name using the generic signature
    116         if (signature != null) {
    117             filterName = String.format("%s#%s%s", mClassName, name, signature);
    118 
    119             if (!mFilter.accept(filterName)) {
    120                 mLog.debug("- Remove method " + filterName);
    121                 return null;
    122             }
    123         }
    124 
    125         // TODO we should produce an error if a filtered desc/signature/exception is being used.
    126 
    127         return super.visitMethod(access, name, desc, signature, exceptions);
    128     }
    129 
    130     @Override
    131     public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    132 
    133         // TODO produce an error if a filtered annotation type is being used
    134         return super.visitAnnotation(desc, visible);
    135     }
    136 
    137     @Override
    138     public void visitAttribute(Attribute attr) {
    139         // pass
    140     }
    141 
    142     @Override
    143     public void visitInnerClass(String name, String outerName, String innerName, int access) {
    144 
    145         // only accept public/protected inner classes
    146         if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
    147             return;
    148         }
    149 
    150         // filter on name
    151         if (!mFilter.accept(name)) {
    152             return;
    153         }
    154 
    155         super.visitInnerClass(name, outerName, innerName, access);
    156     }
    157 
    158     @Override
    159     public void visitOuterClass(String owner, String name, String desc) {
    160         // pass
    161     }
    162 
    163     @Override
    164     public void visitSource(String source, String debug) {
    165         // pass
    166     }
    167 }
    168