mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
#705 No longer closes streams we didn't open
(cherry picked from commit ab08ec1e0d699963fde7dc14e9a3cf32b9d10ea1)
This commit is contained in:
parent
73a58266be
commit
a98224e652
@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.stream;
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStreamImpl;
|
import javax.imageio.stream.ImageInputStreamImpl;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -52,6 +53,10 @@ import static java.lang.Math.max;
|
|||||||
* for shorter reads, like single byte or bit reads.
|
* for shorter reads, like single byte or bit reads.
|
||||||
*/
|
*/
|
||||||
final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
||||||
|
private static final Closeable CLOSEABLE_STUB = new Closeable() {
|
||||||
|
@Override public void close() {}
|
||||||
|
};
|
||||||
|
|
||||||
static final int DEFAULT_BUFFER_SIZE = 8192;
|
static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
private ByteBuffer byteBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
|
private ByteBuffer byteBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
|
||||||
@ -63,6 +68,7 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
|||||||
private final byte[] integralCacheArray = integralCache.array();
|
private final byte[] integralCacheArray = integralCache.array();
|
||||||
|
|
||||||
private SeekableByteChannel channel;
|
private SeekableByteChannel channel;
|
||||||
|
private Closeable closeable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code File}.
|
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code File}.
|
||||||
@ -86,49 +92,62 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
|||||||
* @throws SecurityException if a security manager is installed, and it denies read access to the file.
|
* @throws SecurityException if a security manager is installed, and it denies read access to the file.
|
||||||
*/
|
*/
|
||||||
public BufferedChannelImageInputStream(final Path file) throws IOException {
|
public BufferedChannelImageInputStream(final Path file) throws IOException {
|
||||||
this(FileChannel.open(notNull(file, "file"), StandardOpenOption.READ));
|
this(FileChannel.open(notNull(file, "file"), StandardOpenOption.READ), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code RandomAccessFile}.
|
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code RandomAccessFile}.
|
||||||
* <p>
|
|
||||||
* Closing this stream will close the {@code RandomAccessFile}.
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param file a {@code RandomAccessFile} to read from.
|
* @param file a {@code RandomAccessFile} to read from.
|
||||||
* @throws IllegalArgumentException if {@code file} is {@code null}.
|
* @throws IllegalArgumentException if {@code file} is {@code null}.
|
||||||
*/
|
*/
|
||||||
public BufferedChannelImageInputStream(final RandomAccessFile file) {
|
public BufferedChannelImageInputStream(final RandomAccessFile file) {
|
||||||
// Assumption: Closing the FileChannel will also close its backing RandomAccessFile
|
// Closing the RAF is inconsistent, but emulates the behavior of javax.imageio.stream.FileImageInputStream
|
||||||
// (it does in the OpenJDK implementation, and it makes sense, although I can't see this is documented behaviour).
|
this(notNull(file, "file").getChannel(), true);
|
||||||
this(notNull(file, "file").getChannel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code FileInputStream}.
|
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code FileInputStream}.
|
||||||
* <p>
|
* <p>
|
||||||
* Closing this stream will close the {@code FileInputStream}.
|
* Closing this stream will <em>not</em> close the {@code FileInputStream}.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param inputStream a {@code FileInputStream} to read from.
|
* @param inputStream a {@code FileInputStream} to read from.
|
||||||
* @throws IllegalArgumentException if {@code inputStream} is {@code null}.
|
* @throws IllegalArgumentException if {@code inputStream} is {@code null}.
|
||||||
*/
|
*/
|
||||||
public BufferedChannelImageInputStream(final FileInputStream inputStream) {
|
public BufferedChannelImageInputStream(final FileInputStream inputStream) {
|
||||||
// Assumption: Closing the FileChannel will also close its backing FileInputStream (it does in the OpenJDK implementation, although I can't see this is documented).
|
this(notNull(inputStream, "inputStream").getChannel(), false);
|
||||||
this(notNull(inputStream, "inputStream").getChannel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code SeekableByteChannel}.
|
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code SeekableByteChannel}.
|
||||||
* <p>
|
* <p>
|
||||||
* Closing this stream will close the {@code SeekableByteChannel}.
|
* Closing this stream will <em>not</em> close the {@code SeekableByteChannel}.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param channel a {@code SeekableByteChannel} to read from.
|
* @param channel a {@code SeekableByteChannel} to read from.
|
||||||
* @throws IllegalArgumentException if {@code channel} is {@code null}.
|
* @throws IllegalArgumentException if {@code channel} is {@code null}.
|
||||||
*/
|
*/
|
||||||
public BufferedChannelImageInputStream(final SeekableByteChannel channel) {
|
public BufferedChannelImageInputStream(final SeekableByteChannel channel) {
|
||||||
|
this(notNull(channel, "channel"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code Cache}.
|
||||||
|
* <p>
|
||||||
|
* Closing this stream will close the {@code Cache}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param cache a {@code SeekableByteChannel} to read from.
|
||||||
|
* @throws IllegalArgumentException if {@code channel} is {@code null}.
|
||||||
|
*/
|
||||||
|
BufferedChannelImageInputStream(final Cache cache) {
|
||||||
|
this(notNull(cache, "cache"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedChannelImageInputStream(final SeekableByteChannel channel, boolean closeChannelOnClose) {
|
||||||
this.channel = notNull(channel, "channel");
|
this.channel = notNull(channel, "channel");
|
||||||
|
this.closeable = closeChannelOnClose ? this.channel : CLOSEABLE_STUB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
@ -246,8 +265,14 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
|||||||
buffer = null;
|
buffer = null;
|
||||||
byteBuffer = null;
|
byteBuffer = null;
|
||||||
|
|
||||||
channel.close();
|
|
||||||
channel = null;
|
channel = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
closeable = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to override the readShort(), readInt() and readLong() methods,
|
// Need to override the readShort(), readInt() and readLong() methods,
|
||||||
@ -315,9 +340,9 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
|
|||||||
public void flushBefore(final long pos) throws IOException {
|
public void flushBefore(final long pos) throws IOException {
|
||||||
super.flushBefore(pos);
|
super.flushBefore(pos);
|
||||||
|
|
||||||
if (channel instanceof MemoryCache) {
|
if (channel instanceof Cache) {
|
||||||
// In case of memory cache, free up memory
|
// In case of memory cache, free up memory
|
||||||
((MemoryCache) channel).flushBefore(pos);
|
((Cache) channel).flushBefore(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public final class BufferedInputStreamImageInputStreamSpi extends ImageInputStre
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, create a cache for backwards seeking
|
// Otherwise, create a cache for backwards seeking
|
||||||
return new BufferedChannelImageInputStream(useCacheFile ? new DiskCache(channel, cacheDir): new MemoryCache(channel));
|
return new BufferedChannelImageInputStream(useCacheFile ? new FileCache(channel, cacheDir) : new MemoryCache(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("Expected input of type InputStream: " + input);
|
throw new IllegalArgumentException("Expected input of type InputStream: " + input);
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
|
||||||
|
interface Cache extends SeekableByteChannel {
|
||||||
|
void flushBefore(long pos);
|
||||||
|
}
|
@ -26,19 +26,19 @@ import static java.nio.file.StandardOpenOption.WRITE;
|
|||||||
// the usual {@link #read read} and {@link #write write} methods. From the
|
// the usual {@link #read read} and {@link #write write} methods. From the
|
||||||
// standpoint of performance it is generally only worth mapping relatively
|
// standpoint of performance it is generally only worth mapping relatively
|
||||||
// large files into memory.
|
// large files into memory.
|
||||||
final class DiskCache implements SeekableByteChannel {
|
final class FileCache implements Cache {
|
||||||
final static int BLOCK_SIZE = 1 << 13;
|
final static int BLOCK_SIZE = 1 << 13;
|
||||||
|
|
||||||
private final FileChannel cache;
|
private final FileChannel cache;
|
||||||
private final ReadableByteChannel channel;
|
private final ReadableByteChannel channel;
|
||||||
|
|
||||||
// TODO: Perhaps skip this constructor?
|
// TODO: Perhaps skip this constructor?
|
||||||
DiskCache(InputStream stream, File cacheDir) throws IOException {
|
FileCache(InputStream stream, File cacheDir) throws IOException {
|
||||||
// Stream will be closed with channel, documented behavior
|
// Stream will be closed with channel, documented behavior
|
||||||
this(Channels.newChannel(notNull(stream, "stream")), cacheDir);
|
this(Channels.newChannel(notNull(stream, "stream")), cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiskCache(ReadableByteChannel channel, File cacheDir) throws IOException {
|
public FileCache(ReadableByteChannel channel, File cacheDir) throws IOException {
|
||||||
this.channel = notNull(channel, "channel");
|
this.channel = notNull(channel, "channel");
|
||||||
isTrue(cacheDir == null || cacheDir.isDirectory(), cacheDir, "%s is not a directory");
|
isTrue(cacheDir == null || cacheDir.isDirectory(), cacheDir, "%s is not a directory");
|
||||||
|
|
||||||
@ -65,13 +65,8 @@ final class DiskCache implements SeekableByteChannel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
|
||||||
cache.close();
|
cache.close();
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ByteBuffer dest) throws IOException {
|
public int read(ByteBuffer dest) throws IOException {
|
||||||
@ -110,5 +105,8 @@ final class DiskCache implements SeekableByteChannel {
|
|||||||
public SeekableByteChannel truncate(long size) {
|
public SeekableByteChannel truncate(long size) {
|
||||||
throw new NonWritableChannelException();
|
throw new NonWritableChannelException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void flushBefore(long pos) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ import java.util.List;
|
|||||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||||
import static java.lang.Math.min;
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
public final class MemoryCache implements SeekableByteChannel {
|
final class MemoryCache implements Cache {
|
||||||
|
|
||||||
final static int BLOCK_SIZE = 1 << 13;
|
final static int BLOCK_SIZE = 1 << 13;
|
||||||
|
|
||||||
@ -78,13 +78,8 @@ public final class MemoryCache implements SeekableByteChannel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
|
||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ByteBuffer dest) throws IOException {
|
public int read(ByteBuffer dest) throws IOException {
|
||||||
@ -135,7 +130,8 @@ public final class MemoryCache implements SeekableByteChannel {
|
|||||||
throw new NonWritableChannelException();
|
throw new NonWritableChannelException();
|
||||||
}
|
}
|
||||||
|
|
||||||
void flushBefore(long pos) {
|
@Override
|
||||||
|
public void flushBefore(long pos) {
|
||||||
if (pos < start) {
|
if (pos < start) {
|
||||||
throw new IndexOutOfBoundsException("pos < flushed position");
|
throw new IndexOutOfBoundsException("pos < flushed position");
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public final class URLImageInputStreamSpi extends ImageInputStreamSpi {
|
|||||||
|
|
||||||
// Otherwise revert to cached
|
// Otherwise revert to cached
|
||||||
InputStream urlStream = url.openStream();
|
InputStream urlStream = url.openStream();
|
||||||
return new BufferedChannelImageInputStream(useCacheFile ? new DiskCache(urlStream, cacheDir) : new MemoryCache(urlStream));
|
return new BufferedChannelImageInputStream(useCacheFile ? new FileCache(urlStream, cacheDir) : new MemoryCache(urlStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("Expected input of type URL: " + input);
|
throw new IllegalArgumentException("Expected input of type URL: " + input);
|
||||||
|
@ -57,7 +57,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
* @version $Id: BufferedFileImageInputStreamTestCase.java,v 1.0 Apr 21, 2009 10:58:48 AM haraldk Exp$
|
* @version $Id: BufferedFileImageInputStreamTestCase.java,v 1.0 Apr 21, 2009 10:58:48 AM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
// TODO: Remove this test, and instead test the disk cache directly!
|
// TODO: Remove this test, and instead test the disk cache directly!
|
||||||
public class BufferedChannelImageInputStreamDiskCacheTest {
|
public class BufferedChannelImageInputStreamFileCacheTest {
|
||||||
private final Random random = new Random(170984354357234566L);
|
private final Random random = new Random(170984354357234566L);
|
||||||
|
|
||||||
private InputStream randomDataToInputStream(byte[] data) {
|
private InputStream randomDataToInputStream(byte[] data) {
|
||||||
@ -68,7 +68,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreate() throws IOException {
|
public void testCreate() throws IOException {
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(new ByteArrayInputStream(new byte[0]), null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(new ByteArrayInputStream(new byte[0]), null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateNullStream() throws IOException {
|
public void testCreateNullStream() throws IOException {
|
||||||
try {
|
try {
|
||||||
new DiskCache((InputStream) null, null);
|
new FileCache((InputStream) null, null);
|
||||||
fail("Expected IllegalArgumentException");
|
fail("Expected IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@ -90,7 +90,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateNullChannel() throws IOException {
|
public void testCreateNullChannel() throws IOException {
|
||||||
try {
|
try {
|
||||||
new DiskCache((ReadableByteChannel) null, null);
|
new FileCache((ReadableByteChannel) null, null);
|
||||||
fail("Expected IllegalArgumentException");
|
fail("Expected IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@ -106,7 +106,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] data = new byte[1024 * 1024];
|
byte[] data = new byte[1024 * 1024];
|
||||||
InputStream input = randomDataToInputStream(data);
|
InputStream input = randomDataToInputStream(data);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
|
|
||||||
for (byte value : data) {
|
for (byte value : data) {
|
||||||
@ -122,7 +122,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] data = new byte[1024 * 1024];
|
byte[] data = new byte[1024 * 1024];
|
||||||
InputStream input = randomDataToInputStream(data);
|
InputStream input = randomDataToInputStream(data);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
|
|
||||||
byte[] result = new byte[1024];
|
byte[] result = new byte[1024];
|
||||||
@ -141,7 +141,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] data = new byte[1024 * 14];
|
byte[] data = new byte[1024 * 14];
|
||||||
InputStream input = randomDataToInputStream(data);
|
InputStream input = randomDataToInputStream(data);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
|
|
||||||
byte[] result = new byte[7];
|
byte[] result = new byte[7];
|
||||||
@ -159,7 +159,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] data = new byte[1024 * 18];
|
byte[] data = new byte[1024 * 18];
|
||||||
InputStream input = randomDataToInputStream(data);
|
InputStream input = randomDataToInputStream(data);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
|
|
||||||
byte[] result = new byte[9];
|
byte[] result = new byte[9];
|
||||||
@ -180,7 +180,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] data = new byte[256];
|
byte[] data = new byte[256];
|
||||||
InputStream input = randomDataToInputStream(data);
|
InputStream input = randomDataToInputStream(data);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
assertEquals("Stream length should be unknown", -1, stream.length());
|
assertEquals("Stream length should be unknown", -1, stream.length());
|
||||||
|
|
||||||
byte[] buffer = new byte[data.length * 2];
|
byte[] buffer = new byte[data.length * 2];
|
||||||
@ -198,7 +198,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
long value = ByteBuffer.wrap(bytes).getLong();
|
long value = ByteBuffer.wrap(bytes).getLong();
|
||||||
|
|
||||||
// Create stream
|
// Create stream
|
||||||
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
for (int i = 1; i <= 64; i++) {
|
for (int i = 1; i <= 64; i++) {
|
||||||
assertEquals(String.format("bit %d differ", i), (value << (i - 1L)) >>> 63L, stream.readBit());
|
assertEquals(String.format("bit %d differ", i), (value << (i - 1L)) >>> 63L, stream.readBit());
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
long value = ByteBuffer.wrap(bytes).getLong();
|
long value = ByteBuffer.wrap(bytes).getLong();
|
||||||
|
|
||||||
// Create stream
|
// Create stream
|
||||||
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
for (int i = 1; i <= 64; i++) {
|
for (int i = 1; i <= 64; i++) {
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
assertEquals(String.format("bit %d differ", i), value >>> (64L - i), stream.readBits(i));
|
assertEquals(String.format("bit %d differ", i), value >>> (64L - i), stream.readBits(i));
|
||||||
@ -228,7 +228,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
long value = ByteBuffer.wrap(bytes).getLong();
|
long value = ByteBuffer.wrap(bytes).getLong();
|
||||||
|
|
||||||
// Create stream
|
// Create stream
|
||||||
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
for (int i = 1; i <= 60; i++) {
|
for (int i = 1; i <= 60; i++) {
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
stream.setBitOffset(i % 8);
|
stream.setBitOffset(i % 8);
|
||||||
@ -244,7 +244,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
InputStream input = randomDataToInputStream(bytes);
|
InputStream input = randomDataToInputStream(bytes);
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
for (int i = 0; i < bytes.length / 2; i++) {
|
for (int i = 0; i < bytes.length / 2; i++) {
|
||||||
@ -282,7 +282,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
InputStream input = randomDataToInputStream(bytes);
|
InputStream input = randomDataToInputStream(bytes);
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
for (int i = 0; i < bytes.length / 4; i++) {
|
for (int i = 0; i < bytes.length / 4; i++) {
|
||||||
@ -320,7 +320,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
InputStream input = randomDataToInputStream(bytes);
|
InputStream input = randomDataToInputStream(bytes);
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
for (int i = 0; i < bytes.length / 8; i++) {
|
for (int i = 0; i < bytes.length / 8; i++) {
|
||||||
@ -357,7 +357,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] bytes = new byte[9];
|
byte[] bytes = new byte[9];
|
||||||
InputStream input = randomDataToInputStream(bytes);
|
InputStream input = randomDataToInputStream(bytes);
|
||||||
|
|
||||||
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
stream.seek(1000);
|
stream.seek(1000);
|
||||||
|
|
||||||
assertEquals(-1, stream.read());
|
assertEquals(-1, stream.read());
|
||||||
@ -406,11 +406,11 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testClose() throws IOException {
|
public void testClose() throws IOException {
|
||||||
// Create wrapper stream
|
// Create wrapper stream
|
||||||
InputStream mock = mock(InputStream.class);
|
Cache cache = mock(Cache.class);
|
||||||
ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(mock, null));
|
ImageInputStream stream = new BufferedChannelImageInputStream(cache);
|
||||||
|
|
||||||
stream.close();
|
stream.close();
|
||||||
verify(mock, only()).close();
|
verify(cache, only()).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -422,7 +422,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
|
|||||||
byte[] bytes = new byte[size];
|
byte[] bytes = new byte[size];
|
||||||
InputStream input = randomDataToInputStream(bytes);
|
InputStream input = randomDataToInputStream(bytes);
|
||||||
|
|
||||||
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
|
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
|
||||||
byte[] result = new byte[size];
|
byte[] result = new byte[size];
|
||||||
int head = stream.read(result, 0, 12); // Provoke a buffered read
|
int head = stream.read(result, 0, 12); // Provoke a buffered read
|
||||||
int len = stream.read(result, 12, size - 12); // Rest of buffer + direct read
|
int len = stream.read(result, 12, size - 12); // Rest of buffer + direct read
|
@ -406,11 +406,11 @@ public class BufferedChannelImageInputStreamMemoryCacheTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testClose() throws IOException {
|
public void testClose() throws IOException {
|
||||||
// Create wrapper stream
|
// Create wrapper stream
|
||||||
InputStream mock = mock(InputStream.class);
|
Cache cache = mock(Cache.class);
|
||||||
ImageInputStream stream = new BufferedChannelImageInputStream(new MemoryCache(mock));
|
ImageInputStream stream = new BufferedChannelImageInputStream(cache);
|
||||||
|
|
||||||
stream.close();
|
stream.close();
|
||||||
verify(mock, only()).close();
|
verify(cache, only()).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -47,7 +47,7 @@ import java.util.Random;
|
|||||||
import static com.twelvemonkeys.imageio.stream.BufferedImageInputStreamTest.rangeEquals;
|
import static com.twelvemonkeys.imageio.stream.BufferedImageInputStreamTest.rangeEquals;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.only;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -403,14 +403,11 @@ public class BufferedChannelImageInputStreamTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCloseChannel() throws IOException {
|
public void testCloseChannel() throws IOException {
|
||||||
// NOTE: As the stream-based constructor is chained to the channel-based one,
|
SeekableByteChannel channel = mock(SeekableByteChannel.class);
|
||||||
// we'll rely on the fact that closing the channel will close the stream.
|
ImageInputStream stream = new BufferedChannelImageInputStream(channel);
|
||||||
|
|
||||||
SeekableByteChannel mock = mock(SeekableByteChannel.class);
|
|
||||||
ImageInputStream stream = new BufferedChannelImageInputStream(mock);
|
|
||||||
|
|
||||||
stream.close();
|
stream.close();
|
||||||
verify(mock, only()).close();
|
verify(channel, never()).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user