/* * Copyright (C) 2004, 2005 Joe Walnes. * Copyright (C) 2006, 2007 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD * style license a copy of which has been included with this distribution in * the LICENSE.txt file. * * Created on 24. August 2004 by Joe Walnes */ package com.thoughtworks.acceptance; import com.thoughtworks.acceptance.objects.StandardObject; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class ExternalizableTest extends AbstractAcceptanceTest { public static class SomethingExternalizable extends StandardObject implements Externalizable { private String first; private String last; public SomethingExternalizable() { } public SomethingExternalizable(String first, String last) { this.first = first; this.last = last; } public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(first.length()); out.writeObject(first + last); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { int offset = in.readInt(); String full = (String) in.readObject(); first = full.substring(0, offset); last = full.substring(offset); } } public void testExternalizable() { xstream.alias("something", SomethingExternalizable.class); SomethingExternalizable in = new SomethingExternalizable("Joe", "Walnes"); String expected = "" + "<something>\n" + " <int>3</int>\n" + " <string>JoeWalnes</string>\n" + "</something>"; assertBothWays(in, expected); } static class Owner extends StandardObject { SomethingExternalizable target; } public void testExternalizableAsFieldOfAnotherObject() { xstream.alias("something", SomethingExternalizable.class); xstream.alias("owner", Owner.class); Owner in = new Owner(); in.target = new SomethingExternalizable("Joe", "Walnes"); String expected = "" + "<owner>\n" + " <target>\n" + " <int>3</int>\n" + " <string>JoeWalnes</string>\n" + " </target>\n" + "</owner>"; assertBothWays(in, expected); } public static class CircularExternalizable implements Externalizable { private String name; private CircularExternalizable parent; private CircularExternalizable child; public CircularExternalizable() { } public CircularExternalizable(String name) { this.name = name; } public void setParent(CircularExternalizable parent) { this.parent = parent; if (parent != null) { parent.child = this; } } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); parent = (CircularExternalizable)in.readObject(); child = (CircularExternalizable)in.readObject(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeObject(parent); out.writeObject(child); } // StandardObject uses EqualsBuilder.reflectionEquals of commons-lang, // that does not handle circular dependencies public boolean equals(Object obj) { return obj instanceof CircularExternalizable && name.equals(obj.toString()); } public int hashCode() { return name.hashCode()+1; } public String toString() { return name; } } public void testCircularExternalizable() { xstream.alias("elem", CircularExternalizable.class); CircularExternalizable parent = new CircularExternalizable("parent"); CircularExternalizable child = new CircularExternalizable("child"); child.setParent(parent); String expected = "" + "<elem>\n" + " <string>parent</string>\n" + " <null/>\n" + " <elem>\n" + " <string>child</string>\n" + " <elem reference=\"../..\"/>\n" + " <null/>\n" + " </elem>\n" + "</elem>"; assertBothWays(parent, expected); } }