12270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom/* 22270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * ProGuard -- shrinking, optimization, obfuscation, and preverification 32270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * of Java bytecode. 42270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 62270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 72270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * This program is free software; you can redistribute it and/or modify it 82270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * under the terms of the GNU General Public License as published by the Free 92270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Software Foundation; either version 2 of the License, or (at your option) 102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * any later version. 112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * This program is distributed in the hope that it will be useful, but WITHOUT 132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * more details. 162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * You should have received a copy of the GNU General Public License along 182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * with this program; if not, write to the Free Software Foundation, Inc., 192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrompackage proguard.classfile.editor; 222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.*; 242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.*; 252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.visitor.AttributeVisitor; 262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.constant.Utf8Constant; 272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.util.*; 282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.visitor.ClassVisitor; 292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport java.util.Arrays; 312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom/** 332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * This ClassVisitor removes specified interfaces from the classes and class 342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * signatures that it visits. 352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * 362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * @author Eric Lafortune 372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrompublic class InterfaceDeleter 392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromextends SimplifiedVisitor 402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimplements ClassVisitor, 412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom AttributeVisitor 422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom{ 432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static final boolean DEBUG = false; 442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private final boolean[] delete; 472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Creates a new InterfaceDeleter to remove the specified interfaces. 512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * @param delete an array that corresponds to the interfaces of a class 522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * and that specifies the ones to be removed. 532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public InterfaceDeleter(boolean[] delete) 552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom this.delete = delete; 572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Implementations for ClassVisitor. 612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitProgramClass(ProgramClass programClass) 632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] interfaces = programClass.u2interfaces; 652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int interfacesCount = programClass.u2interfacesCount; 662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (DEBUG) 682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("InterfaceDeleter: "+programClass.getName()+" ("+interfacesCount+" interfaces)"); 702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy the interfaces that aren't deleted. 732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newInterfacesCount = 0; 742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int index = 0; index < interfacesCount; index++) 752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (DEBUG) 772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("InterfaceDeleter: "+(delete[index]?"- ":"+ ")+programClass.getInterfaceName(index)); 792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!delete[index]) 822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom interfaces[newInterfacesCount++] = interfaces[index]; 842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the signature. 882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (newInterfacesCount < interfacesCount) 892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom programClass.u2interfacesCount = newInterfacesCount; 912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom programClass.attributesAccept(this); 932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Implementations for AttributeVisitor. 982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 1002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 1032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom Clazz[] referencedClasses = signatureAttribute.referencedClasses; 1052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (referencedClasses != null) 1062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Process the generic definitions, superclass, and implemented 1082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // interfaces. 1092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom InternalTypeEnumeration internalTypeEnumeration = 1102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new InternalTypeEnumeration(signatureAttribute.getSignature(clazz)); 1112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Recompose the signature types in a string buffer. 1132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom StringBuffer newSignatureBuffer = new StringBuffer(); 1142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Also update the array with referenced classes. 1162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int referencedClassIndex = 0; 1172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newReferencedClassIndex = 0; 1182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy the variable type declarations and the super class type. 1202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom while (internalTypeEnumeration.hasMoreTypes()) 1212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom String internalType = internalTypeEnumeration.nextType(); 1232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Append the type. 1252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newSignatureBuffer.append(internalType); 1262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy any referenced classes. 1282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int classCount = 1292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new DescriptorClassEnumeration(internalType).classCount(); 1302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int counter = 0; counter < classCount; counter++) 1322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClasses[newReferencedClassIndex++] = 1342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClasses[referencedClassIndex++]; 1352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (DEBUG) 1382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("InterfaceDeleter: type = " + internalType + " (" + classCount + " referenced classes)"); 1402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (ClassUtil.isInternalClassType(internalType)) 1432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom break; 1452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy the interface types. 1492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int index = 0; 1502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom while (internalTypeEnumeration.hasMoreTypes()) 1512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom String internalType = internalTypeEnumeration.nextType(); 1532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int classCount = 1552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new DescriptorClassEnumeration(internalType).classCount(); 1562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (DEBUG) 1582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("InterfaceDeleter: type " + (delete[index] ? "- " : "+ ") + internalType + " (" + classCount + " referenced classes)"); 1602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!delete[index++]) 1632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Append the type. 1652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newSignatureBuffer.append(internalType); 1662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy any referenced classes. 1682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int counter = 0; counter < classCount; counter++) 1692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClasses[newReferencedClassIndex++] = 1712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClasses[referencedClassIndex++]; 1722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom else 1752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 1762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClassIndex += classCount; 1772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the signature. 1812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString()); 1822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Clear the remaining referenced classes. 1842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom Arrays.fill(referencedClasses, 1852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newReferencedClassIndex, 1862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referencedClassIndex, 1872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom null); 1882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom} 191