1 #!/usr/bin/env python 2 3 """ 4 Java class file decoder. Specification found at the following URL: 5 http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html 6 """ 7 8 import struct # for general decoding of class files 9 10 # Utility functions. 11 12 def u1(data): 13 return struct.unpack(">B", data[0:1])[0] 14 15 def u2(data): 16 return struct.unpack(">H", data[0:2])[0] 17 18 def s2(data): 19 return struct.unpack(">h", data[0:2])[0] 20 21 def u4(data): 22 return struct.unpack(">L", data[0:4])[0] 23 24 def s4(data): 25 return struct.unpack(">l", data[0:4])[0] 26 27 def s8(data): 28 return struct.unpack(">q", data[0:8])[0] 29 30 def f4(data): 31 return struct.unpack(">f", data[0:4])[0] 32 33 def f8(data): 34 return struct.unpack(">d", data[0:8])[0] 35 36 def su1(value): 37 return struct.pack(">B", value) 38 39 def su2(value): 40 return struct.pack(">H", value) 41 42 def ss2(value): 43 return struct.pack(">h", value) 44 45 def su4(value): 46 return struct.pack(">L", value) 47 48 def ss4(value): 49 return struct.pack(">l", value) 50 51 def ss8(value): 52 return struct.pack(">q", value) 53 54 def sf4(value): 55 return struct.pack(">f", value) 56 57 def sf8(value): 58 return struct.pack(">d", value) 59 60 # Useful tables and constants. 61 62 descriptor_base_type_mapping = { 63 "B" : "int", 64 "C" : "str", 65 "D" : "float", 66 "F" : "float", 67 "I" : "int", 68 "J" : "int", 69 "L" : "object", 70 "S" : "int", 71 "Z" : "bool", 72 "[" : "list" 73 } 74 75 type_names_to_default_values = { 76 "int" : 0, 77 "str" : u"", 78 "float" : 0.0, 79 "object" : None, 80 "bool" : 0, # NOTE: Should be False. 81 "list" : [] 82 } 83 84 def get_default_for_type(type_name): 85 global type_names_to_default_values 86 return type_names_to_default_values.get(type_name) 87 88 PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SUPER, SYNCHRONIZED, VOLATILE, TRANSIENT, NATIVE, INTERFACE, ABSTRACT, STRICT = \ 89 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800 90 91 def has_flags(flags, desired): 92 desired_flags = reduce(lambda a, b: a | b, desired, 0) 93 return (flags & desired_flags) == desired_flags 94 95 # Useful mix-ins. 96 97 class PythonMethodUtils: 98 symbol_sep = "___" # was "$" 99 type_sep = "__" # replaces "/" 100 array_sep = "_array_" # was "[]" 101 base_seps = ("_", "_") # was "<" and ">" 102 103 def get_unqualified_python_name(self): 104 name = self.get_name() 105 if str(name) == "<init>": 106 return "__init__" 107 elif str(name) == "<clinit>": 108 return "__clinit__" 109 else: 110 return str(name) 111 112 def get_python_name(self): 113 name = self.get_unqualified_python_name() 114 if name == "__clinit__": 115 return name 116 return name + self.symbol_sep + self._get_descriptor_as_name() 117 118 def _get_descriptor_as_name(self): 119 l = [] 120 for descriptor_type in self.get_descriptor()[0]: 121 l.append(self._get_type_as_name(descriptor_type)) 122 return self.symbol_sep.join(l) 123 124 def _get_type_as_name(self, descriptor_type, s=""): 125 base_type, object_type, array_type = descriptor_type 126 if base_type == "L": 127 return object_type.replace("/", self.type_sep) + s 128 elif base_type == "[": 129 return self._get_type_as_name(array_type, s + self.array_sep) 130 else: 131 return self.base_seps[0] + base_type + self.base_seps[1] + s 132 133 class PythonNameUtils: 134 def get_python_name(self): 135 # NOTE: This may not be comprehensive. 136 if not str(self.get_name()).startswith("["): 137 return str(self.get_name()).replace("/", ".") 138 else: 139 return self._get_type_name( 140 get_field_descriptor( 141 str(self.get_name()) 142 ) 143 ).replace("/", ".") 144 145 def _get_type_name(self, descriptor_type): 146 base_type, object_type, array_type = descriptor_type 147 if base_type == "L": 148 return object_type 149 elif base_type == "[": 150 return self._get_type_name(array_type) 151 else: 152 return descriptor_base_type_mapping[base_type] 153 154 class NameUtils: 155 def get_name(self): 156 if self.name_index != 0: 157 return self.class_file.constants[self.name_index - 1] 158 else: 159 # Some name indexes are zero to indicate special conditions. 160 return None 161 162 class NameAndTypeUtils: 163 def get_name(self): 164 if self.name_and_type_index != 0: 165 return self.class_file.constants[self.name_and_type_index - 1].get_name() 166 else: 167 # Some name indexes are zero to indicate special conditions. 168 return None 169 170 def get_field_descriptor(self): 171 if self.name_and_type_index != 0: 172 return self.class_file.constants[self.name_and_type_index - 1].get_field_descriptor() 173 else: 174 # Some name indexes are zero to indicate special conditions. 175 return None 176 177 def get_method_descriptor(self): 178 if self.name_and_type_index != 0: 179 return self.class_file.constants[self.name_and_type_index - 1].get_method_descriptor() 180 else: 181 # Some name indexes are zero to indicate special conditions. 182 return None 183 184 def get_class(self): 185 return self.class_file.constants[self.class_index - 1] 186 187 # Symbol parsing. 188 189 def get_method_descriptor(s): 190 assert s[0] == "(" 191 params = [] 192 s = s[1:] 193 while s[0] != ")": 194 parameter_descriptor, s = _get_parameter_descriptor(s) 195 params.append(parameter_descriptor) 196 if s[1] != "V": 197 return_type, s = _get_field_type(s[1:]) 198 else: 199 return_type, s = None, s[1:] 200 return params, return_type 201 202 def get_field_descriptor(s): 203 return _get_field_type(s)[0] 204 205 def _get_parameter_descriptor(s): 206 return _get_field_type(s) 207 208 def _get_component_type(s): 209 return _get_field_type(s) 210 211 def _get_field_type(s): 212 base_type, s = _get_base_type(s) 213 object_type = None 214 array_type = None 215 if base_type == "L": 216 object_type, s = _get_object_type(s) 217 elif base_type == "[": 218 array_type, s = _get_array_type(s) 219 return (base_type, object_type, array_type), s 220 221 def _get_base_type(s): 222 if len(s) > 0: 223 return s[0], s[1:] 224 else: 225 return None, s 226 227 def _get_object_type(s): 228 if len(s) > 0: 229 s_end = s.find(";") 230 assert s_end != -1 231 return s[:s_end], s[s_end+1:] 232 else: 233 return None, s 234 235 def _get_array_type(s): 236 if len(s) > 0: 237 return _get_component_type(s) 238 else: 239 return None, s 240 241 # Constant information. 242 243 class ClassInfo(NameUtils, PythonNameUtils): 244 def init(self, data, class_file): 245 self.class_file = class_file 246 self.name_index = u2(data[0:2]) 247 return data[2:] 248 def serialize(self): 249 return su2(self.name_index) 250 251 class RefInfo(NameAndTypeUtils): 252 def init(self, data, class_file): 253 self.class_file = class_file 254 self.class_index = u2(data[0:2]) 255 self.name_and_type_index = u2(data[2:4]) 256 return data[4:] 257 def serialize(self): 258 return su2(self.class_index)+su2(self.name_and_type_index) 259 260 class FieldRefInfo(RefInfo, PythonNameUtils): 261 def get_descriptor(self): 262 return RefInfo.get_field_descriptor(self) 263 264 class MethodRefInfo(RefInfo, PythonMethodUtils): 265 def get_descriptor(self): 266 return RefInfo.get_method_descriptor(self) 267 268 class InterfaceMethodRefInfo(MethodRefInfo): 269 pass 270 271 class NameAndTypeInfo(NameUtils, PythonNameUtils): 272 def init(self, data, class_file): 273 self.class_file = class_file 274 self.name_index = u2(data[0:2]) 275 self.descriptor_index = u2(data[2:4]) 276 return data[4:] 277 278 def serialize(self): 279 return su2(self.name_index)+su2(self.descriptor_index) 280 281 def get_field_descriptor(self): 282 return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1])) 283 284 def get_method_descriptor(self): 285 return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1])) 286 287 class Utf8Info: 288 def init(self, data, class_file): 289 self.class_file = class_file 290 self.length = u2(data[0:2]) 291 self.bytes = data[2:2+self.length] 292 return data[2+self.length:] 293 294 def serialize(self): 295 return su2(self.length)+self.bytes 296 297 def __str__(self): 298 return self.bytes 299 300 def __unicode__(self): 301 return unicode(self.bytes, "utf-8") 302 303 def get_value(self): 304 return str(self) 305 306 class StringInfo: 307 def init(self, data, class_file): 308 self.class_file = class_file 309 self.string_index = u2(data[0:2]) 310 return data[2:] 311 312 def serialize(self): 313 return su2(self.string_index) 314 315 def __str__(self): 316 return str(self.class_file.constants[self.string_index - 1]) 317 318 def __unicode__(self): 319 return unicode(self.class_file.constants[self.string_index - 1]) 320 321 def get_value(self): 322 return str(self) 323 324 class SmallNumInfo: 325 def init(self, data, class_file): 326 self.class_file = class_file 327 self.bytes = data[0:4] 328 return data[4:] 329 def serialize(self): 330 return self.bytes 331 332 class IntegerInfo(SmallNumInfo): 333 def get_value(self): 334 return s4(self.bytes) 335 336 class FloatInfo(SmallNumInfo): 337 def get_value(self): 338 return f4(self.bytes) 339 340 class LargeNumInfo: 341 def init(self, data, class_file): 342 self.class_file = class_file 343 self.high_bytes = data[0:4] 344 self.low_bytes = data[4:8] 345 return data[8:] 346 def serialize(self): 347 return self.high_bytes+self.low_bytes 348 349 350 class LongInfo(LargeNumInfo): 351 def get_value(self): 352 return s8(self.high_bytes + self.low_bytes) 353 354 class DoubleInfo(LargeNumInfo): 355 def get_value(self): 356 return f8(self.high_bytes + self.low_bytes) 357 358 # Other information. 359 # Objects of these classes are generally aware of the class they reside in. 360 361 class ItemInfo(NameUtils): 362 def init(self, data, class_file): 363 self.class_file = class_file 364 self.access_flags = u2(data[0:2]) 365 self.name_index = u2(data[2:4]) 366 self.descriptor_index = u2(data[4:6]) 367 self.attributes, data = self.class_file._get_attributes(data[6:]) 368 return data 369 def serialize(self): 370 od = su2(self.access_flags)+su2(self.name_index)+su2(self.descriptor_index) 371 od += self.class_file._serialize_attributes(self.attributes) 372 return od 373 374 class FieldInfo(ItemInfo, PythonNameUtils): 375 def get_descriptor(self): 376 return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1])) 377 378 class MethodInfo(ItemInfo, PythonMethodUtils): 379 def get_descriptor(self): 380 return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1])) 381 382 class AttributeInfo: 383 def init(self, data, class_file): 384 self.attribute_length = u4(data[0:4]) 385 self.info = data[4:4+self.attribute_length] 386 return data[4+self.attribute_length:] 387 def serialize(self): 388 return su4(self.attribute_length)+self.info 389 390 # NOTE: Decode the different attribute formats. 391 392 class SourceFileAttributeInfo(AttributeInfo, NameUtils, PythonNameUtils): 393 def init(self, data, class_file): 394 self.class_file = class_file 395 self.attribute_length = u4(data[0:4]) 396 # Permit the NameUtils mix-in. 397 self.name_index = self.sourcefile_index = u2(data[4:6]) 398 return data[6:] 399 def serialize(self): 400 return su4(self.attribute_length)+su2(self.name_index) 401 402 class ConstantValueAttributeInfo(AttributeInfo): 403 def init(self, data, class_file): 404 self.class_file = class_file 405 self.attribute_length = u4(data[0:4]) 406 self.constant_value_index = u2(data[4:6]) 407 assert 4+self.attribute_length == 6 408 return data[4+self.attribute_length:] 409 410 def get_value(self): 411 return self.class_file.constants[self.constant_value_index - 1].get_value() 412 413 def serialize(self): 414 return su4(self.attribute_length)+su2(self.constant_value_index) 415 416 class CodeAttributeInfo(AttributeInfo): 417 def init(self, data, class_file): 418 self.class_file = class_file 419 self.attribute_length = u4(data[0:4]) 420 self.max_stack = u2(data[4:6]) 421 self.max_locals = u2(data[6:8]) 422 self.code_length = u4(data[8:12]) 423 end_of_code = 12+self.code_length 424 self.code = data[12:end_of_code] 425 self.exception_table_length = u2(data[end_of_code:end_of_code+2]) 426 self.exception_table = [] 427 data = data[end_of_code + 2:] 428 for i in range(0, self.exception_table_length): 429 exception = ExceptionInfo() 430 data = exception.init(data) 431 self.exception_table.append(exception) 432 self.attributes, data = self.class_file._get_attributes(data) 433 return data 434 def serialize(self): 435 od = su4(self.attribute_length)+su2(self.max_stack)+su2(self.max_locals)+su4(self.code_length)+self.code 436 od += su2(self.exception_table_length) 437 for e in self.exception_table: 438 od += e.serialize() 439 od += self.class_file._serialize_attributes(self.attributes) 440 return od 441 442 class ExceptionsAttributeInfo(AttributeInfo): 443 def init(self, data, class_file): 444 self.class_file = class_file 445 self.attribute_length = u4(data[0:4]) 446 self.number_of_exceptions = u2(data[4:6]) 447 self.exception_index_table = [] 448 index = 6 449 for i in range(0, self.number_of_exceptions): 450 self.exception_index_table.append(u2(data[index:index+2])) 451 index += 2 452 return data[index:] 453 454 def get_exception(self, i): 455 exception_index = self.exception_index_table[i] 456 return self.class_file.constants[exception_index - 1] 457 458 def serialize(self): 459 od = su4(self.attribute_length)+su2(self.number_of_exceptions) 460 for ei in self.exception_index_table: 461 od += su2(ei) 462 return od 463 464 class InnerClassesAttributeInfo(AttributeInfo): 465 def init(self, data, class_file): 466 self.class_file = class_file 467 self.attribute_length = u4(data[0:4]) 468 self.number_of_classes = u2(data[4:6]) 469 self.classes = [] 470 data = data[6:] 471 for i in range(0, self.number_of_classes): 472 inner_class = InnerClassInfo() 473 data = inner_class.init(data, self.class_file) 474 self.classes.append(inner_class) 475 return data 476 477 def serialize(self): 478 od = su4(self.attribute_length)+su2(self.number_of_classes) 479 for c in self.classes: 480 od += c.serialize() 481 return od 482 483 class SyntheticAttributeInfo(AttributeInfo): 484 pass 485 486 class LineNumberAttributeInfo(AttributeInfo): 487 def init(self, data, class_file): 488 self.class_file = class_file 489 self.attribute_length = u4(data[0:4]) 490 self.line_number_table_length = u2(data[4:6]) 491 self.line_number_table = [] 492 data = data[6:] 493 for i in range(0, self.line_number_table_length): 494 line_number = LineNumberInfo() 495 data = line_number.init(data) 496 self.line_number_table.append(line_number) 497 return data 498 499 def serialize(self): 500 od = su4(self.attribute_length)+su2(self.line_number_table_length) 501 for ln in self.line_number_table: 502 od += ln.serialize() 503 return od 504 505 class LocalVariableAttributeInfo(AttributeInfo): 506 def init(self, data, class_file): 507 self.class_file = class_file 508 self.attribute_length = u4(data[0:4]) 509 self.local_variable_table_length = u2(data[4:6]) 510 self.local_variable_table = [] 511 data = data[6:] 512 for i in range(0, self.local_variable_table_length): 513 local_variable = LocalVariableInfo() 514 data = local_variable.init(data, self.class_file) 515 self.local_variable_table.append(local_variable) 516 return data 517 518 def serialize(self): 519 od = su4(self.attribute_length)+su2(self.local_variable_table_length) 520 for lv in self.local_variable_table: 521 od += lv.serialize() 522 return od 523 524 class DeprecatedAttributeInfo(AttributeInfo): 525 pass 526 527 # Child classes of the attribute information classes. 528 529 class ExceptionInfo: 530 def init(self, data): 531 self.start_pc = u2(data[0:2]) 532 self.end_pc = u2(data[2:4]) 533 self.handler_pc = u2(data[4:6]) 534 self.catch_type = u2(data[6:8]) 535 return data[8:] 536 def serialize(self): 537 return su2(self.start_pc)+su2(self.end_pc)+su2(self.handler_pc)+su2(self.catch_type) 538 539 class InnerClassInfo(NameUtils): 540 def init(self, data, class_file): 541 self.class_file = class_file 542 self.inner_class_info_index = u2(data[0:2]) 543 self.outer_class_info_index = u2(data[2:4]) 544 # Permit the NameUtils mix-in. 545 self.name_index = self.inner_name_index = u2(data[4:6]) 546 self.inner_class_access_flags = u2(data[6:8]) 547 return data[8:] 548 def serialize(self): 549 return su2(self.inner_class_info_index)+su2(self.outer_class_info_index)+su2(self.name_index)+su2(self.inner_class_access_flags) 550 551 class LineNumberInfo: 552 def init(self, data): 553 self.start_pc = u2(data[0:2]) 554 self.line_number = u2(data[2:4]) 555 return data[4:] 556 557 def serialize(self): 558 return su2(self.start_pc)+su2(self.line_number) 559 560 class LocalVariableInfo(NameUtils, PythonNameUtils): 561 def init(self, data, class_file): 562 self.class_file = class_file 563 self.start_pc = u2(data[0:2]) 564 self.length = u2(data[2:4]) 565 self.name_index = u2(data[4:6]) 566 self.descriptor_index = u2(data[6:8]) 567 self.index = u2(data[8:10]) 568 return data[10:] 569 570 def get_descriptor(self): 571 return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1])) 572 573 def serialize(self): 574 return su2(self.start_pc)+su2(self.length)+su2(self.name_index)+su2(self.descriptor_index)+su2(self.index) 575 576 # Exceptions. 577 578 class UnknownTag(Exception): 579 pass 580 581 class UnknownAttribute(Exception): 582 pass 583 584 # Abstractions for the main structures. 585 586 class ClassFile: 587 588 "A class representing a Java class file." 589 590 def __init__(self, s): 591 592 """ 593 Process the given string 's', populating the object with the class 594 file's details. 595 """ 596 597 self.attribute_class_to_index = None 598 self.minorv,self.majorv = u2(s[4:]),u2(s[6:]) 599 self.constants, s = self._get_constants(s[8:]) 600 self.access_flags, s = self._get_access_flags(s) 601 self.this_class, s = self._get_this_class(s) 602 self.super_class, s = self._get_super_class(s) 603 self.interfaces, s = self._get_interfaces(s) 604 self.fields, s = self._get_fields(s) 605 self.methods, s = self._get_methods(s) 606 self.attributes, s = self._get_attributes(s) 607 608 def serialize(self): 609 od = su4(0xCAFEBABE)+su2(self.minorv)+su2(self.majorv) 610 od += self._serialize_constants() 611 od += self._serialize_access_flags() 612 od += self._serialize_this_class() 613 od += self._serialize_super_class() 614 od += self._serialize_interfaces() 615 od += self._serialize_fields() 616 od += self._serialize_methods() 617 od += self._serialize_attributes(self.attributes) 618 return od 619 620 def _encode_const(self, c): 621 od = '' 622 if isinstance(c, Utf8Info): 623 od += su1(1) 624 elif isinstance(c, IntegerInfo): 625 od += su1(3) 626 elif isinstance(c, FloatInfo): 627 od += su1(4) 628 elif isinstance(c, LongInfo): 629 od += su1(5) 630 elif isinstance(c, DoubleInfo): 631 od += su1(6) 632 elif isinstance(c, ClassInfo): 633 od += su1(7) 634 elif isinstance(c, StringInfo): 635 od += su1(8) 636 elif isinstance(c, FieldRefInfo): 637 od += su1(9) 638 elif isinstance(c, MethodRefInfo): 639 od += su1(10) 640 elif isinstance(c, InterfaceMethodRefInfo): 641 od += su1(11) 642 elif isinstance(c, NameAndTypeInfo): 643 od += su1(12) 644 else: 645 return od 646 od += c.serialize() 647 return od 648 649 def _decode_const(self, s): 650 tag = u1(s[0:1]) 651 if tag == 1: 652 const = Utf8Info() 653 elif tag == 3: 654 const = IntegerInfo() 655 elif tag == 4: 656 const = FloatInfo() 657 elif tag == 5: 658 const = LongInfo() 659 elif tag == 6: 660 const = DoubleInfo() 661 elif tag == 7: 662 const = ClassInfo() 663 elif tag == 8: 664 const = StringInfo() 665 elif tag == 9: 666 const = FieldRefInfo() 667 elif tag == 10: 668 const = MethodRefInfo() 669 elif tag == 11: 670 const = InterfaceMethodRefInfo() 671 elif tag == 12: 672 const = NameAndTypeInfo() 673 else: 674 raise UnknownTag, tag 675 676 # Initialise the constant object. 677 678 s = const.init(s[1:], self) 679 return const, s 680 681 def _get_constants_from_table(self, count, s): 682 l = [] 683 # Have to skip certain entries specially. 684 i = 1 685 while i < count: 686 c, s = self._decode_const(s) 687 l.append(c) 688 # Add a blank entry after "large" entries. 689 if isinstance(c, LargeNumInfo): 690 l.append(None) 691 i += 1 692 i += 1 693 return l, s 694 695 def _get_items_from_table(self, cls, number, s): 696 l = [] 697 for i in range(0, number): 698 f = cls() 699 s = f.init(s, self) 700 l.append(f) 701 return l, s 702 703 def _get_methods_from_table(self, number, s): 704 return self._get_items_from_table(MethodInfo, number, s) 705 706 def _get_fields_from_table(self, number, s): 707 return self._get_items_from_table(FieldInfo, number, s) 708 709 def _get_attribute_from_table(self, s): 710 attribute_name_index = u2(s[0:2]) 711 constant_name = self.constants[attribute_name_index - 1].bytes 712 if constant_name == "SourceFile": 713 attribute = SourceFileAttributeInfo() 714 elif constant_name == "ConstantValue": 715 attribute = ConstantValueAttributeInfo() 716 elif constant_name == "Code": 717 attribute = CodeAttributeInfo() 718 elif constant_name == "Exceptions": 719 attribute = ExceptionsAttributeInfo() 720 elif constant_name == "InnerClasses": 721 attribute = InnerClassesAttributeInfo() 722 elif constant_name == "Synthetic": 723 attribute = SyntheticAttributeInfo() 724 elif constant_name == "LineNumberTable": 725 attribute = LineNumberAttributeInfo() 726 elif constant_name == "LocalVariableTable": 727 attribute = LocalVariableAttributeInfo() 728 elif constant_name == "Deprecated": 729 attribute = DeprecatedAttributeInfo() 730 else: 731 raise UnknownAttribute, constant_name 732 s = attribute.init(s[2:], self) 733 return attribute, s 734 735 def _get_attributes_from_table(self, number, s): 736 attributes = [] 737 for i in range(0, number): 738 attribute, s = self._get_attribute_from_table(s) 739 attributes.append(attribute) 740 return attributes, s 741 742 def _get_constants(self, s): 743 count = u2(s[0:2]) 744 return self._get_constants_from_table(count, s[2:]) 745 746 def _serialize_constants(self): 747 return su2(len(self.constants)+1)+"".join([self._encode_const(c) for c in self.constants]) 748 749 def _get_access_flags(self, s): 750 return u2(s[0:2]), s[2:] 751 752 def _serialize_access_flags(self): 753 return su2(self.access_flags) 754 755 def _get_this_class(self, s): 756 index = u2(s[0:2]) 757 return self.constants[index - 1], s[2:] 758 759 def _serialize_this_class(self): 760 return su2(self.constants.index(self.this_class)+1) 761 762 def _serialize_super_class(self): 763 return su2(self.constants.index(self.super_class)+1) 764 765 def _get_super_class(self, s): 766 index = u2(s[0:2]) 767 if index != 0: 768 return self.constants[index - 1], s[2:] 769 else: 770 return None, s[2:] 771 772 def _get_interfaces(self, s): 773 interfaces = [] 774 number = u2(s[0:2]) 775 s = s[2:] 776 for i in range(0, number): 777 index = u2(s[0:2]) 778 interfaces.append(self.constants[index - 1]) 779 s = s[2:] 780 return interfaces, s 781 782 def _serialize_interfaces(self): 783 return su2(len(self.interfaces))+"".join([su2(self.interfaces.index(interf)+1) for interf in self.interfaces]) 784 785 def _get_fields(self, s): 786 number = u2(s[0:2]) 787 return self._get_fields_from_table(number, s[2:]) 788 789 def _serialize_fields(self): 790 od = su2(len(self.fields)) 791 od += "".join([f.serialize() for f in self.fields]) 792 return od 793 794 def _get_attributes(self, s): 795 number = u2(s[0:2]) 796 return self._get_attributes_from_table(number, s[2:]) 797 798 def _serialize_attributes(self, attrs): 799 od = su2(len(attrs)) 800 if len(attrs) == 0: return od 801 if self.attribute_class_to_index == None: 802 self.attribute_class_to_index = {} 803 attr_names_to_class = {"SourceFile":SourceFileAttributeInfo, "ConstantValue":ConstantValueAttributeInfo, 804 "Code":CodeAttributeInfo, "Exceptions":ExceptionsAttributeInfo, 805 "InnerClasses":InnerClassesAttributeInfo, "Synthetic":SyntheticAttributeInfo, 806 "LineNumberTable":LineNumberAttributeInfo, "LocalVariableTable":LocalVariableAttributeInfo, 807 "Deprecated":DeprecatedAttributeInfo} 808 index = 0 809 for c in self.constants: 810 index += 1 811 if isinstance(c, Utf8Info) and str(c) in attr_names_to_class.keys(): 812 self.attribute_class_to_index[attr_names_to_class[str(c)]]=index 813 for attribute in attrs: 814 for (classtype,name_index) in self.attribute_class_to_index.iteritems(): 815 if isinstance(attribute, classtype): 816 od += su2(name_index) 817 break 818 od += attribute.serialize() 819 return od 820 821 def _get_methods(self, s): 822 number = u2(s[0:2]) 823 return self._get_methods_from_table(number, s[2:]) 824 825 def _serialize_methods(self): 826 od = su2(len(self.methods)) 827 od += "".join([m.serialize() for m in self.methods]) 828 return od 829 830 831 if __name__ == "__main__": 832 import sys 833 f = open(sys.argv[1], "rb") 834 c = ClassFile(f.read()) 835 f.close() 836 837 # vim: tabstop=4 expandtab shiftwidth=4