1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2013 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 */ 21package proguard.classfile.editor; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.*; 25import proguard.classfile.attribute.annotation.*; 26import proguard.classfile.attribute.preverification.*; 27import proguard.classfile.attribute.visitor.AttributeVisitor; 28import proguard.classfile.util.SimplifiedVisitor; 29 30/** 31 * This AttributeVisitor adds all attributes that it visits to the given 32 * target class, class member, or attribute. 33 * 34 * @author Eric Lafortune 35 */ 36public class AttributeAdder 37extends SimplifiedVisitor 38implements AttributeVisitor 39{ 40 private static final byte[] EMPTY_BYTES = new byte[0]; 41 private static final int[] EMPTY_INTS = new int[0]; 42 private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; 43 private static final ExceptionInfo[] EMPTY_EXCEPTIONS = new ExceptionInfo[0]; 44 45 46 private final ProgramClass targetClass; 47 private final ProgramMember targetMember; 48 private final CodeAttribute targetCodeAttribute; 49 private final boolean replaceAttributes; 50 51 private final ConstantAdder constantAdder; 52 private final AttributesEditor attributesEditor; 53 54 55 /** 56 * Creates a new AttributeAdder that will copy attributes into the given 57 * target class. 58 */ 59 public AttributeAdder(ProgramClass targetClass, 60 boolean replaceAttributes) 61 { 62 this(targetClass, null, null, replaceAttributes); 63 } 64 65 66 /** 67 * Creates a new AttributeAdder that will copy attributes into the given 68 * target class member. 69 */ 70 public AttributeAdder(ProgramClass targetClass, 71 ProgramMember targetMember, 72 boolean replaceAttributes) 73 { 74 this(targetClass, targetMember, null, replaceAttributes); 75 } 76 77 78 /** 79 * Creates a new AttributeAdder that will copy attributes into the given 80 * target attribute. 81 */ 82 public AttributeAdder(ProgramClass targetClass, 83 ProgramMember targetMember, 84 CodeAttribute targetCodeAttribute, 85 boolean replaceAttributes) 86 { 87 this.targetClass = targetClass; 88 this.targetMember = targetMember; 89 this.targetCodeAttribute = targetCodeAttribute; 90 this.replaceAttributes = replaceAttributes; 91 92 constantAdder = new ConstantAdder(targetClass); 93 attributesEditor = new AttributesEditor(targetClass, 94 targetMember, 95 targetCodeAttribute, 96 replaceAttributes); 97 } 98 99 100 // Implementations for AttributeVisitor. 101 102 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 103 { 104 // Create a copy of the attribute. 105 UnknownAttribute newUnknownAttribute = 106 new UnknownAttribute(constantAdder.addConstant(clazz, unknownAttribute.u2attributeNameIndex), 107 unknownAttribute.u4attributeLength, 108 unknownAttribute.info); 109 110 // Add it to the target class. 111 attributesEditor.addAttribute(newUnknownAttribute); 112 } 113 114 115 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 116 { 117 // Create a copy of the attribute. 118 SourceFileAttribute newSourceFileAttribute = 119 new SourceFileAttribute(constantAdder.addConstant(clazz, sourceFileAttribute.u2attributeNameIndex), 120 constantAdder.addConstant(clazz, sourceFileAttribute.u2sourceFileIndex)); 121 122 // Add it to the target class. 123 attributesEditor.addAttribute(newSourceFileAttribute); 124 } 125 126 127 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 128 { 129 // Create a copy of the attribute. 130 SourceDirAttribute newSourceDirAttribute = 131 new SourceDirAttribute(constantAdder.addConstant(clazz, sourceDirAttribute.u2attributeNameIndex), 132 constantAdder.addConstant(clazz, sourceDirAttribute.u2sourceDirIndex)); 133 134 // Add it to the target class. 135 attributesEditor.addAttribute(newSourceDirAttribute); 136 } 137 138 139 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 140 { 141 // Create a copy of the attribute. 142 InnerClassesAttribute newInnerClassesAttribute = 143 new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex), 144 0, 145 null); 146 147 // Add it to the target class. 148 attributesEditor.addAttribute(newInnerClassesAttribute); 149 } 150 151 152 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 153 { 154 // Create a copy of the attribute. 155 EnclosingMethodAttribute newEnclosingMethodAttribute = 156 new EnclosingMethodAttribute(constantAdder.addConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex), 157 constantAdder.addConstant(clazz, enclosingMethodAttribute.u2classIndex), 158 enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? 0 : 159 constantAdder.addConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex)); 160 161 newEnclosingMethodAttribute.referencedClass = enclosingMethodAttribute.referencedClass; 162 newEnclosingMethodAttribute.referencedMethod = enclosingMethodAttribute.referencedMethod; 163 164 // Add it to the target class. 165 attributesEditor.addAttribute(newEnclosingMethodAttribute); 166 } 167 168 169 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 170 { 171 // Create a copy of the attribute. 172 DeprecatedAttribute newDeprecatedAttribute = 173 new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex)); 174 175 // Add it to the target. 176 attributesEditor.addAttribute(newDeprecatedAttribute); 177 } 178 179 180 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 181 { 182 // Create a copy of the attribute. 183 SyntheticAttribute newSyntheticAttribute = 184 new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex)); 185 186 // Add it to the target. 187 attributesEditor.addAttribute(newSyntheticAttribute); 188 } 189 190 191 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 192 { 193 // Create a copy of the attribute. 194 SignatureAttribute newSignatureAttribute = 195 new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex), 196 constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex)); 197 198 newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses; 199 200 // Add it to the target. 201 attributesEditor.addAttribute(newSignatureAttribute); 202 } 203 204 205 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 206 { 207 // Create a copy of the attribute. 208 ConstantValueAttribute newConstantValueAttribute = 209 new ConstantValueAttribute(constantAdder.addConstant(clazz, constantValueAttribute.u2attributeNameIndex), 210 constantAdder.addConstant(clazz, constantValueAttribute.u2constantValueIndex)); 211 212 // Add it to the target field. 213 attributesEditor.addAttribute(newConstantValueAttribute); 214 } 215 216 217 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 218 { 219 // Create a new exceptions attribute. 220 ExceptionsAttribute newExceptionsAttribute = 221 new ExceptionsAttribute(constantAdder.addConstant(clazz, exceptionsAttribute.u2attributeNameIndex), 222 0, 223 exceptionsAttribute.u2exceptionIndexTableLength > 0 ? 224 new int[exceptionsAttribute.u2exceptionIndexTableLength] : 225 EMPTY_INTS); 226 227 // Add the exceptions. 228 exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, 229 new ExceptionAdder(targetClass, 230 newExceptionsAttribute)); 231 232 // Add it to the target method. 233 attributesEditor.addAttribute(newExceptionsAttribute); 234 } 235 236 237 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 238 { 239 // Create a new code attribute. 240 CodeAttribute newCodeAttribute = 241 new CodeAttribute(constantAdder.addConstant(clazz, codeAttribute.u2attributeNameIndex), 242 codeAttribute.u2maxStack, 243 codeAttribute.u2maxLocals, 244 0, 245 EMPTY_BYTES, 246 0, 247 codeAttribute.u2exceptionTableLength > 0 ? 248 new ExceptionInfo[codeAttribute.u2exceptionTableLength] : 249 EMPTY_EXCEPTIONS, 250 0, 251 codeAttribute.u2attributesCount > 0 ? 252 new Attribute[codeAttribute.u2attributesCount] : 253 EMPTY_ATTRIBUTES); 254 255 CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(); 256 257 codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength + 32); 258 259 // Add the instructions. 260 codeAttribute.instructionsAccept(clazz, 261 method, 262 new InstructionAdder(targetClass, 263 codeAttributeComposer)); 264 265 // Append a label just after the code. 266 codeAttributeComposer.appendLabel(codeAttribute.u4codeLength); 267 268 // Add the exceptions. 269 codeAttribute.exceptionsAccept(clazz, 270 method, 271 new ExceptionInfoAdder(targetClass, 272 codeAttributeComposer)); 273 274 codeAttributeComposer.endCodeFragment(); 275 276 // Add the attributes. 277 codeAttribute.attributesAccept(clazz, 278 method, 279 new AttributeAdder(targetClass, 280 targetMember, 281 newCodeAttribute, 282 replaceAttributes)); 283 284 // Apply these changes to the new code attribute. 285 codeAttributeComposer.visitCodeAttribute(targetClass, 286 (Method)targetMember, 287 newCodeAttribute); 288 289 // Add the completed code attribute to the target method. 290 attributesEditor.addAttribute(newCodeAttribute); 291 } 292 293 294 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 295 { 296 // TODO: Implement method. 297 } 298 299 300 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 301 { 302 // TODO: Implement method. 303 } 304 305 306 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 307 { 308 // Create a new line number table attribute. 309 LineNumberTableAttribute newLineNumberTableAttribute = 310 new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex), 311 0, 312 new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]); 313 314 // Add the line numbers. 315 lineNumberTableAttribute.lineNumbersAccept(clazz, 316 method, 317 codeAttribute, 318 new LineNumberInfoAdder(newLineNumberTableAttribute)); 319 320 // Add it to the target. 321 attributesEditor.addAttribute(newLineNumberTableAttribute); 322 } 323 324 325 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 326 { 327 // Create a new local variable table attribute. 328 LocalVariableTableAttribute newLocalVariableTableAttribute = 329 new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex), 330 0, 331 new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]); 332 333 // Add the local variables. 334 localVariableTableAttribute.localVariablesAccept(clazz, 335 method, 336 codeAttribute, 337 new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute)); 338 339 // Add it to the target. 340 attributesEditor.addAttribute(newLocalVariableTableAttribute); 341 } 342 343 344 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 345 { 346 // Create a new local variable type table attribute. 347 LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute = 348 new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex), 349 0, 350 new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]); 351 352 // Add the local variable types. 353 localVariableTypeTableAttribute.localVariablesAccept(clazz, 354 method, 355 codeAttribute, 356 new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute)); 357 358 // Add it to the target. 359 attributesEditor.addAttribute(newLocalVariableTypeTableAttribute); 360 } 361 362 363 public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) 364 { 365 // Create a new annotations attribute. 366 RuntimeVisibleAnnotationsAttribute newAnnotationsAttribute = 367 new RuntimeVisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleAnnotationsAttribute.u2attributeNameIndex), 368 0, 369 new Annotation[runtimeVisibleAnnotationsAttribute.u2annotationsCount]); 370 371 // Add the annotations. 372 runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, 373 new AnnotationAdder(targetClass, 374 newAnnotationsAttribute)); 375 376 // Add it to the target. 377 attributesEditor.addAttribute(newAnnotationsAttribute); 378 } 379 380 381 public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) 382 { 383 // Create a new annotations attribute. 384 RuntimeInvisibleAnnotationsAttribute newAnnotationsAttribute = 385 new RuntimeInvisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleAnnotationsAttribute.u2attributeNameIndex), 386 0, 387 new Annotation[runtimeInvisibleAnnotationsAttribute.u2annotationsCount]); 388 389 // Add the annotations. 390 runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, 391 new AnnotationAdder(targetClass, 392 newAnnotationsAttribute)); 393 394 // Add it to the target. 395 attributesEditor.addAttribute(newAnnotationsAttribute); 396 } 397 398 399 public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) 400 { 401 // Create a new annotations attribute. 402 RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = 403 new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex), 404 0, 405 new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount], 406 new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]); 407 408 // Add the annotations. 409 runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, 410 method, 411 new AnnotationAdder(targetClass, 412 newParameterAnnotationsAttribute)); 413 414 // Add it to the target. 415 attributesEditor.addAttribute(newParameterAnnotationsAttribute); 416 } 417 418 419 public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) 420 { 421 // Create a new annotations attribute. 422 RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = 423 new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex), 424 0, 425 new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount], 426 new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]); 427 428 // Add the annotations. 429 runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, 430 method, 431 new AnnotationAdder(targetClass, 432 newParameterAnnotationsAttribute)); 433 434 // Add it to the target. 435 attributesEditor.addAttribute(newParameterAnnotationsAttribute); 436 } 437 438 439 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 440 { 441 // Create a new annotation default attribute. 442 AnnotationDefaultAttribute newAnnotationDefaultAttribute = 443 new AnnotationDefaultAttribute(constantAdder.addConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex), 444 null); 445 446 // Add the annotations. 447 annotationDefaultAttribute.defaultValueAccept(clazz, 448 new ElementValueAdder(targetClass, 449 newAnnotationDefaultAttribute, 450 false)); 451 452 // Add it to the target. 453 attributesEditor.addAttribute(newAnnotationDefaultAttribute); 454 } 455} 456