package org.limewire.nio.statemachine;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
/**
* An abstract class reading state that reads all its data first, then validates
* the data at the end. <code>SimpleReadState</code> also clears all data it
* reads from the <code>ByteBuffer buffer</code> after the buffer is filled and
* validated.
*/
//TODO rename to AbstractValidatingReadState
public abstract class SimpleReadState extends ReadState {
/** The amount of data we expected to read. */
private final int expect;
/** The total amount of data we've read. */
private int amountRead = 0;
/** The ByteBuffer we'll be using. */
private ByteBuffer buffer;
public SimpleReadState(int expect) {
this.expect = expect;
}
@Override
protected boolean processRead(ReadableByteChannel channel, ByteBuffer scratchBuffer) throws IOException {
if(buffer == null) {
buffer = scratchBuffer.slice();
buffer.limit(expect);
}
int read = 0;
while(buffer.hasRemaining() && (read = channel.read(buffer)) > 0)
amountRead += read;
if(buffer.hasRemaining() && read == -1)
throw new IOException("EOF");
// if finished filling the buffer...
if(!buffer.hasRemaining()) {
validateBuffer(buffer);
buffer.clear();
return false;
}
// still need to read more
return true;
}
public long getAmountProcessed() {
return amountRead;
}
/**
* Validates the buffer, after it is filled. Throws an
* <code>IOException</code> if there are validation errors. For example,
* you can check <code>buffer.get(0)</code> is the proper version, or even
* <code>buffer.get(1)</code> contains the proper status.
*/
public abstract void validateBuffer(ByteBuffer buffer) throws IOException;
}