Skip to content

Commit 64de2e4

Browse files
author
vbuell
committed
Simple objects are working
1 parent af723c4 commit 64de2e4

File tree

2 files changed

+75
-26
lines changed

2 files changed

+75
-26
lines changed

javaobj.py

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class JavaObjectMarshaller:
2323
STREAM_MAGIC = 0xaced
2424
STREAM_VERSION = 0x05
2525

26+
TC_NULL = 0x70
2627
TC_REFERENCE = 0x71
2728
TC_CLASSDESC = 0x72
2829
TC_OBJECT = 0x73
@@ -41,16 +42,18 @@ class JavaObjectMarshaller:
4142

4243
def __init__(self, stream):
4344
self.opmap = {
44-
self.TC_CLASSDESC: self.do_classdesc,
45-
self.TC_OBJECT: self.do_object,
46-
self.TC_STRING: self.do_string,
47-
self.TC_CLASS: self.do_class,
48-
self.TC_BLOCKDATA: self.do_blockdata,
49-
self.TC_REFERENCE: self.do_reference
45+
self.TC_NULL: self.do_null,
46+
self.TC_CLASSDESC: self.do_classdesc,
47+
self.TC_OBJECT: self.do_object,
48+
self.TC_STRING: self.do_string,
49+
self.TC_CLASS: self.do_class,
50+
self.TC_BLOCKDATA: self.do_blockdata,
51+
self.TC_REFERENCE: self.do_reference
5052
}
5153
self.object_stream = stream
5254
self._readStreamHeader()
5355
self.finalValue = True
56+
self.current_object = None
5457

5558
def _readStreamHeader(self):
5659
(magic, version) = self._readStruct(">HH", 4)
@@ -60,8 +63,13 @@ def _readStreamHeader(self):
6063
def readObject(self):
6164
(opid, ) = self._readStruct(">B", 1)
6265
print "OpCode: 0x%X" % opid
63-
self.opmap.get(opid, self.do_default_stuff)()
64-
return self.finalValue
66+
res = self.opmap.get(opid, self.do_default_stuff)()
67+
return res
68+
69+
def read_and_exec_opcode(self):
70+
(opid, ) = self._readStruct(">B", 1)
71+
print "OpCode: 0x%X" % opid
72+
return self.opmap.get(opid, self.do_default_stuff)()
6573

6674
def _readStruct(self, unpack, length):
6775
ba = self.object_stream.read(length)
@@ -80,58 +88,95 @@ def do_classdesc(self, parent=None):
8088
# (byte) // Defined in Terminal Symbols and Constants
8189
# fields:
8290
# (short)<count> fieldDesc[count]
83-
91+
8492
# fieldDesc:
8593
# primitiveDesc
8694
# objectDesc
8795
# primitiveDesc:
8896
# prim_typecode fieldName
8997
# objectDesc:
9098
# obj_typecode fieldName className1
99+
class JavaClass(object):
100+
def __init__(self):
101+
self.name = None
102+
self.serialVersionUID = None
103+
self.flags = None
104+
self.fields_names = []
105+
self.fields_types = []
106+
107+
def __str__(self):
108+
return "[%s:0x%X]" % (self.name, self.serialVersionUID)
109+
110+
clazz = JavaClass()
91111
print "[classdesc]"
92112
ba = self._readString()
113+
clazz.name = ba
93114
print "Class name:", ba
94115
(serialVersionUID, newHandle, classDescFlags) = self._readStruct(">LLB", 4+4+1)
116+
clazz.serialVersionUID = serialVersionUID
117+
clazz.flags = classDescFlags
95118
print "Serial: 0x%X newHanle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID, newHandle, classDescFlags)
96119
(length, ) = self._readStruct(">H", 2)
97120
print "Fields num: 0x%X" % length
98121

