Skip to content

Commit 6eb21d9

Browse files
author
Timo Schmid
committed
Some marshalling code
1 parent bdd7b9b commit 6eb21d9

File tree

1 file changed

+198
-29
lines changed

1 file changed

+198
-29
lines changed

javaobj.py

Lines changed: 198 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,10 @@ class JavaObjectMarshaller(JavaObjectConstants):
584584

585585
def __init__(self, stream=None):
586586
self.object_stream = stream
587+
self.object_transformers = []
588+
589+
def add_transformer(self, transformer):
590+
self.object_transformers.append(transformer)
587591

588592
def dump(self, obj):
589593

@@ -597,9 +601,19 @@ def _writeStreamHeader(self):
597601
self._writeStruct(">HH", 4, (self.STREAM_MAGIC, self.STREAM_VERSION))
598602

599603
def writeObject(self, obj):
600-
log_debug("Writing object of type " + str(type(obj)))
601-
if type(obj) is JavaObject:
604+
log_debug("Writing object of type " + str(type(obj)) + " " + str(obj))
605+
if isinstance(obj, JavaArray):
606+
self.write_array(obj)
607+
elif isinstance(obj, JavaEnum):
608+
self.write_enum(obj)
609+
elif isinstance(obj, JavaObject):
602610
self.write_object(obj)
611+
elif isinstance(obj, JavaString):
612+
self.write_string(obj)
613+
elif isinstance(obj, JavaClass):
614+
self.write_class(obj)
615+
elif obj is None:
616+
self.write_null()
603617
elif type(obj) is str:
604618
self.write_blockdata(obj)
605619
else:
@@ -610,67 +624,222 @@ def _writeStruct(self, unpack, length, args):
610624
self.object_stream.write(ba)
611625

612626
def _writeString(self, string):
613-
len = len(string)
614-
self._writeStruct(">H", 2, (len, ))
627+
length = len(string)
628+
self._writeStruct(">H", 2, (length, ))
615629
self.object_stream.write(string)
616630

631+
def write_string(self, obj):
632+
self._writeStruct(">B", 1, (self.TC_STRING,))
633+
self._writeString(obj)
634+
635+
def write_enum(self, obj):
636+
self._writeStruct(">B", 1, (self.TC_ENUM, ))
637+
self.write_classdesc(obj.get_class())
638+
639+
self.write_string(obj.constant)
640+
617641
def write_blockdata(self, obj, parent=None):
618642
# TC_BLOCKDATA (unsigned byte)<size> (byte)[size]
619-
self._writeStruct(">B", 1, (self.TC_BLOCKDATA, ))
620-
if type(obj) is str:
621-
self._writeStruct(">B", 1, (len(obj), ))
622-
self.object_stream.write(obj)
643+
length = len(obj)
644+
if length <= 256:
645+
self._writeStruct(">B", 1, (self.TC_BLOCKDATA, ))
646+
self._writeStruct(">B", 1, (length, ))
647+
else:
648+
self._writeStruct(">B", 1, (self.TC_BLOCKDATALONG, ))
649+
self._writeStruct(">I", 1, (length, ))
650+
self.object_stream.write(obj)
651+
652+
def write_null(self):
653+
self._writeStruct(">B", 1, (self.TC_NULL, ))
623654

