Index: E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
===================================================================
--- E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (revision 865)
+++ E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (working copy)
@@ -5,6 +5,7 @@
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
+import com.thoughtworks.xstream.core.util.CustomObjectOutputStream.StreamCallback;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
@@ -185,8 +186,9 @@
if (serializationMethodInvoker.supportsWriteObject(currentType[0], false)) {
writtenClassWrapper[0] = true;
writer.startNode(mapper.serializedClass(currentType[0]));
- ObjectOutputStream objectOutputStream = CustomObjectOutputStream.getInstance(context, callback);
+ CustomObjectOutputStream objectOutputStream = CustomObjectOutputStream.getInstance(context, callback);
serializationMethodInvoker.callWriteObject(currentType[0], source, objectOutputStream);
+ StreamCallback popped = objectOutputStream.popCallback();
writer.endNode();
} else if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
// Special case for objects that have readObject(), but not writeObject().
@@ -361,8 +363,9 @@
} else {
currentType[0] = mapper.defaultImplementationOf(mapper.realClass(nodeName));
if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
- ObjectInputStream objectInputStream = CustomObjectInputStream.getInstance(context, callback);
+ CustomObjectInputStream objectInputStream = CustomObjectInputStream.getInstance(context, callback);
serializationMethodInvoker.callReadObject(currentType[0], result, objectInputStream);
+ CustomObjectInputStream.StreamCallback popped = objectInputStream.popCallback();
} else {
try {
callback.defaultReadObject();
Index: E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java
===================================================================
--- E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java (revision 865)
+++ E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java (working copy)
@@ -2,6 +2,7 @@
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.core.util.CustomObjectOutputStream.StreamCallback;
import java.io.IOException;
import java.io.InvalidObjectException;
@@ -13,7 +14,7 @@
public class CustomObjectInputStream extends ObjectInputStream {
- private StreamCallback callback;
+ private FastStack callbacks = new FastStack(1);
private static final String DATA_HOLDER_KEY = CustomObjectInputStream.class.getName();
@@ -32,7 +33,7 @@
result = new CustomObjectInputStream(callback);
whereFrom.put(DATA_HOLDER_KEY, result);
} else {
- result.setCallback(callback);
+ result.pushCallback(callback);
}
return result;
} catch (IOException e) {
@@ -48,7 +49,7 @@
*/
public CustomObjectInputStream(StreamCallback callback) throws IOException, SecurityException {
super();
- this.callback = callback;
+ this.callbacks.push(callback);
}
/**
@@ -54,52 +55,54 @@
/**
* Allows the CustomObjectInputStream (which is expensive to create) to be reused.
*/
- public void setCallback(StreamCallback callback) {
- this.callback = callback;
+ public void pushCallback(StreamCallback callback) {
+ this.callbacks.push(callback);
+ }
+ public StreamCallback popCallback(){
+ return (StreamCallback) this.callbacks.pop();
}
-
public void defaultReadObject() throws IOException {
- callback.defaultReadObject();
+ ((StreamCallback) callbacks.peek()).defaultReadObject();
}
protected Object readObjectOverride() throws IOException {
- return callback.readFromStream();
+ return ((StreamCallback) callbacks.peek()).readFromStream();
}
public boolean readBoolean() throws IOException {
- return ((Boolean)callback.readFromStream()).booleanValue();
+ return ((Boolean)((StreamCallback) callbacks.peek()).readFromStream()).booleanValue();
}
public byte readByte() throws IOException {
- return ((Byte)callback.readFromStream()).byteValue();
+ return ((Byte)((StreamCallback) callbacks.peek()).readFromStream()).byteValue();
}
public int readInt() throws IOException {
- return ((Integer)callback.readFromStream()).intValue();
+ return ((Integer)((StreamCallback) callbacks.peek()).readFromStream()).intValue();
}
public char readChar() throws IOException {
- return ((Character)callback.readFromStream()).charValue();
+ return ((Character)((StreamCallback) callbacks.peek()).readFromStream()).charValue();
}
public float readFloat() throws IOException {
- return ((Float)callback.readFromStream()).floatValue();
+ return ((Float)((StreamCallback) callbacks.peek()).readFromStream()).floatValue();
}
public double readDouble() throws IOException {
- return ((Double)callback.readFromStream()).doubleValue();
+ return ((Double)((StreamCallback) callbacks.peek()).readFromStream()).doubleValue();
}
public long readLong() throws IOException {
- return ((Long)callback.readFromStream()).longValue();
+ return ((Long)((StreamCallback) callbacks.peek()).readFromStream()).longValue();
}
public short readShort() throws IOException {
- return ((Short)callback.readFromStream()).shortValue();
+ return ((Short)((StreamCallback) callbacks.peek()).readFromStream()).shortValue();
}
public String readUTF() throws IOException {
- return (String) callback.readFromStream();
+ return (String) ((StreamCallback) callbacks.peek()).readFromStream();
}
public void readFully(byte[] buf) throws IOException {
@@ -107,7 +110,7 @@
}
public void readFully(byte[] buf, int off, int len) throws IOException {
- byte[] b = (byte[])callback.readFromStream();
+ byte[] b = (byte[])((StreamCallback) callbacks.peek()).readFromStream();
System.arraycopy(b, 0, buf, off, len);
}
@@ -112,7 +115,7 @@
}
public GetField readFields() throws IOException {
- return new CustomGetField(callback.readFieldsFromStream());
+ return new CustomGetField(((StreamCallback) callbacks.peek()).readFieldsFromStream());
}
private class CustomGetField extends GetField {
@@ -174,11 +177,11 @@
}
public void registerValidation(ObjectInputValidation validation, int priority) throws NotActiveException, InvalidObjectException {
- callback.registerValidation(validation, priority);
+ ((StreamCallback) callbacks.peek()).registerValidation(validation, priority);
}
public void close() throws IOException {
- callback.close();
+ ((StreamCallback) callbacks.peek()).close();
}
/****** Unsupported methods ******/
Index: E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java
===================================================================
--- E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java (revision 865)
+++ E:/data/workspace/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java (working copy)
@@ -10,7 +10,7 @@
public class CustomObjectOutputStream extends ObjectOutputStream {
- private StreamCallback callback;
+ private FastStack callbacks = new FastStack(1);
private FastStack customFields = new FastStack(1);
private static final String DATA_HOLDER_KEY = CustomObjectOutputStream.class.getName();
@@ -16,6 +16,7 @@
private static final String DATA_HOLDER_KEY = CustomObjectOutputStream.class.getName();
public static synchronized CustomObjectOutputStream getInstance(DataHolder whereFrom, StreamCallback callback) {
+ //System.out.println("> CustomObjectOutputStream.getInstance(callback=" + callback + ")");
try {
CustomObjectOutputStream result = (CustomObjectOutputStream) whereFrom.get(DATA_HOLDER_KEY);
if (result == null) {
@@ -22,8 +23,9 @@
result = new CustomObjectOutputStream(callback);
whereFrom.put(DATA_HOLDER_KEY, result);
} else {
- result.setCallback(callback);
+ result.pushCallback(callback);
}
+ //System.out.println("< CustomObjectOutputStream.getInstance(callback=" + callback + "):" + result);
return result;
} catch (IOException e) {
throw new ConversionException("Cannot create CustomObjectStream", e);
@@ -36,6 +38,7 @@
void defaultWriteObject() throws IOException;
void flush() throws IOException;
void close() throws IOException;
+
}
/**
@@ -45,7 +48,7 @@
* @see #getInstance(com.thoughtworks.xstream.converters.DataHolder, com.thoughtworks.xstream.core.util.CustomObjectOutputStream.StreamCallback)
*/
public CustomObjectOutputStream(StreamCallback callback) throws IOException, SecurityException {
- this.callback = callback;
+ this.callbacks.push(callback);
}
/**
@@ -51,66 +54,68 @@
/**
* Allows the CustomObjectOutputStream (which is expensive to create) to be reused.
*/
- public void setCallback(StreamCallback callback) {
- this.callback = callback;
+ public void pushCallback(StreamCallback callback) {
+ this.callbacks.push(callback);
+ }
+ public StreamCallback popCallback(){
+ return (StreamCallback) this.callbacks.pop();
}
-
/*** Methods to delegate to callback ***/
public void defaultWriteObject() throws IOException {
- callback.defaultWriteObject();
+ ((StreamCallback) callbacks.peek()).defaultWriteObject();
}
protected void writeObjectOverride(Object obj) throws IOException {
- callback.writeToStream(obj);
+ ((StreamCallback) callbacks.peek()).writeToStream(obj);
}
public void writeBoolean(boolean val) throws IOException {
- callback.writeToStream(val ? Boolean.TRUE : Boolean.FALSE); // JDK 1.3 friendly
+ ((StreamCallback) callbacks.peek()).writeToStream(val ? Boolean.TRUE : Boolean.FALSE); // JDK 1.3 friendly
}
public void writeByte(int val) throws IOException {
- callback.writeToStream(new Byte((byte) val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Byte((byte) val));
}
public void writeInt(int val) throws IOException {
- callback.writeToStream(new Integer(val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Integer(val));
}
public void writeChar(int val) throws IOException {
- callback.writeToStream(new Character((char)val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Character((char)val));
}
public void writeDouble(double val) throws IOException {
- callback.writeToStream(new Double(val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Double(val));
}
public void writeFloat(float val) throws IOException {
- callback.writeToStream(new Float(val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Float(val));
}
public void writeLong(long val) throws IOException {
- callback.writeToStream(new Long(val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Long(val));
}
public void writeShort(int val) throws IOException {
- callback.writeToStream(new Short((short) val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Short((short) val));
}
public void write(byte[] buf) throws IOException {
- callback.writeToStream(buf);
+ ((StreamCallback) callbacks.peek()).writeToStream(buf);
}
public void writeChars(String str) throws IOException {
- callback.writeToStream(str.toCharArray());
+ ((StreamCallback) callbacks.peek()).writeToStream(str.toCharArray());
}
public void writeUTF(String str) throws IOException {
- callback.writeToStream(str);
+ ((StreamCallback) callbacks.peek()).writeToStream(str);
}
public void write(int val) throws IOException {
- callback.writeToStream(new Byte((byte) val));
+ ((StreamCallback) callbacks.peek()).writeToStream(new Byte((byte) val));
}
public void write(byte[] buf, int off, int len) throws IOException {
@@ -116,15 +121,15 @@
public void write(byte[] buf, int off, int len) throws IOException {
byte[] b = new byte[len];
System.arraycopy(buf, off, b, 0, len);
- callback.writeToStream(b);
+ ((StreamCallback) callbacks.peek()).writeToStream(b);
}
public void flush() throws IOException {
- callback.flush();
+ ((StreamCallback) callbacks.peek()).flush();
}
public void close() throws IOException {
- callback.close();
+ ((StreamCallback) callbacks.peek()).close();
}
public PutField putFields() {
@@ -135,7 +140,7 @@
public void writeFields() throws IOException {
CustomPutField customPutField = (CustomPutField) customFields.pop();
- callback.writeFieldsToStream(customPutField.asMap());
+ ((StreamCallback) callbacks.peek()).writeFieldsToStream(customPutField.asMap());
}
private class CustomPutField extends PutField {
@@ -147,7 +152,7 @@
}
public void write(ObjectOutput out) throws IOException {
- callback.writeToStream(asMap());
+ ((StreamCallback) callbacks.peek()).writeToStream(asMap());
}
public void put(String name, Object val) {
@@ -205,5 +210,9 @@
public void writeUnshared(Object obj) {
throw new UnsupportedOperationException();
}
+
+ public String toString() {
+ return "CustomObjectOutputstream[top callback=" + callbacks.peek() + ", customFields=" + customFields + "]";
+ }
}
Index: E:/data/workspace/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SerializableConverterTest.java
===================================================================
--- E:/data/workspace/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SerializableConverterTest.java (revision 0)
+++ E:/data/workspace/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SerializableConverterTest.java (revision 0)
@@ -0,0 +1,129 @@
+/*
+ * Created on Jun 6, 2006
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import com.thoughtworks.acceptance.AbstractAcceptanceTest;
+
+public class SerializableConverterTest extends AbstractAcceptanceTest {
+
+ public static class Child implements Serializable {
+
+ private int i = 3;
+
+ public Child(int i) {
+ this.i = i;
+ }
+
+ public int getI() {
+ return i;
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ }
+ }
+
+ public static class Parent implements Serializable {
+
+ private String name;
+
+ private transient Child child;
+
+ public Parent(String name, Child child) {
+ this.name = name;
+ this.child = child;
+ }
+
+ public Child getChild() {
+ return child;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ this.child = (Child) in.readObject();
+ in.defaultReadObject();
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.writeObject(this.child);
+ out.defaultWriteObject();
+ }
+ }
+
+ public void testObjectInputStream() throws Exception {
+ xstream.alias("parent", Parent.class);
+ xstream.alias("child", Child.class);
+
+ String sourceXml = "\n" + " \n"
+ + " \n" + " \n"
+ + " \n" + " \n" + " 1\n"
+ + " \n" + " \n" + " \n"
+ + " \n" + " ze-name\n" + " \n"
+ + " \n" + " \n" + "";
+
+ ObjectInputStream objectInputStream = xstream.createObjectInputStream(new StringReader(
+ sourceXml));
+
+ Parent parent = (Parent) objectInputStream.readObject();
+
+ assertEquals("ze-name", parent.getName());
+ assertEquals(1, parent.getChild().getI());
+ }
+
+ public void testObjectOutputStream() throws Exception {
+ xstream.alias("parent", Parent.class);
+ xstream.alias("child", Child.class);
+
+ String expectedXml = "\n" + " \n"
+ + " \n" + " \n"
+ + " \n" + " \n" + " 1\n"
+ + " \n" + " \n" + " \n"
+ + " \n" + " ze-name\n" + " \n"
+ + " \n" + " \n" + "";
+
+ Parent parent = new Parent("ze-name", new Child(1));
+ StringWriter stringWriter = new StringWriter();
+ ObjectOutputStream os = xstream.createObjectOutputStream(stringWriter);
+ os.writeObject(parent);
+ os.close();
+ String actualXml = stringWriter.getBuffer().toString();
+ assertEquals(expectedXml, actualXml);
+
+ xstream.createObjectInputStream(new StringReader(actualXml));
+
+ }
+
+ public void testToXML() {
+
+ xstream.alias("parent", Parent.class);
+ xstream.alias("child", Child.class);
+
+ String expected = "\n" + " \n"
+ + " \n" + " \n"
+ + " \n" + " 1\n" + " \n"
+ + " \n" + " \n" + " \n"
+ + " ze-name\n" + " \n" + " \n"
+ + "";
+
+ Parent parent = new Parent("ze-name", new Child(1));
+
+ assertBothWays(parent, expected);
+ }
+}