4848 ExceptionRead ,
4949 ClassDescType ,
5050 FieldType ,
51+ ClassDataType ,
5152)
5253from .stream import DataStreamReader
5354from ..constants import (
5758 TypeCode ,
5859 PRIMITIVE_TYPES ,
5960)
61+
6062from ..modifiedutf8 import decode_modified_utf8
6163
6264# ------------------------------------------------------------------------------
@@ -276,7 +278,7 @@ def _do_null(self, _):
276278 """
277279 return None
278280
279- def _read_content (self , type_code , block_data ):
281+ def _read_content (self , type_code , block_data , class_desc = None ):
280282 # type: (int, bool) -> ParsedJavaContent
281283 """
282284 Parses the next content
@@ -290,14 +292,17 @@ def _read_content(self, type_code, block_data):
290292 try :
291293 handler = self .__type_code_handlers [type_code ]
292294 except KeyError :
295+ '''Looking for an external reader'''
296+ if class_desc and class_desc .data_type == ClassDataType .WRCLASS :
297+ return self ._custom_readObject (class_desc .name )
293298 raise ValueError ("Unknown type code: 0x{0:x}" .format (type_code ))
294299 else :
295300 try :
296301 return handler (type_code )
297302 except ExceptionRead as ex :
298303 return ex .exception_object
299304
300- def _read_new_string (self , type_code ):
305+ def _read_new_string (self , type_code , field_name = None ):
301306 # type: (int) -> JavaString
302307 """
303308 Reads a Java String
@@ -321,7 +326,7 @@ def _read_new_string(self, type_code):
321326 raise ValueError ("Invalid string length: {0}" .format (length ))
322327 elif length < 65536 :
323328 self ._log .warning ("Small string stored as a long one" )
324-
329+
325330 # Parse the content
326331 data = self .__fd .read (length )
327332 java_str = JavaString (handle , data )
@@ -338,12 +343,10 @@ def _read_classdesc(self):
338343 type_code = self .__reader .read_byte ()
339344 return self ._do_classdesc (type_code )
340345
341- def _do_classdesc (self , type_code , must_be_new = False ):
346+ def _do_classdesc (self , type_code ):
342347 # type: (int, bool) -> JavaClassDesc
343348 """
344349 Parses a class description
345-
346- :param must_be_new: Check if the class description is really a new one
347350 """
348351 if type_code == TerminalCode .TC_CLASSDESC :
349352 # Do the real job
@@ -352,57 +355,47 @@ def _do_classdesc(self, type_code, must_be_new=False):
352355 handle = self ._new_handle ()
353356 desc_flags = self .__reader .read_byte ()
354357 nb_fields = self .__reader .read_short ()
358+
355359 if nb_fields < 0 :
356360 raise ValueError ("Invalid field count: {0}" .format (nb_fields ))
357361
358362 fields = [] # type: List[JavaField]
359363 for _ in range (nb_fields ):
360364 field_type = self .__reader .read_byte ()
361- if field_type in PRIMITIVE_TYPES :
362- # Primitive type
363- field_name = self .__reader .read_UTF ()
364- fields .append (JavaField (FieldType (field_type ), field_name ))
365- elif field_type in (TypeCode .TYPE_OBJECT , TypeCode .TYPE_ARRAY ,):
366- # Array or object type
367- field_name = self .__reader .read_UTF ()
365+ field_name = self .__reader .read_UTF ()
366+ class_name = None
367+
368+ if field_type in (TypeCode .TYPE_OBJECT , TypeCode .TYPE_ARRAY ):
368369 # String type code
369370 str_type_code = self .__reader .read_byte ()
370371 class_name = self ._read_new_string (str_type_code )
371- fields .append (
372- JavaField (
373- FieldType (field_type ), field_name , class_name ,
374- ),
375- )
376- else :
372+ elif field_type not in PRIMITIVE_TYPES :
377373 raise ValueError (
378374 "Invalid field type char: 0x{0:x}" .format (field_type )
379375 )
380376
377+ fields .append (JavaField (
378+ FieldType (field_type ), field_name , class_name
379+ ))
380+
381381 # Setup the class description bean
382382 class_desc = JavaClassDesc (ClassDescType .NORMALCLASS )
383383 class_desc .name = name
384384 class_desc .serial_version_uid = serial_version_uid
385385 class_desc .handle = handle
386386 class_desc .desc_flags = desc_flags
387387 class_desc .fields = fields
388- class_desc .annotations = self ._read_class_annotations ()
388+ class_desc .annotations = self ._read_class_annotations (class_desc )
389389 class_desc .super_class = self ._read_classdesc ()
390390
391391 # Store the reference to the parsed bean
392392 self ._set_handle (handle , class_desc )
393393 return class_desc
394394 elif type_code == TerminalCode .TC_NULL :
395395 # Null reference
396- if must_be_new :
397- raise ValueError ("Got Null instead of a new class description" )
398396 return None
399397 elif type_code == TerminalCode .TC_REFERENCE :
400398 # Reference to an already loading class description
401- if must_be_new :
402- raise ValueError (
403- "Got a reference instead of a new class description"
404- )
405-
406399 previous = self ._do_reference ()
407400 if not isinstance (previous , JavaClassDesc ):
408401 raise ValueError ("Referenced object is not a class description" )
@@ -424,10 +417,20 @@ def _do_classdesc(self, type_code, must_be_new=False):
424417 # Store the reference to the parsed bean
425418 self ._set_handle (handle , class_desc )
426419 return class_desc
427-
420+
428421 raise ValueError ("Expected a valid class description starter" )
429422
430- def _read_class_annotations (self ):
423+
424+ def _custom_readObject (self , class_name ):
425+ self .__fd .seek (- 1 , os .SEEK_CUR )
426+ for transformer in self .__transformers :
427+ class_data = transformer .load_custom_writeObject (self , self .__reader , class_name )
428+ if class_data :
429+ return class_data
430+ raise ValueError ("Custom readObject can not be processed" )
431+
432+
433+ def _read_class_annotations (self , class_desc = None ):
431434 # type: () -> List[ParsedJavaContent]
432435 """
433436 Reads the annotations associated to a class
@@ -442,8 +445,8 @@ def _read_class_annotations(self):
442445 # Reset references
443446 self ._reset ()
444447 continue
448+ java_object = self ._read_content (type_code , True , class_desc )
445449
446- java_object = self ._read_content (type_code , True )
447450 if java_object is not None and java_object .is_exception :
448451 raise ExceptionRead (java_object )
449452
@@ -503,40 +506,24 @@ def _read_class_data(self, instance):
503506
504507 for cd in classes :
505508 values = {} # type: Dict[JavaField, Any]
506- if cd .desc_flags & ClassDescFlags .SC_SERIALIZABLE :
507- if cd .desc_flags & ClassDescFlags .SC_EXTERNALIZABLE :
508- raise ValueError (
509- "SC_EXTERNALIZABLE & SC_SERIALIZABLE encountered"
510- )
511-
512- for field in cd .fields :
513- values [field ] = self ._read_field_value (field .type )
514-
515- all_data [cd ] = values
516-
517- if cd .desc_flags & ClassDescFlags .SC_WRITE_METHOD :
518- if cd .desc_flags & ClassDescFlags .SC_ENUM :
519- raise ValueError (
520- "SC_ENUM & SC_WRITE_METHOD encountered!"
521- )
522-
523- annotations [cd ] = self ._read_class_annotations ()
524- elif cd .desc_flags & ClassDescFlags .SC_EXTERNALIZABLE :
525- if cd .desc_flags & ClassDescFlags .SC_SERIALIZABLE :
526- raise ValueError (
527- "SC_EXTERNALIZABLE & SC_SERIALIZABLE encountered"
528- )
529-
530- if cd .desc_flags & ClassDescFlags .SC_BLOCK_DATA :
509+ cd .validate ()
510+ if cd .data_type == ClassDataType .NOWRCLASS or cd .data_type == ClassDataType .WRCLASS :
511+ if cd .data_type == ClassDataType .NOWRCLASS :
512+ for field in cd .fields :
513+ values [field ] = self ._read_field_value (field .type )
514+ all_data [cd ] = values
515+ else :
516+ annotations [cd ] = self ._read_class_annotations (cd )
517+ else :
518+ if cd .data_type == ClassDataType .OBJECT_ANNOTATION :
531519 # Call the transformer if possible
532520 if not instance .load_from_blockdata (self , self .__reader ):
533521 # Can't read :/
534522 raise ValueError (
535523 "hit externalizable with nonzero SC_BLOCK_DATA; "
536524 "can't interpret data"
537525 )
538-
539- annotations [cd ] = self ._read_class_annotations ()
526+ annotations [cd ] = self ._read_class_annotations (cd )
540527
541528 # Fill the instance object
542529 instance .annotations = annotations
@@ -568,11 +555,11 @@ def _read_field_value(self, field_type):
568555 return self .__reader .read_bool ()
569556 elif field_type in (FieldType .OBJECT , FieldType .ARRAY ):
570557 sub_type_code = self .__reader .read_byte ()
571- if (
572- field_type == FieldType . ARRAY
573- and sub_type_code != TerminalCode . TC_ARRAY
574- ) :
575- raise ValueError ("Array type listed, but type code != TC_ARRAY" )
558+ if field_type == FieldType . ARRAY :
559+ if sub_type_code == TerminalCode . TC_REFERENCE :
560+ return self . _do_classdesc ( sub_type_code )
561+ elif sub_type_code != TerminalCode . TC_ARRAY :
562+ raise ValueError ("Array type listed, but type code != TC_ARRAY" )
576563
577564 content = self ._read_content (sub_type_code , False )
578565 if content is not None and content .is_exception :
0 commit comments