Index: /apps/workspaces/main/xstream/src/java/com/thoughtworks/xstream/XStream.java =================================================================== --- /apps/workspaces/main/xstream/src/java/com/thoughtworks/xstream/XStream.java (revision 719) +++ /apps/workspaces/main/xstream/src/java/com/thoughtworks/xstream/XStream.java (working copy) @@ -97,6 +97,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamDriver; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.StreamException; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import com.thoughtworks.xstream.io.xml.XppDriver; import com.thoughtworks.xstream.mapper.ArrayMapper; @@ -873,7 +874,11 @@ public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, String rootNodeName) throws IOException { writer.startNode(rootNodeName); return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() { + private boolean closed; public void writeToStream(Object object) { + if(closed) { + throw new StreamException(new IOException("Object output stream was already closed")); + } marshal(object, writer); } @@ -886,12 +891,18 @@ } public void flush() { - writer.flush(); + if(closed) { + throw new StreamException(new IOException("Object output stream was already closed")); + } + writer.flush(); } public void close() { - writer.endNode(); - writer.close(); + if(!this.closed) { + writer.endNode(); + writer.close(); + this.closed = true; + } } }); } Index: /apps/workspaces/main/xstream/src/test/com/thoughtworks/xstream/XStreamTest.java =================================================================== --- /apps/workspaces/main/xstream/src/test/com/thoughtworks/xstream/XStreamTest.java (revision 719) +++ /apps/workspaces/main/xstream/src/test/com/thoughtworks/xstream/XStreamTest.java (working copy) @@ -1,5 +1,14 @@ package com.thoughtworks.xstream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.StringReader; +import java.io.StringWriter; + +import junit.framework.TestCase; + +import org.dom4j.Element; + import com.thoughtworks.acceptance.StandardObject; import com.thoughtworks.acceptance.someobjects.FunnyConstructor; import com.thoughtworks.acceptance.someobjects.Handler; @@ -17,15 +26,10 @@ import com.thoughtworks.xstream.core.JVM; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.StreamException; import com.thoughtworks.xstream.io.xml.AbstractDocumentReader; import com.thoughtworks.xstream.io.xml.Dom4JDriver; -import junit.framework.TestCase; - -import org.dom4j.Element; - -import java.io.StringReader; - public class XStreamTest extends TestCase { private transient XStream xstream; @@ -310,4 +314,36 @@ assertEquals("z", z.field); } + public void testObjectOutputStreamCloseTwice() throws IOException { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + oout.close(); + } + + public void testObjectOutputStreamCloseAndFlush() throws IOException { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + try { + oout.flush(); + fail( "Closing and flushing should throw a StreamException" ); + } catch (StreamException e) { + // ok + } + } + + public void testObjectOutputStreamCloseAndWrite() throws IOException { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + try { + oout.writeObject( new Integer( 2 ) ); + fail( "Closing and writing should throw a StreamException" ); + } catch (StreamException e) { + // ok + } + } + + }