99-
fields_vals = []
100-
fields_type = []
122+
fields_names = []
123+
fields_types = []
101124
for fieldId in range(length):
102125
(type, ) = self._readStruct(">B", 1)
103126
ba = self._readString()
104127
print "FieldType: 0x%X" % type, ba
105128
(opid, ) = self._readStruct(">B", 1)
106129
print "OpCode: 0x%X" % opid
107130
res = self.opmap.get(opid, self.do_default_stuff)()
108-
fields_vals.append(res)
109-
fields_type.append(type)
131+
fields_names.append(ba)
132+
fields_types.append(res)
110133
if parent:
111-
parent.__setattr__("__fields", fields_vals)
112-
parent.__setattr__("__types", fields_types)
134+
parent.__fields = fields_names
135+
parent.__types = fields_types
136+
# classAnnotation
137+
(opid, ) = self._readStruct(">B", 1)
138+
if opid != self.TC_ENDBLOCKDATA:
139+
raise NotImplementedError("classAnnotation isn't implemented yet")
140+
print "OpCode: 0x%X" % opid
141+
# superClassDesc
142+
(opid, ) = self._readStruct(">B", 1)
143+
print "OpCode: 0x%X" % opid
144+
self.opmap.get(opid, self.do_default_stuff)()
145+
146+
return clazz
113147

114148
def do_blockdata(self, parent=None):
115149
# TC_BLOCKDATA (unsigned byte)<size> (byte)[size]
116150
print "[blockdata]"
117151
(length, ) = self._readStruct(">B", 1)
118152
ba = self.object_stream.read(length)
119-
self.finalValue = ba
153+
return ba
120154

121155
def do_class(self, parent=None):
122156
# TC_CLASS classDesc newHandle
123157
print "[class]"
158+
clazz = self.read_and_exec_opcode()
159+
print "Class:", clazz
160+
return clazz
124161

125162
def do_object(self, parent=None):
163+
# TC_OBJECT classDesc newHandle classdata[] // data for each class
126164
class JavaObject(object):
127165
pass
128-
object = JavaObject()
129-
# TC_OBJECT classDesc newHandle classdata[] // data for each class
166+
self.current_object = JavaObject()
130167
print "[object]"
131168
(opid, ) = self._readStruct(">B", 1)
132169
print "OpCode: 0x%X" % opid
133-
res = self.opmap.get(opid, self.do_default_stuff)(object)
170+
res = self.opmap.get(opid, self.do_default_stuff)(self.current_object)
134171
self.finalValue = res
172+
# classdata[]
173+
174+
for field_name in self.current_object.__fields:
175+
(opid, ) = self._readStruct(">B", 1)
176+
print "OpCode: 0x%X" % opid
177+
res = self.opmap.get(opid, self.do_default_stuff)(self.current_object)
178+
self.current_object.__setattr__(field_name, res)
179+
return self.current_object
135180

136181
def do_string(self, parent=None):
137182
print "[string]"
@@ -141,7 +186,9 @@ def do_string(self, parent=None):
141186

142187
def do_reference(self, parent=None):
143188
(handle, reference) = self._readStruct(">HH", 4)
144-
pass
189+
190+
def do_null(self, parent=None):
191+
return None
145192

146193
def do_default_stuff(self, parent=None):
147194
raise RuntimeError("Unknown opcode")

tests.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ def test_5(self):
4545
jobj = self.read_file("obj5.ser")
4646
pobj = javaobj.loads(jobj)
4747
print pobj
48-
self.assertEqual(pobj, 'HelloWorld')
4948

50-
# def test_6(self):
51-
# jobj = self.read_file("obj6.ser")
52-
# pobj = javaobj.loads(jobj)
53-
# print pobj
54-
# self.assertEqual(pobj, 'HelloWorld')
49+
self.assertEqual(pobj.aField1, 'Gabba')
50+
self.assertEqual(pobj.aField2, None)
51+
52+
def test_6(self):
53+
jobj = self.read_file("obj6.ser")
54+
pobj = javaobj.loads(jobj)
55+
print pobj
56+
self.assertEqual(pobj.name, 'java.lang.String')
5557

5658
# def test_choice(self):
5759
# element = random.choice(self.seq)

0 commit comments

Comments
 (0)