624655
def write_object(self, obj, parent=None):
656+
657+
# Transform object
658+
for transformer in self.object_transformers:
659+
tmp_object = transformer.transform(obj)
660+
if tmp_object is not obj:
661+
obj = tmp_object
662+
break
663+
625664
self._writeStruct(">B", 1, (self.TC_OBJECT, ))
665+
cls = obj.get_class()
666+
self.write_classdesc(cls)
667+
668+
all_names = []
669+
all_types = []
670+
tmpcls = cls
671+
while tmpcls:
672+
all_names += tmpcls.fields_names
673+
all_types += tmpcls.fields_types
674+
tmpcls = tmpcls.superclass
675+
676+
del tmpcls
677+
for name, type in zip(all_names, all_types):
678+
try:
679+
self._write_value(type, getattr(obj, name))
680+
except AttributeError, e:
681+
log_error("%s e, %s %s" % (str(e), repr(obj), repr(dir(obj))))
682+
raise
683+
684+
del all_names, all_types
685+
686+
if (cls.flags & self.SC_SERIALIZABLE and cls.flags & self.SC_WRITE_METHOD or
687+
cls.flags & self.SC_EXTERNALIZABLE and cls.flags & self.SC_BLOCK_DATA):
688+
for annot in obj.annotations:
689+
log_debug("Write annotation %s for %s" % (repr(annot), repr(obj),))
690+
if annot == None:
691+
self.write_null()
692+
else:
693+
self.writeObject(annot)
694+
self._writeStruct('>B', 1, (self.TC_ENDBLOCKDATA,))
695+
696+
def write_class(self, obj, parent=None):
697+
self._writeStruct(">B", 1, (self.TC_CLASS,))
698+
self.write_classdesc(obj)
699+
700+
def write_classdesc(self, obj, parent=None):
626701
self._writeStruct(">B", 1, (self.TC_CLASSDESC, ))
702+
self._writeString(obj.name)
703+
self._writeStruct(">LLB", 1, (obj.serialVersionUID, obj.handle, obj.flags))
704+
self._writeStruct(">H", 1, (len(obj.fields_names), ))
705+
706+
for name,type in zip(obj.fields_names, obj.fields_types):
707+
self._writeStruct(">B", 1,
708+
(self._convert_type_to_char(type),))
709+
self._writeString(name)
710+
if type[0] in (self.TYPE_OBJECT, self.TYPE_ARRAY):
711+
self.write_string(type)
712+
713+
self._writeStruct(">B", 1, (self.TC_ENDBLOCKDATA,))
714+
if obj.superclass:
715+
self.write_classdesc(obj.superclass)
716+
else:
717+
self.write_null()
718+
719+
def write_array(self, obj):
720+
self._writeStruct(">B", 1, (self.TC_ARRAY,))
721+
self.write_classdesc(obj.get_class())
722+
self._writeStruct(">i", 1, (len(obj),))
723+
724+
classdesc = obj.get_class()
725+
726+
type_char = classdesc.name[0]
727+
assert type_char == self.TYPE_ARRAY
728+
type_char = classdesc.name[1]
729+
730+
if type_char == self.TYPE_OBJECT:
731+
for o in obj:
732+
self.write_object(o)
733+
elif type_char == self.TYPE_ARRAY:
734+
for a in obj:
735+
self.write_array(a)
736+
else:
737+
log_debug("Write array of type %s" % type_char)
738+
for v in obj:
739+
self._write_value(type_char, v)
740+
741+
def _write_value(self, field_type, value):
742+
if len(field_type) > 1:
743+
field_type = field_type[0] # We don't need details for arrays and objects
744+
745+
if field_type == self.TYPE_BOOLEAN:
746+
self._writeStruct(">B", 1, (1 if value else 0,))
747+
elif field_type == self.TYPE_BYTE:
748+
if value > 127:
749+
self._writeStruct(">B", 1, (value,))
750+
else:
751+
self._writeStruct(">b", 1, (value,))
752+
elif field_type == self.TYPE_SHORT:
753+
self._writeStruct(">h", 1, (value,))
754+
elif field_type == self.TYPE_INTEGER:
755+
self._writeStruct(">i", 1, (value,))
756+
elif field_type == self.TYPE_LONG:
757+
self._writeStruct(">q", 1, (value,))
758+
elif field_type == self.TYPE_FLOAT:
759+
self._writeStruct(">f", 1, (value,))
760+
elif field_type == self.TYPE_DOUBLE:
761+
self._writeStruct(">d", 1, (value,))
762+
elif field_type == self.TYPE_OBJECT or field_type == self.TYPE_ARRAY:
763+
if value == None:
764+
self.write_null()
765+
elif isinstance(value, JavaEnum):
766+
self.write_enum(value)
767+
elif isinstance(value, JavaObject):
768+
self.write_object(value)
769+
elif isinstance(value, JavaString):
770+
self.write_string(value)
771+
elif isinstance(value, str):
772+
self.write_blockdata(value)
773+
else:
774+
raise RuntimeError("Unknown typecode: %s" % field_type)
775+
else:
776+
raise RuntimeError("Unknown typecode: %s" % field_type)
777+
778+
def _convert_type_to_char(self, type_char):
779+
typecode = type_char
780+
if type(type_char) is int:
781+
typecode = chr(type_char)
782+
783+
if typecode in self.TYPECODES_LIST:
784+
return ord(typecode)
785+
elif len(typecode) > 1:
786+
if typecode[0] == 'L':
787+
return ord(self.TYPE_OBJECT)
788+
elif typecode[0] == '[':
789+
return ord(self.TYPE_ARRAY)
790+
791+
raise RuntimeError("Typecode %s (%s) isn't supported." % (type_char, typecode))
627792

628793
class DefaultObjectTransformer(object):
629794

630795
class JavaList(list, JavaObject):
631-
pass
796+
def __init__(self, *args, **kwargs):
797+
list.__init__(self, *args, **kwargs)
798+
JavaObject.__init__(self)
632799

633800
class JavaMap(dict, JavaObject):
634-
pass
801+
def __init__(self, *args, **kwargs):
802+
dict.__init__(self, *args, **kwargs)
803+
JavaObject.__init__(self)
635804

636805
def transform(self, object):
637806
if object.get_class().name == "java.util.ArrayList":
638807
# * @serialData The length of the array backing the <tt>ArrayList</tt>
639808
# * instance is emitted (int), followed by all of its elements
640809
# * (each an <tt>Object</tt>) in the proper order.
641-
print "---"
642-
print "java.util.ArrayList"
643-
print object.annotations
644-
print "---"
810+
#print "---"
811+
#print "java.util.ArrayList"
812+
#print object.annotations
813+
#print "---"
645814
new_object = self.JavaList()
646815
object.copy(new_object)
647816
new_object.extend(object.annotations[1:])
648-
print ">>> object:", new_object
817+
#print ">>> object:", new_object
649818
return new_object
650819
if object.get_class().name == "java.util.LinkedList":
651-
print "---"
652-
print
653-
print "java.util.LinkedList"
654-
print object.annotations
655-
print "---"
820+
#print "---"
821+
#print
822+
#print "java.util.LinkedList"
823+
#print object.annotations
824+
#print "---"
656825
new_object = self.JavaList()
657826
object.copy(new_object)
658827
new_object.extend(object.annotations[1:])
659-
print ">>> object:", new_object
828+
#print ">>> object:", new_object
660829
return new_object
661830
if object.get_class().name == "java.util.HashMap":
662-
print "---"
663-
print
664-
print "java.util.HashMap"
665-
print object.annotations
666-
print "---"
831+
#print "---"
832+
#print
833+
#print "java.util.HashMap"
834+
#print object.annotations
835+
#print "---"
667836
new_object = self.JavaMap()
668837
object.copy(new_object)
669838

670-
for i in range((len(object.annotations)-1)/2):
671-
new_object[object.annotations[i*2+1]] = object.annotations[i*2+2]
839+
for i in range(1, len(object.annotations),2):
840+
new_object[object.annotations[i]] = object.annotations[i+1]
672841

673-
print ">>> object:", new_object
842+
#print ">>> object:", new_object
674843
return new_object
675844

676845
return object

0 commit comments

Comments
 (0)