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