DelegateClassAdapter.java revision bc101806249eb883f89c4a770a8c27f9ac315837
1/* 2 * Copyright (C) 2010 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 17package com.android.tools.layoutlib.create; 18 19import org.objectweb.asm.ClassAdapter; 20import org.objectweb.asm.ClassVisitor; 21import org.objectweb.asm.MethodVisitor; 22import org.objectweb.asm.Opcodes; 23 24import java.util.Set; 25 26/** 27 * A {@link DelegateClassAdapter} can transform some methods from a class into 28 * delegates that defer the call to an associated delegate class. 29 * <p/> 30 * This is used to override specific methods and or all native methods in classes. 31 */ 32public class DelegateClassAdapter extends ClassAdapter { 33 34 public final static String ALL_NATIVES = "<<all_natives>>"; 35 36 private final String mClassName; 37 private final Set<String> mDelegateMethods; 38 private final Log mLog; 39 40 /** 41 * Creates a new {@link DelegateClassAdapter} that can transform some methods 42 * from a class into delegates that defer the call to an associated delegate class. 43 * <p/> 44 * This is used to override specific methods and or all native methods in classes. 45 * 46 * @param log The logger object. Must not be null. 47 * @param cv the class visitor to which this adapter must delegate calls. 48 * @param className The internal class name of the class to visit, 49 * e.g. <code>com/android/SomeClass$InnerClass</code>. 50 * @param delegateMethods The set of method names to modify and/or the 51 * special constant {@link #ALL_NATIVES} to convert all native methods. 52 */ 53 public DelegateClassAdapter(Log log, 54 ClassVisitor cv, 55 String className, 56 Set<String> delegateMethods) { 57 super(cv); 58 mLog = log; 59 mClassName = className; 60 mDelegateMethods = delegateMethods; 61 } 62 63 //---------------------------------- 64 // Methods from the ClassAdapter 65 66 @Override 67 public MethodVisitor visitMethod(int access, String name, String desc, 68 String signature, String[] exceptions) { 69 70 boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; 71 boolean isNative = (access & Opcodes.ACC_NATIVE) != 0; 72 73 boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) || 74 mDelegateMethods.contains(name); 75 76 if (useDelegate) { 77 // remove native 78 access = access & ~Opcodes.ACC_NATIVE; 79 } 80 81 MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions); 82 if (useDelegate) { 83 DelegateMethodAdapter a = new DelegateMethodAdapter(mLog, mw, mClassName, 84 name, desc, isStatic); 85 if (isNative) { 86 // A native has no code to visit, so we need to generate it directly. 87 a.generateCode(); 88 } else { 89 return a; 90 } 91 } 92 return mw; 93 } 94} 95