package org.sample.nio.connection.handler.parser; import java.nio.ByteBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import com.sun.grizzly.ProtocolParser; import com.sun.grizzly.util.ByteBufferFactory; import com.sun.grizzly.util.WorkerThread; public class QuoteQueryProtocolParser implements ProtocolParser { // the limit, if the limit is reach the connection will be closed protected static final int LIMITBB = 5; protected CharsetDecoder f_asciiDecoder = Charset.forName("ISO-8859-1").newDecoder(); protected ByteBuffer processingBuffer; protected String query = null; private boolean eoqFound = false; private boolean maxBufferReached = false; // first method to been called /** * Is this ProtocolParser expecting more data ? * * This method is typically called after a call to parseBytes() * to determine if the {@link ByteBuffer} which has been parsed * contains a partial message * * @return - true if more bytes are needed to construct a * message; false, if no * additional bytes remain to be parsed into a T. * Note that if no partial message exists, this method should * return false. */ public boolean isExpectingMoreData() { System.out.println("isExpectingMoreData"); // we need to loop until when get a query return !eoqFound; } // next method after isExpectingMoreData or releaseBuffer /** * Are there more bytes to be parsed in the {@link ByteBuffer} given * to this ProtocolParser's setBuffer ? * * This method is typically called after a call to parseBytes() * to determine if the {@link ByteBuffer} has more bytes which need to * parsed into a message. * * @return true if there are more bytes to be parsed. * Otherwise false. */ public boolean hasMoreBytesToParse() { System.out.println("hasMoreBytesToParse"); /* if (debug) System.out.println("hasMoreBytesToParse()"); if (savedBuffer == null) { if (debug) System.out.println("hasMoreBytesToParse() savedBuffer == null, return false"); return false; } */ return eoqFound && processingBuffer != null && processingBuffer.position() > 0; } // if isExpectingMoreData : 2th method /** * No more parsing will be done on the buffer passed to * startBuffer. * Set up the buffer so that its position is the first byte that was * not part of a full message, and its limit is the original limit of * the buffer. * * @return -- true if the parser has saved some state (e.g. information * data in the buffer that hasn't been returned in a full message); * otherwise false. If this method returns true, the framework will * make sure that the same parser is used to process the buffer after * more data has been read. */ public boolean releaseBuffer() { System.out.println("releaseBuffer"); if (processingBuffer != null) { processingBuffer.compact(); } processingBuffer = null; eoqFound = false; return false; } // method after hasMoreBytesToParse if it's true /** * Set the buffer to be parsed. This method should store the buffer and * its state so that subsequent calls to getNextMessage * will return distinct messages, and the buffer can be restored after * parsing when the releaseBuffer method is called. */ public void startBuffer(ByteBuffer bb) { System.out.println("startBuffer"); bb.flip(); processingBuffer = bb; //System.out.println("capacity=" + processingBuffer.capacity()); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Get the next complete message from the buffer, which can then be * processed by the next filter in the protocol chain. Because not all * filters will understand protocol messages, this method should also * set the position and limit of the buffer at the start and end * boundaries of the message. Filters in the protocol chain can * retrieve this message via context.getAttribute(MESSAGE) * * @return The next message in the buffer. If there isn't such a message, * return null. * */ public String getNextMessage() { System.out.println("getNextMessage"); if(maxBufferReached){ return "MAX"; } return query; } /** * Indicates whether the buffer has a complete message that can be * returned from getNextMessage. Smart implementations of * this will set up all the information so that an actual call to * getNextMessage doesn't need to re-parse the data. */ public boolean hasNextMessage() { System.out.println("hasNextMessage"); if (processingBuffer == null) { return false; } if (processingBuffer.hasRemaining()) { System.out.println("hasNextMessage: " + new String(processingBuffer.array(), processingBuffer.arrayOffset(), processingBuffer.remaining())); // decode the buffer String msg = null; try { ByteBuffer tmp = processingBuffer.duplicate(); //tmp.flip(); // not needed because processingBuffer was previously flip msg = f_asciiDecoder.decode(tmp).toString(); } catch (CharacterCodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } //System.out.println("msg=" + msg); int index = msg.indexOf("[eoq]"); if (index > -1) { query = msg.substring(0, index); //System.out.println("Query = " + query); // We need to kept what is after the EOQ processingBuffer.clear(); String substr = msg.substring(index + "[eoq]".length()); System.out.println("index: " + index + " substr: " + substr + " substr.len: " + substr.length()); processingBuffer.put(msg.substring(index + "[eoq]".length()).getBytes()); processingBuffer.flip(); eoqFound = true; } else { // Check if buffer is full if (processingBuffer.remaining() == processingBuffer.capacity()) { // If full - reallocate // but check if the max length is attein if(processingBuffer.capacity() + processingBuffer.remaining()