javaclass

Change of javaclass/classfile.py

137:182cba61327c
javaclass/classfile.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/javaclass/classfile.py	Fri Jan 21 17:05:06 2005 +0100
     1.3 @@ -0,0 +1,633 @@
     1.4 +#!/usr/bin/env python
     1.5 +
     1.6 +"""
     1.7 +Java class file decoder. Specification found at the following URL:
     1.8 +http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
     1.9 +"""
    1.10 +
    1.11 +import struct # for general decoding of class files
    1.12 +
    1.13 +# Utility functions.
    1.14 +
    1.15 +def u1(data):
    1.16 +    return struct.unpack(">B", data[0:1])[0]
    1.17 +
    1.18 +def u2(data):
    1.19 +    return struct.unpack(">H", data[0:2])[0]
    1.20 +
    1.21 +def s2(data):
    1.22 +    return struct.unpack(">h", data[0:2])[0]
    1.23 +
    1.24 +def u4(data):
    1.25 +    return struct.unpack(">L", data[0:4])[0]
    1.26 +
    1.27 +def s4(data):
    1.28 +    return struct.unpack(">l", data[0:4])[0]
    1.29 +
    1.30 +def s8(data):
    1.31 +    return struct.unpack(">q", data[0:8])[0]
    1.32 +
    1.33 +def f4(data):
    1.34 +    return struct.unpack(">f", data[0:4])[0]
    1.35 +
    1.36 +def f8(data):
    1.37 +    return struct.unpack(">d", data[0:8])[0]
    1.38 +
    1.39 +# Useful tables and constants.
    1.40 +
    1.41 +descriptor_base_type_mapping = {
    1.42 +    "B" : "int",
    1.43 +    "C" : "str",
    1.44 +    "D" : "float",
    1.45 +    "F" : "float",
    1.46 +    "I" : "int",
    1.47 +    "J" : "int",
    1.48 +    "L" : "object",
    1.49 +    "S" : "int",
    1.50 +    "Z" : "bool",
    1.51 +    "[" : "list"
    1.52 +    }
    1.53 +
    1.54 +PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL,  SUPER,  SYNCHRONIZED, VOLATILE, TRANSIENT, NATIVE, INTERFACE, ABSTRACT, STRICT = \
    1.55 +0x0001, 0x0002,  0x0004,    0x0008, 0x0010, 0x0020, 0x0020,       0x0040,   0x0080,    0x0100, 0x0200,    0x0400,   0x0800
    1.56 +
    1.57 +def has_flags(flags, desired):
    1.58 +    desired_flags = reduce(lambda a, b: a | b, desired, 0)
    1.59 +    return (flags & desired_flags) == desired_flags
    1.60 +
    1.61 +# Useful mix-ins.
    1.62 +
    1.63 +class PythonMethodUtils:
    1.64 +    symbol_sep = "___" # was "$"
    1.65 +    type_sep = "__" # replaces "/"
    1.66 +    array_sep = "_array_" # was "[]"
    1.67 +    base_seps = ("_", "_") # was "<" and ">"
    1.68 +
    1.69 +    def get_unqualified_python_name(self):
    1.70 +        name = self.get_name()
    1.71 +        if str(name) == "<init>":
    1.72 +            return "__init__"
    1.73 +        elif str(name) == "<clinit>":
    1.74 +            return "__clinit__"
    1.75 +        else:
    1.76 +            return str(name)
    1.77 +
    1.78 +    def get_python_name(self):
    1.79 +        name = self.get_unqualified_python_name()
    1.80 +        if name == "__clinit__":
    1.81 +            return name
    1.82 +        return name + self.symbol_sep + self._get_descriptor_as_name()
    1.83 +
    1.84 +    def _get_descriptor_as_name(self):
    1.85 +        l = []
    1.86 +        for descriptor_type in self.get_descriptor()[0]:
    1.87 +            l.append(self._get_type_as_name(descriptor_type))
    1.88 +        return self.symbol_sep.join(l)
    1.89 +
    1.90 +    def _get_type_as_name(self, descriptor_type, s=""):
    1.91 +        base_type, object_type, array_type = descriptor_type
    1.92 +        if base_type == "L":
    1.93 +            return object_type.replace("/", self.type_sep) + s
    1.94 +        elif base_type == "[":
    1.95 +            return self._get_type_as_name(array_type, s + self.array_sep)
    1.96 +        else:
    1.97 +            return self.base_seps[0] + base_type + self.base_seps[1] + s
    1.98 +
    1.99 +class PythonNameUtils:
   1.100 +    def get_python_name(self):
   1.101 +        # NOTE: This may not be comprehensive.
   1.102 +        if not str(self.get_name()).startswith("["):
   1.103 +            return str(self.get_name()).replace("/", ".")
   1.104 +        else:
   1.105 +            return self._get_type_name(
   1.106 +                get_field_descriptor(
   1.107 +                    str(self.get_name())
   1.108 +                    )
   1.109 +                ).replace("/", ".")
   1.110 +
   1.111 +    def _get_type_name(self, descriptor_type):
   1.112 +        base_type, object_type, array_type = descriptor_type
   1.113 +        if base_type == "L":
   1.114 +            return object_type
   1.115 +        elif base_type == "[":
   1.116 +            return self._get_type_name(array_type)
   1.117 +        else:
   1.118 +            return descriptor_base_type_mapping[base_type]
   1.119 +
   1.120 +class NameUtils:
   1.121 +    def get_name(self):
   1.122 +        if self.name_index != 0:
   1.123 +            return self.class_file.constants[self.name_index - 1]
   1.124 +        else:
   1.125 +            # Some name indexes are zero to indicate special conditions.
   1.126 +            return None
   1.127 +
   1.128 +class NameAndTypeUtils:
   1.129 +    def get_name(self):
   1.130 +        if self.name_and_type_index != 0:
   1.131 +            return self.class_file.constants[self.name_and_type_index - 1].get_name()
   1.132 +        else:
   1.133 +            # Some name indexes are zero to indicate special conditions.
   1.134 +            return None
   1.135 +
   1.136 +    def get_field_descriptor(self):
   1.137 +        if self.name_and_type_index != 0:
   1.138 +            return self.class_file.constants[self.name_and_type_index - 1].get_field_descriptor()
   1.139 +        else:
   1.140 +            # Some name indexes are zero to indicate special conditions.
   1.141 +            return None
   1.142 +
   1.143 +    def get_method_descriptor(self):
   1.144 +        if self.name_and_type_index != 0:
   1.145 +            return self.class_file.constants[self.name_and_type_index - 1].get_method_descriptor()
   1.146 +        else:
   1.147 +            # Some name indexes are zero to indicate special conditions.
   1.148 +            return None
   1.149 +
   1.150 +    def get_class(self):
   1.151 +        return self.class_file.constants[self.class_index - 1]
   1.152 +
   1.153 +# Symbol parsing.
   1.154 +
   1.155 +def get_method_descriptor(s):
   1.156 +    assert s[0] == "("
   1.157 +    params = []
   1.158 +    s = s[1:]
   1.159 +    while s[0] != ")":
   1.160 +        parameter_descriptor, s = _get_parameter_descriptor(s)
   1.161 +        params.append(parameter_descriptor)
   1.162 +    if s[1] != "V":
   1.163 +        return_type, s = _get_field_type(s[1:])
   1.164 +    else:
   1.165 +        return_type, s = None, s[1:]
   1.166 +    return params, return_type
   1.167 +
   1.168 +def get_field_descriptor(s):
   1.169 +    return _get_field_type(s)[0]
   1.170 +
   1.171 +def _get_parameter_descriptor(s):
   1.172 +    return _get_field_type(s)
   1.173 +
   1.174 +def _get_component_type(s):
   1.175 +    return _get_field_type(s)
   1.176 +
   1.177 +def _get_field_type(s):
   1.178 +    base_type, s = _get_base_type(s)
   1.179 +    object_type = None
   1.180 +    array_type = None
   1.181 +    if base_type == "L":
   1.182 +        object_type, s = _get_object_type(s)
   1.183 +    elif base_type == "[":
   1.184 +        array_type, s = _get_array_type(s)
   1.185 +    return (base_type, object_type, array_type), s
   1.186 +
   1.187 +def _get_base_type(s):
   1.188 +    if len(s) > 0:
   1.189 +        return s[0], s[1:]
   1.190 +    else:
   1.191 +        return None, s
   1.192 +
   1.193 +def _get_object_type(s):
   1.194 +    if len(s) > 0:
   1.195 +        s_end = s.find(";")
   1.196 +        assert s_end != -1
   1.197 +        return s[:s_end], s[s_end+1:]
   1.198 +    else:
   1.199 +        return None, s
   1.200 +
   1.201 +def _get_array_type(s):
   1.202 +    if len(s) > 0:
   1.203 +        return _get_component_type(s)
   1.204 +    else:
   1.205 +        return None, s
   1.206 +
   1.207 +# Constant information.
   1.208 +
   1.209 +class ClassInfo(NameUtils, PythonNameUtils):
   1.210 +    def init(self, data, class_file):
   1.211 +        self.class_file = class_file
   1.212 +        self.name_index = u2(data[0:2])
   1.213 +        return data[2:]
   1.214 +
   1.215 +class RefInfo(NameAndTypeUtils):
   1.216 +    def init(self, data, class_file):
   1.217 +        self.class_file = class_file
   1.218 +        self.class_index = u2(data[0:2])
   1.219 +        self.name_and_type_index = u2(data[2:4])
   1.220 +        return data[4:]
   1.221 +
   1.222 +class FieldRefInfo(RefInfo, PythonNameUtils):
   1.223 +    def get_descriptor(self):
   1.224 +        return RefInfo.get_field_descriptor(self)
   1.225 +
   1.226 +class MethodRefInfo(RefInfo, PythonMethodUtils):
   1.227 +    def get_descriptor(self):
   1.228 +        return RefInfo.get_method_descriptor(self)
   1.229 +
   1.230 +class InterfaceMethodRefInfo(MethodRefInfo):
   1.231 +    pass
   1.232 +
   1.233 +class NameAndTypeInfo(NameUtils, PythonNameUtils):
   1.234 +    def init(self, data, class_file):
   1.235 +        self.class_file = class_file
   1.236 +        self.name_index = u2(data[0:2])
   1.237 +        self.descriptor_index = u2(data[2:4])
   1.238 +        return data[4:]
   1.239 +
   1.240 +    def get_field_descriptor(self):
   1.241 +        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   1.242 +
   1.243 +    def get_method_descriptor(self):
   1.244 +        return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   1.245 +
   1.246 +class Utf8Info:
   1.247 +    def init(self, data, class_file):
   1.248 +        self.class_file = class_file
   1.249 +        self.length = u2(data[0:2])
   1.250 +        self.bytes = data[2:2+self.length]
   1.251 +        return data[2+self.length:]
   1.252 +
   1.253 +    def __str__(self):
   1.254 +        return self.bytes
   1.255 +
   1.256 +    def __unicode__(self):
   1.257 +        return unicode(self.bytes, "utf-8")
   1.258 +
   1.259 +    def get_value(self):
   1.260 +        return str(self)
   1.261 +
   1.262 +class StringInfo:
   1.263 +    def init(self, data, class_file):
   1.264 +        self.class_file = class_file
   1.265 +        self.string_index = u2(data[0:2])
   1.266 +        return data[2:]
   1.267 +
   1.268 +    def __str__(self):
   1.269 +        return str(self.class_file.constants[self.string_index - 1])
   1.270 +
   1.271 +    def __unicode__(self):
   1.272 +        return unicode(self.class_file.constants[self.string_index - 1])
   1.273 +
   1.274 +    def get_value(self):
   1.275 +        return str(self)
   1.276 +
   1.277 +class SmallNumInfo:
   1.278 +    def init(self, data, class_file):
   1.279 +        self.class_file = class_file
   1.280 +        self.bytes = data[0:4]
   1.281 +        return data[4:]
   1.282 +
   1.283 +class IntegerInfo(SmallNumInfo):
   1.284 +    def get_value(self):
   1.285 +        return s4(self.bytes)
   1.286 +
   1.287 +class FloatInfo(SmallNumInfo):
   1.288 +    def get_value(self):
   1.289 +        return f4(self.bytes)
   1.290 +
   1.291 +class LargeNumInfo:
   1.292 +    def init(self, data, class_file):
   1.293 +        self.class_file = class_file
   1.294 +        self.high_bytes = data[0:4]
   1.295 +        self.low_bytes = data[4:8]
   1.296 +        return data[8:]
   1.297 +
   1.298 +class LongInfo(LargeNumInfo):
   1.299 +    def get_value(self):
   1.300 +        return s8(self.high_bytes + self.low_bytes)
   1.301 +
   1.302 +class DoubleInfo(LargeNumInfo):
   1.303 +    def get_value(self):
   1.304 +        return f8(self.high_bytes + self.low_bytes)
   1.305 +
   1.306 +# Other information.
   1.307 +# Objects of these classes are generally aware of the class they reside in.
   1.308 +
   1.309 +class ItemInfo(NameUtils):
   1.310 +    def init(self, data, class_file):
   1.311 +        self.class_file = class_file
   1.312 +        self.access_flags = u2(data[0:2])
   1.313 +        self.name_index = u2(data[2:4])
   1.314 +        self.descriptor_index = u2(data[4:6])
   1.315 +        self.attributes, data = self.class_file._get_attributes(data[6:])
   1.316 +        return data
   1.317 +
   1.318 +class FieldInfo(ItemInfo, PythonNameUtils):
   1.319 +    def get_descriptor(self):
   1.320 +        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   1.321 +
   1.322 +class MethodInfo(ItemInfo, PythonMethodUtils):
   1.323 +    def get_descriptor(self):
   1.324 +        return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   1.325 +
   1.326 +class AttributeInfo:
   1.327 +    def init(self, data, class_file):
   1.328 +        self.attribute_length = u4(data[0:4])
   1.329 +        self.info = data[4:4+self.attribute_length]
   1.330 +        return data[4+self.attribute_length:]
   1.331 +
   1.332 +# NOTE: Decode the different attribute formats.
   1.333 +
   1.334 +class SourceFileAttributeInfo(AttributeInfo, NameUtils, PythonNameUtils):
   1.335 +    def init(self, data, class_file):
   1.336 +        self.class_file = class_file
   1.337 +        self.attribute_length = u4(data[0:4])
   1.338 +        # Permit the NameUtils mix-in.
   1.339 +        self.name_index = self.sourcefile_index = u2(data[4:6])
   1.340 +        return data[6:]
   1.341 +
   1.342 +class ConstantValueAttributeInfo(AttributeInfo):
   1.343 +    def init(self, data, class_file):
   1.344 +        self.class_file = class_file
   1.345 +        self.attribute_length = u4(data[0:4])
   1.346 +        self.constant_value_index = u2(data[4:6])
   1.347 +        assert 4+self.attribute_length == 6
   1.348 +        return data[4+self.attribute_length:]
   1.349 +
   1.350 +    def get_value(self):
   1.351 +        return self.class_file.constants[self.constant_value_index - 1].get_value()
   1.352 +
   1.353 +class CodeAttributeInfo(AttributeInfo):
   1.354 +    def init(self, data, class_file):
   1.355 +        self.class_file = class_file
   1.356 +        self.attribute_length = u4(data[0:4])
   1.357 +        self.max_stack = u2(data[4:6])
   1.358 +        self.max_locals = u2(data[6:8])
   1.359 +        self.code_length = u4(data[8:12])
   1.360 +        end_of_code = 12+self.code_length
   1.361 +        self.code = data[12:end_of_code]
   1.362 +        self.exception_table_length = u2(data[end_of_code:end_of_code+2])
   1.363 +        self.exception_table = []
   1.364 +        data = data[end_of_code + 2:]
   1.365 +        for i in range(0, self.exception_table_length):
   1.366 +            exception = ExceptionInfo()
   1.367 +            data = exception.init(data)
   1.368 +            self.exception_table.append(exception)
   1.369 +        self.attributes, data = self.class_file._get_attributes(data)
   1.370 +        return data
   1.371 +
   1.372 +class ExceptionsAttributeInfo(AttributeInfo):
   1.373 +    def init(self, data, class_file):
   1.374 +        self.class_file = class_file
   1.375 +        self.attribute_length = u4(data[0:4])
   1.376 +        self.number_of_exceptions = u2(data[4:6])
   1.377 +        self.exception_index_table = []
   1.378 +        index = 6
   1.379 +        for i in range(0, self.number_of_exceptions):
   1.380 +            self.exception_index_table.append(u2(data[index:index+2]))
   1.381 +            index += 2
   1.382 +        return data[index:]
   1.383 +
   1.384 +    def get_exception(self, i):
   1.385 +        exception_index = self.exception_index_table[i]
   1.386 +        return self.class_file.constants[exception_index - 1]
   1.387 +
   1.388 +class InnerClassesAttributeInfo(AttributeInfo):
   1.389 +    def init(self, data, class_file):
   1.390 +        self.class_file = class_file
   1.391 +        self.attribute_length = u4(data[0:4])
   1.392 +        self.number_of_classes = u2(data[4:6])
   1.393 +        self.classes = []
   1.394 +        data = data[6:]
   1.395 +        for i in range(0, self.number_of_classes):
   1.396 +            inner_class = InnerClassInfo()
   1.397 +            data = inner_class.init(data, self.class_file)
   1.398 +            self.classes.append(inner_class)
   1.399 +        return data
   1.400 +
   1.401 +class SyntheticAttributeInfo(AttributeInfo):
   1.402 +    pass
   1.403 +
   1.404 +class LineNumberAttributeInfo(AttributeInfo):
   1.405 +    def init(self, data, class_file):
   1.406 +        self.class_file = class_file
   1.407 +        self.attribute_length = u4(data[0:4])
   1.408 +        self.line_number_table_length = u2(data[4:6])
   1.409 +        self.line_number_table = []
   1.410 +        data = data[6:]
   1.411 +        for i in range(0, self.line_number_table_length):
   1.412 +            line_number = LineNumberInfo()
   1.413 +            data = line_number.init(data)
   1.414 +            self.line_number_table.append(line_number)
   1.415 +        return data
   1.416 +
   1.417 +class LocalVariableAttributeInfo(AttributeInfo):
   1.418 +    def init(self, data, class_file):
   1.419 +        self.class_file = class_file
   1.420 +        self.attribute_length = u4(data[0:4])
   1.421 +        self.local_variable_table_length = u2(data[4:6])
   1.422 +        self.local_variable_table = []
   1.423 +        data = data[6:]
   1.424 +        for i in range(0, self.local_variable_table_length):
   1.425 +            local_variable = LocalVariableInfo()
   1.426 +            data = local_variable.init(data, self.class_file)
   1.427 +            self.local_variable_table.append(local_variable)
   1.428 +        return data
   1.429 +
   1.430 +class DeprecatedAttributeInfo(AttributeInfo):
   1.431 +    pass
   1.432 +
   1.433 +# Child classes of the attribute information classes.
   1.434 +
   1.435 +class ExceptionInfo:
   1.436 +    def init(self, data):
   1.437 +        self.start_pc = u2(data[0:2])
   1.438 +        self.end_pc = u2(data[2:4])
   1.439 +        self.handler_pc = u2(data[4:6])
   1.440 +        self.catch_type = u2(data[6:8])
   1.441 +        return data[8:]
   1.442 +
   1.443 +class InnerClassInfo(NameUtils):
   1.444 +    def init(self, data, class_file):
   1.445 +        self.class_file = class_file
   1.446 +        self.inner_class_info_index = u2(data[0:2])
   1.447 +        self.outer_class_info_index = u2(data[2:4])
   1.448 +        # Permit the NameUtils mix-in.
   1.449 +        self.name_index = self.inner_name_index = u2(data[4:6])
   1.450 +        self.inner_class_access_flags = u2(data[6:8])
   1.451 +        return data[8:]
   1.452 +
   1.453 +class LineNumberInfo:
   1.454 +    def init(self, data):
   1.455 +        self.start_pc = u2(data[0:2])
   1.456 +        self.line_number = u2(data[2:4])
   1.457 +        return data[4:]
   1.458 +
   1.459 +class LocalVariableInfo(NameUtils, PythonNameUtils):
   1.460 +    def init(self, data, class_file):
   1.461 +        self.class_file = class_file
   1.462 +        self.start_pc = u2(data[0:2])
   1.463 +        self.length = u2(data[2:4])
   1.464 +        self.name_index = u2(data[4:6])
   1.465 +        self.descriptor_index = u2(data[6:8])
   1.466 +        self.index = u2(data[8:10])
   1.467 +        return data[10:]
   1.468 +
   1.469 +    def get_descriptor(self):
   1.470 +        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   1.471 +
   1.472 +# Exceptions.
   1.473 +
   1.474 +class UnknownTag(Exception):
   1.475 +    pass
   1.476 +
   1.477 +class UnknownAttribute(Exception):
   1.478 +    pass
   1.479 +
   1.480 +# Abstractions for the main structures.
   1.481 +
   1.482 +class ClassFile:
   1.483 +
   1.484 +    "A class representing a Java class file."
   1.485 +
   1.486 +    def __init__(self, s):
   1.487 +
   1.488 +        """
   1.489 +        Process the given string 's', populating the object with the class
   1.490 +        file's details.
   1.491 +        """
   1.492 +
   1.493 +        self.constants, s = self._get_constants(s[8:])
   1.494 +        self.access_flags, s = self._get_access_flags(s)
   1.495 +        self.this_class, s = self._get_this_class(s)
   1.496 +        self.super_class, s = self._get_super_class(s)
   1.497 +        self.interfaces, s = self._get_interfaces(s)
   1.498 +        self.fields, s = self._get_fields(s)
   1.499 +        self.methods, s = self._get_methods(s)
   1.500 +        self.attributes, s = self._get_attributes(s)
   1.501 +
   1.502 +    def _decode_const(self, s):
   1.503 +        tag = u1(s[0:1])
   1.504 +        if tag == 1:
   1.505 +            const = Utf8Info()
   1.506 +        elif tag == 3:
   1.507 +            const = IntegerInfo()
   1.508 +        elif tag == 4:
   1.509 +            const = FloatInfo()
   1.510 +        elif tag == 5:
   1.511 +            const = LongInfo()
   1.512 +        elif tag == 6:
   1.513 +            const = DoubleInfo()
   1.514 +        elif tag == 7:
   1.515 +            const = ClassInfo()
   1.516 +        elif tag == 8:
   1.517 +            const = StringInfo()
   1.518 +        elif tag == 9:
   1.519 +            const = FieldRefInfo()
   1.520 +        elif tag == 10:
   1.521 +            const = MethodRefInfo()
   1.522 +        elif tag == 11:
   1.523 +            const = InterfaceMethodRefInfo()
   1.524 +        elif tag == 12:
   1.525 +            const = NameAndTypeInfo()
   1.526 +        else:
   1.527 +            raise UnknownTag, tag
   1.528 +
   1.529 +        # Initialise the constant object.
   1.530 +
   1.531 +        s = const.init(s[1:], self)
   1.532 +        return const, s
   1.533 +
   1.534 +    def _get_constants_from_table(self, count, s):
   1.535 +        l = []
   1.536 +        # Have to skip certain entries specially.
   1.537 +        i = 1
   1.538 +        while i < count:
   1.539 +            c, s = self._decode_const(s)
   1.540 +            l.append(c)
   1.541 +            # Add a blank entry after "large" entries.
   1.542 +            if isinstance(c, LargeNumInfo):
   1.543 +                l.append(None)
   1.544 +                i += 1
   1.545 +            i += 1
   1.546 +        return l, s
   1.547 +
   1.548 +    def _get_items_from_table(self, cls, number, s):
   1.549 +        l = []
   1.550 +        for i in range(0, number):
   1.551 +            f = cls()
   1.552 +            s = f.init(s, self)
   1.553 +            l.append(f)
   1.554 +        return l, s
   1.555 +
   1.556 +    def _get_methods_from_table(self, number, s):
   1.557 +        return self._get_items_from_table(MethodInfo, number, s)
   1.558 +
   1.559 +    def _get_fields_from_table(self, number, s):
   1.560 +        return self._get_items_from_table(FieldInfo, number, s)
   1.561 +
   1.562 +    def _get_attribute_from_table(self, s):
   1.563 +        attribute_name_index = u2(s[0:2])
   1.564 +        constant_name = self.constants[attribute_name_index - 1].bytes
   1.565 +        if constant_name == "SourceFile":
   1.566 +            attribute = SourceFileAttributeInfo()
   1.567 +        elif constant_name == "ConstantValue":
   1.568 +            attribute = ConstantValueAttributeInfo()
   1.569 +        elif constant_name == "Code":
   1.570 +            attribute = CodeAttributeInfo()
   1.571 +        elif constant_name == "Exceptions":
   1.572 +            attribute = ExceptionsAttributeInfo()
   1.573 +        elif constant_name == "InnerClasses":
   1.574 +            attribute = InnerClassesAttributeInfo()
   1.575 +        elif constant_name == "Synthetic":
   1.576 +            attribute = SyntheticAttributeInfo()
   1.577 +        elif constant_name == "LineNumberTable":
   1.578 +            attribute = LineNumberAttributeInfo()
   1.579 +        elif constant_name == "LocalVariableTable":
   1.580 +            attribute = LocalVariableAttributeInfo()
   1.581 +        elif constant_name == "Deprecated":
   1.582 +            attribute = DeprecatedAttributeInfo()
   1.583 +        else:
   1.584 +            raise UnknownAttribute, constant_name
   1.585 +        s = attribute.init(s[2:], self)
   1.586 +        return attribute, s
   1.587 +
   1.588 +    def _get_attributes_from_table(self, number, s):
   1.589 +        attributes = []
   1.590 +        for i in range(0, number):
   1.591 +            attribute, s = self._get_attribute_from_table(s)
   1.592 +            attributes.append(attribute)
   1.593 +        return attributes, s
   1.594 +
   1.595 +    def _get_constants(self, s):
   1.596 +        count = u2(s[0:2])
   1.597 +        return self._get_constants_from_table(count, s[2:])
   1.598 +
   1.599 +    def _get_access_flags(self, s):
   1.600 +        return u2(s[0:2]), s[2:]
   1.601 +
   1.602 +    def _get_this_class(self, s):
   1.603 +        index = u2(s[0:2])
   1.604 +        return self.constants[index - 1], s[2:]
   1.605 +
   1.606 +    _get_super_class = _get_this_class
   1.607 +
   1.608 +    def _get_interfaces(self, s):
   1.609 +        interfaces = []
   1.610 +        number = u2(s[0:2])
   1.611 +        s = s[2:]
   1.612 +        for i in range(0, number):
   1.613 +            index = u2(s[0:2])
   1.614 +            interfaces.append(self.constants[index - 1])
   1.615 +            s = s[2:]
   1.616 +        return interfaces, s
   1.617 +
   1.618 +    def _get_fields(self, s):
   1.619 +        number = u2(s[0:2])
   1.620 +        return self._get_fields_from_table(number, s[2:])
   1.621 +
   1.622 +    def _get_attributes(self, s):
   1.623 +        number = u2(s[0:2])
   1.624 +        return self._get_attributes_from_table(number, s[2:])
   1.625 +
   1.626 +    def _get_methods(self, s):
   1.627 +        number = u2(s[0:2])
   1.628 +        return self._get_methods_from_table(number, s[2:])
   1.629 +
   1.630 +if __name__ == "__main__":
   1.631 +    import sys
   1.632 +    f = open(sys.argv[1], "rb")
   1.633 +    c = ClassFile(f.read())
   1.634 +    f.close()
   1.635 +
   1.636 +# vim: tabstop=4 expandtab shiftwidth=4