| /* |
| * ProGuard -- shrinking, optimization, obfuscation, and preverification |
| * of Java bytecode. |
| * |
| * Copyright (c) 2002-2009 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 |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| package proguard.classfile.editor; |
| |
| import proguard.classfile.*; |
| import proguard.classfile.attribute.*; |
| import proguard.classfile.attribute.annotation.*; |
| import proguard.classfile.attribute.preverification.*; |
| import proguard.classfile.attribute.visitor.AttributeVisitor; |
| import proguard.classfile.util.SimplifiedVisitor; |
| |
| /** |
| * This AttributeVisitor adds all attributes that it visits to the given |
| * target class, class member, or attribute. |
| * |
| * @author Eric Lafortune |
| */ |
| public class AttributeAdder |
| extends SimplifiedVisitor |
| implements AttributeVisitor |
| { |
| private static final byte[] EMPTY_BYTES = new byte[0]; |
| private static final int[] EMPTY_INTS = new int[0]; |
| private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; |
| private static final ExceptionInfo[] EMPTY_EXCEPTIONS = new ExceptionInfo[0]; |
| |
| |
| private final ProgramClass targetClass; |
| private final ProgramMember targetMember; |
| private final CodeAttribute targetCodeAttribute; |
| private final boolean replaceAttributes; |
| |
| private final ConstantAdder constantAdder; |
| private final AttributesEditor attributesEditor; |
| |
| |
| /** |
| * Creates a new AttributeAdder that will copy attributes into the given |
| * target class. |
| */ |
| public AttributeAdder(ProgramClass targetClass, |
| boolean replaceAttributes) |
| { |
| this(targetClass, null, null, replaceAttributes); |
| } |
| |
| |
| /** |
| * Creates a new AttributeAdder that will copy attributes into the given |
| * target class member. |
| */ |
| public AttributeAdder(ProgramClass targetClass, |
| ProgramMember targetMember, |
| boolean replaceAttributes) |
| { |
| this(targetClass, targetMember, null, replaceAttributes); |
| } |
| |
| |
| /** |
| * Creates a new AttributeAdder that will copy attributes into the given |
| * target attribute. |
| */ |
| public AttributeAdder(ProgramClass targetClass, |
| ProgramMember targetMember, |
| CodeAttribute targetCodeAttribute, |
| boolean replaceAttributes) |
| { |
| this.targetClass = targetClass; |
| this.targetMember = targetMember; |
| this.targetCodeAttribute = targetCodeAttribute; |
| this.replaceAttributes = replaceAttributes; |
| |
| constantAdder = new ConstantAdder(targetClass); |
| attributesEditor = new AttributesEditor(targetClass, |
| targetMember, |
| targetCodeAttribute, |
| replaceAttributes); |
| } |
| |
| |
| // Implementations for AttributeVisitor. |
| |
| public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) |
| { |
| // Create a copy of the attribute. |
| UnknownAttribute newUnknownAttribute = |
| new UnknownAttribute(constantAdder.addConstant(clazz, unknownAttribute.u2attributeNameIndex), |
| unknownAttribute.u4attributeLength, |
| unknownAttribute.info); |
| |
| // Add it to the target class. |
| attributesEditor.addAttribute(newUnknownAttribute); |
| } |
| |
| |
| public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) |
| { |
| // Create a copy of the attribute. |
| SourceFileAttribute newSourceFileAttribute = |
| new SourceFileAttribute(constantAdder.addConstant(clazz, sourceFileAttribute.u2attributeNameIndex), |
| constantAdder.addConstant(clazz, sourceFileAttribute.u2sourceFileIndex)); |
| |
| // Add it to the target class. |
| attributesEditor.addAttribute(newSourceFileAttribute); |
| } |
| |
| |
| public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) |
| { |
| // Create a copy of the attribute. |
| SourceDirAttribute newSourceDirAttribute = |
| new SourceDirAttribute(constantAdder.addConstant(clazz, sourceDirAttribute.u2attributeNameIndex), |
| constantAdder.addConstant(clazz, sourceDirAttribute.u2sourceDirIndex)); |
| |
| // Add it to the target class. |
| attributesEditor.addAttribute(newSourceDirAttribute); |
| } |
| |
| |
| public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) |
| { |
| // TODO: Implement method. |
| // Note that the attribute may already be present. |
| // // Create a copy of the attribute. |
| // InnerClassesAttribute newInnerClassesAttribute = |
| // new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex), |
| // 0, |
| // null); |
| // |
| // // Add it to the target class. |
| // attributesEditor.addClassAttribute(newInnerClassesAttribute); |
| } |
| |
| |
| public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) |
| { |
| // Create a copy of the attribute. |
| EnclosingMethodAttribute newEnclosingMethodAttribute = |
| new EnclosingMethodAttribute(constantAdder.addConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex), |
| constantAdder.addConstant(clazz, enclosingMethodAttribute.u2classIndex), |
| enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? 0 : |
| constantAdder.addConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex)); |
| |
| newEnclosingMethodAttribute.referencedClass = enclosingMethodAttribute.referencedClass; |
| newEnclosingMethodAttribute.referencedMethod = enclosingMethodAttribute.referencedMethod; |
| |
| // Add it to the target class. |
| attributesEditor.addAttribute(newEnclosingMethodAttribute); |
| } |
| |
| |
| public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) |
| { |
| // Create a copy of the attribute. |
| DeprecatedAttribute newDeprecatedAttribute = |
| new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newDeprecatedAttribute); |
| } |
| |
| |
| public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) |
| { |
| // Create a copy of the attribute. |
| SyntheticAttribute newSyntheticAttribute = |
| new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newSyntheticAttribute); |
| } |
| |
| |
| public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) |
| { |
| // Create a copy of the attribute. |
| SignatureAttribute newSignatureAttribute = |
| new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex), |
| constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex)); |
| |
| newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses; |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newSignatureAttribute); |
| } |
| |
| |
| public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) |
| { |
| // Create a copy of the attribute. |
| ConstantValueAttribute newConstantValueAttribute = |
| new ConstantValueAttribute(constantAdder.addConstant(clazz, constantValueAttribute.u2attributeNameIndex), |
| constantAdder.addConstant(clazz, constantValueAttribute.u2constantValueIndex)); |
| |
| // Add it to the target field. |
| attributesEditor.addAttribute(newConstantValueAttribute); |
| } |
| |
| |
| public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) |
| { |
| // Create a new exceptions attribute. |
| ExceptionsAttribute newExceptionsAttribute = |
| new ExceptionsAttribute(constantAdder.addConstant(clazz, exceptionsAttribute.u2attributeNameIndex), |
| 0, |
| exceptionsAttribute.u2exceptionIndexTableLength > 0 ? |
| new int[exceptionsAttribute.u2exceptionIndexTableLength] : |
| EMPTY_INTS); |
| |
| // Add the exceptions. |
| exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, |
| new ExceptionAdder(targetClass, |
| newExceptionsAttribute)); |
| |
| // Add it to the target method. |
| attributesEditor.addAttribute(newExceptionsAttribute); |
| } |
| |
| |
| public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) |
| { |
| // Create a new code attribute. |
| CodeAttribute newCodeAttribute = |
| new CodeAttribute(constantAdder.addConstant(clazz, codeAttribute.u2attributeNameIndex), |
| codeAttribute.u2maxStack, |
| codeAttribute.u2maxLocals, |
| 0, |
| EMPTY_BYTES, |
| 0, |
| codeAttribute.u2exceptionTableLength > 0 ? |
| new ExceptionInfo[codeAttribute.u2exceptionTableLength] : |
| EMPTY_EXCEPTIONS, |
| 0, |
| codeAttribute.u2attributesCount > 0 ? |
| new Attribute[codeAttribute.u2attributesCount] : |
| EMPTY_ATTRIBUTES); |
| |
| CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(); |
| |
| codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength); |
| |
| // Add the instructions. |
| codeAttribute.instructionsAccept(clazz, |
| method, |
| new InstructionAdder(targetClass, |
| codeAttributeComposer)); |
| |
| // Append a label just after the code. |
| codeAttributeComposer.appendLabel(codeAttribute.u4codeLength); |
| |
| // Add the exceptions. |
| codeAttribute.exceptionsAccept(clazz, |
| method, |
| new ExceptionInfoAdder(targetClass, |
| codeAttributeComposer)); |
| |
| codeAttributeComposer.endCodeFragment(); |
| |
| // Add the attributes. |
| codeAttribute.attributesAccept(clazz, |
| method, |
| new AttributeAdder(targetClass, |
| targetMember, |
| newCodeAttribute, |
| replaceAttributes)); |
| |
| // Apply these changes to the new code attribute. |
| codeAttributeComposer.visitCodeAttribute(targetClass, |
| (Method)targetMember, |
| newCodeAttribute); |
| |
| // Add the completed code attribute to the target method. |
| attributesEditor.addAttribute(newCodeAttribute); |
| } |
| |
| |
| public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) |
| { |
| // TODO: Implement method. |
| } |
| |
| |
| public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) |
| { |
| // TODO: Implement method. |
| } |
| |
| |
| public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) |
| { |
| // Create a new line number table attribute. |
| LineNumberTableAttribute newLineNumberTableAttribute = |
| new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex), |
| 0, |
| new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]); |
| |
| // Add the line numbers. |
| lineNumberTableAttribute.lineNumbersAccept(clazz, |
| method, |
| codeAttribute, |
| new LineNumberInfoAdder(newLineNumberTableAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newLineNumberTableAttribute); |
| } |
| |
| |
| public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) |
| { |
| // Create a new local variable table attribute. |
| LocalVariableTableAttribute newLocalVariableTableAttribute = |
| new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex), |
| 0, |
| new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]); |
| |
| // Add the local variables. |
| localVariableTableAttribute.localVariablesAccept(clazz, |
| method, |
| codeAttribute, |
| new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newLocalVariableTableAttribute); |
| } |
| |
| |
| public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) |
| { |
| // Create a new local variable type table attribute. |
| LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute = |
| new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex), |
| 0, |
| new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]); |
| |
| // Add the local variable types. |
| localVariableTypeTableAttribute.localVariablesAccept(clazz, |
| method, |
| codeAttribute, |
| new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newLocalVariableTypeTableAttribute); |
| } |
| |
| |
| public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) |
| { |
| // Create a new annotations attribute. |
| RuntimeVisibleAnnotationsAttribute newAnnotationsAttribute = |
| new RuntimeVisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleAnnotationsAttribute.u2attributeNameIndex), |
| 0, |
| new Annotation[runtimeVisibleAnnotationsAttribute.u2annotationsCount]); |
| |
| // Add the annotations. |
| runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, |
| new AnnotationAdder(targetClass, |
| newAnnotationsAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newAnnotationsAttribute); |
| } |
| |
| |
| public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) |
| { |
| // Create a new annotations attribute. |
| RuntimeInvisibleAnnotationsAttribute newAnnotationsAttribute = |
| new RuntimeInvisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleAnnotationsAttribute.u2attributeNameIndex), |
| 0, |
| new Annotation[runtimeInvisibleAnnotationsAttribute.u2annotationsCount]); |
| |
| // Add the annotations. |
| runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, |
| new AnnotationAdder(targetClass, |
| newAnnotationsAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newAnnotationsAttribute); |
| } |
| |
| |
| public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) |
| { |
| // Create a new annotations attribute. |
| RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = |
| new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex), |
| 0, |
| new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount], |
| new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]); |
| |
| // Add the annotations. |
| runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, |
| method, |
| new AnnotationAdder(targetClass, |
| newParameterAnnotationsAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newParameterAnnotationsAttribute); |
| } |
| |
| |
| public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) |
| { |
| // Create a new annotations attribute. |
| RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = |
| new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex), |
| 0, |
| new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount], |
| new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]); |
| |
| // Add the annotations. |
| runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, |
| method, |
| new AnnotationAdder(targetClass, |
| newParameterAnnotationsAttribute)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newParameterAnnotationsAttribute); |
| } |
| |
| |
| public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) |
| { |
| // Create a new annotation default attribute. |
| AnnotationDefaultAttribute newAnnotationDefaultAttribute = |
| new AnnotationDefaultAttribute(constantAdder.addConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex), |
| null); |
| |
| // Add the annotations. |
| annotationDefaultAttribute.defaultValueAccept(clazz, |
| new ElementValueAdder(targetClass, |
| newAnnotationDefaultAttribute, |
| false)); |
| |
| // Add it to the target. |
| attributesEditor.addAttribute(newAnnotationDefaultAttribute); |
| } |
| } |