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