1.1 --- a/javaclass/classfile.py Wed Mar 23 23:15:41 2011 +0100
1.2 +++ b/javaclass/classfile.py Thu Mar 24 00:54:11 2011 +0100
1.3 @@ -33,6 +33,30 @@
1.4 def f8(data):
1.5 return struct.unpack(">d", data[0:8])[0]
1.6
1.7 +def su1(value):
1.8 + return struct.pack(">B", value)
1.9 +
1.10 +def su2(value):
1.11 + return struct.pack(">H", value)
1.12 +
1.13 +def ss2(value):
1.14 + return struct.pack(">h", value)
1.15 +
1.16 +def su4(value):
1.17 + return struct.pack(">L", value)
1.18 +
1.19 +def ss4(value):
1.20 + return struct.pack(">l", value)
1.21 +
1.22 +def ss8(value):
1.23 + return struct.pack(">q", value)
1.24 +
1.25 +def sf4(value):
1.26 + return struct.pack(">f", value)
1.27 +
1.28 +def sf8(value):
1.29 + return struct.pack(">d", value)
1.30 +
1.31 # Useful tables and constants.
1.32
1.33 descriptor_base_type_mapping = {
1.34 @@ -221,6 +245,8 @@
1.35 self.class_file = class_file
1.36 self.name_index = u2(data[0:2])
1.37 return data[2:]
1.38 + def serialize(self):
1.39 + return su2(self.name_index)
1.40
1.41 class RefInfo(NameAndTypeUtils):
1.42 def init(self, data, class_file):
1.43 @@ -228,6 +254,8 @@
1.44 self.class_index = u2(data[0:2])
1.45 self.name_and_type_index = u2(data[2:4])
1.46 return data[4:]
1.47 + def serialize(self):
1.48 + return su2(self.class_index)+su2(self.name_and_type_index)
1.49
1.50 class FieldRefInfo(RefInfo, PythonNameUtils):
1.51 def get_descriptor(self):
1.52 @@ -247,6 +275,9 @@
1.53 self.descriptor_index = u2(data[2:4])
1.54 return data[4:]
1.55
1.56 + def serialize(self):
1.57 + return su2(self.name_index)+su2(self.descriptor_index)
1.58 +
1.59 def get_field_descriptor(self):
1.60 return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.61
1.62 @@ -260,6 +291,9 @@
1.63 self.bytes = data[2:2+self.length]
1.64 return data[2+self.length:]
1.65
1.66 + def serialize(self):
1.67 + return su2(self.length)+self.bytes
1.68 +
1.69 def __str__(self):
1.70 return self.bytes
1.71
1.72 @@ -275,6 +309,9 @@
1.73 self.string_index = u2(data[0:2])
1.74 return data[2:]
1.75
1.76 + def serialize(self):
1.77 + return su2(self.string_index)
1.78 +
1.79 def __str__(self):
1.80 return str(self.class_file.constants[self.string_index - 1])
1.81
1.82 @@ -289,6 +326,8 @@
1.83 self.class_file = class_file
1.84 self.bytes = data[0:4]
1.85 return data[4:]
1.86 + def serialize(self):
1.87 + return self.bytes
1.88
1.89 class IntegerInfo(SmallNumInfo):
1.90 def get_value(self):
1.91 @@ -304,6 +343,9 @@
1.92 self.high_bytes = data[0:4]
1.93 self.low_bytes = data[4:8]
1.94 return data[8:]
1.95 + def serialize(self):
1.96 + return self.high_bytes+self.low_bytes
1.97 +
1.98
1.99 class LongInfo(LargeNumInfo):
1.100 def get_value(self):
1.101 @@ -324,6 +366,10 @@
1.102 self.descriptor_index = u2(data[4:6])
1.103 self.attributes, data = self.class_file._get_attributes(data[6:])
1.104 return data
1.105 + def serialize(self):
1.106 + od = su2(self.access_flags)+su2(self.name_index)+su2(self.descriptor_index)
1.107 + od += self.class_file._serialize_attributes(self.attributes)
1.108 + return od
1.109
1.110 class FieldInfo(ItemInfo, PythonNameUtils):
1.111 def get_descriptor(self):
1.112 @@ -338,6 +384,8 @@
1.113 self.attribute_length = u4(data[0:4])
1.114 self.info = data[4:4+self.attribute_length]
1.115 return data[4+self.attribute_length:]
1.116 + def serialize(self):
1.117 + return su4(self.attribute_length)+self.info
1.118
1.119 # NOTE: Decode the different attribute formats.
1.120
1.121 @@ -348,6 +396,8 @@
1.122 # Permit the NameUtils mix-in.
1.123 self.name_index = self.sourcefile_index = u2(data[4:6])
1.124 return data[6:]
1.125 + def serialize(self):
1.126 + return su4(self.attribute_length)+su2(self.name_index)
1.127
1.128 class ConstantValueAttributeInfo(AttributeInfo):
1.129 def init(self, data, class_file):
1.130 @@ -360,6 +410,9 @@
1.131 def get_value(self):
1.132 return self.class_file.constants[self.constant_value_index - 1].get_value()
1.133
1.134 + def serialize(self):
1.135 + return su4(self.attribute_length)+su2(self.constant_value_index)
1.136 +
1.137 class CodeAttributeInfo(AttributeInfo):
1.138 def init(self, data, class_file):
1.139 self.class_file = class_file
1.140 @@ -378,6 +431,13 @@
1.141 self.exception_table.append(exception)
1.142 self.attributes, data = self.class_file._get_attributes(data)
1.143 return data
1.144 + def serialize(self):
1.145 + od = su4(self.attribute_length)+su2(self.max_stack)+su2(self.max_locals)+su4(self.code_length)+self.code
1.146 + od += su2(self.exception_table_length)
1.147 + for e in self.exception_table:
1.148 + od += e.serialize()
1.149 + od += self.class_file._serialize_attributes(self.attributes)
1.150 + return od
1.151
1.152 class ExceptionsAttributeInfo(AttributeInfo):
1.153 def init(self, data, class_file):
1.154 @@ -394,6 +454,12 @@
1.155 def get_exception(self, i):
1.156 exception_index = self.exception_index_table[i]
1.157 return self.class_file.constants[exception_index - 1]
1.158 +
1.159 + def serialize(self):
1.160 + od = su4(self.attribute_length)+su2(self.number_of_exceptions)
1.161 + for ei in self.exception_index_table:
1.162 + od += su2(ei)
1.163 + return od
1.164
1.165 class InnerClassesAttributeInfo(AttributeInfo):
1.166 def init(self, data, class_file):
1.167 @@ -408,6 +474,12 @@
1.168 self.classes.append(inner_class)
1.169 return data
1.170
1.171 + def serialize(self):
1.172 + od = su4(self.attribute_length)+su2(self.number_of_classes)
1.173 + for c in self.classes:
1.174 + od += c.serialize()
1.175 + return od
1.176 +
1.177 class SyntheticAttributeInfo(AttributeInfo):
1.178 pass
1.179
1.180 @@ -423,6 +495,12 @@
1.181 data = line_number.init(data)
1.182 self.line_number_table.append(line_number)
1.183 return data
1.184 +
1.185 + def serialize(self):
1.186 + od = su4(self.attribute_length)+su2(self.line_number_table_length)
1.187 + for ln in self.line_number_table:
1.188 + od += ln.serialize()
1.189 + return od
1.190
1.191 class LocalVariableAttributeInfo(AttributeInfo):
1.192 def init(self, data, class_file):
1.193 @@ -437,6 +515,12 @@
1.194 self.local_variable_table.append(local_variable)
1.195 return data
1.196
1.197 + def serialize(self):
1.198 + od = su4(self.attribute_length)+su2(self.local_variable_table_length)
1.199 + for lv in self.local_variable_table:
1.200 + od += lv.serialize()
1.201 + return od
1.202 +
1.203 class DeprecatedAttributeInfo(AttributeInfo):
1.204 pass
1.205
1.206 @@ -449,6 +533,8 @@
1.207 self.handler_pc = u2(data[4:6])
1.208 self.catch_type = u2(data[6:8])
1.209 return data[8:]
1.210 + def serialize(self):
1.211 + return su2(self.start_pc)+su2(self.end_pc)+su2(self.handler_pc)+su2(self.catch_type)
1.212
1.213 class InnerClassInfo(NameUtils):
1.214 def init(self, data, class_file):
1.215 @@ -459,12 +545,17 @@
1.216 self.name_index = self.inner_name_index = u2(data[4:6])
1.217 self.inner_class_access_flags = u2(data[6:8])
1.218 return data[8:]
1.219 + def serialize(self):
1.220 + return su2(self.inner_class_info_index)+su2(self.outer_class_info_index)+su2(self.name_index)+su2(self.inner_class_access_flags)
1.221
1.222 class LineNumberInfo:
1.223 def init(self, data):
1.224 self.start_pc = u2(data[0:2])
1.225 self.line_number = u2(data[2:4])
1.226 return data[4:]
1.227 +
1.228 + def serialize(self):
1.229 + return su2(self.start_pc)+su2(self.line_number)
1.230
1.231 class LocalVariableInfo(NameUtils, PythonNameUtils):
1.232 def init(self, data, class_file):
1.233 @@ -478,6 +569,9 @@
1.234
1.235 def get_descriptor(self):
1.236 return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.237 +
1.238 + def serialize(self):
1.239 + return su2(self.start_pc)+su2(self.length)+su2(self.name_index)+su2(self.descriptor_index)+su2(self.index)
1.240
1.241 # Exceptions.
1.242
1.243 @@ -500,6 +594,8 @@
1.244 file's details.
1.245 """
1.246
1.247 + self.attribute_class_to_index = None
1.248 + self.minorv,self.majorv = u2(s[4:]),u2(s[6:])
1.249 self.constants, s = self._get_constants(s[8:])
1.250 self.access_flags, s = self._get_access_flags(s)
1.251 self.this_class, s = self._get_this_class(s)
1.252 @@ -509,6 +605,47 @@
1.253 self.methods, s = self._get_methods(s)
1.254 self.attributes, s = self._get_attributes(s)
1.255
1.256 + def serialize(self):
1.257 + od = su4(0xCAFEBABE)+su2(self.minorv)+su2(self.majorv)
1.258 + od += self._serialize_constants()
1.259 + od += self._serialize_access_flags()
1.260 + od += self._serialize_this_class()
1.261 + od += self._serialize_super_class()
1.262 + od += self._serialize_interfaces()
1.263 + od += self._serialize_fields()
1.264 + od += self._serialize_methods()
1.265 + od += self._serialize_attributes(self.attributes)
1.266 + return od
1.267 +
1.268 + def _encode_const(self, c):
1.269 + od = ''
1.270 + if isinstance(c, Utf8Info):
1.271 + od += su1(1)
1.272 + elif isinstance(c, IntegerInfo):
1.273 + od += su1(3)
1.274 + elif isinstance(c, FloatInfo):
1.275 + od += su1(4)
1.276 + elif isinstance(c, LongInfo):
1.277 + od += su1(5)
1.278 + elif isinstance(c, DoubleInfo):
1.279 + od += su1(6)
1.280 + elif isinstance(c, ClassInfo):
1.281 + od += su1(7)
1.282 + elif isinstance(c, StringInfo):
1.283 + od += su1(8)
1.284 + elif isinstance(c, FieldRefInfo):
1.285 + od += su1(9)
1.286 + elif isinstance(c, MethodRefInfo):
1.287 + od += su1(10)
1.288 + elif isinstance(c, InterfaceMethodRefInfo):
1.289 + od += su1(11)
1.290 + elif isinstance(c, NameAndTypeInfo):
1.291 + od += su1(12)
1.292 + else:
1.293 + return od
1.294 + od += c.serialize()
1.295 + return od
1.296 +
1.297 def _decode_const(self, s):
1.298 tag = u1(s[0:1])
1.299 if tag == 1:
1.300 @@ -606,13 +743,25 @@
1.301 count = u2(s[0:2])
1.302 return self._get_constants_from_table(count, s[2:])
1.303
1.304 + def _serialize_constants(self):
1.305 + return su2(len(self.constants)+1)+"".join([self._encode_const(c) for c in self.constants])
1.306 +
1.307 def _get_access_flags(self, s):
1.308 return u2(s[0:2]), s[2:]
1.309 +
1.310 + def _serialize_access_flags(self):
1.311 + return su2(self.access_flags)
1.312
1.313 def _get_this_class(self, s):
1.314 index = u2(s[0:2])
1.315 return self.constants[index - 1], s[2:]
1.316
1.317 + def _serialize_this_class(self):
1.318 + return su2(self.constants.index(self.this_class)+1)
1.319 +
1.320 + def _serialize_super_class(self):
1.321 + return su2(self.constants.index(self.super_class)+1)
1.322 +
1.323 def _get_super_class(self, s):
1.324 index = u2(s[0:2])
1.325 if index != 0:
1.326 @@ -630,18 +779,55 @@
1.327 s = s[2:]
1.328 return interfaces, s
1.329
1.330 + def _serialize_interfaces(self):
1.331 + return su2(len(self.interfaces))+"".join([su2(self.interfaces.index(interf)+1) for interf in self.interfaces])
1.332 +
1.333 def _get_fields(self, s):
1.334 number = u2(s[0:2])
1.335 return self._get_fields_from_table(number, s[2:])
1.336
1.337 + def _serialize_fields(self):
1.338 + od = su2(len(self.fields))
1.339 + od += "".join([f.serialize() for f in self.fields])
1.340 + return od
1.341 +
1.342 def _get_attributes(self, s):
1.343 number = u2(s[0:2])
1.344 return self._get_attributes_from_table(number, s[2:])
1.345
1.346 + def _serialize_attributes(self, attrs):
1.347 + od = su2(len(attrs))
1.348 + if len(attrs) == 0: return od
1.349 + if self.attribute_class_to_index == None:
1.350 + self.attribute_class_to_index = {}
1.351 + attr_names_to_class = {"SourceFile":SourceFileAttributeInfo, "ConstantValue":ConstantValueAttributeInfo,
1.352 + "Code":CodeAttributeInfo, "Exceptions":ExceptionsAttributeInfo,
1.353 + "InnerClasses":InnerClassesAttributeInfo, "Synthetic":SyntheticAttributeInfo,
1.354 + "LineNumberTable":LineNumberAttributeInfo, "LocalVariableTable":LocalVariableAttributeInfo,
1.355 + "Deprecated":DeprecatedAttributeInfo}
1.356 + index = 0
1.357 + for c in self.constants:
1.358 + index += 1
1.359 + if isinstance(c, Utf8Info) and str(c) in attr_names_to_class.keys():
1.360 + self.attribute_class_to_index[attr_names_to_class[str(c)]]=index
1.361 + for attribute in attrs:
1.362 + for (classtype,name_index) in self.attribute_class_to_index.iteritems():
1.363 + if isinstance(attribute, classtype):
1.364 + od += su2(name_index)
1.365 + break
1.366 + od += attribute.serialize()
1.367 + return od
1.368 +
1.369 def _get_methods(self, s):
1.370 number = u2(s[0:2])
1.371 return self._get_methods_from_table(number, s[2:])
1.372
1.373 + def _serialize_methods(self):
1.374 + od = su2(len(self.methods))
1.375 + od += "".join([m.serialize() for m in self.methods])
1.376 + return od
1.377 +
1.378 +
1.379 if __name__ == "__main__":
1.380 import sys
1.381 f = open(sys.argv[1], "rb")