1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.preverification.*; 27 import proguard.classfile.attribute.visitor.AttributeVisitor; 28 import 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 */ 36 public class AttributeAdder 37 extends SimplifiedVisitor 38 implements 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 // TODO: Implement method. 142 // Note that the attribute may already be present. 143 // // Create a copy of the attribute. 144 // InnerClassesAttribute newInnerClassesAttribute = 145 // new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex), 146 // 0, 147 // null); 148 // 149 // // Add it to the target class. 150 // attributesEditor.addClassAttribute(newInnerClassesAttribute); 151 } 152 153 154 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 155 { 156 // Create a copy of the attribute. 157 EnclosingMethodAttribute newEnclosingMethodAttribute = 158 new EnclosingMethodAttribute(constantAdder.addConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex), 159 constantAdder.addConstant(clazz, enclosingMethodAttribute.u2classIndex), 160 enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? 0 : 161 constantAdder.addConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex)); 162 163 newEnclosingMethodAttribute.referencedClass = enclosingMethodAttribute.referencedClass; 164 newEnclosingMethodAttribute.referencedMethod = enclosingMethodAttribute.referencedMethod; 165 166 // Add it to the target class. 167 attributesEditor.addAttribute(newEnclosingMethodAttribute); 168 } 169 170 171 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 172 { 173 // Create a copy of the attribute. 174 DeprecatedAttribute newDeprecatedAttribute = 175 new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex)); 176 177 // Add it to the target. 178 attributesEditor.addAttribute(newDeprecatedAttribute); 179 } 180 181 182 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 183 { 184 // Create a copy of the attribute. 185 SyntheticAttribute newSyntheticAttribute = 186 new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex)); 187 188 // Add it to the target. 189 attributesEditor.addAttribute(newSyntheticAttribute); 190 } 191 192 193 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 194 { 195 // Create a copy of the attribute. 196 SignatureAttribute newSignatureAttribute = 197 new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex), 198 constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex)); 199 200 newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses; 201 202 // Add it to the target. 203 attributesEditor.addAttribute(newSignatureAttribute); 204 } 205 206 207 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 208 { 209 // Create a copy of the attribute. 210 ConstantValueAttribute newConstantValueAttribute = 211 new ConstantValueAttribute(constantAdder.addConstant(clazz, constantValueAttribute.u2attributeNameIndex), 212 constantAdder.addConstant(clazz, constantValueAttribute.u2constantValueIndex)); 213 214 // Add it to the target field. 215 attributesEditor.addAttribute(newConstantValueAttribute); 216 } 217 218 219 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 220 { 221 // Create a new exceptions attribute. 222 ExceptionsAttribute newExceptionsAttribute = 223 new ExceptionsAttribute(constantAdder.addConstant(clazz, exceptionsAttribute.u2attributeNameIndex), 224 0, 225 exceptionsAttribute.u2exceptionIndexTableLength > 0 ? 226 new int[exceptionsAttribute.u2exceptionIndexTableLength] : 227 EMPTY_INTS); 228 229 // Add the exceptions. 230 exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, 231 new ExceptionAdder(targetClass, 232 newExceptionsAttribute)); 233 234 // Add it to the target method. 235 attributesEditor.addAttribute(newExceptionsAttribute); 236 } 237 238 239 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 240 { 241 // Create a new code attribute. 242 CodeAttribute newCodeAttribute = 243 new CodeAttribute(constantAdder.addConstant(clazz, codeAttribute.u2attributeNameIndex), 244 codeAttribute.u2maxStack, 245 codeAttribute.u2maxLocals, 246 0, 247 EMPTY_BYTES, 248 0, 249 codeAttribute.u2exceptionTableLength > 0 ? 250 new ExceptionInfo[codeAttribute.u2exceptionTableLength] : 251 EMPTY_EXCEPTIONS, 252 0, 253 codeAttribute.u2attributesCount > 0 ? 254 new Attribute[codeAttribute.u2attributesCount] : 255 EMPTY_ATTRIBUTES); 256 257 CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(); 258 259 codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength); 260 261 // Add the instructions. 262 codeAttribute.instructionsAccept(clazz, 263 method, 264 new InstructionAdder(targetClass, 265 codeAttributeComposer)); 266 267 // Append a label just after the code. 268 codeAttributeComposer.appendLabel(codeAttribute.u4codeLength); 269 270 // Add the exceptions. 271 codeAttribute.exceptionsAccept(clazz, 272 method, 273 new ExceptionInfoAdder(targetClass, 274 codeAttributeComposer)); 275 276 codeAttributeComposer.endCodeFragment(); 277 278 // Add the attributes. 279 codeAttribute.attributesAccept(clazz, 280 method, 281 new AttributeAdder(targetClass, 282 targetMember, 283 newCodeAttribute, 284 replaceAttributes)); 285 286 // Apply these changes to the new code attribute. 287 codeAttributeComposer.visitCodeAttribute(targetClass, 288 (Method)targetMember, 289 newCodeAttribute); 290 291 // Add the completed code attribute to the target method. 292 attributesEditor.addAttribute(newCodeAttribute); 293 } 294 295 296 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 297 { 298 // TODO: Implement method. 299 } 300 301 302 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 303 { 304 // TODO: Implement method. 305 } 306 307 308 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 309 { 310 // Create a new line number table attribute. 311 LineNumberTableAttribute newLineNumberTableAttribute = 312 new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex), 313 0, 314 new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]); 315 316 // Add the line numbers. 317 lineNumberTableAttribute.lineNumbersAccept(clazz, 318 method, 319 codeAttribute, 320 new LineNumberInfoAdder(newLineNumberTableAttribute)); 321 322 // Add it to the target. 323 attributesEditor.addAttribute(newLineNumberTableAttribute); 324 } 325 326 327 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 328 { 329 // Create a new local variable table attribute. 330 LocalVariableTableAttribute newLocalVariableTableAttribute = 331 new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex), 332 0, 333 new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]); 334 335 // Add the local variables. 336 localVariableTableAttribute.localVariablesAccept(clazz, 337 method, 338 codeAttribute, 339 new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute)); 340 341 // Add it to the target. 342 attributesEditor.addAttribute(newLocalVariableTableAttribute); 343 } 344 345 346 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 347 { 348 // Create a new local variable type table attribute. 349 LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute = 350 new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex), 351 0, 352 new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]); 353 354 // Add the local variable types. 355 localVariableTypeTableAttribute.localVariablesAccept(clazz, 356 method, 357 codeAttribute, 358 new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute)); 359 360 // Add it to the target. 361 attributesEditor.addAttribute(newLocalVariableTypeTableAttribute); 362 } 363 364 365 public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) 366 { 367 // Create a new annotations attribute. 368 RuntimeVisibleAnnotationsAttribute newAnnotationsAttribute = 369 new RuntimeVisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleAnnotationsAttribute.u2attributeNameIndex), 370 0, 371 new Annotation[runtimeVisibleAnnotationsAttribute.u2annotationsCount]); 372 373 // Add the annotations. 374 runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, 375 new AnnotationAdder(targetClass, 376 newAnnotationsAttribute)); 377 378 // Add it to the target. 379 attributesEditor.addAttribute(newAnnotationsAttribute); 380 } 381 382 383 public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) 384 { 385 // Create a new annotations attribute. 386 RuntimeInvisibleAnnotationsAttribute newAnnotationsAttribute = 387 new RuntimeInvisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleAnnotationsAttribute.u2attributeNameIndex), 388 0, 389 new Annotation[runtimeInvisibleAnnotationsAttribute.u2annotationsCount]); 390 391 // Add the annotations. 392 runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, 393 new AnnotationAdder(targetClass, 394 newAnnotationsAttribute)); 395 396 // Add it to the target. 397 attributesEditor.addAttribute(newAnnotationsAttribute); 398 } 399 400 401 public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) 402 { 403 // Create a new annotations attribute. 404 RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = 405 new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex), 406 0, 407 new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount], 408 new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]); 409 410 // Add the annotations. 411 runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, 412 method, 413 new AnnotationAdder(targetClass, 414 newParameterAnnotationsAttribute)); 415 416 // Add it to the target. 417 attributesEditor.addAttribute(newParameterAnnotationsAttribute); 418 } 419 420 421 public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) 422 { 423 // Create a new annotations attribute. 424 RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = 425 new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex), 426 0, 427 new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount], 428 new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]); 429 430 // Add the annotations. 431 runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, 432 method, 433 new AnnotationAdder(targetClass, 434 newParameterAnnotationsAttribute)); 435 436 // Add it to the target. 437 attributesEditor.addAttribute(newParameterAnnotationsAttribute); 438 } 439 440 441 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 442 { 443 // Create a new annotation default attribute. 444 AnnotationDefaultAttribute newAnnotationDefaultAttribute = 445 new AnnotationDefaultAttribute(constantAdder.addConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex), 446 null); 447 448 // Add the annotations. 449 annotationDefaultAttribute.defaultValueAccept(clazz, 450 new ElementValueAdder(targetClass, 451 newAnnotationDefaultAttribute, 452 false)); 453 454 // Add it to the target. 455 attributesEditor.addAttribute(newAnnotationDefaultAttribute); 456 } 457 } 458