• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: WOXMLCoder uses objectIDRef for mutable objects
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: WOXMLCoder uses objectIDRef for mutable objects


  • Subject: Re: WOXMLCoder uses objectIDRef for mutable objects
  • From: Anjo Krank <email@hidden>
  • Date: Fri, 4 Jul 2008 05:39:20 +0200

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@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

_______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Follow-Ups:
    • Re: WOXMLCoder uses objectIDRef for mutable objects
      • From: Timo Hoepfner <email@hidden>
References: 
 >WOXMLCoder uses objectIDRef for mutable objects (From: Timo Hoepfner <email@hidden>)

  • Prev by Date: Re: DB uniqueness constraints and dealing with them
  • Next by Date: Re: Back To Basics : Databases Active Editing Context
  • Previous by thread: WOXMLCoder uses objectIDRef for mutable objects
  • Next by thread: Re: WOXMLCoder uses objectIDRef for mutable objects
  • Index(es):
    • Date
    • Thread