1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.classfile.editor; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.annotation.*; 25 import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor; 26 27 /** 28 * This AnnotationVisitor adds all element values that it visits to the given 29 * target annotation default attribute, annotation, or element value. 30 * 31 * @author Eric Lafortune 32 */ 33 public class ElementValueAdder 34 implements ElementValueVisitor 35 { 36 private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0]; 37 38 39 private final ProgramClass targetClass; 40 private final AnnotationDefaultAttribute targetAnnotationDefaultAttribute; 41 42 private final ConstantAdder constantAdder; 43 private final ElementValuesEditor elementValuesEditor; 44 45 46 /** 47 * Creates a new ElementValueAdder that will copy element values into the 48 * given target annotation default attribute value. 49 */ ElementValueAdder(ProgramClass targetClass, AnnotationDefaultAttribute targetAnnotationDefaultAttribute, boolean replaceElementValues)50 public ElementValueAdder(ProgramClass targetClass, 51 AnnotationDefaultAttribute targetAnnotationDefaultAttribute, 52 boolean replaceElementValues) 53 { 54 this.targetClass = targetClass; 55 this.targetAnnotationDefaultAttribute = targetAnnotationDefaultAttribute; 56 57 constantAdder = new ConstantAdder(targetClass); 58 elementValuesEditor = null; 59 } 60 61 62 /** 63 * Creates a new ElementValueAdder that will copy element values into the 64 * given target annotation. 65 */ ElementValueAdder(ProgramClass targetClass, Annotation targetAnnotation, boolean replaceElementValues)66 public ElementValueAdder(ProgramClass targetClass, 67 Annotation targetAnnotation, 68 boolean replaceElementValues) 69 { 70 this.targetClass = targetClass; 71 this.targetAnnotationDefaultAttribute = null; 72 73 constantAdder = new ConstantAdder(targetClass); 74 elementValuesEditor = new ElementValuesEditor(targetClass, 75 targetAnnotation, 76 replaceElementValues); 77 } 78 79 80 /** 81 * Creates a new ElementValueAdder that will copy element values into the 82 * given target element value. 83 */ ElementValueAdder(ProgramClass targetClass, ArrayElementValue targetArrayElementValue, boolean replaceElementValues)84 public ElementValueAdder(ProgramClass targetClass, 85 ArrayElementValue targetArrayElementValue, 86 boolean replaceElementValues) 87 { 88 this.targetClass = targetClass; 89 this.targetAnnotationDefaultAttribute = null; 90 91 constantAdder = new ConstantAdder(targetClass); 92 elementValuesEditor = new ElementValuesEditor(targetClass, 93 targetArrayElementValue, 94 replaceElementValues); 95 } 96 97 98 // Implementations for ElementValueVisitor. 99 visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)100 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 101 { 102 // Create a copy of the element value. 103 ConstantElementValue newConstantElementValue = 104 new ConstantElementValue(constantElementValue.u1tag, 105 constantElementValue.u2elementNameIndex == 0 ? 0 : 106 constantAdder.addConstant(clazz, constantElementValue.u2elementNameIndex), 107 constantAdder.addConstant(clazz, constantElementValue.u2constantValueIndex)); 108 109 newConstantElementValue.referencedClass = constantElementValue.referencedClass; 110 newConstantElementValue.referencedMethod = constantElementValue.referencedMethod; 111 112 // Add it to the target. 113 addElementValue(newConstantElementValue); 114 } 115 116 visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)117 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 118 { 119 // Create a copy of the element value. 120 EnumConstantElementValue newEnumConstantElementValue = 121 new EnumConstantElementValue(enumConstantElementValue.u2elementNameIndex == 0 ? 0 : 122 constantAdder.addConstant(clazz, enumConstantElementValue.u2elementNameIndex), 123 constantAdder.addConstant(clazz, enumConstantElementValue.u2typeNameIndex), 124 constantAdder.addConstant(clazz, enumConstantElementValue.u2constantNameIndex)); 125 126 newEnumConstantElementValue.referencedClass = enumConstantElementValue.referencedClass; 127 newEnumConstantElementValue.referencedMethod = enumConstantElementValue.referencedMethod; 128 129 // TODO: Clone array. 130 newEnumConstantElementValue.referencedClasses = enumConstantElementValue.referencedClasses; 131 132 // Add it to the target. 133 addElementValue(newEnumConstantElementValue); 134 } 135 136 visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)137 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 138 { 139 // Create a copy of the element value. 140 ClassElementValue newClassElementValue = 141 new ClassElementValue(classElementValue.u2elementNameIndex == 0 ? 0 : 142 constantAdder.addConstant(clazz, classElementValue.u2elementNameIndex), 143 constantAdder.addConstant(clazz, classElementValue.u2classInfoIndex)); 144 145 newClassElementValue.referencedClass = classElementValue.referencedClass; 146 newClassElementValue.referencedMethod = classElementValue.referencedMethod; 147 148 // TODO: Clone array. 149 newClassElementValue.referencedClasses = classElementValue.referencedClasses; 150 151 // Add it to the target. 152 addElementValue(newClassElementValue); 153 } 154 155 visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)156 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 157 { 158 // Create a copy of the element value. 159 AnnotationElementValue newAnnotationElementValue = 160 new AnnotationElementValue(annotationElementValue.u2elementNameIndex == 0 ? 0 : 161 constantAdder.addConstant(clazz, annotationElementValue.u2elementNameIndex), 162 new Annotation()); 163 164 newAnnotationElementValue.referencedClass = annotationElementValue.referencedClass; 165 newAnnotationElementValue.referencedMethod = annotationElementValue.referencedMethod; 166 167 annotationElementValue.annotationAccept(clazz, 168 new AnnotationAdder(targetClass, 169 newAnnotationElementValue)); 170 171 // Add it to the target. 172 addElementValue(newAnnotationElementValue); 173 } 174 175 visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)176 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 177 { 178 // Create a copy of the element value. 179 ArrayElementValue newArrayElementValue = 180 new ArrayElementValue(arrayElementValue.u2elementNameIndex == 0 ? 0 : 181 constantAdder.addConstant(clazz, arrayElementValue.u2elementNameIndex), 182 0, 183 arrayElementValue.u2elementValuesCount > 0 ? 184 new ElementValue[arrayElementValue.u2elementValuesCount] : 185 EMPTY_ELEMENT_VALUES); 186 187 newArrayElementValue.referencedClass = arrayElementValue.referencedClass; 188 newArrayElementValue.referencedMethod = arrayElementValue.referencedMethod; 189 190 arrayElementValue.elementValuesAccept(clazz, 191 annotation, 192 new ElementValueAdder(targetClass, 193 newArrayElementValue, 194 false)); 195 196 // Add it to the target. 197 addElementValue(newArrayElementValue); 198 } 199 200 201 // Small utility methods. 202 addElementValue(ElementValue newElementValue)203 private void addElementValue(ElementValue newElementValue) 204 { 205 // What's the target? 206 if (targetAnnotationDefaultAttribute != null) 207 { 208 // Simply set the completed element value. 209 targetAnnotationDefaultAttribute.defaultValue = newElementValue; 210 } 211 else 212 { 213 // Add it to the target. 214 elementValuesEditor.addElementValue(newElementValue); 215 } 216 } 217 }