package protocol; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.IntBuffer; import org.apache.log4j.Logger; import com.sun.grizzly.ProtocolParser; public class MyProtocolParser implements ProtocolParser { private static final Logger LOG = Logger.getLogger(MyProtocolParser.class); private boolean isExpectingMoreData = false; private ByteBuffer byteBuffer; private int byteBufferLimit; private int position; private String message; public boolean hasMoreBytesToParse() { boolean hasMoreBytesToParse = position < byteBufferLimit; /* if(LOG.isTraceEnabled()) { LOG.trace("hasMoreBytesToParse: " + hasMoreBytesToParse); } */ return hasMoreBytesToParse; } public boolean isExpectingMoreData() { /* if(LOG.isTraceEnabled()) { LOG.trace("isExpectingMoreData: " + isExpectingMoreData); } */ return isExpectingMoreData; } public String getNextMessage() { if(LOG.isTraceEnabled()) { LOG.trace("Message [" + message + "] parsed from bytes received"); } return message; } /* * byte tokens */ private static final char CRs = 0x0d; private static final char LFs = 0x0a; private static final char EOSs = 0x00; private static final byte CR = 0x0d; private static final byte LF = 0x0a; private static final ProtocolToken PASS = new ProtocolToken("" + CRs + LFs + "PASS" + CRs + LFs + EOSs); public boolean hasNextMessage() { /* * We should never mess around with the original's byteBuffer when doing * parsing. This way we avoid setting its position and limit to wrong * values */ ByteBuffer roDuplicateBuffer = byteBuffer.asReadOnlyBuffer(); if (byteBuffer.position() == 0){ isExpectingMoreData = true; return false; } roDuplicateBuffer.flip(); byteBufferLimit = roDuplicateBuffer.limit(); byte[] bufferContent = new byte[roDuplicateBuffer.remaining()]; roDuplicateBuffer.get(bufferContent); String bufferContentString = new String(bufferContent); if(LOG.isTraceEnabled()) { LOG.trace("Parsing : " + bufferContentString); } /* * Validates that the buffer contains at least 2 bytes so we can proceed to input validation */ if(bufferContent.length < 2) { isExpectingMoreData = true; return !isExpectingMoreData; // 1.1) if(CR == bufferContent[0]) { if(LF == bufferContent[1]) { // 1.1.1) if(bufferContentString.contains(PASS.toString())) { if(LOG.isTraceEnabled()) { LOG.trace("Found: PASS"); } isExpectingMoreData = false; message = PASS.toString(); position = PASS.toBytes().length; } else { if(LOG.isTraceEnabled()) { LOG.trace("Did not found any reconizable token"); } isExpectingMoreData = true; position = bufferContentString.getBytes().length; } } } // 1.1.2) else if(bufferContent.length > 8) { IntBuffer bufferAsInt = byteBuffer.asIntBuffer(); int msgLength = bufferAsInt.get(0); // 1.1.2.1) if(bufferContent.length < msgLength) { isExpectingMoreData = true; } else // 1.1.2.2) { message = new String(bufferContent, 0, msgLength); position = msgLength; isExpectingMoreData = false; } } else { isExpectingMoreData = true; } return !isExpectingMoreData; } public void startBuffer(ByteBuffer bb) { if(LOG.isTraceEnabled()) { LOG.trace("startBuffer"); } byteBuffer = bb; position = byteBuffer.position(); } public boolean releaseBuffer() { if(LOG.isTraceEnabled()) { LOG.trace("Releasing buffer"); } if(!hasMoreBytesToParse()) { if(LOG.isTraceEnabled()) { LOG.trace("clearing buffer"); } this.byteBuffer.clear(); this.position = 0; this.byteBufferLimit = 0; } else { byteBuffer.position(position); } return hasMoreBytesToParse(); } }