@@ -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
628793class 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