package net.sf.cotta.memory; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.*; class InMemoryInputFileChannel extends FileChannel { private long position = 0; private ByteArrayBuffer content; public InMemoryInputFileChannel(ByteArrayBuffer content) { this.content = content; } public int read(ByteBuffer dst) throws IOException { int copied = read(dst, position); position = position + copied; return copied; } public int read(ByteBuffer dst, long position) throws IOException { int available = dst.limit() - dst.position(); if (available == 0) { return 0; } if (position >= size()) { return -1; } long end = Math.min(content.size(), position + available); int copied = (int) (end - position); content.copyTo(dst, (int) position, copied); return copied; } public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { int readCount = 0; for (int i = offset; i < offset + length; i++) { if (position == content.size()) { break; } readCount += read(dsts[i]); } return readCount; } private NonWritableChannelException nonWritableChannelException() { //noinspection ThrowableInstanceNeverThrown return new NonWritableChannelException(); } public int write(ByteBuffer src) throws IOException { throw nonWritableChannelException(); } public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { throw nonWritableChannelException(); } public long position() throws IOException { return position; } public FileChannel position(long newPosition) throws IOException { this.position = newPosition; return this; } public long size() throws IOException { return content.size(); } public FileChannel truncate(long size) throws IOException { throw nonWritableChannelException(); } public void force(boolean metaData) throws IOException { // no op since I have no idea what to do } public long transferTo(long position, long count, WritableByteChannel target) throws IOException { return content.copyTo(target, position, count); } public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException { throw nonWritableChannelException(); } public int write(ByteBuffer src, long position) throws IOException { throw nonWritableChannelException(); } public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException { if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE) { throw new NonWritableChannelException(); } throw new UnsupportedOperationException("map is not supported for in-memory input file channel because MappedByteBuffer can not be instantiated directly from outside the package"); } public FileLock lock(long position, long size, boolean shared) throws IOException { throw new UnsupportedOperationException("lock is not supported for in-memory input file channel because tryLock is not supported"); } public FileLock tryLock(long position, long size, boolean shared) throws IOException { throw new UnsupportedOperationException("tryLock is not supported for in-memory input file channel because FileLock can not be instantiated from outside the package"); } protected void implCloseChannel() throws IOException { } }