103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta/* 203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Copyright (C) 2013 The Android Open Source Project 303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * 403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License"); 503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * you may not use this file except in compliance with the License. 603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * You may obtain a copy of the License at 703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * 803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * http://www.apache.org/licenses/LICENSE-2.0 903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * 1003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software 1103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS, 1203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * See the License for the specific language governing permissions and 1403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * limitations under the License. 1503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 1603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 1703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptapackage com.android.tools.layoutlib.create; 1803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 1903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.AnnotationVisitor; 2003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.ClassVisitor; 2103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.FieldVisitor; 2203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.Label; 2303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.MethodVisitor; 2403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.Type; 2503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.signature.SignatureReader; 2603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.signature.SignatureVisitor; 2703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptaimport org.objectweb.asm.signature.SignatureWriter; 2803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 2903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta/** 3003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Provides the common code for RenameClassAdapter and RefactorClassAdapter. It 3103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * goes through the complete class and finds references to other classes. It 3203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * then calls {@link #renameInternalType(String)} to convert the className to 3303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * the new value, if need be. 3403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 3503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Guptapublic abstract class AbstractClassAdapter extends ClassVisitor { 3603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 3703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 3803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Returns the new FQCN for the class, if the reference to this class needs 3903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * to be updated. Else, it returns the same string. 4003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * @param name Old FQCN 4103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * @return New FQCN if it needs to be renamed, else the old FQCN 4203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 4303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta abstract String renameInternalType(String name); 4403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 4503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public AbstractClassAdapter(ClassVisitor cv) { 4623e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta super(Main.ASM_VERSION, cv); 4703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 4803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 4903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 5003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames a type descriptor, e.g. "Lcom.package.MyClass;" 5103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * If the type doesn't need to be renamed, returns the input string as-is. 5203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 5303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String renameTypeDesc(String desc) { 5403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (desc == null) { 5503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return null; 5603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 5703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 5803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return renameType(Type.getType(desc)); 5903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 6003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 6103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 6203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an 6303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * object element, e.g. "[Lcom.package.MyClass;" 6403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * If the type doesn't need to be renamed, returns the internal name of the input type. 6503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 6603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String renameType(Type type) { 6703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (type == null) { 6803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return null; 6903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 7003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 7103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (type.getSort() == Type.OBJECT) { 7203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String in = type.getInternalName(); 7303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return "L" + renameInternalType(in) + ";"; 7403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } else if (type.getSort() == Type.ARRAY) { 7503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta StringBuilder sb = new StringBuilder(); 7603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta for (int n = type.getDimensions(); n > 0; n--) { 7703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append('['); 7803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 7903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append(renameType(type.getElementType())); 8003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return sb.toString(); 8103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 8203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return type.getDescriptor(); 8303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 8403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 8503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 8603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an 8703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * object element, e.g. "[Lcom.package.MyClass;". 8803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * This is like renameType() except that it returns a Type object. 8903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * If the type doesn't need to be renamed, returns the input type object. 9003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 9103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta Type renameTypeAsType(Type type) { 9203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (type == null) { 9303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return null; 9403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 9503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 9603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (type.getSort() == Type.OBJECT) { 9703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String in = type.getInternalName(); 9803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String newIn = renameInternalType(in); 99d2a411840c58eaee05499bab0190e3f3656e2e84Deepanshu Gupta if (!newIn.equals(in)) { 10003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return Type.getType("L" + newIn + ";"); 10103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 10203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } else if (type.getSort() == Type.ARRAY) { 10303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta StringBuilder sb = new StringBuilder(); 10403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta for (int n = type.getDimensions(); n > 0; n--) { 10503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append('['); 10603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 10703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append(renameType(type.getElementType())); 10803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return Type.getType(sb.toString()); 10903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 11003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return type; 11103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 11203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 11303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 11403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames a method descriptor, i.e. applies renameType to all arguments and to the 11503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * return value. 11603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 11703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String renameMethodDesc(String desc) { 11803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (desc == null) { 11903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return null; 12003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 12103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 12203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta Type[] args = Type.getArgumentTypes(desc); 12303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 12403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta StringBuilder sb = new StringBuilder("("); 12503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta for (Type arg : args) { 12603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String name = renameType(arg); 12703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append(name); 12803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 12903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append(')'); 13003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 13103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta Type ret = Type.getReturnType(desc); 13203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String name = renameType(ret); 13303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sb.append(name); 13403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 13503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return sb.toString(); 13603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 13703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 13803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 13903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 14003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames the ClassSignature handled by ClassVisitor.visit 14103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * or the MethodTypeSignature handled by ClassVisitor.visitMethod. 14203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 14303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String renameTypeSignature(String sig) { 14403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (sig == null) { 14503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return null; 14603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 14703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureReader reader = new SignatureReader(sig); 14803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureWriter writer = new SignatureWriter(); 14903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta reader.accept(new RenameSignatureAdapter(writer)); 15003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta sig = writer.toString(); 15103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return sig; 15203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 15303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 15403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 15503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 15603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Renames the FieldTypeSignature handled by ClassVisitor.visitField 15703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * or MethodVisitor.visitLocalVariable. 15803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 15903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String renameFieldSignature(String sig) { 16003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return renameTypeSignature(sig); 16103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 16203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 16303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 16403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta //---------------------------------- 16503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // Methods from the ClassAdapter 16603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 16703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 16803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visit(int version, int access, String name, String signature, 16903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String superName, String[] interfaces) { 17003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta name = renameInternalType(name); 17103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta superName = renameInternalType(superName); 17203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta signature = renameTypeSignature(signature); 17303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (interfaces != null) { 17403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta for (int i = 0; i < interfaces.length; ++i) { 17503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta interfaces[i] = renameInternalType(interfaces[i]); 17603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 17703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 17803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 17903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visit(version, access, name, signature, superName, interfaces); 18003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 18103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 18203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 18303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitInnerClass(String name, String outerName, String innerName, int access) { 18403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta name = renameInternalType(name); 18503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta outerName = renameInternalType(outerName); 18603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitInnerClass(name, outerName, innerName, access); 18703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 18803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 18903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 19003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitOuterClass(String owner, String name, String desc) { 19103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitOuterClass(renameInternalType(owner), name, renameTypeDesc(desc)); 19203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 19303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 19403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 19503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public MethodVisitor visitMethod(int access, String name, String desc, 19603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String signature, String[] exceptions) { 19703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameMethodDesc(desc); 19803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta signature = renameTypeSignature(signature); 19903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions); 20003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameMethodAdapter(mw); 20103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 20203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 20303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 20403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 20503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 20603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return super.visitAnnotation(desc, visible); 20703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 20803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 20903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 21003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public FieldVisitor visitField(int access, String name, String desc, 21103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta String signature, Object value) { 21203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 21303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return super.visitField(access, name, desc, signature, value); 21403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 21503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 21603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 21703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta //---------------------------------- 21803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 21903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 22003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * A method visitor that renames all references from an old class name to a new class name. 22103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 22203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public class RenameMethodAdapter extends MethodVisitor { 22303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 22403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta /** 22503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * Creates a method visitor that renames all references from a given old name to a given new 22603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * name. The method visitor will also rename all inner classes. 22703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass). 22803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta */ 22903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public RenameMethodAdapter(MethodVisitor mv) { 23023e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta super(Main.ASM_VERSION, mv); 23103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 23203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 23303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 23403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 23503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 23603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 23703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return super.visitAnnotation(desc, visible); 23803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 23903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 24003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 24103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { 24203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 24303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 24403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return super.visitParameterAnnotation(parameter, desc, visible); 24503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 24603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 24703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 24803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitTypeInsn(int opcode, String type) { 24903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // The type sometimes turns out to be a type descriptor. We try to detect it and fix. 25003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (type.indexOf(';') > 0) { 25103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta type = renameTypeDesc(type); 25203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } else { 25303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta type = renameInternalType(type); 25403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 25503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitTypeInsn(opcode, type); 25603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 25703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 25803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 25903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitFieldInsn(int opcode, String owner, String name, String desc) { 26003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta owner = renameInternalType(owner); 26103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 26203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 26303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitFieldInsn(opcode, owner, name, desc); 26403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 26503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 26603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 26723e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta public void visitMethodInsn(int opcode, String owner, String name, String desc, 26823e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta boolean itf) { 26903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // The owner sometimes turns out to be a type descriptor. We try to detect it and fix. 27003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (owner.indexOf(';') > 0) { 27103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta owner = renameTypeDesc(owner); 27203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } else { 27303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta owner = renameInternalType(owner); 27403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 27503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameMethodDesc(desc); 27603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 27723e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta super.visitMethodInsn(opcode, owner, name, desc, itf); 27803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 27903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 28003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 28103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitLdcInsn(Object cst) { 28203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // If cst is a Type, this means the code is trying to pull the .class constant 28303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // for this class, so it needs to be renamed too. 28403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (cst instanceof Type) { 28503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta cst = renameTypeAsType((Type) cst); 28603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 28703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitLdcInsn(cst); 28803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 28903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 29003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 29103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitMultiANewArrayInsn(String desc, int dims) { 29203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 29303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 29403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitMultiANewArrayInsn(desc, dims); 29503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 29603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 29703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 29803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 29903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta type = renameInternalType(type); 30003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 30103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitTryCatchBlock(start, end, handler, type); 30203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 30303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 30403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 30503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitLocalVariable(String name, String desc, String signature, 30603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta Label start, Label end, int index) { 30703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta desc = renameTypeDesc(desc); 30803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta signature = renameFieldSignature(signature); 30903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 31003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta super.visitLocalVariable(name, desc, signature, start, end, index); 31103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 31203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 31303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 31403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 31503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta //---------------------------------- 31603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 31703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public class RenameSignatureAdapter extends SignatureVisitor { 31803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 31903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta private final SignatureVisitor mSv; 32003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 32103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public RenameSignatureAdapter(SignatureVisitor sv) { 32223e47f5621271db9b84f53f15a3e3d81d8b8b48dDeepanshu Gupta super(Main.ASM_VERSION); 32303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv = sv; 32403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 32503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 32603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 32703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitClassType(String name) { 32803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta name = renameInternalType(name); 32903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitClassType(name); 33003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 33103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 33203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 33303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitInnerClassType(String name) { 33403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta name = renameInternalType(name); 33503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitInnerClassType(name); 33603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 33703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 33803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 33903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitArrayType() { 34003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitArrayType(); 34103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 34203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 34303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 34403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 34503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitBaseType(char descriptor) { 34603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitBaseType(descriptor); 34703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 34803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 34903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 35003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitClassBound() { 35103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitClassBound(); 35203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 35303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 35403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 35503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 35603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitEnd() { 35703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitEnd(); 35803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 35903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 36003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 36103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitExceptionType() { 36203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitExceptionType(); 36303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 36403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 36503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 36603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 36703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitFormalTypeParameter(String name) { 36803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitFormalTypeParameter(name); 36903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 37003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 37103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 37203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitInterface() { 37303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitInterface(); 37403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 37503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 37603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 37703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 37803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitInterfaceBound() { 37903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitInterfaceBound(); 38003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 38103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 38203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 38303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 38403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitParameterType() { 38503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitParameterType(); 38603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 38703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 38803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 38903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 39003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitReturnType() { 39103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitReturnType(); 39203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 39303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 39403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 39503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 39603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitSuperclass() { 39703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitSuperclass(); 39803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 39903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 40003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 40103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 40203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitTypeArgument() { 40303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitTypeArgument(); 40403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 40503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 40603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 40703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public SignatureVisitor visitTypeArgument(char wildcard) { 40803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta SignatureVisitor sv = mSv.visitTypeArgument(wildcard); 40903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta return new RenameSignatureAdapter(sv); 41003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 41103a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 41203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta @Override 41303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta public void visitTypeVariable(String name) { 41403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mSv.visitTypeVariable(name); 41503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 41603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta 41703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 41803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta} 419