Neither is OK. object.hashCode is not unique (can be a constant if overridden) and System.identityHashCode is not unique either.

Cheers, Anjo

Am 03.07.2008 um 22:35 schrieb Timo Hoepfner:

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 protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/krank%40logicunited.com

This email sent to [EMAIL PROTECTED]

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to