1 21 package proguard.classfile.io; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.visitor.*; 27 import proguard.classfile.attribute.preverification.*; 28 import proguard.classfile.attribute.preverification.visitor.*; 29 import proguard.classfile.attribute.visitor.*; 30 import proguard.classfile.constant.*; 31 import proguard.classfile.constant.visitor.ConstantVisitor; 32 import proguard.classfile.util.*; 33 import proguard.classfile.visitor.*; 34 35 import java.io.*; 36 37 43 public class ProgramClassWriter 44 extends SimplifiedVisitor 45 implements ClassVisitor, 46 MemberVisitor, 47 ConstantVisitor, 48 AttributeVisitor 49 { 50 private RuntimeDataOutput dataOutput; 51 52 private ConstantBodyWriter constantBodyWriter = new ConstantBodyWriter(); 53 private AttributeBodyWriter attributeBodyWriter = new AttributeBodyWriter(); 54 private StackMapFrameBodyWriter stackMapFrameBodyWriter = new StackMapFrameBodyWriter(); 55 private VerificationTypeBodyWriter verificationTypeBodyWriter = new VerificationTypeBodyWriter(); 56 private ElementValueBodyWriter elementValueBodyWriter = new ElementValueBodyWriter(); 57 58 59 62 public ProgramClassWriter(DataOutput dataOutput) 63 { 64 this.dataOutput = new RuntimeDataOutput(dataOutput); 65 } 66 67 68 70 public void visitProgramClass(ProgramClass programClass) 71 { 72 dataOutput.writeInt(programClass.u4magic); 74 75 dataOutput.writeShort(ClassUtil.internalMinorClassVersion(programClass.u4version)); 77 dataOutput.writeShort(ClassUtil.internalMajorClassVersion(programClass.u4version)); 78 79 dataOutput.writeShort(programClass.u2constantPoolCount); 81 82 programClass.constantPoolEntriesAccept(this); 83 84 dataOutput.writeShort(programClass.u2accessFlags); 86 dataOutput.writeShort(programClass.u2thisClass); 87 dataOutput.writeShort(programClass.u2superClass); 88 89 dataOutput.writeShort(programClass.u2interfacesCount); 91 92 for (int index = 0; index < programClass.u2interfacesCount; index++) 93 { 94 dataOutput.writeShort(programClass.u2interfaces[index]); 95 } 96 97 dataOutput.writeShort(programClass.u2fieldsCount); 99 100 programClass.fieldsAccept(this); 101 102 dataOutput.writeShort(programClass.u2methodsCount); 104 105 programClass.methodsAccept(this); 106 107 dataOutput.writeShort(programClass.u2attributesCount); 109 110 programClass.attributesAccept(this); 111 } 112 113 114 public void visitLibraryClass(LibraryClass libraryClass) 115 { 116 } 117 118 119 121 public void visitProgramField(ProgramClass programClass, ProgramField programField) 122 { 123 dataOutput.writeShort(programField.u2accessFlags); 125 dataOutput.writeShort(programField.u2nameIndex); 126 dataOutput.writeShort(programField.u2descriptorIndex); 127 128 dataOutput.writeShort(programField.u2attributesCount); 130 131 programField.attributesAccept(programClass, this); 132 } 133 134 135 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 136 { 137 dataOutput.writeShort(programMethod.u2accessFlags); 139 dataOutput.writeShort(programMethod.u2nameIndex); 140 dataOutput.writeShort(programMethod.u2descriptorIndex); 141 142 dataOutput.writeShort(programMethod.u2attributesCount); 144 145 programMethod.attributesAccept(programClass, this); 146 } 147 148 149 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 150 { 151 } 152 153 154 156 public void visitAnyConstant(Clazz clazz, Constant constant) 157 { 158 dataOutput.writeByte(constant.getTag()); 160 161 constant.accept(clazz, constantBodyWriter); 163 } 164 165 166 private class ConstantBodyWriter 167 extends SimplifiedVisitor 168 implements ConstantVisitor 169 { 170 172 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 173 { 174 dataOutput.writeInt(integerConstant.u4value); 175 } 176 177 178 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 179 { 180 dataOutput.writeLong(longConstant.u8value); 181 } 182 183 184 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 185 { 186 dataOutput.writeFloat(floatConstant.f4value); 187 } 188 189 190 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 191 { 192 dataOutput.writeDouble(doubleConstant.f8value); 193 } 194 195 196 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 197 { 198 dataOutput.writeShort(stringConstant.u2stringIndex); 199 } 200 201 202 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 203 { 204 byte[] bytes = utf8Constant.getBytes(); 205 206 dataOutput.writeShort(bytes.length); 207 dataOutput.write(bytes); 208 } 209 210 211 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 212 { 213 dataOutput.writeShort(refConstant.u2classIndex); 214 dataOutput.writeShort(refConstant.u2nameAndTypeIndex); 215 } 216 217 218 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 219 { 220 dataOutput.writeShort(classConstant.u2nameIndex); 221 } 222 223 224 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 225 { 226 dataOutput.writeShort(nameAndTypeConstant.u2nameIndex); 227 dataOutput.writeShort(nameAndTypeConstant.u2descriptorIndex); 228 } 229 } 230 231 232 234 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 235 { 236 dataOutput.writeShort(attribute.u2attributeNameIndex); 238 239 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 242 243 RuntimeDataOutput oldDataOutput = dataOutput; 245 dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream)); 246 247 attribute.accept(clazz, null, null, attributeBodyWriter); 251 252 dataOutput = oldDataOutput; 254 255 byte[] info = byteArrayOutputStream.toByteArray(); 257 258 dataOutput.writeInt(info.length); 259 dataOutput.write(info); 260 } 261 262 263 private class AttributeBodyWriter 264 extends SimplifiedVisitor 265 implements AttributeVisitor, 266 InnerClassesInfoVisitor, 267 ExceptionInfoVisitor, 268 StackMapFrameVisitor, 269 VerificationTypeVisitor, 270 LineNumberInfoVisitor, 271 LocalVariableInfoVisitor, 272 LocalVariableTypeInfoVisitor, 273 AnnotationVisitor, 274 ElementValueVisitor 275 { 276 278 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 279 { 280 byte[] info = new byte[unknownAttribute.u4attributeLength]; 282 dataOutput.write(info); 283 unknownAttribute.info = info; 284 } 285 286 287 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 288 { 289 dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex); 290 } 291 292 293 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 294 { 295 dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex); 296 } 297 298 299 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 300 { 301 dataOutput.writeShort(innerClassesAttribute.u2classesCount); 303 304 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 305 } 306 307 308 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 309 { 310 dataOutput.writeShort(enclosingMethodAttribute.u2classIndex); 311 dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex); 312 } 313 314 315 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 316 { 317 } 319 320 321 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 322 { 323 } 325 326 327 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 328 { 329 dataOutput.writeShort(signatureAttribute.u2signatureIndex); 330 } 331 332 333 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 334 { 335 dataOutput.writeShort(constantValueAttribute.u2constantValueIndex); 336 } 337 338 339 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 340 { 341 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTableLength); 343 344 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 345 { 346 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTable[index]); 347 } 348 } 349 350 351 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 352 { 353 dataOutput.writeShort(codeAttribute.u2maxStack); 355 dataOutput.writeShort(codeAttribute.u2maxLocals); 356 357 dataOutput.writeInt(codeAttribute.u4codeLength); 359 360 dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength); 361 362 dataOutput.writeShort(codeAttribute.u2exceptionTableLength); 364 365 codeAttribute.exceptionsAccept(clazz, method, this); 366 367 dataOutput.writeShort(codeAttribute.u2attributesCount); 369 370 codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this); 371 } 372 373 374 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 375 { 376 dataOutput.writeShort(stackMapAttribute.u2stackMapFramesCount); 378 379 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter); 380 } 381 382 383 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 384 { 385 dataOutput.writeShort(stackMapTableAttribute.u2stackMapFramesCount); 387 388 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 389 } 390 391 392 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 393 { 394 dataOutput.writeShort(lineNumberTableAttribute.u2lineNumberTableLength); 396 397 lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 398 } 399 400 401 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 402 { 403 dataOutput.writeShort(localVariableTableAttribute.u2localVariableTableLength); 405 406 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 407 } 408 409 410 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 411 { 412 dataOutput.writeShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength); 414 415 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 416 } 417 418 419 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 420 { 421 dataOutput.writeShort(annotationsAttribute.u2annotationsCount); 423 424 annotationsAttribute.annotationsAccept(clazz, this); 425 } 426 427 428 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 429 { 430 dataOutput.writeByte(parameterAnnotationsAttribute.u2parametersCount); 432 433 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) 434 { 435 int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; 437 Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; 438 439 dataOutput.writeShort(u2annotationsCount); 440 441 for (int index = 0; index < u2annotationsCount; index++) 442 { 443 Annotation annotation = annotations[index]; 444 this.visitAnnotation(clazz, annotation); 445 } 446 447 } 448 } 449 450 451 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 452 { 453 annotationDefaultAttribute.defaultValue.accept(clazz, null, this); 455 } 456 457 458 460 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 461 { 462 dataOutput.writeShort(innerClassesInfo.u2innerClassIndex); 463 dataOutput.writeShort(innerClassesInfo.u2outerClassIndex); 464 dataOutput.writeShort(innerClassesInfo.u2innerNameIndex); 465 dataOutput.writeShort(innerClassesInfo.u2innerClassAccessFlags); 466 } 467 468 469 471 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 472 { 473 dataOutput.writeShort(exceptionInfo.u2startPC); 474 dataOutput.writeShort(exceptionInfo.u2endPC); 475 dataOutput.writeShort(exceptionInfo.u2handlerPC); 476 dataOutput.writeShort(exceptionInfo.u2catchType); 477 } 478 479 480 482 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 483 { 484 dataOutput.writeByte(stackMapFrame.getTag()); 486 487 stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter); 489 } 490 491 492 494 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 495 { 496 dataOutput.writeShort(lineNumberInfo.u2startPC); 497 dataOutput.writeShort(lineNumberInfo.u2lineNumber); 498 } 499 500 501 503 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 504 { 505 dataOutput.writeShort(localVariableInfo.u2startPC); 506 dataOutput.writeShort(localVariableInfo.u2length); 507 dataOutput.writeShort(localVariableInfo.u2nameIndex); 508 dataOutput.writeShort(localVariableInfo.u2descriptorIndex); 509 dataOutput.writeShort(localVariableInfo.u2index); 510 } 511 512 513 515 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 516 { 517 dataOutput.writeShort(localVariableTypeInfo.u2startPC); 518 dataOutput.writeShort(localVariableTypeInfo.u2length); 519 dataOutput.writeShort(localVariableTypeInfo.u2nameIndex); 520 dataOutput.writeShort(localVariableTypeInfo.u2signatureIndex); 521 dataOutput.writeShort(localVariableTypeInfo.u2index); 522 } 523 524 525 527 public void visitAnnotation(Clazz clazz, Annotation annotation) 528 { 529 dataOutput.writeShort(annotation.u2typeIndex); 531 532 dataOutput.writeShort(annotation.u2elementValuesCount); 534 535 annotation.elementValuesAccept(clazz, this); 536 } 537 538 539 541 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 542 { 543 int u2elementNameIndex = elementValue.u2elementNameIndex; 545 if (u2elementNameIndex != 0) 546 { 547 dataOutput.writeShort(u2elementNameIndex); 548 } 549 550 dataOutput.writeByte(elementValue.getTag()); 552 553 elementValue.accept(clazz, annotation, elementValueBodyWriter); 555 } 556 } 557 558 559 private class StackMapFrameBodyWriter 560 extends SimplifiedVisitor 561 implements StackMapFrameVisitor, 562 VerificationTypeVisitor 563 { 564 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 565 { 566 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 567 { 568 dataOutput.writeShort(sameZeroFrame.u2offsetDelta); 569 } 570 } 571 572 573 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 574 { 575 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 576 { 577 dataOutput.writeShort(sameOneFrame.u2offsetDelta); 578 } 579 580 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 582 } 583 584 585 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 586 { 587 dataOutput.writeShort(lessZeroFrame.u2offsetDelta); 588 } 589 590 591 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 592 { 593 dataOutput.writeShort(moreZeroFrame.u2offsetDelta); 594 595 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 597 } 598 599 600 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 601 { 602 dataOutput.writeShort(fullFrame.u2offsetDelta); 603 604 dataOutput.writeShort(fullFrame.variablesCount); 606 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 607 608 dataOutput.writeShort(fullFrame.stackCount); 610 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 611 } 612 613 614 616 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 617 { 618 dataOutput.writeByte(verificationType.getTag()); 620 621 verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter); 623 } 624 } 625 626 627 private class VerificationTypeBodyWriter 628 extends SimplifiedVisitor 629 implements VerificationTypeVisitor 630 { 631 633 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 634 { 635 } 637 638 639 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 640 { 641 dataOutput.writeShort(objectType.u2classIndex); 642 } 643 644 645 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 646 { 647 dataOutput.writeShort(uninitializedType.u2newInstructionOffset); 648 } 649 } 650 651 652 private class ElementValueBodyWriter 653 extends SimplifiedVisitor 654 implements ElementValueVisitor 655 { 656 658 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 659 { 660 dataOutput.writeShort(constantElementValue.u2constantValueIndex); 661 } 662 663 664 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 665 { 666 dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex); 667 dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex); 668 } 669 670 671 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 672 { 673 dataOutput.writeShort(classElementValue.u2classInfoIndex); 674 } 675 676 677 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 678 { 679 attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue); 681 } 682 683 684 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 685 { 686 dataOutput.writeShort(arrayElementValue.u2elementValuesCount); 688 689 arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter); 690 } 691 } 692 } 693 | Popular Tags |