/* * 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.annotation.*; import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor; /** * This AnnotationVisitor adds all element values that it visits to the given * target annotation default attribute, annotation, or element value. * * @author Eric Lafortune */ public class ElementValueAdder implements ElementValueVisitor { private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0]; private final ProgramClass targetClass; private final AnnotationDefaultAttribute targetAnnotationDefaultAttribute; private final ConstantAdder constantAdder; private final ElementValuesEditor elementValuesEditor; /** * Creates a new ElementValueAdder that will copy element values into the * given target annotation default attribute value. */ public ElementValueAdder(ProgramClass targetClass, AnnotationDefaultAttribute targetAnnotationDefaultAttribute, boolean replaceElementValues) { this.targetClass = targetClass; this.targetAnnotationDefaultAttribute = targetAnnotationDefaultAttribute; constantAdder = new ConstantAdder(targetClass); elementValuesEditor = null; } /** * Creates a new ElementValueAdder that will copy element values into the * given target annotation. */ public ElementValueAdder(ProgramClass targetClass, Annotation targetAnnotation, boolean replaceElementValues) { this.targetClass = targetClass; this.targetAnnotationDefaultAttribute = null; constantAdder = new ConstantAdder(targetClass); elementValuesEditor = new ElementValuesEditor(targetClass, targetAnnotation, replaceElementValues); } /** * Creates a new ElementValueAdder that will copy element values into the * given target element value. */ public ElementValueAdder(ProgramClass targetClass, ArrayElementValue targetArrayElementValue, boolean replaceElementValues) { this.targetClass = targetClass; this.targetAnnotationDefaultAttribute = null; constantAdder = new ConstantAdder(targetClass); elementValuesEditor = new ElementValuesEditor(targetClass, targetArrayElementValue, replaceElementValues); } // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) { // Create a copy of the element value. ConstantElementValue newConstantElementValue = new ConstantElementValue(constantElementValue.u1tag, constantElementValue.u2elementNameIndex == 0 ? 0 : constantAdder.addConstant(clazz, constantElementValue.u2elementNameIndex), constantAdder.addConstant(clazz, constantElementValue.u2constantValueIndex)); newConstantElementValue.referencedClass = constantElementValue.referencedClass; newConstantElementValue.referencedMethod = constantElementValue.referencedMethod; // Add it to the target. addElementValue(newConstantElementValue); } public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) { // Create a copy of the element value. EnumConstantElementValue newEnumConstantElementValue = new EnumConstantElementValue(enumConstantElementValue.u2elementNameIndex == 0 ? 0 : constantAdder.addConstant(clazz, enumConstantElementValue.u2elementNameIndex), constantAdder.addConstant(clazz, enumConstantElementValue.u2typeNameIndex), constantAdder.addConstant(clazz, enumConstantElementValue.u2constantNameIndex)); newEnumConstantElementValue.referencedClass = enumConstantElementValue.referencedClass; newEnumConstantElementValue.referencedMethod = enumConstantElementValue.referencedMethod; // TODO: Clone array. newEnumConstantElementValue.referencedClasses = enumConstantElementValue.referencedClasses; // Add it to the target. addElementValue(newEnumConstantElementValue); } public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) { // Create a copy of the element value. ClassElementValue newClassElementValue = new ClassElementValue(classElementValue.u2elementNameIndex == 0 ? 0 : constantAdder.addConstant(clazz, classElementValue.u2elementNameIndex), constantAdder.addConstant(clazz, classElementValue.u2classInfoIndex)); newClassElementValue.referencedClass = classElementValue.referencedClass; newClassElementValue.referencedMethod = classElementValue.referencedMethod; // TODO: Clone array. newClassElementValue.referencedClasses = classElementValue.referencedClasses; // Add it to the target. addElementValue(newClassElementValue); } public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) { // Create a copy of the element value. AnnotationElementValue newAnnotationElementValue = new AnnotationElementValue(annotationElementValue.u2elementNameIndex == 0 ? 0 : constantAdder.addConstant(clazz, annotationElementValue.u2elementNameIndex), new Annotation()); newAnnotationElementValue.referencedClass = annotationElementValue.referencedClass; newAnnotationElementValue.referencedMethod = annotationElementValue.referencedMethod; annotationElementValue.annotationAccept(clazz, new AnnotationAdder(targetClass, newAnnotationElementValue)); // Add it to the target. addElementValue(newAnnotationElementValue); } public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) { // Create a copy of the element value. ArrayElementValue newArrayElementValue = new ArrayElementValue(arrayElementValue.u2elementNameIndex == 0 ? 0 : constantAdder.addConstant(clazz, arrayElementValue.u2elementNameIndex), 0, arrayElementValue.u2elementValuesCount > 0 ? new ElementValue[arrayElementValue.u2elementValuesCount] : EMPTY_ELEMENT_VALUES); newArrayElementValue.referencedClass = arrayElementValue.referencedClass; newArrayElementValue.referencedMethod = arrayElementValue.referencedMethod; arrayElementValue.elementValuesAccept(clazz, annotation, new ElementValueAdder(targetClass, newArrayElementValue, false)); // Add it to the target. addElementValue(newArrayElementValue); } // Small utility methods. private void addElementValue(ElementValue newElementValue) { // What's the target? if (targetAnnotationDefaultAttribute != null) { // Simply set the completed element value. targetAnnotationDefaultAttribute.defaultValue = newElementValue; } else { // Add it to the target. elementValuesEditor.addElementValue(newElementValue); } } }