SubChannel.java
package doss.local;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.SeekableByteChannel;
/**
* SubChannel is read only so write and truncate methods are not implemented
*
*/
class SubChannel implements SeekableByteChannel {
final SeekableByteChannel containerChannel;
final long offset;
final long length;
SubChannel(SeekableByteChannel containerChannel, long blobOffset,
long blobLength) throws IOException {
if (blobOffset > containerChannel.size()
|| blobLength > containerChannel.size() - blobOffset) {
throw new IllegalArgumentException(
"Can not create SubChannel for the container channel size "
+ containerChannel.size() + " with offset = "
+ blobOffset + " and length = " + blobLength);
}
this.containerChannel = containerChannel;
containerChannel.position(blobOffset);
this.offset = blobOffset;
this.length = blobLength;
}
@Override
public boolean isOpen() {
return containerChannel.isOpen();
}
@Override
public void close() throws IOException {
containerChannel.close();
}
@Override
public int read(ByteBuffer b) throws IOException {
int originalLimit = b.limit();
long capacity = offset + length;
try {
if (b.remaining() > capacity - containerChannel.position()) {
// buffer has more space available than we've got left in the
// blob so temporarily change its limit so we don't read past
// the end of the blob
b.limit((int) (b.position() + capacity - containerChannel
.position()));
}
return containerChannel.read(b);
} finally {
// restore the original limit
b.limit(originalLimit);
}
}
@Override
public int write(ByteBuffer src) throws IOException {
throw new NonWritableChannelException();
}
@Override
public long position() throws IOException {
return containerChannel.position() - offset;
}
@Override
// input parameter new position is constrained by the size and offset,
public SeekableByteChannel position(long newPosition) throws IOException {
if ((newPosition < 0) || (newPosition > length)) {
throw new IllegalArgumentException();
}
return containerChannel.position(offset + newPosition);
}
@Override
public long size() throws IOException {
return length;
}
@Override
public SeekableByteChannel truncate(long size) throws IOException {
throw new NonWritableChannelException();
}
}