1 /* 2 * Copyright (C) 2008 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.tools.layoutlib.create; 18 19 import org.objectweb.asm.ClassVisitor; 20 21 /** 22 * This class visitor renames a class from a given old name to a given new name. 23 * The class visitor will also rename all inner classes and references in the methods. 24 * <p/> 25 * 26 * For inner classes, this handles only the case where the outer class name changes. 27 * The inner class name should remain the same. 28 */ 29 public class RenameClassAdapter extends AbstractClassAdapter { 30 31 32 private final String mOldName; 33 private final String mNewName; 34 private String mOldBase; 35 private String mNewBase; 36 37 /** 38 * Creates a class visitor that renames a class from a given old name to a given new name. 39 * The class visitor will also rename all inner classes and references in the methods. 40 * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass). 41 */ 42 public RenameClassAdapter(ClassVisitor cv, String oldName, String newName) { 43 super(cv); 44 mOldBase = mOldName = oldName; 45 mNewBase = mNewName = newName; 46 47 int pos = mOldName.indexOf('$'); 48 if (pos > 0) { 49 mOldBase = mOldName.substring(0, pos); 50 } 51 pos = mNewName.indexOf('$'); 52 if (pos > 0) { 53 mNewBase = mNewName.substring(0, pos); 54 } 55 56 assert (mOldBase == null && mNewBase == null) || (mOldBase != null && mNewBase != null); 57 } 58 59 /** 60 * Renames an internal type name, e.g. "com.package.MyClass". 61 * If the type doesn't need to be renamed, returns the input string as-is. 62 * <p/> 63 * The internal type of some of the MethodVisitor turns out to be a type 64 descriptor sometimes so descriptors are renamed too. 65 */ 66 @Override 67 protected String renameInternalType(String type) { 68 if (type == null) { 69 return null; 70 } 71 72 if (type.equals(mOldName)) { 73 return mNewName; 74 } 75 76 if (!mOldBase.equals(mOldName) && type.equals(mOldBase)) { 77 return mNewBase; 78 } 79 80 int pos = type.indexOf('$'); 81 if (pos == mOldBase.length() && type.startsWith(mOldBase)) { 82 return mNewBase + type.substring(pos); 83 } 84 return type; 85 } 86 87 } 88