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("Object output stream was already closed"); + } marshal(object, writer); } @@ -886,12 +891,18 @@ } public void flush() { - writer.flush(); + if(closed) { + throw new StreamException("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/java/com/thoughtworks/xstream/io/StreamException.java =================================================================== --- /apps/workspaces/main/xstream/src/java/com/thoughtworks/xstream/io/StreamException.java (revision 719) +++ /apps/workspaces/main/xstream/src/java/com/thoughtworks/xstream/io/StreamException.java (working copy) @@ -6,4 +6,8 @@ public StreamException(Throwable e) { super(e); } + + public StreamException(String message) { + super(message); + } } 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,13 @@ package com.thoughtworks.xstream; +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; @@ -20,12 +28,6 @@ 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; @@ -309,5 +311,52 @@ assertEquals("z", z.field); } + + public void testMultipleClose() { + try { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + oout.close(); + } catch( Exception ex ) { + ex.printStackTrace(); + fail( ex.toString() ); + } + } + + public void testObjectOutputStreamCloseTwice() { + try { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + oout.close(); + } catch( Exception ex ) { + ex.printStackTrace(); + fail( ex.toString() ); + } + } + + public void testObjectOutputStreamCloseAndFlush() { + try { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + oout.flush(); + fail( "Closing and flushing should throw an IOException" ); + } catch( Exception ex ) { + } + } + + public void testObjectOutputStreamCloseAndWrite() { + try { + ObjectOutputStream oout = xstream.createObjectOutputStream( new StringWriter() ); + oout.writeObject( new Integer( 1 ) ); + oout.close(); + oout.writeObject( new Integer( 2 ) ); + fail( "Closing and writing should throw an IOException" ); + } catch( Exception ex ) { + } + } + }