hessianobjc-user Mailing List for HessianObjC
Status: Alpha
Brought to you by:
cocoa_dood
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(18) |
Sep
(13) |
Oct
(10) |
Nov
(2) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(15) |
2008 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
(3) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Tore H. <ha...@pv...> - 2008-05-15 08:30:29
|
On 14. mai. 2008, at 22.09, Byron Wright wrote: > I'll take a closer look but is this compatible with the 1.0 version > (at first glance it mostly does look compatible)? Version 2 is just some things in addition to version 1. So all version 2 decoders handles version 1 data just fine. > I'll need to decide on whether to branch or allow support for the > 1.0 and 2.0 protocol. The change in BBSHessianCall.m tell the server that the client support version 2 of the protocol. An old server will still answer with version 1 only objects and it should work fine. It should be just fine to have just one decoder. Regards, - Tore. |
From: Byron W. <by...@bl...> - 2008-05-14 20:10:03
|
thanks Tore you rock! I'll patch and add some unit tests around this when I get a chance. I'll take a closer look but is this compatible with the 1.0 version (at first glance it mostly does look compatible)? I'll need to decide on whether to branch or allow support for the 1.0 and 2.0 protocol. thanks again, Byron On May 14, 2008, at 11:08 AM, Tore Halset wrote: > Hello. > > I have implemented support for decoding of the new hessian-2 > protocol. The patch is attached. It may not be complete for all > datatypes, but works fine so far in my application. > > Things to note: > * It is tested against a hessian-3.1.6 server > * hessian-3.1.6 has a bug in its enum encoding that this patch has a > simple workaround for. When/if the bug is fixed in the java > implementation, the workaround must be removed. See http://bugs.caucho.com/view.php?id=2662 > * ref-handling has been improved. The object is now alloc'ed before > adding to the refArray. Before this fix, getting a reffed object > would always result in a NSDictionary, not the real object. > > Things to do: > * more data types. I think compact double/float/binary is missing. > * fix byte order stuff for iPhone. > > Regards, > - Tore. > <hessianobjc.patch> > > > > > Index: BBSHessianDecoder.h > =================================================================== > --- BBSHessianDecoder.h (revision 92) > +++ BBSHessianDecoder.h (working copy) > @@ -24,6 +24,10 @@ > NSInputStream * dataInputStream; > NSMutableDictionary * classMapping; > NSMutableArray * refArray; > + NSMutableArray * classDef; > + NSMutableArray * typeMap; > + NSMutableArray * objectDefinitionMap; > + NSMutableDictionary * fieldsByTypeName; > } > > /** Static method that decodes an object encoded in Hessian binary > protocol and returns the object value. > Index: BBSHessianMapDecoder.m > =================================================================== > --- BBSHessianMapDecoder.m (revision 92) > +++ BBSHessianMapDecoder.m (working copy) > @@ -110,8 +110,10 @@ > return YES; > } > > +- (BOOL)containsValueForKey:(NSString *)key { > + return [[hessianMap allKeys] containsObject:key]; > +} > > - > - (void) dealloc { > [hessianMap release]; > hessianMap = nil; > Index: BBSHessianDecoder.m > =================================================================== > --- BBSHessianDecoder.m (revision 92) > +++ BBSHessianDecoder.m (working copy) > @@ -27,18 +27,24 @@ > - (int) decodeStringLength; > - (NSString *) decodeXml:(uint8_t) startCode; > - (NSString *) decodeString:(uint8_t) startCode; > -- (NSString *) decodeStringChunk; > +- (NSString *) decodeStringChunk:(int) len; > +- (NSString *) decodeCompactString; > - (NSNumber *) decodeInt; > +- (NSNumber *) decodeIntForCode:(uint8_t) startCode; > +- (id) allocObjectWithType:(NSMutableDictionary *)dict andType: > (NSString *)type; > /** Return an NSDictionary or a class instance if a mapping for this > "map" is available */ > - (id) decodeMap; > -- (NSArray * ) decodeList; > +- (NSArray * ) decodeList:(uint8_t) startCode; > - (NSNumber *) decodeLong; > - (NSNumber *) decodeDouble; > - (NSDate *) decodeDate; > - (NSData *) decodeByteChunks; > - (NSData *) decodeBytes; > - (NSError *) decodeFault; > -- (id) decodeRef; > +- (void) addToRefArray:(id) val; > +- (id) decodeRef:(uint8_t) startCode; > +- (void) decodeCompactObjectHeader; > +- (id) decodeCompactObject; > > @end > > @@ -54,6 +60,10 @@ > if((self = [super init]) != nil) { > classMapping = [[NSMutableDictionary dictionary] retain]; > refArray = [[NSMutableArray array] retain]; > + classDef = [[NSMutableArray array] retain]; > + typeMap = [[NSMutableArray array] retain]; > + objectDefinitionMap = [[NSMutableArray array] retain]; > + fieldsByTypeName = [[NSMutableDictionary dictionary] retain]; > } > return self; > } > @@ -107,6 +117,14 @@ > dataInputStream = nil; > [refArray release]; > refArray = nil; > + [classDef release]; > + classDef = nil; > + [typeMap release]; > + typeMap = nil; > + [objectDefinitionMap release]; > + objectDefinitionMap = nil; > + [fieldsByTypeName release]; > + fieldsByTypeName = nil; > [super dealloc]; > } > @end > @@ -121,7 +139,7 @@ > return [self decodeObjectForCode:objectTag]; > } > else { > - NSLog(@"no data available"); > + NSLog(@"ERROR: no data available"); > } > return obj; > } > @@ -137,17 +155,38 @@ > case 'd': obj = [self decodeDate];break; > case 'D': obj = [self decodeDouble];break; > case 'f': obj = [self decodeFault] ; break; > - case 'I': obj = [self decodeInt]; break; > - case 'V': obj = [self decodeList]; break; > + case 'I': obj = [self decodeIntForCode:code]; break; > + case 'v': obj = [self decodeList:code]; break; > + case 'V': obj = [self decodeList:code]; break; > case 'L': obj = [self decodeLong] ;break; > case 'M': obj = [self decodeMap]; break; > case 'N': obj = nil ;break; > - case 'R': obj = [self decodeRef];break; > - case 's': obj = [self decodeString:'s'];break; > - case 'S': obj = [self decodeString:'S'];break; > + case 'o': obj = [self decodeCompactObject]; break; > + case 'O': [self decodeCompactObjectHeader] ; obj = [self > decodeObject]; break; > + case 'R': obj = [self decodeRef:code];break; > + case 0x4a: obj = [self decodeRef:code];break; > + case 0x4b: obj = [self decodeRef:code];break; > + case 's': obj = [self decodeString:code];break; > + case 'S': obj = [self decodeString:code];break; > case 'x': obj = [self decodeXml:'x'];break; > case 'X': obj = [self decodeXml:'X'];break; > default: { > + > + // TODO: fix. something fishy with the int type here > + if ((code >= 0x00)&&(code <= 0x1f)) { > + return [self decodeStringChunk:code]; > + } > + if ((code >= 0x80)&&(code <= 0xbf)) { > + return [self decodeIntForCode:code]; > + } > + if ((code >= 0xc0)&&(code <= 0xcf)) { > + return [self decodeIntForCode:code]; > + } > + if ((code >= 0xd0)&&(code <= 0xd7)) { > + return [self decodeIntForCode:code]; > + } > + > + > NSDictionary * userInfo = [NSDictionary > dictionaryWithObject:[NSString stringWithFormat:@"Unknown tag > returned %c",code] > > forKey:NSLocalizedDescriptionKey]; > obj = [NSError errorWithDomain:BBSHessianObjCError > @@ -162,11 +201,11 @@ > - (NSString *) decodeXml:(uint8_t) startCode { > NSMutableString * xmlString = [NSMutableString string]; > while(startCode == 'x') { //decode chunks > - [xmlString appendString:[self decodeStringChunk]]; > + [xmlString appendString:[self decodeString:'S']]; > [dataInputStream read:&startCode maxLength:1]; > } > if(startCode == 'X') { > - [xmlString appendString:[self decodeStringChunk]]; > + [xmlString appendString:[self decodeString:'S']]; > } > else { > NSLog(@"expected 'X' for last xml chunk"); > @@ -174,8 +213,7 @@ > return xmlString; > } > > -- (NSString *) decodeStringChunk { > - int len = [self decodeStringLength]; > +- (NSString *) decodeStringChunk:(int) len { > if(len == 0) { > return @""; > } > @@ -194,63 +232,157 @@ > } > > - (NSString *) decodeString:(uint8_t) startCode { > + int stringLength = 0; > > + // Strings with length less than 32 may be encoded with a > single octet > + if (startCode < 32) { > + stringLength = startCode; > + return [self decodeStringChunk:stringLength]; > + } > + > NSMutableString * retString = [NSMutableString string]; > while(startCode == 's') { //decode chunks > - [retString appendString:[self decodeStringChunk]]; > + stringLength = [self decodeStringLength]; > + if(stringLength == 0) { > + NSLog(@"ERROR: why have a string chunk of lenght 0?"); > + break; > + } > + [retString appendString:[self > decodeStringChunk:stringLength]]; > [dataInputStream read:&startCode maxLength:1]; > } > if(startCode == 'S') { > - [retString appendString:[self decodeStringChunk]]; > + stringLength = [self decodeStringLength]; > + [retString appendString:[self > decodeStringChunk:stringLength]]; > } > else { > - NSLog(@"expected 'S' for last string chunk"); > + NSLog(@"ERROR: expected 'S' for last string chunk"); > } > return retString; > } > > +- (NSString *) decodeCompactString { > + uint8_t startCode = 'e'; > + [dataInputStream read:&startCode maxLength:1]; > + > + // check if we should fall back to old > + if ((startCode == 's')||(startCode == 'S')) { > + return [self decodeString:startCode]; > + } > + > + int len = 0; > + if (startCode < 32) { > + len = startCode; > + } else { > + len = [[self decodeIntForCode:startCode] intValue]; > + } > + return [self decodeStringChunk:len]; > +} > + > - (NSNumber *) decodeInt { > - SInt32 val = 0; > - if([dataInputStream hasBytesAvailable]) { > - [dataInputStream read:(uint8_t *)&val maxLength:4]; > - val = EndianS32_BtoN(val); > - return [NSNumber numberWithInt:val]; > + return [self decodeIntForCode:'I']; > +} > + > +- (NSNumber *) decodeIntForCode:(uint8_t) startCode { > + > + if (startCode == 'I') { > + SInt32 val = 0; > + if([dataInputStream hasBytesAvailable]) { > + [dataInputStream read:(uint8_t *)&val maxLength:4]; > + val = EndianS32_BtoN(val); > + return [NSNumber numberWithInt:val]; > + } > + return nil; > } > + > + NSNumber *val = nil; > + if ((startCode >= 0x80)&&(startCode <= 0xbf)) { > + // compact single octet integer > + val = [NSNumber numberWithInt:(startCode - 0x90)]; > + } else if ((startCode >= 0xc0)&&(startCode <= 0xcf)) { > + // compact two octet integer > + uint8_t b0 = 0; > + [dataInputStream read:&b0 maxLength:1]; > + val = [NSNumber numberWithInt:(((startCode - 0xc8) << 8) + > b0)]; > + } else if ((startCode >= 0xd0)&&(startCode <= 0xd7)) { > + // compact three octet integer > + uint8_t b0 = 0; > + uint8_t b1 = 0; > + [dataInputStream read:&b0 maxLength:1]; > + [dataInputStream read:&b1 maxLength:1]; > + val = [NSNumber numberWithInt:(((startCode - 0xd4) << 16) + > (b1 << 8) + b0)]; > + } else { > + NSLog(@"ERROR: unknown int start code %i", startCode); > + } > + return val; > +} > + > +- (id) allocObjectWithType:(NSMutableDictionary *)dict andType: > (NSString *)type { > + > + if((!type) || ([type length] == 0)) { > + return nil; > + } > + > + Class mappedClass = nil; > + mappedClass = [self classForClassName:type]; > + if(!mappedClass) { //try the global mapping > + mappedClass = [BBSHessianDecoder classForClassName:type]; > + } > + if(mappedClass) { > + [dict setObject:NSStringFromClass(mappedClass) > forKey:BBSHessianClassNameKey]; > + } > + else { > + // not a mapped class. remember hessian class name > + [dict setObject:type forKey:BBSHessianClassNameKey]; > + } > + > + if(mappedClass) { > + // a mapped class, user map decoder to init object > + return [mappedClass alloc]; > + } > return nil; > } > > + > - (id) decodeMap { > id dict = [NSMutableDictionary dictionary]; > - //add the pointer to the ref array and not the actually value. > - [refArray addObject:[NSValue valueWithPointer:dict]]; > - Class mappedClass = nil; > uint8_t objectTag = 'e'; > + NSString *type = nil; > if([dataInputStream hasBytesAvailable]) { > [dataInputStream read:&objectTag maxLength:1]; > if(objectTag == 't') { > //decode the type of map, maps with a type are objects > of a particular class > //if we have a class mapping for this then > - NSString * type = [self decodeString:'S']; > - if(type != nil && [type length] > 0) { > - mappedClass = [self classForClassName:type]; > - if(!mappedClass) { //try the global mapping > - mappedClass = [BBSHessianDecoder > classForClassName:type]; > - } > - if(mappedClass) { > - [dict setObject:NSStringFromClass(mappedClass) > forKey:BBSHessianClassNameKey]; > - } > - else { > - // not a mapped class. remember hessian class > name > - [dict setObject:type > forKey:BBSHessianClassNameKey]; > - } > - } > - } > + type = [self decodeString:'S']; > + [typeMap addObject:type]; > + } else if (objectTag == 0x75) { > + // type ref. > + [dataInputStream read:&objectTag maxLength:1]; > + int typeRef = [[self decodeIntForCode:objectTag] > intValue]; > + type = [typeMap objectAtIndex:typeRef]; > + } > > + id val = [self allocObjectWithType:dict andType:type]; > + if(val) { > + [self addToRefArray:val]; > + } else { > + [self addToRefArray:dict]; > + } > + > [dataInputStream read:&objectTag maxLength:1]; > while(objectTag != 'z' && [dataInputStream > hasBytesAvailable]) { > //read the type > id key = [self decodeObjectForCode:objectTag]; > [dataInputStream read:&objectTag maxLength:1]; > + if(objectTag == 'z') { > + // java enum are serialized by hessian using a Map > with a single key, but no value > + [dict setObject:[NSNull null] forKey:key]; > + > + // special case for enum. looks like a bug in the > java implementation > + // http://bugs.caucho.com/view.php?id=2662 > + NSLog(@"DEBUG: enum encoded as map should not be > added to refArray. remove"); > + [refArray removeLastObject]; > + break; > + } > id value = [self decodeObjectForCode:objectTag]; > if(key != nil) { > if(value == nil) { > @@ -261,13 +393,14 @@ > [dataInputStream read:&objectTag maxLength:1]; > } > > - if(mappedClass) { > - //a mapped class, user map decoder to init object > + if(val) { > BBSHessianMapDecoder * mapDecoder = > [[[BBSHessianMapDecoder alloc] initForReadingWithDictionary:dict] > autorelease]; > - id obj = [[[mappedClass alloc] > initWithCoder:mapDecoder] autorelease]; > - return obj; > + val = [[val initWithCoder:mapDecoder] autorelease]; > + return val; > + } else { > + return dict; > } > - return dict; > + > } > else { > NSLog(@"no data available"); > @@ -275,45 +408,78 @@ > return nil; > } > > -- (NSArray * ) decodeList { > +- (NSArray * ) decodeList:(uint8_t) startCode { > + > + NSString *type = nil; > + int length = -1; > + > + if (startCode == 'v') { > + uint8_t st = 'e'; > + > + [dataInputStream read:&st maxLength:1]; > + int typeRef = [[self decodeIntForCode:st] intValue]; > + type = [typeMap objectAtIndex:typeRef]; > + > + [dataInputStream read:&st maxLength:1]; > + length = [[self decodeIntForCode:st] intValue]; > + } > + > NSMutableArray * array = [NSMutableArray array]; > - [refArray addObject:[NSValue valueWithPointer:array]]; > + [self addToRefArray:array]; > uint8_t objectTag = 'e'; > - if([dataInputStream hasBytesAvailable]) { > - //type and length might be available, accord to the spec > - //type comes first then the length. > - [dataInputStream read:&objectTag maxLength:1]; > - if(objectTag == 't') { > - //decode the type of list, we don't really care about > this > - //because we are using an NSArray > - NSString * type = [self decodeString:'S']; > - //if type exists then check for length also > - [dataInputStream read:&objectTag maxLength:1]; > - #pragma unused (type) > - } > + uint8_t st = 'e'; > + > + // handle 'v' list with zero length as it does not end with a z > + if(length == 0) { > + return array; > + } > + > + [dataInputStream read:&objectTag maxLength:1]; > + while(objectTag != 'z' && [dataInputStream hasBytesAvailable]) { > + > + switch(objectTag) { > + case 't': > + // type > + type = [self decodeString:'S']; > + [typeMap addObject:type]; > + [dataInputStream read:&objectTag maxLength:1]; > + continue; > + case 0x75: > + // type ref. > + st = 'e'; > + [dataInputStream read:&st maxLength:1]; > + int typeRef = [[self decodeIntForCode:st] intValue]; > + type = [typeMap objectAtIndex:typeRef]; > + continue; > + case 0x6e: > + st = 'e'; > + [dataInputStream read:&st maxLength:1]; > + length = [[self decodeIntForCode:st] intValue]; > + [dataInputStream read:&objectTag maxLength:1]; > + continue; > + case 'l': > + length = [[self decodeInt] intValue]; > + [dataInputStream read:&objectTag maxLength:1]; > + continue; > + } > + > + id obj = [self decodeObjectForCode:objectTag]; > + if(!obj) { > + obj = [NSNull null]; > + } > + [array addObject:obj]; > > - if(objectTag == 'l') { > - //length of object in reply, gobble it up because we > don't really > - //care about this because we're creating an NSArray > - NSNumber * len = [self decodeInt]; > - #pragma unused (len) > - //length exists, read in the next tag > - [dataInputStream read:&objectTag maxLength:1]; > + // 'v' list does not end with a z > + if ((startCode == 'v') && (length == [array count])) { > + break; > } > - > - while(objectTag != 'z' && [dataInputStream > hasBytesAvailable]) { > - id obj = [self decodeObjectForCode:objectTag]; > - if(obj) { > - [array addObject:obj]; > - } > - [dataInputStream read:&objectTag maxLength:1]; > - } > - return array; > - } > - return nil; > + > + [dataInputStream read:&objectTag maxLength:1]; > + } > + > + return array; > } > > - > - (NSNumber *) decodeLong { > SInt64 aLong = 0; > if([dataInputStream hasBytesAvailable]) { > @@ -473,11 +639,93 @@ > > } > > -- (id) decodeRef { - int ref = [[self decodeInt] intValue]; > - return [[refArray objectAtIndex:ref] pointerValue]; > +- (void) addToRefArray:(id) val > +{ > + [refArray addObject:[NSValue valueWithPointer:val]]; > } > > +- (id) decodeRef:(uint8_t) startCode { > + int ref = 0; > + uint8_t helper = 'e'; > + switch(startCode) { > + case 'R': > + ref = [[self decodeInt] intValue]; > + break; > + case 0x4a: > + helper = 0; > + [dataInputStream read:&helper maxLength:1]; > + ref = helper; > + break; > + case 0x4b: > + helper = 0; > + [dataInputStream read:&helper maxLength:1]; > + ref = (helper << 8); > + helper = 0; > + [dataInputStream read:&helper maxLength:1]; > + ref = ref + helper; > + break; > + } > + NSObject *val = [[refArray objectAtIndex:ref] pointerValue]; > + return val; > +} > + > +- (void) decodeCompactObjectHeader { > + NSString *type = [self decodeCompactString]; > + [objectDefinitionMap addObject:type]; > + > + uint8_t aCode = 'e'; > + [dataInputStream read:&aCode maxLength:1]; > + int numOfFields = [[self decodeIntForCode:aCode] intValue]; > + > + NSMutableArray *fields = [NSMutableArray array]; > + while(numOfFields-- > 0) { > + NSString *fieldName = [self decodeCompactString]; > + [fields addObject:fieldName]; > + } > + [fieldsByTypeName setObject:[NSArray arrayWithArray:fields] > forKey:type]; > +} > + > +- (id) decodeCompactObject { > + > + uint8_t aCode = 'e'; > + [dataInputStream read:&aCode maxLength:1]; > + int typeIdx = [[self decodeIntForCode:aCode] intValue]; > + NSString *type = [objectDefinitionMap objectAtIndex:typeIdx]; > + NSArray *fields = [fieldsByTypeName objectForKey:type]; > + > + if(!fields) { > + NSLog(@"ERROR: could not find fields for type %@", type); > + } > + > + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; > + > + id val = [self allocObjectWithType:dict andType:type]; > + if(val) { > + [self addToRefArray:val]; > + } else { > + [self addToRefArray:dict]; > + } > + > + unsigned int i = 0; > + for (i = 0; i < [fields count]; i++) { > + NSString *fieldName = [fields objectAtIndex:i]; > + > + id fieldValue = [self decodeObject]; > + if (!fieldValue) { > + fieldValue = [NSNull null]; > + } > + [dict setObject:fieldValue forKey:fieldName]; > + } > + > + if(val) { > + BBSHessianMapDecoder * mapDecoder = [[[BBSHessianMapDecoder > alloc] initForReadingWithDictionary:dict] autorelease]; > + val = [[val initWithCoder:mapDecoder] autorelease]; > + return val; > + } else { > + return dict; > + } > +} > + > - (int) decodeStringLength { > UInt16 len = 0; > if([dataInputStream hasBytesAvailable]) { > Index: BBSHessianCall.m > =================================================================== > --- BBSHessianCall.m (revision 92) > +++ BBSHessianCall.m (working copy) > @@ -83,7 +83,11 @@ > > - (void) startCall { > char call = 'c'; > - char char1 = 0x01; > + // 1.0 > + //char char1 = 0x01; > + //char char0 = 0x00; > + // 2.0 > + char char1 = 0x02; > char char0 = 0x00; > char m = 'm'; > /*char H = 'H'; > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/_______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user |
From: Tore H. <ha...@pv...> - 2008-05-14 18:06:18
|
Hello. I have implemented support for decoding of the new hessian-2 protocol. The patch is attached. It may not be complete for all datatypes, but works fine so far in my application. Things to note: * It is tested against a hessian-3.1.6 server * hessian-3.1.6 has a bug in its enum encoding that this patch has a simple workaround for. When/if the bug is fixed in the java implementation, the workaround must be removed. See http://bugs.caucho.com/view.php?id=2662 * ref-handling has been improved. The object is now alloc'ed before adding to the refArray. Before this fix, getting a reffed object would always result in a NSDictionary, not the real object. Things to do: * more data types. I think compact double/float/binary is missing. * fix byte order stuff for iPhone. Regards, - Tore. |
From: Byron W. <by...@bl...> - 2008-01-07 19:20:35
|
Hi Tore, sorry I just have not had time to do write a unit test and apply this patch. I'll take a look at it later tonight and let you know once I've applied a patch. cheers, Byron On Jan 4, 2008, at 4:46 PM, Tore Halset wrote: > Hello. > > Anyone able to take a look at this one? And perhaps commit an > acceptable fix? > > - Tore. > > On Dec 17, 2007, at 01:43, Tore Halset wrote: > >> Hello. >> >> Okay, I found a solution. Looks like hessian serialize a enum >> variable >> as a Map with a single key, but no value. Here is a working patch >> that >> fixes my problem. >> >> Index: BBSHessianDecoder.m >> =================================================================== >> --- BBSHessianDecoder.m (revision 92) >> +++ BBSHessianDecoder.m (working copy) >> @@ -251,6 +251,11 @@ >> //read the type >> id key = [self decodeObjectForCode:objectTag]; >> [dataInputStream read:&objectTag maxLength:1]; >> + if(objectTag == 'z') { >> + // java enum are serialized by hessian using a Map >> with a single key, but no value >> + [dict setObject:[NSNull null] forKey:key]; >> + break; >> + } >> id value = [self decodeObjectForCode:objectTag]; >> if(key != nil) { >> if(value == nil) { >> >> >> Regards, >> - Tore. >> >> On Dec 17, 2007, at 01:17, Tore Halset wrote: >> >>> Hello. >>> >>> Sorry, but the map is not related to TreeMap, but encoding a enum. >>> This enum is burryed far down in the object graph, but I have >>> isolated >>> this by trying everything with the transient-keyword. >>> >>> The problem is this instanse variable: >>> protected LifecycleEvent callbackType; >>> >>> This is how LifecycleEvent look like: >>> public enum LifecycleEvent { >>> PRE_PERSIST, PRE_REMOVE, PRE_UPDATE, POST_PERSIST, POST_REMOVE, >>> POST_UPDATE, POST_LOAD; >>> } >>> >>> Here is a output from tcpdump. >>> >>> 0x0410: 0000 074d 7400 296f 7267 2e61 7061 >>> 6368 ...Mt.)org.apach >>> 0x0420: 652e 6361 7965 6e6e 652e 6d61 702e 4361 >>> e.cayenne.map.Ca >>> 0x0430: 6c6c 6261 636b 4465 7363 7269 7074 6f72 >>> llbackDescriptor >>> 0x0440: 5300 0c63 616c 6c62 6163 6b54 7970 654d >>> S..callbackTypeM >>> 0x0450: 7400 256f 7267 2e61 7061 6368 652e 6361 t. >>> %org.apache.ca >>> 0x0460: 7965 6e6e 652e 6d61 702e 4c69 6665 6379 >>> yenne.map.Lifecy >>> 0x0470: 636c 6545 7665 6e74 5300 0b50 5245 5f50 >>> cleEventS..PRE_P >>> 0x0480: 4552 5349 5354 7a53 000f 6361 6c6c 6261 >>> ERSISTzS..callba >>> 0x0490: 636b 4d65 7468 6f64 7356 7400 176a 6176 >>> ckMethodsVt..jav >>> 0x04a0: 612e 7574 696c 2e4c 696e 6b65 6448 6173 >>> a.util.LinkedHas >>> 0x04b0: 6853 6574 6c00 0000 007a 7a4d 7400 296f >>> hSetl....zzMt.)o >>> 0x04c0: 7267 2e61 7061 6368 652e 6361 7965 6e6e >>> rg.apache.cayenn >>> 0x04d0: 652e 6d61 702e 4361 6c6c 6261 636b 4465 >>> e.map.CallbackDe >>> 0x04e0: 7363 7269 7074 6f72 5300 0c63 616c 6c62 >>> scriptorS..callb >>> 0x04f0: 6163 6b54 7970 654d 7400 256f 7267 2e61 ackTypeMt. >>> %org.a >>> 0x0500: 7061 6368 652e 6361 7965 6e6e 652e 6d61 >>> pache.cayenne.ma >>> 0x0510: 702e 4c69 6665 6379 636c 6545 7665 6e74 >>> p.LifecycleEvent >>> 0x0520: 5300 0a50 5245 5f52 454d 4f56 457a 5300 >>> S..PRE_REMOVEzS. >>> >>> Anyone know where to start on the objc side of it? >>> >>> - Tore. >>> >>> On Dec 13, 2007, at 01:17, Tore Halset wrote: >>> >>>> Hello. >>>> >>>> I was able to decode java.util.TreeMap with HessianObjC before, but >>>> now (after leopard?), they are just decoded as null. The TreeMap >>>> is a >>>> member of a mapped class. >>>> >>>> Anyone else seen something like this? >>>> >>>> Regards, >>>> - Tore. >>>> >>>> ------------------------------------------------------------------------- >>>> SF.Net email is sponsored by: >>>> Check out the new SourceForge.net Marketplace. >>>> It's the best place to buy or sell services >>>> for just about anything Open Source. >>>> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >>>> _______________________________________________ >>>> Hessianobjc-user mailing list >>>> Hes...@li... >>>> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >>>> >>> >>> >>> ------------------------------------------------------------------------- >>> SF.Net email is sponsored by: >>> Check out the new SourceForge.net Marketplace. >>> It's the best place to buy or sell services >>> for just about anything Open Source. >>> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >>> _______________________________________________ >>> Hessianobjc-user mailing list >>> Hes...@li... >>> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >>> >> >> >> ------------------------------------------------------------------------- >> SF.Net email is sponsored by: >> Check out the new SourceForge.net Marketplace. >> It's the best place to buy or sell services >> for just about anything Open Source. >> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >> _______________________________________________ >> Hessianobjc-user mailing list >> Hes...@li... >> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >> > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2005. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user |
From: Tore H. <ha...@pv...> - 2008-01-05 00:44:13
|
Hello. Anyone able to take a look at this one? And perhaps commit an acceptable fix? - Tore. On Dec 17, 2007, at 01:43, Tore Halset wrote: > Hello. > > Okay, I found a solution. Looks like hessian serialize a enum variable > as a Map with a single key, but no value. Here is a working patch that > fixes my problem. > > Index: BBSHessianDecoder.m > =================================================================== > --- BBSHessianDecoder.m (revision 92) > +++ BBSHessianDecoder.m (working copy) > @@ -251,6 +251,11 @@ > //read the type > id key = [self decodeObjectForCode:objectTag]; > [dataInputStream read:&objectTag maxLength:1]; > + if(objectTag == 'z') { > + // java enum are serialized by hessian using a Map > with a single key, but no value > + [dict setObject:[NSNull null] forKey:key]; > + break; > + } > id value = [self decodeObjectForCode:objectTag]; > if(key != nil) { > if(value == nil) { > > > Regards, > - Tore. > > On Dec 17, 2007, at 01:17, Tore Halset wrote: > >> Hello. >> >> Sorry, but the map is not related to TreeMap, but encoding a enum. >> This enum is burryed far down in the object graph, but I have >> isolated >> this by trying everything with the transient-keyword. >> >> The problem is this instanse variable: >> protected LifecycleEvent callbackType; >> >> This is how LifecycleEvent look like: >> public enum LifecycleEvent { >> PRE_PERSIST, PRE_REMOVE, PRE_UPDATE, POST_PERSIST, POST_REMOVE, >> POST_UPDATE, POST_LOAD; >> } >> >> Here is a output from tcpdump. >> >> 0x0410: 0000 074d 7400 296f 7267 2e61 7061 >> 6368 ...Mt.)org.apach >> 0x0420: 652e 6361 7965 6e6e 652e 6d61 702e 4361 >> e.cayenne.map.Ca >> 0x0430: 6c6c 6261 636b 4465 7363 7269 7074 6f72 >> llbackDescriptor >> 0x0440: 5300 0c63 616c 6c62 6163 6b54 7970 654d >> S..callbackTypeM >> 0x0450: 7400 256f 7267 2e61 7061 6368 652e 6361 t. >> %org.apache.ca >> 0x0460: 7965 6e6e 652e 6d61 702e 4c69 6665 6379 >> yenne.map.Lifecy >> 0x0470: 636c 6545 7665 6e74 5300 0b50 5245 5f50 >> cleEventS..PRE_P >> 0x0480: 4552 5349 5354 7a53 000f 6361 6c6c 6261 >> ERSISTzS..callba >> 0x0490: 636b 4d65 7468 6f64 7356 7400 176a 6176 >> ckMethodsVt..jav >> 0x04a0: 612e 7574 696c 2e4c 696e 6b65 6448 6173 >> a.util.LinkedHas >> 0x04b0: 6853 6574 6c00 0000 007a 7a4d 7400 296f >> hSetl....zzMt.)o >> 0x04c0: 7267 2e61 7061 6368 652e 6361 7965 6e6e >> rg.apache.cayenn >> 0x04d0: 652e 6d61 702e 4361 6c6c 6261 636b 4465 >> e.map.CallbackDe >> 0x04e0: 7363 7269 7074 6f72 5300 0c63 616c 6c62 >> scriptorS..callb >> 0x04f0: 6163 6b54 7970 654d 7400 256f 7267 2e61 ackTypeMt. >> %org.a >> 0x0500: 7061 6368 652e 6361 7965 6e6e 652e 6d61 >> pache.cayenne.ma >> 0x0510: 702e 4c69 6665 6379 636c 6545 7665 6e74 >> p.LifecycleEvent >> 0x0520: 5300 0a50 5245 5f52 454d 4f56 457a 5300 >> S..PRE_REMOVEzS. >> >> Anyone know where to start on the objc side of it? >> >> - Tore. >> >> On Dec 13, 2007, at 01:17, Tore Halset wrote: >> >>> Hello. >>> >>> I was able to decode java.util.TreeMap with HessianObjC before, but >>> now (after leopard?), they are just decoded as null. The TreeMap >>> is a >>> member of a mapped class. >>> >>> Anyone else seen something like this? >>> >>> Regards, >>> - Tore. >>> >>> ------------------------------------------------------------------------- >>> SF.Net email is sponsored by: >>> Check out the new SourceForge.net Marketplace. >>> It's the best place to buy or sell services >>> for just about anything Open Source. >>> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >>> _______________________________________________ >>> Hessianobjc-user mailing list >>> Hes...@li... >>> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >>> >> >> >> ------------------------------------------------------------------------- >> SF.Net email is sponsored by: >> Check out the new SourceForge.net Marketplace. >> It's the best place to buy or sell services >> for just about anything Open Source. >> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >> _______________________________________________ >> Hessianobjc-user mailing list >> Hes...@li... >> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >> > > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services > for just about anything Open Source. > http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Tore H. <ha...@pv...> - 2007-12-17 00:42:21
|
Hello. Okay, I found a solution. Looks like hessian serialize a enum variable as a Map with a single key, but no value. Here is a working patch that fixes my problem. Index: BBSHessianDecoder.m =================================================================== --- BBSHessianDecoder.m (revision 92) +++ BBSHessianDecoder.m (working copy) @@ -251,6 +251,11 @@ //read the type id key = [self decodeObjectForCode:objectTag]; [dataInputStream read:&objectTag maxLength:1]; + if(objectTag == 'z') { + // java enum are serialized by hessian using a Map with a single key, but no value + [dict setObject:[NSNull null] forKey:key]; + break; + } id value = [self decodeObjectForCode:objectTag]; if(key != nil) { if(value == nil) { Regards, - Tore. On Dec 17, 2007, at 01:17, Tore Halset wrote: > Hello. > > Sorry, but the map is not related to TreeMap, but encoding a enum. > This enum is burryed far down in the object graph, but I have isolated > this by trying everything with the transient-keyword. > > The problem is this instanse variable: > protected LifecycleEvent callbackType; > > This is how LifecycleEvent look like: > public enum LifecycleEvent { > PRE_PERSIST, PRE_REMOVE, PRE_UPDATE, POST_PERSIST, POST_REMOVE, > POST_UPDATE, POST_LOAD; > } > > Here is a output from tcpdump. > > 0x0410: 0000 074d 7400 296f 7267 2e61 7061 > 6368 ...Mt.)org.apach > 0x0420: 652e 6361 7965 6e6e 652e 6d61 702e 4361 > e.cayenne.map.Ca > 0x0430: 6c6c 6261 636b 4465 7363 7269 7074 6f72 > llbackDescriptor > 0x0440: 5300 0c63 616c 6c62 6163 6b54 7970 654d > S..callbackTypeM > 0x0450: 7400 256f 7267 2e61 7061 6368 652e 6361 t. > %org.apache.ca > 0x0460: 7965 6e6e 652e 6d61 702e 4c69 6665 6379 > yenne.map.Lifecy > 0x0470: 636c 6545 7665 6e74 5300 0b50 5245 5f50 > cleEventS..PRE_P > 0x0480: 4552 5349 5354 7a53 000f 6361 6c6c 6261 > ERSISTzS..callba > 0x0490: 636b 4d65 7468 6f64 7356 7400 176a 6176 > ckMethodsVt..jav > 0x04a0: 612e 7574 696c 2e4c 696e 6b65 6448 6173 > a.util.LinkedHas > 0x04b0: 6853 6574 6c00 0000 007a 7a4d 7400 296f > hSetl....zzMt.)o > 0x04c0: 7267 2e61 7061 6368 652e 6361 7965 6e6e > rg.apache.cayenn > 0x04d0: 652e 6d61 702e 4361 6c6c 6261 636b 4465 > e.map.CallbackDe > 0x04e0: 7363 7269 7074 6f72 5300 0c63 616c 6c62 > scriptorS..callb > 0x04f0: 6163 6b54 7970 654d 7400 256f 7267 2e61 ackTypeMt. > %org.a > 0x0500: 7061 6368 652e 6361 7965 6e6e 652e 6d61 > pache.cayenne.ma > 0x0510: 702e 4c69 6665 6379 636c 6545 7665 6e74 > p.LifecycleEvent > 0x0520: 5300 0a50 5245 5f52 454d 4f56 457a 5300 > S..PRE_REMOVEzS. > > Anyone know where to start on the objc side of it? > > - Tore. > > On Dec 13, 2007, at 01:17, Tore Halset wrote: > >> Hello. >> >> I was able to decode java.util.TreeMap with HessianObjC before, but >> now (after leopard?), they are just decoded as null. The TreeMap is a >> member of a mapped class. >> >> Anyone else seen something like this? >> >> Regards, >> - Tore. >> >> ------------------------------------------------------------------------- >> SF.Net email is sponsored by: >> Check out the new SourceForge.net Marketplace. >> It's the best place to buy or sell services >> for just about anything Open Source. >> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace >> _______________________________________________ >> Hessianobjc-user mailing list >> Hes...@li... >> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user >> > > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services > for just about anything Open Source. > http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Tore H. <ha...@pv...> - 2007-12-17 00:16:56
|
Hello. Sorry, but the map is not related to TreeMap, but encoding a enum. This enum is burryed far down in the object graph, but I have isolated this by trying everything with the transient-keyword. The problem is this instanse variable: protected LifecycleEvent callbackType; This is how LifecycleEvent look like: public enum LifecycleEvent { PRE_PERSIST, PRE_REMOVE, PRE_UPDATE, POST_PERSIST, POST_REMOVE, POST_UPDATE, POST_LOAD; } Here is a output from tcpdump. 0x0410: 0000 074d 7400 296f 7267 2e61 7061 6368 ...Mt.)org.apach 0x0420: 652e 6361 7965 6e6e 652e 6d61 702e 4361 e.cayenne.map.Ca 0x0430: 6c6c 6261 636b 4465 7363 7269 7074 6f72 llbackDescriptor 0x0440: 5300 0c63 616c 6c62 6163 6b54 7970 654d S..callbackTypeM 0x0450: 7400 256f 7267 2e61 7061 6368 652e 6361 t. %org.apache.ca 0x0460: 7965 6e6e 652e 6d61 702e 4c69 6665 6379 yenne.map.Lifecy 0x0470: 636c 6545 7665 6e74 5300 0b50 5245 5f50 cleEventS..PRE_P 0x0480: 4552 5349 5354 7a53 000f 6361 6c6c 6261 ERSISTzS..callba 0x0490: 636b 4d65 7468 6f64 7356 7400 176a 6176 ckMethodsVt..jav 0x04a0: 612e 7574 696c 2e4c 696e 6b65 6448 6173 a.util.LinkedHas 0x04b0: 6853 6574 6c00 0000 007a 7a4d 7400 296f hSetl....zzMt.)o 0x04c0: 7267 2e61 7061 6368 652e 6361 7965 6e6e rg.apache.cayenn 0x04d0: 652e 6d61 702e 4361 6c6c 6261 636b 4465 e.map.CallbackDe 0x04e0: 7363 7269 7074 6f72 5300 0c63 616c 6c62 scriptorS..callb 0x04f0: 6163 6b54 7970 654d 7400 256f 7267 2e61 ackTypeMt. %org.a 0x0500: 7061 6368 652e 6361 7965 6e6e 652e 6d61 pache.cayenne.ma 0x0510: 702e 4c69 6665 6379 636c 6545 7665 6e74 p.LifecycleEvent 0x0520: 5300 0a50 5245 5f52 454d 4f56 457a 5300 S..PRE_REMOVEzS. Anyone know where to start on the objc side of it? - Tore. On Dec 13, 2007, at 01:17, Tore Halset wrote: > Hello. > > I was able to decode java.util.TreeMap with HessianObjC before, but > now (after leopard?), they are just decoded as null. The TreeMap is a > member of a mapped class. > > Anyone else seen something like this? > > Regards, > - Tore. > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services > for just about anything Open Source. > http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Tore H. <ha...@pv...> - 2007-12-16 22:32:00
|
Hello. This patch make it impossible to decode self-refering object graphs as you sometimes need an updated refArray before the complete Map is decoded. I think this should be handled as a special case in decodeRef instead. Regards, - Tore. On Dec 15, 2007, at 02:22, Tom Davies wrote: > When a map is decoded, the NSDictionary is stored in the refArray, > even if the dictionary is subsequently mapped to a class. This means > that references get the dictionary, not the class: > > Here's a simple fix which defers storing the reference until the end: > > - (id) decodeMap { > id dict = [NSMutableDictionary dictionary]; > - //add the pointer to the ref array and not the actually value. > - [refArray addObject:[NSValue valueWithPointer:dict]]; > Class mappedClass = nil; > uint8_t objectTag = 'e'; > if([dataInputStream hasBytesAvailable]) { > @@ -264,9 +297,11 @@ > if(mappedClass) { > //a mapped class, user map decoder to init object > BBSHessianMapDecoder * mapDecoder = > [[[BBSHessianMapDecoder alloc] initForReadingWithDictionary:dict] > autorelease]; > - id obj = [[[mappedClass alloc] initWithCoder:mapDecoder] > autorelease]; > + id obj = [[[mappedClass alloc] initWithCoder:mapDecoder] > autorelease]; > + [refArray addObject:[NSValue valueWithPointer:obj]]; > return obj; > } > + [refArray addObject:[NSValue valueWithPointer:dict]]; > return dict; > } > else { > > > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services > for just about anything Open Source. > http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Tom D. <tgd...@gm...> - 2007-12-16 07:40:49
|
I've found two problems here -- first the mallocs are: uint8_t * readData = NULL; readData = malloc(len * sizeof(readData)); sizeof(readData) is 4 -- the malloc should just be len bytes. more seriously, the last block doesn't read it's length, so it assumes the length is the same as the previous block (and has two extra bytes of data which are actually the length) Tom |
From: Tom D. <tgd...@gm...> - 2007-12-15 01:22:30
|
When a map is decoded, the NSDictionary is stored in the refArray, even if the dictionary is subsequently mapped to a class. This means that references get the dictionary, not the class: Here's a simple fix which defers storing the reference until the end: - (id) decodeMap { id dict = [NSMutableDictionary dictionary]; - //add the pointer to the ref array and not the actually value. - [refArray addObject:[NSValue valueWithPointer:dict]]; Class mappedClass = nil; uint8_t objectTag = 'e'; if([dataInputStream hasBytesAvailable]) { @@ -264,9 +297,11 @@ if(mappedClass) { //a mapped class, user map decoder to init object BBSHessianMapDecoder * mapDecoder = [[[BBSHessianMapDecoder alloc] initForReadingWithDictionary:dict] autorelease]; - id obj = [[[mappedClass alloc] initWithCoder:mapDecoder] autorelease]; + id obj = [[[mappedClass alloc] initWithCoder:mapDecoder] autorelease]; + [refArray addObject:[NSValue valueWithPointer:obj]]; return obj; } + [refArray addObject:[NSValue valueWithPointer:dict]]; return dict; } else { |
From: Tore H. <ha...@pv...> - 2007-12-13 08:25:01
|
One more thing. The rest of the response are not decoded. The object with the TreeMap was one of several in a List. Only the first was decoded, and that one only partial. This is on a 32bit iMac with Leopard. I should probably test on other platforms as well. - Tore. On Dec 13, 2007, at 1:17 , Tore Halset wrote: > Hello. > > I was able to decode java.util.TreeMap with HessianObjC before, but > now (after leopard?), they are just decoded as null. The TreeMap is a > member of a mapped class. > > Anyone else seen something like this? > > Regards, > - Tore. > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services > for just about anything Open Source. > http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Tore H. <ha...@pv...> - 2007-12-13 05:54:08
|
Hello. I was able to decode java.util.TreeMap with HessianObjC before, but now (after leopard?), they are just decoded as null. The TreeMap is a member of a mapped class. Anyone else seen something like this? Regards, - Tore. |
From: Tom D. <tgd...@gm...> - 2007-12-10 12:23:00
|
Here's a barely-tested fix which seems to work for me -- I haven't set SVN up yet, so it isn't a patch... - (NSString *) decodeStringChunk { int len = [self decodeStringLength]; if(len == 0) { return @""; } //alloc enough memory for the string +1 for null terminator // this may be twice the number of characters + 1 for a pathological // case where each character is a two byte character in UTF-8 uint8_t * readData = malloc((2*len+1) * sizeof(uint8_t)); if(readData == NULL) { NSLog(@"failed to alloc memory for string with len =%i",len); return @""; } //set all to null. memset(readData,0,2*len+1); // we need to read at least 'len' bytes, but then need to check if we need // to read more [dataInputStream read:readData maxLength:len]; int totalLength = len; int multiByteCharsFound = 0; while ([self countUTFChars:readData length:totalLength found:&multiByteCharsFound] < len) { [dataInputStream read:(readData + totalLength) maxLength:multiByteCharsFound - (len - totalLength)]; totalLength += multiByteCharsFound - (len - totalLength); } NSString * retString = [NSString stringWithUTF8String:(const char *)readData] ; free(readData); return retString; } - (int) countUTFChars:(uint8_t*)data length:(int)length found: (int*)foundp { *foundp = 0; int i; int count = 0; for (i = 0; i < length; ++i) { ++count; if (data[i] > 0x7f) { int extra = 1; if (data[i] > 0xdf) { extra = 2; if (data[i] > 0xef) { extra = 3; } } *foundp += extra; i += extra; } } return count; } |
From: Tom D. <tgd...@gm...> - 2007-12-10 11:48:25
|
On 09/12/2007, at 7:54 AM, Byron Wright wrote: >> >> BTW, If you happen to track this problem down and find a fix I'd be >> happy to accept patches :) >> Hi Byron, The problem (which occurs with 3.0.20 as well) seems to be a byte/vs UTF character issue. When the Java client returns a string which contains a character with a multi-byte representation in UTF-8, the size of the string is given as the number of characters, not the number of bytes in the representation, so decodeStringChunk doesn't read enough bytes (although it does correctly create the final string with stringWithUTF8String) This is correct: http://www.caucho.com/resin-3.0//protocols/hessian-1.0-spec.xtp#string says "The length is the number of characters, which may be different than the number of bytes." That's a very irritating choice for clients who aren't using a UTF-16 encoding! Why couldn't they have encoded the number of bytes? Off the top of my head I don't see an easy fix other than reading the string one byte at a time. I may just use binary data for any strings which might contain special characters, and rehydrate them afterwards... Regards, Tom |
From: Tore H. <ha...@pv...> - 2007-12-09 22:20:31
|
On Dec 9, 2007, at 02:33, Byron Wright wrote: > I was originally relying on the classString property because any of > the class that use class cluster don't have true inheritance > therefore [NSCalendarDate class] != [NSDate class] (as you've > already demonstrated with your fix) even though according to the > documentation NSCalendarDate inherits from NSDate (as this is the > nature of class clusters). I'll re-address this to come up with a > better equality test for class clusters. Yes, I almost remember the class cluster thing. Thanks for committing a fix! - Tore. |
From: Byron W. <by...@bl...> - 2007-12-09 01:34:08
|
Hi Tore, thanks for pointing this out. I've updated the website, applied your patch and have run successfully run the unit tests on Leopard. I've also adjusted the unit tests to use the Caucho test end point "http://hessian.caucho.com/test/test " now that it's up and running again, unit tests should be passing without running a local hessian service. Ideally the unit tests shouldn't rely on a running service (especially an external end point), something I need to address. I was originally relying on the classString property because any of the class that use class cluster don't have true inheritance therefore [NSCalendarDate class] != [NSDate class] (as you've already demonstrated with your fix) even though according to the documentation NSCalendarDate inherits from NSDate (as this is the nature of class clusters). I'll re-address this to come up with a better equality test for class clusters. Cheers, Byron On Dec 8, 2007, at 3:21 PM, Tore Halset wrote: > Hello. > > The svn url mentioned on top of http://www.bluebearstudio.com/hessianobjc/ > does not seem to work anymore. I think the new one is > svn co https://hessianobjc.svn.sourceforge.net/svnroot/hessianobjc/ > trunk hessianobjc > > I just tried my project with Leopard and got an issue encoding NSDate. > Looks like the classString now is "__NSCFDate" instead of "NSCFDate". > I therefore suggest the following patch and recomend to not rely on > class names. > > Index: BBSHessianEncoder.m > =================================================================== > --- BBSHessianEncoder.m (revision 90) > +++ BBSHessianEncoder.m (working copy) > @@ -221,7 +221,7 @@ > else if([classString isEqualToString:@"NSCFDictionary"]) { > [self encodeDictionary:anyObject]; > } > - else if([classString isEqualToString:@"NSCFDate"] || > + else if([anyObject isKindOfClass:[NSDate class]] || > [anyObject isKindOfClass:[NSCalendarDate class]]) { > [self encodeDate:anyObject]; > } > > Regards, > - Tore. > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services for > just about anything Open Source. > http://sourceforge.net/services/buy/index.php > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user |
From: Tore H. <ha...@pv...> - 2007-12-08 23:20:03
|
Hello. The svn url mentioned on top of http://www.bluebearstudio.com/hessianobjc/ does not seem to work anymore. I think the new one is svn co https://hessianobjc.svn.sourceforge.net/svnroot/hessianobjc/ trunk hessianobjc I just tried my project with Leopard and got an issue encoding NSDate. Looks like the classString now is "__NSCFDate" instead of "NSCFDate". I therefore suggest the following patch and recomend to not rely on class names. Index: BBSHessianEncoder.m =================================================================== --- BBSHessianEncoder.m (revision 90) +++ BBSHessianEncoder.m (working copy) @@ -221,7 +221,7 @@ else if([classString isEqualToString:@"NSCFDictionary"]) { [self encodeDictionary:anyObject]; } - else if([classString isEqualToString:@"NSCFDate"] || + else if([anyObject isKindOfClass:[NSDate class]] || [anyObject isKindOfClass:[NSCalendarDate class]]) { [self encodeDate:anyObject]; } Regards, - Tore. |
From: Byron W. <by...@bl...> - 2007-12-08 20:54:51
|
> From: Byron Wright <by...@bl...> > Date: December 8, 2007 12:53:37 PM PST > To: Tom Davies <tgd...@gm...> > Subject: Re: [Hessianobjc-user] Which hessian jar to use? > > Hi Tom, > > HessianObjC 0.6.1 was implemented against the 1.0 version of the > protocol and hessian-3.0.20.jar. It's not clear on Caucho's Hessian > page what has changed between 3.1.3 and 3.0.20. Based on the error > message it looks like the the response from the 3.1.3 service is not > being decoded correctly. I'll need to track this down. If > hessian-3.0.20.jar works for you needs I'd say use that until this > is resolved. > >> Additionally, I see that this list is quiet -- have people shifted to >> a different protocol for ObjC-Java integration? What other *binary* >> alternatives are there? IIOP... > > The list has always been kinda quiet, my guess is that HessianObjC > fills a very small niche and that most people doing any sort of > remoting over HTTP can fill the requirements using non-binary > protocols. I don't know of many other alternative binary RPC > protocols for ObjC->Java besides rolling your own (yikes), using the > deprecated ObjC-Java bridge and RMI (JVM running inside of ObjC app) > or using something like Corba. You could get really exotic and do > something like using RubyCocoa [http://rubycocoa.sourceforge.net/HomePage > ] on the ObjC side, DRb as the protocol and JRuby on the server > end... like I said, very exotic. However, if you need to communicate > over HTTP you're options become limited if you are required to use a > binary protocol. > > BTW, If you happen to track this problem down and find a fix I'd be > happy to accept patches :) > > cheers, > Byron > > > On Dec 7, 2007, at 10:58 PM, Tom Davies wrote: > >> Hi, >> >> I'd like to double check that HessianObjC is compatible with the >> 3.1.3 >> jar from Caucho. >> >> I'm getting this error: >> >> 2007-12-08 14:20:26.458 otest[55210:80f] ERROR: excepted 'B' tag for >> binary chunk sequence >> 2007-12-08 14:20:26.477 otest[55210:80f] expected 'S' for last string >> chunk >> 2007-12-08 14:20:26.479 otest[55210:80f] expected 'S' for last string >> chunk >> 2007-12-08 14:20:26.480 otest[55210:80f] expected 'X' for last xml >> chunk >> 2007-12-08 14:20:26.483 otest[55210:80f] expected 'X' for last xml >> chunk >> 2007-12-08 14:20:26.484 otest[55210:80f] expected 'S' for last string >> chunk >> 2007-12-08 14:20:26.488 otest[55210:80f] ERROR: excepted 'B' tag for >> binary chunk sequence >> 2007-12-08 14:20:26.489 otest[55210:80f] expected 'X' for last xml >> chunk >> 2007-12-08 14:20:26.491 otest[55210:80f] ERROR: excepted 'B' tag for >> binary chunk sequence >> >> calling from ObjC to Java -- I haven't done any debugging yet, but >> I'd >> just like to know if my two endpoints are compatible. >> >> Additionally, I see that this list is quiet -- have people shifted to >> a different protocol for ObjC-Java integration? What other *binary* >> alternatives are there? IIOP... >> >> Thanks, >> Tom >> >> ------------------------------------------------------------------------- >> SF.Net email is sponsored by: >> Check out the new SourceForge.net Marketplace. >> It's the best place to buy or sell services for >> just about anything Open Source. >> http://sourceforge.net/services/buy/index.php >> _______________________________________________ >> Hessianobjc-user mailing list >> Hes...@li... >> https://lists.sourceforge.net/lists/listinfo/hessianobjc-user > |
From: Byron W. <by...@bl...> - 2007-12-08 20:54:08
|
On Dec 7, 2007, at 10:58 PM, Tom Davies wrote: > Hi, > > I'd like to double check that HessianObjC is compatible with the 3.1.3 > jar from Caucho. > > I'm getting this error: > > 2007-12-08 14:20:26.458 otest[55210:80f] ERROR: excepted 'B' tag for > binary chunk sequence > 2007-12-08 14:20:26.477 otest[55210:80f] expected 'S' for last string > chunk > 2007-12-08 14:20:26.479 otest[55210:80f] expected 'S' for last string > chunk > 2007-12-08 14:20:26.480 otest[55210:80f] expected 'X' for last xml > chunk > 2007-12-08 14:20:26.483 otest[55210:80f] expected 'X' for last xml > chunk > 2007-12-08 14:20:26.484 otest[55210:80f] expected 'S' for last string > chunk > 2007-12-08 14:20:26.488 otest[55210:80f] ERROR: excepted 'B' tag for > binary chunk sequence > 2007-12-08 14:20:26.489 otest[55210:80f] expected 'X' for last xml > chunk > 2007-12-08 14:20:26.491 otest[55210:80f] ERROR: excepted 'B' tag for > binary chunk sequence > > calling from ObjC to Java -- I haven't done any debugging yet, but I'd > just like to know if my two endpoints are compatible. > > Additionally, I see that this list is quiet -- have people shifted to > a different protocol for ObjC-Java integration? What other *binary* > alternatives are there? IIOP... > > Thanks, > Tom > > ------------------------------------------------------------------------- > SF.Net email is sponsored by: > Check out the new SourceForge.net Marketplace. > It's the best place to buy or sell services for > just about anything Open Source. > http://sourceforge.net/services/buy/index.php > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user |
From: Tom D. <tgd...@gm...> - 2007-12-08 06:58:50
|
Hi, I'd like to double check that HessianObjC is compatible with the 3.1.3 jar from Caucho. I'm getting this error: 2007-12-08 14:20:26.458 otest[55210:80f] ERROR: excepted 'B' tag for binary chunk sequence 2007-12-08 14:20:26.477 otest[55210:80f] expected 'S' for last string chunk 2007-12-08 14:20:26.479 otest[55210:80f] expected 'S' for last string chunk 2007-12-08 14:20:26.480 otest[55210:80f] expected 'X' for last xml chunk 2007-12-08 14:20:26.483 otest[55210:80f] expected 'X' for last xml chunk 2007-12-08 14:20:26.484 otest[55210:80f] expected 'S' for last string chunk 2007-12-08 14:20:26.488 otest[55210:80f] ERROR: excepted 'B' tag for binary chunk sequence 2007-12-08 14:20:26.489 otest[55210:80f] expected 'X' for last xml chunk 2007-12-08 14:20:26.491 otest[55210:80f] ERROR: excepted 'B' tag for binary chunk sequence calling from ObjC to Java -- I haven't done any debugging yet, but I'd just like to know if my two endpoints are compatible. Additionally, I see that this list is quiet -- have people shifted to a different protocol for ObjC-Java integration? What other *binary* alternatives are there? IIOP... Thanks, Tom |
From: Byron W. <by...@bl...> - 2006-11-04 18:52:24
|
Thanks Tore, your changes have been committed and the unit tests have been updated for this case. On Nov 3, 2006, at 12:59 PM, Tore Halset wrote: > Hello. > > Just a small fix to allow encoding of a NSDictionary with NSNull > values. > > - Tore. > <p.txt> > Index: BBSHessianEncoder.m > =================================================================== > --- BBSHessianEncoder.m (revision 84) > +++ BBSHessianEncoder.m (working copy) > @@ -212,6 +212,9 @@ > else if([anyObject isKindOfClass:[NSNumber class]]) { > [self encodeNumber:anyObject]; > } > + else if([anyObject isKindOfClass:[NSNull class]]) { > + [self encodeNil]; > + } > else if([objClass isKindOfClass:[NSValue class]] || > [classString isEqualToString:@"NSConcreteValue"]) { > } > |
From: Tore H. <ha...@pv...> - 2006-11-03 20:59:35
|
Hello. Just a small fix to allow encoding of a NSDictionary with NSNull values. - Tore. |
From: Byron W. <by...@bl...> - 2006-10-12 03:26:56
|
Hi Tore, let me see your initWithCoder method and class interface. My BBSHessianMapDecoder class only implements the keyed archive methods. decodeValueOfObjCType:at: isn't a keyed archiver method of NSCoder. This is how I might implement my custom BigDecimalNumber custom class initWithCoder method: @interface MyBigDecimalNumber: NSDecimalNumber <NSCoding> { } ... ... ... - (id) initWithCoder : (NSCoder *) decoder { self = [[NSDecimalNumber alloc] initWithString:[decoder objectForKey:"value"]]; return self; } ... similar thing for encoding MyBigDecli On Oct 11, 2006, at 5:29 PM, Tore Halset wrote: > Hello. > > Do you know how to map a java.math.BigDecimal to NSDecimalNumber? > BigDecimal has a single key named "value" with the String version of > the value. I tried to create a subclass of NSDecimalNumber with > custom initWithCoder:, but I then got famous "*** - > decodeValueOfObjCType:at: only defined for abstract class. Define - > [BBSHessianMapDecoder decodeValueOfObjCType:at:]!" > > - Tore. > > ---------------------------------------------------------------------- > --- > Using Tomcat but need to do more? Need to support web services, > security? > Get stuff done quickly with pre-integrated technology to make your > job easier > Download IBM WebSphere Application Server v.1.0.1 based on Apache > Geronimo > http://sel.as-us.falkag.net/sel? > cmd=lnk&kid=120709&bid=263057&dat=121642 > _______________________________________________ > Hessianobjc-user mailing list > Hes...@li... > https://lists.sourceforge.net/lists/listinfo/hessianobjc-user |
From: Tore H. <ha...@pv...> - 2006-10-12 00:29:35
|
Hello. Do you know how to map a java.math.BigDecimal to NSDecimalNumber? BigDecimal has a single key named "value" with the String version of the value. I tried to create a subclass of NSDecimalNumber with custom initWithCoder:, but I then got famous "*** - decodeValueOfObjCType:at: only defined for abstract class. Define - [BBSHessianMapDecoder decodeValueOfObjCType:at:]!" - Tore. |
From: Byron W. <by...@bl...> - 2006-10-10 04:06:16
|
Tore, after following the cocoa thread about this I implemented BBSHessianEncoder using the CFSwap and CFConvert functions instead of the Endian ones. My units tests were successful so I checked my latest into svn. Please let me know if there are any issues on Intel ASAP, I believe they should now be resolved. Cheers, Byron On Oct 8, 2006, at 4:47 PM, Tore Halset wrote: > On Oct 9, 2006, at 01:26, Byron Wright wrote: > >> As you can see testDecimal is 23.0. In BBSHessianEncoder - (void) >> encodeNumber:(NSNumber *) aNumber , I compare the underlying >> objCType to determine what kind of number this is and encode >> accordingly. For NSDecimalNumber this should always 'd' and >> should therefore get encoded using - (void) encodeDouble:(double) >> aDouble. So something (perhaps an Endian issue) might be going >> wrong there. Perhaps you could debug this and tell me what the >> character for this is [aNumber objCType] when using >> NSDecimalNumber (it should be 'd'). It's a little difficult to >> test endian issues without an intel mac :( > > > I entered "12.25" this time to be able to compare to the example at > http://www.caucho.com/resin-3.0/protocols/hessian-1.0-spec.xtp#double > > I added the following debug-NSLog to the start of encodeNumber: > NSLog(@"encodeNumber. objCType: %s, value: %@", [aNumber objCType], > aNumber); > It wrote the following line: > encodeNumber. objCType: d, value: 12.25 > > The value sent over the wire to the server is "4400 0000 0000 00a8 > 43" where "44" is "D" for Double. > > Looks like a powerpc contra intel bug not related to endian. I'll > let you know if I find a solution... > > - Tore. > |