@@ -38,6 +38,9 @@ def __init__(self):
3838 self .superclass = None
3939
4040 def __str__ (self ):
41+ return self .__repr__ ()
42+
43+ def __repr__ (self ):
4144 return "[%s:0x%X]" % (self .name , self .serialVersionUID )
4245
4346
@@ -77,6 +80,35 @@ class JavaObjectMarshaller:
7780 SC_EXTERNALIZABLE = 0x04
7881 SC_ENUM = 0x10
7982
83+ # type definition chars (typecode)
84+ TYPE_BYTE = 'B' # 0x42
85+ TYPE_CHAR = 'C'
86+ TYPE_DOUBLE = 'D' # 0x44
87+ TYPE_FLOAT = 'F' # 0x46
88+ TYPE_INTEGER = 'I' # 0x49
89+ TYPE_LONG = 'J' # 0x4A
90+ TYPE_SHORT = 'S' # 0x53
91+ TYPE_BOOLEAN = 'Z' # 0x5A
92+ TYPE_OBJECT = 'L' # 0x4C
93+ TYPE_ARRAY = '[' # 0x5B
94+
95+ # list of supported typecodes listed above
96+ TYPECODES_LIST = [
97+ # primitive types
98+ TYPE_BYTE ,
99+ TYPE_CHAR ,
100+ TYPE_DOUBLE ,
101+ TYPE_FLOAT ,
102+ TYPE_INTEGER ,
103+ TYPE_LONG ,
104+ TYPE_SHORT ,
105+ TYPE_BOOLEAN ,
106+ # object types
107+ TYPE_OBJECT ,
108+ TYPE_ARRAY ]
109+
110+ BASE_REFERENCE_IDX = 0x7E0000
111+
80112 def __init__ (self ):
81113 self .opmap = {
82114 self .TC_NULL : self .do_null ,
@@ -89,11 +121,17 @@ def __init__(self):
89121 self .TC_REFERENCE : self .do_reference
90122 }
91123 self .current_object = None
124+ self .reference_counter = 0
125+ self .references = []
92126
93127 def load_stream (self , stream ):
94- self .object_stream = stream
95- self ._readStreamHeader ()
96- return self .readObject ()
128+ try :
129+ self .object_stream = stream
130+ self ._readStreamHeader ()
131+ return self .readObject ()
132+ except Exception , e :
133+ self .dump_state ()
134+ raise
97135
98136 def _readStreamHeader (self ):
99137 (magic , version ) = self ._readStruct (">HH" )
@@ -153,7 +191,10 @@ def do_classdesc(self, parent=None, ident=0):
153191 (serialVersionUID , newHandle , classDescFlags ) = self ._readStruct (">LLB" )
154192 clazz .serialVersionUID = serialVersionUID
155193 clazz .flags = classDescFlags
156- self .print_ident ("Serial: 0x%X newHanle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID , newHandle , classDescFlags ), ident )
194+
195+ self .add_reference (clazz )
196+
197+ self .print_ident ("Serial: 0x%X newHandle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID , newHandle , classDescFlags ), ident )
157198 (length , ) = self ._readStruct (">H" )
158199 self .print_ident ("Fields num: 0x%X" % length , ident )
159200
@@ -165,16 +206,19 @@ def do_classdesc(self, parent=None, ident=0):
165206 field_type = None
166207 field_type = self .convert_char_to_type (type )
167208
168- if field_type == "array" :
209+ if field_type == self . TYPE_ARRAY :
169210 field_type = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_STRING , self .TC_REFERENCE ])
170211 if field_type is not None :
171212 field_type = "array of " + field_type
172213 else :
173214 field_type = "array of None"
174- elif field_type == "object" :
215+ elif field_type == self . TYPE_OBJECT :
175216 field_type = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_STRING , self .TC_REFERENCE ])
176217
177218 self .print_ident ("FieldName: 0x%X" % type + " " + str (field_name ) + " " + str (field_type ), ident )
219+ assert field_name is not None
220+ assert field_type is not None
221+
178222 clazz .fields_names .append (field_name )
179223 clazz .fields_types .append (field_type )
180224 if parent :
@@ -206,6 +250,7 @@ def do_class(self, parent=None, ident=0):
206250 # TODO: what to do with "(ClassDesc)prevObject". (see 3rd line for classDesc:)
207251 classdesc = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_CLASSDESC , self .TC_PROXYCLASSDESC , self .TC_NULL ])
208252 self .print_ident ("Classdesc: %s" % classdesc , ident )
253+ self .add_reference (classdesc )
209254 return classdesc
210255
211256 def do_object (self , parent = None , ident = 0 ):
@@ -214,7 +259,10 @@ def do_object(self, parent=None, ident=0):
214259 self .print_ident ("[object]" , ident )
215260
216261 # TODO: what to do with "(ClassDesc)prevObject". (see 3rd line for classDesc:)
217- classdesc = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_CLASSDESC , self .TC_PROXYCLASSDESC , self .TC_NULL ])
262+ classdesc = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_CLASSDESC , self .TC_PROXYCLASSDESC , self .TC_NULL , self .TC_REFERENCE ])
263+ # self.TC_REFERENCE hasn't shown in spec, but actually is here
264+
265+ self .add_reference (java_object )
218266
219267 # classdata[]
220268
@@ -254,23 +302,27 @@ def do_object(self, parent=None, ident=0):
254302 def do_string (self , parent = None , ident = 0 ):
255303 self .print_ident ("[string]" , ident )
256304 ba = self ._readString ()
305+ self .add_reference (str (ba ))
257306 return str (ba )
258307
259308 def do_array (self , parent = None , ident = 0 ):
260309 # TC_ARRAY classDesc newHandle (int)<size> values[size]
261310 self .print_ident ("[array]" , ident )
262311 classdesc = self .read_and_exec_opcode (ident = ident + 1 , expect = [self .TC_CLASSDESC , self .TC_PROXYCLASSDESC , self .TC_NULL ])
263- (size , ) = self ._readStruct (">i" )
264- self .print_ident ("size: " + str (size ), ident )
265312
266313 array = []
267314
315+ self .add_reference (array )
316+
317+ (size , ) = self ._readStruct (">i" )
318+ self .print_ident ("size: " + str (size ), ident )
319+
268320# for char in classdesc.name:
269- typestr = self . convert_char_to_type ( classdesc .name [0 ])
270- assert typestr == "array"
271- typestr = self . convert_char_to_type ( classdesc .name [1 ])
321+ type_char = classdesc .name [0 ]
322+ assert type_char == self . TYPE_ARRAY
323+ type_char = classdesc .name [1 ]
272324
273- if typestr == "object" or typestr == "array" :
325+ if type_char == self . TYPE_OBJECT or type_char == self . TYPE_ARRAY :
274326 for i in range (size ):
275327 res = self .read_and_exec_opcode (ident = ident + 1 )
276328 print res
@@ -285,9 +337,10 @@ def do_array(self, parent=None, ident=0):
285337 return None
286338
287339 def do_reference (self , parent = None , ident = 0 ):
288- # TODO: Reference isn't supported yed
289- (handle , reference ) = self ._readStruct (">HH" )
290- print "## Reference:" , handle , reference
340+ # TODO: Reference isn't supported yet
341+ (handle , ) = self ._readStruct (">L" )
342+ print "## Reference handle: 0x%x" % (handle )
343+ return self .references [handle - self .BASE_REFERENCE_IDX ]
291344# raise NotImplementedError("Reference isn't supported yed.")
292345
293346 def do_null (self , parent = None , ident = 0 ):
@@ -310,50 +363,48 @@ def hexdump(self, src, length=16):
310363 return '' .join (result )
311364
312365 def read_native (self , field_type , ident ):
313- if field_type == "boolean" :
366+ if len (field_type ) > 1 :
367+ field_type = field_type [0 ] # We don't need details for arrays and objects
368+
369+ if field_type == self .TYPE_BOOLEAN :
314370 (val , ) = self ._readStruct (">B" )
315371 res = bool (val )
316- elif field_type == "byte" :
372+ elif field_type == self . TYPE_BYTE :
317373 (res , ) = self ._readStruct (">b" )
318- elif field_type == "short" :
374+ elif field_type == self . TYPE_SHORT :
319375 (res , ) = self ._readStruct (">h" )
320- elif field_type == "integer" :
376+ elif field_type == self . TYPE_INTEGER :
321377 (res , ) = self ._readStruct (">i" )
322- elif field_type == "long" :
378+ elif field_type == self . TYPE_LONG :
323379 (res , ) = self ._readStruct (">q" )
324- elif field_type == "float" :
380+ elif field_type == self . TYPE_FLOAT :
325381 (res , ) = self ._readStruct (">f" )
326- elif field_type == "double" :
382+ elif field_type == self . TYPE_DOUBLE :
327383 (res , ) = self ._readStruct (">d" )
328- else :
384+ elif field_type == self . TYPE_OBJECT or field_type == self . TYPE_ARRAY :
329385 res = self .read_and_exec_opcode (ident = ident + 1 )
386+ else :
387+ raise RuntimeError ("Unknown typecode: %s" % field_type )
330388 return res
331389
332390 def convert_char_to_type (self , type_char ):
333- if type (type_char ) is str :
334- type_char = ord (type_char )
335-
336- if type_char == 0x44 : # 'D': Double
337- return "double"
338- elif type_char == 0x49 : # 'I': Integer
339- return "integer"
340- elif type_char == 0x4A : # 'J': Long
341- return "long"
342- elif type_char == 0x53 : # 'S': Short
343- return "short"
344- elif type_char == 0x5A : # 'Z': Boolean
345- return "boolean"
346- elif type_char == 0x5B : # '[': Array
347- return "array"
348- elif type_char == 0x42 : # 'B': Byte
349- return "byte"
350- elif type_char == 0x46 : # 'F': Float
351- return "float"
352- elif type_char == 0x4C : # 'L': Object
353- return "object"
391+ typecode = type_char
392+ print ">>>> type:" , type (type_char )
393+ if type (type_char ) is int :
394+ typecode = chr (type_char )
395+
396+ if typecode in self .TYPECODES_LIST :
397+ return typecode
354398 else :
355- raise NotImplementedError ("type 0x%X (%s) isn't implemented yet" % (0 , type_char ))
399+ raise RuntimeError ("Typecode %s (%s) isn't supported." % (type_char , typecode ))
400+
401+ def add_reference (self , obj ):
402+ self .references .append (obj )
356403
404+ def dump_state (self ):
405+ print "==Oops state dump" + "=" * (30 - 17 )
406+ print "Referenes:" , self .references
407+ print "=" * 30
357408 # =====================================================================================
358409
359410 def dump (self , obj ):
0 commit comments