diff options
Diffstat (limited to 'src/proguard/classfile/editor/MemberAdder.java')
-rw-r--r-- | src/proguard/classfile/editor/MemberAdder.java | 147 |
1 files changed, 92 insertions, 55 deletions
diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java index 5f939bb..811acae 100644 --- a/src/proguard/classfile/editor/MemberAdder.java +++ b/src/proguard/classfile/editor/MemberAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -26,8 +26,9 @@ import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.MemberVisitor; /** - * This ConstantVisitor adds all class members that it visits to the given - * target class. + * This MemberVisitor copies all class members that it visits to the given + * target class. Their visitor info is set to the class members from which they + * were copied. * * @author Eric Lafortune */ @@ -45,8 +46,9 @@ implements MemberVisitor private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; - private final ProgramClass targetClass; -// private final boolean addFields; + private final ProgramClass targetClass; +// private final boolean addFields; + private final MemberVisitor extraMemberVisitor; private final ConstantAdder constantAdder; private final ClassEditor classEditor; @@ -59,13 +61,30 @@ implements MemberVisitor * @param targetClass the class to which all visited class members will be * added. */ + public MemberAdder(ProgramClass targetClass) + { + this(targetClass, null); + } + + + /** + * Creates a new MemberAdder that will copy methods into the given target + * class. + * @param targetClass the class to which all visited class members + * will be added. + * @param extraMemberVisitor an optional member visitor that visits each + * new member right after it has been added. This + * allows changing the visitor info, for instance. + */ // * @param addFields specifies whether fields should be added, or fused // * with the present fields. - public MemberAdder(ProgramClass targetClass)//), -// boolean addFields) + public MemberAdder(ProgramClass targetClass, +// boolean addFields, + MemberVisitor extraMemberVisitor) { - this.targetClass = targetClass; -// this.addFields = addFields; + this.targetClass = targetClass; +// this.addFields = addFields; + this.extraMemberVisitor = extraMemberVisitor; constantAdder = new ConstantAdder(targetClass); classEditor = new ClassEditor(targetClass); @@ -77,51 +96,54 @@ implements MemberVisitor public void visitProgramField(ProgramClass programClass, ProgramField programField) { - String name = programField.getName(programClass); - String descriptor = programField.getDescriptor(programClass); + //String name = programField.getName(programClass); + //String descriptor = programField.getDescriptor(programClass); int accessFlags = programField.getAccessFlags(); - // Does the target class already have such a field? - ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor); - if (targetField != null) - { - // Is the field private or static? - int targetAccessFlags = targetField.getAccessFlags(); - if ((targetAccessFlags & - (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC)) != 0) - { - if (DEBUG) - { - System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]"); - } - - // Rename the private or static field. - targetField.u2nameIndex = - constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName())); - } -// else -// { -// // Keep the non-private and non-static field, but update its -// // contents, in order to keep any references to it valid. -// if (DEBUG) -// { -// System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]"); -// } -// -// // Combine the access flags. -// targetField.u2accessFlags = accessFlags | targetAccessFlags; -// -// // Add and replace any attributes. -// programField.attributesAccept(programClass, -// new AttributeAdder(targetClass, -// targetField, -// true)); -// -// // Don't add a new field. -// return; -// } - } + // TODO: Handle field with the same name and descriptor in the target class. + // We currently avoid this case, since renaming the identical field + // still causes confused field references. + //// Does the target class already have such a field? + //ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor); + //if (targetField != null) + //{ + // // Is the field private or static? + // int targetAccessFlags = targetField.getAccessFlags(); + // if ((targetAccessFlags & + // (ClassConstants.INTERNAL_ACC_PRIVATE | + // ClassConstants.INTERNAL_ACC_STATIC)) != 0) + // { + // if (DEBUG) + // { + // System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]"); + // } + // + // // Rename the private or static field. + // targetField.u2nameIndex = + // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName())); + // } + // else + // { + // // Keep the non-private and non-static field, but update its + // // contents, in order to keep any references to it valid. + // if (DEBUG) + // { + // System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]"); + // } + // + // // Combine the access flags. + // targetField.u2accessFlags = accessFlags | targetAccessFlags; + // + // // Add and replace any attributes. + // programField.attributesAccept(programClass, + // new AttributeAdder(targetClass, + // targetField, + // true)); + // + // // Don't add a new field. + // return; + // } + //} if (DEBUG) { @@ -150,6 +172,12 @@ implements MemberVisitor // Add the completed field. classEditor.addField(newProgramField); + + // Visit the newly added field, if necessary. + if (extraMemberVisitor != null) + { + extraMemberVisitor.visitProgramField(targetClass, newProgramField); + } } @@ -206,9 +234,12 @@ implements MemberVisitor System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]"); } - // Rename the private (non-abstract) or static method. - targetMethod.u2nameIndex = - constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor)); + // TODO: Handle non-abstract method with the same name and descriptor in the target class. + // We currently avoid this case, since renaming the identical method + // still causes confused method references. + //// Rename the private (non-abstract) or static method. + //targetMethod.u2nameIndex = + // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor)); } if (DEBUG) @@ -240,6 +271,12 @@ implements MemberVisitor // Add the completed method. classEditor.addMethod(newProgramMethod); + + // Visit the newly added method, if necessary. + if (extraMemberVisitor != null) + { + extraMemberVisitor.visitProgramMethod(targetClass, newProgramMethod); + } } |