FYI: I just filed this as rdar://6053207
Summary:
========
WOXMLCoder uses objectIDRef for mutable objects. IMHO it should
only use objectIDRefs, when it encounters an object with the same
System.identityHashCode(object) as a previously serialized object.
Currently it seems to rely on object.hashCode(), which is OK for
immutable objects, but not for mutable objects.
Steps to Reproduce:
===================
NSMutableArray a = new NSMutableArray();
NSMutableArray b = new NSMutableArray();
System.out.println("a: "+a);
System.out.println("b: "+b);
System.out.println("a==b? " + (a == b));
System.out.println("----------------------");
NSArray wrapper = new NSArray(new Object[] { a, b });
WOXMLCoder coder = WOXMLCoder.coder();
String s = coder.encodeRootObjectForKey(wrapper, "wrapper");
System.out.print(s);
System.out.println("----------------------");
WOXMLDecoder decoder = WOXMLDecoder.decoder();
NSArray deserializedWrapper = (NSArray) decoder.decodeRootObject
(new NSData(s.getBytes()));
NSMutableArray deserializedA = (NSMutableArray)
deserializedWrapper.objectAtIndex(0);
NSMutableArray deserializedB = (NSMutableArray)
deserializedWrapper.objectAtIndex(1);
System.out.println("deserializedA: " + deserializedA);
System.out.println("deserializedB: " + deserializedB);
System.out.println("deserializedA==deserializedB? " +
(deserializedA == deserializedB));
System.out.println("----------------------");
System.out.println("Adding 'foo' to 'a'");
deserializedA.addObject("foo");
System.out.println("Adding 'bar' to 'b'");
deserializedB.addObject("bar");
System.out.println("----------------------");
System.out.println("deserializedA: " + deserializedA);
System.out.println("deserializedB: " + deserializedB);
Actual Results:
===============
a: ()
b: ()
a==b? false
----------------------
<wrapper type="com.webobjects.foundation.NSArray" objectID="1">
<element type="com.webobjects.foundation.NSMutableArray"
objectID="2">
</element>
<element type="com.webobjects.foundation.NSMutableArray"
objectIDRef="2"></element>
</wrapper>
----------------------
deserializedA: ()
deserializedB: ()
deserializedA==deserializedB? true
----------------------
Adding 'foo' to 'a'
Adding 'bar' to 'b'
----------------------
deserializedA: ("foo", "bar")
deserializedB: ("foo", "bar")
Expected Results:
=================
deserializedA==deserializedB? false
Workarounds:
============
This subclass of WOXMLCoder hacks around the problem:
public class PDXMLCoder extends WOXMLCoder {
@SuppressWarnings("unchecked")
@Override
public void encodeObjectForKey(Object object, String s) {
if (object instanceof NSMutableArray) {
object = new _MutableArray((NSMutableArray) object);
}
else if (object instanceof NSMutableDictionary) {
object = new _MutableDictionary((NSMutableDictionary) object);
}
else if (object instanceof NSMutableData) {
object = new _MutableData((NSMutableData) object);
}
super.encodeObjectForKey(object, s);
}
public PDXMLCoder() {
super();
}
public static WOXMLCoder coder() {
return new PDXMLCoder();
}
@SuppressWarnings("unchecked")
public static class _MutableArray extends NSMutableArray {
public _MutableArray() {
super();
}
public _MutableArray(NSArray array) {
super(array);
}
@Override
public Class classForCoder() {
return NSMutableArray.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
@SuppressWarnings("unchecked")
public static class _MutableDictionary extends NSMutableDictionary {
public _MutableDictionary() {
super();
}
public _MutableDictionary(NSDictionary dict) {
super(dict);
}
@Override
public Class classForCoder() {
return NSMutableDictionary.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
@SuppressWarnings("unchecked")
public static class _MutableData extends NSMutableData {
public _MutableData() {
super();
}
public _MutableData(NSMutableData data) {
super(data);
}
@Override
public Class classForCoder() {
return NSMutableData.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
}
If you already have screwed serialized data, using this subclass
of WOXMLDecoder for deserializing can help in some situations:
public class PDXMLDecoder extends WOXMLDecoder {
@SuppressWarnings("unchecked")
@Override
public Object decodeObjectForKey(String s) {
Object object = super.decodeObjectForKey(s);
if (object instanceof NSMutableArray) {
NSMutableArray a = (NSMutableArray) object;
object = a.mutableClone();
}
else if (object instanceof NSMutableDictionary) {
NSMutableDictionary d = (NSMutableDictionary) object;
object = d.mutableClone();
}
else if (object instanceof NSMutableData) {
NSMutableData d = (NSMutableData) object;
object = d.clone();
}
return object;
}
public PDXMLDecoder() {
super();
}
public static WOXMLDecoder decoder(){
return new PDXMLDecoder();
}
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40logicunited.com
This email sent to email@hidden