1 ## Copyright (C) 2004, 2005 Free Software Foundation
2 ## Written by Gary Benson <gbenson@redhat.com>
4 ## This program is free software; you can redistribute it and/or modify
5 ## it under the terms of the GNU General Public License as published by
6 ## the Free Software Foundation; either version 2 of the License, or
7 ## (at your option) any later version.
9 ## This program is distributed in the hope that it will be useful,
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details.
14 """Read Java(TM) class files."""
16 import cStringIO
as StringIO
20 def __init__(self
, arg
):
21 if hasattr(arg
, "read"):
23 elif type(arg
) == type(""):
24 if arg
.startswith("\xca\xfe\xba\xbe"):
25 self
.fp
= StringIO
.StringIO(arg
)
27 self
.fp
= open(arg
, "r")
29 raise TypeError, type(arg
)
31 magic
= self
._read
_int
()
32 assert magic
== 0xcafebabeL
33 minor
, major
= self
._read
(">HH")
34 self
.version
= (major
, minor
)
36 self
.pool_integrity_checks
= None
39 except AssertionError:
40 self
.pool_integrity_checks
= []
42 self
._read
_constants
_pool
()
44 self
.access_flags
= self
._read
_short
()
45 self
.name
= self
._read
_reference
_Class
()
46 self
.super = self
._read
_reference
_Class
()
48 self
.interfaces
= self
._read
_interfaces
()
49 self
.fields
= self
._read
_fieldsormethods
()
50 self
.methods
= self
._read
_fieldsormethods
()
51 self
.attributes
= self
._read
_attributes
()
53 if self
.pool_integrity_checks
is not None:
54 for index
, tag
in self
.pool_integrity_checks
:
55 assert self
.constants
[index
][0] == tag
57 del self
.fp
, self
.pool_integrity_checks
61 attrs
= [attr
for attr
in dir(self
)
62 if not attr
.startswith("_") and attr
!= "Member"]
65 result
.append("%-13s %s" % (
66 attr
+ ":", attr
== "constants" and
67 "<ELIDED>" or repr(getattr(self
, attr
))))
68 return "\n".join(result
)
70 def _read_constants_pool(self
):
73 for i
in xrange(1, self
._read
_short
()):
78 1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
79 6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
80 10: "Methodref", 11: "InterfaceMethodref",
81 12: "NameAndType"}[self
._read
_byte
()]
82 skip
= tag
in ("Long", "Double") # crack crack crack!
83 self
.constants
[i
] = (tag
, getattr(self
, "_read_constant_" + tag
)())
85 def _read_interfaces(self
):
87 for i
in xrange(self
._read
_short
()):
88 result
.append(self
._read
_reference
_Class
())
91 def _read_fieldsormethods(self
):
93 for i
in xrange(self
._read
_short
()):
94 result
.append(self
.Member(self
))
98 def __init__(self
, source
):
99 self
.access_flags
= source
._read
_short
()
100 self
.name
= source
._read
_reference
_Utf
8()
101 self
.descriptor
= source
._read
_reference
_Utf
8()
102 self
.attributes
= source
._read
_attributes
()
106 attrs
= [attr
for attr
in dir(self
) if not attr
.startswith("_")]
109 value
= getattr(self
, attr
)
110 if attr
== "attributes" and value
.has_key("Code"):
112 value
.update({"Code": "<ELIDED>"})
113 result
.append("%-13s %s" % (
114 attr
+ ":", repr(value
).replace(
115 "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
116 return ("\n%s" % (15 * " ")).join(result
)
118 def _read_attributes(self
):
120 for i
in xrange(self
._read
_short
()):
121 name
= self
._read
_reference
_Utf
8()
122 data
= self
.fp
.read(self
._read
_int
())
123 assert not result
.has_key(name
)
127 # Constants pool reference reader convenience functions
129 def _read_reference_Utf8(self
):
130 return self
._read
_references
("Utf8")[0]
132 def _read_reference_Class(self
):
133 return self
._read
_references
("Class")[0]
135 def _read_reference_Class_NameAndType(self
):
136 return self
._read
_references
("Class", "NameAndType")
138 def _read_references(self
, *args
):
141 index
= self
._read
_short
()
142 if self
.pool_integrity_checks
is not None:
143 self
.pool_integrity_checks
.append((index
, arg
))
147 # Constants pool constant reader functions
149 def _read_constant_Utf8(self
):
150 constant
= self
.fp
.read(self
._read
_short
())
152 constant
= constant
.decode("utf-8")
154 constant
= _bork_utf8_decode(constant
)
156 constant
= constant
.encode("us-ascii")
161 def _read_constant_Integer(self
):
162 return self
._read
_int
()
164 def _read_constant_Float(self
):
165 return self
._read
(">f")[0]
167 def _read_constant_Long(self
):
168 return self
._read
(">q")[0]
170 def _read_constant_Double(self
):
171 return self
._read
(">d")[0]
173 _read_constant_Class
= _read_reference_Utf8
174 _read_constant_String
= _read_reference_Utf8
175 _read_constant_Fieldref
= _read_reference_Class_NameAndType
176 _read_constant_Methodref
= _read_reference_Class_NameAndType
177 _read_constant_InterfaceMethodref
= _read_reference_Class_NameAndType
179 def _read_constant_NameAndType(self
):
180 return self
._read
_reference
_Utf
8(), self
._read
_reference
_Utf
8()
182 # Generic reader functions
185 # XXX how else to read 32 bits on a 64-bit box?
186 h
, l
= map(long, self
._read
(">HH"))
189 def _read_short(self
):
190 return self
._read
(">H")[0]
192 def _read_byte(self
):
193 return self
._read
("B")[0]
195 def _read(self
, fmt
):
196 return struct
.unpack(fmt
, self
.fp
.read(struct
.calcsize(fmt
)))
198 def _bork_utf8_decode(data
):
200 bytes
, unicode = map(ord, data
), ""
206 assert b2
& 0xC0 == 0x80
210 assert b3
& 0xC0 == 0x80
212 ((b1
& 0x0f) << 12) + ((b2
& 0x3f) << 6) + (b3
& 0x3f))
214 unicode += unichr(((b1
& 0x1f) << 6) + (b2
& 0x3f))
216 unicode += unichr(b1
)
219 if __name__
== "__main__":
220 print Class("/usr/share/katana/build/ListDependentClasses.class")