diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java index be74f179..9e5b1d52 100755 --- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java +++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapter.java @@ -28,6 +28,8 @@ package com.twelvemonkeys.imageio.util; +import com.twelvemonkeys.lang.Validate; + import javax.imageio.stream.ImageInputStream; import java.io.IOException; import java.io.InputStream; @@ -75,16 +77,12 @@ class IIOInputStreamAdapter extends InputStream { } private IIOInputStreamAdapter(ImageInputStream pInput, long pLength, boolean pHasLength) { - if (pInput == null) { - throw new IllegalArgumentException("stream == null"); - } - if (pHasLength && pLength < 0) { - throw new IllegalArgumentException("length < 0"); - } + Validate.notNull(pInput, "stream"); + Validate.isTrue(!pHasLength || pLength >= 0, pLength, "length < 0: %f"); input = pInput; - hasLength = pHasLength; left = pLength; + hasLength = pHasLength; } @@ -105,6 +103,7 @@ class IIOInputStreamAdapter extends InputStream { if (hasLength) { return left > 0 ? (int) Math.min(Integer.MAX_VALUE, left) : 0; } + return 0; // We don't really know, so we say 0 to be safe. } diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java index 38a3031f..c83fd3d4 100755 --- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java +++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapter.java @@ -28,6 +28,8 @@ package com.twelvemonkeys.imageio.util; +import com.twelvemonkeys.lang.Validate; + import javax.imageio.stream.ImageOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -43,27 +45,40 @@ class IIOOutputStreamAdapter extends OutputStream { private ImageOutputStream output; public IIOOutputStreamAdapter(final ImageOutputStream pOutput) { + Validate.notNull(pOutput, "stream == null"); + output = pOutput; } @Override public void write(final byte[] pBytes) throws IOException { + assertOpen(); output.write(pBytes); } @Override public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException { + assertOpen(); output.write(pBytes, pOffset, pLength); } @Override public void write(final int pByte) throws IOException { + assertOpen(); output.write(pByte); } @Override public void flush() throws IOException { - output.flush(); + // NOTE: The contract of OutputStream.flush is very different from ImageOutputStream.flush. We can't delegate. + // TODO: Fulfill the contract of OutputStream.flush? This seems to be good enough for now. + assertOpen(); + } + + private void assertOpen() throws IOException { + if (output == null) { + throw new IOException("stream already closed"); + } } @Override diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapterTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapterTestCase.java index 753d5240..bb725a5f 100755 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapterTestCase.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOInputStreamAdapterTestCase.java @@ -51,6 +51,11 @@ public class IIOInputStreamAdapterTestCase extends InputStreamAbstractTestCase { return new IIOInputStreamAdapter(new MemoryCacheImageInputStream(new ByteArrayInputStream(pBytes)), pBytes.length); } + @Test(expected = IllegalArgumentException.class) + public void testCreateNull() { + new IIOInputStreamAdapter(null); + } + @Test public void testReadSubstreamOpenEnd() throws IOException { byte[] bytes = new byte[20]; diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapterTestCase.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapterTestCase.java new file mode 100644 index 00000000..0fdcf9a4 --- /dev/null +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/IIOOutputStreamAdapterTestCase.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.twelvemonkeys.imageio.util; + +import com.twelvemonkeys.io.OutputStreamAbstractTestCase; +import org.junit.Test; + +import javax.imageio.stream.MemoryCacheImageOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import static org.junit.Assert.*; + +/** + * IIOOutputStreamAdapterTestCase + * + * @author Harald Kuhr + * @author last modified by $Author: haraldk$ + * @version $Id: IIOOutputStreamAdapterTestCase.java,v 1.0 30.11.11 12:21 haraldk Exp$ + */ +public class IIOOutputStreamAdapterTestCase extends OutputStreamAbstractTestCase { + @Override + protected OutputStream makeObject() { + return new IIOOutputStreamAdapter(new MemoryCacheImageOutputStream(new ByteArrayOutputStream())); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateNull() { + new IIOOutputStreamAdapter(null); + } + + @Test + public void testFlushOnAdapterDoesNotMoveFlushedPositionInBacking() throws IOException { + MemoryCacheImageOutputStream backing = new MemoryCacheImageOutputStream(new ByteArrayOutputStream()); + IIOOutputStreamAdapter adapter = new IIOOutputStreamAdapter(backing); + + // Sanity check + assertEquals(0, backing.getFlushedPosition()); + + // Write & flush + adapter.write(0xCA); + adapter.write(new byte[8]); + adapter.write(0xFE); + adapter.flush(); + + // Assertions + assertEquals(10, backing.length()); + assertEquals(10, backing.getStreamPosition()); + assertEquals(0, backing.getFlushedPosition()); + + // Just make sure we can safely seek back to start and read data back + backing.seek(0); + assertEquals(0, backing.getStreamPosition()); + + // If this can be read, I think the contract of flush is also fulfilled (kind of) + assertEquals(0xCA, backing.read()); + assertEquals(8, backing.skipBytes(8)); + assertEquals(0xFE, backing.read()); + } +}