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