summaryrefslogtreecommitdiff
path: root/src/proguard/classfile/editor/AttributeAdder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/editor/AttributeAdder.java')
-rw-r--r--src/proguard/classfile/editor/AttributeAdder.java457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/proguard/classfile/editor/AttributeAdder.java b/src/proguard/classfile/editor/AttributeAdder.java
new file mode 100644
index 0000000..2b610b7
--- /dev/null
+++ b/src/proguard/classfile/editor/AttributeAdder.java
@@ -0,0 +1,457 @@
+/*
+ * 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);
+ }
+}