Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
This file is part of Niowire. Niowire is free software: you can redistribute it and/or modify it under the terms of the Lesser GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Niowire is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public License for more details. You should have received a copy of the Lesser GNU General Public License along with Niowire. If not, see <http://www.gnu.org/licenses/>.
 
 package io.niowire.serializer;
 
 import java.util.List;
This class is the most basic serializer. It scans the input stream for a particular byte (or set of bytes) and removes them from the stream, and uses all the data up to that point as it's data. This class may be overridden and the serializeBlob() method can be used to take the delimited output to be further processed. Note that this class as it uses a static byte buffer for its operations, is not thread safe across instances. Only one instance of this class can be performing operations at any one time. In the context of Niowire as there is one main thread doing all of the IO this should not be a problem. But if it is going to be used elsewhere this must be considered.

Author(s):
Trent Houliston
 
 public abstract class DelimitedSerializer implements NioSerializer
 {

This is the static byte buffer shared between all instances of the serializer.
 
 	private static final Logger LOG = LoggerFactory.getLogger(DelimitedSerializer.class.getName());
 	private static final ByteBuffer tb = ByteBuffer.allocateDirect(32768);
 	//This buffer is allocated as needed if there is any leftover data (split packets)
 	private ByteBuffer residual = null;
 	private boolean open = true;
 	protected Context context = null;
 	private Queue<ByteBuffersendQueue = new LinkedList<ByteBuffer>();
 	private ByteBuffer rebuffer = null;

 
 	public List<NioPacketdeserialize(ByteBuffer bufferthrows IOException
 	{
 		//Check if the channel is closed
 		if (!)
 		{
 			throw new ClosedChannelException();
 		}
 
 		//Our start point is initially 0
 		int startPoint = 0;
 
 		//Create a new list to hold the packets we find
 		LinkedList<NioPacketpackets = new LinkedList<NioPacket>();
 
 		//The delimiter is removed from the stream and used to break up packets
 		byte[] delimiter = getDelimiter();
 
 		//This is how far seraching the delimiter we are
 		int depth = 0;
 
 		//Clear the buffer ready for putting data into
 		.clear();
 
 		//If we have residual from the last run then add it to the transient buffer
 		if ( != null && .hasRemaining())
 		{
 			//Our start point is initially
 			startPoint = .remaining();
 		}
 
 		//Add our data into the buffer as well and get it ready for reading
 		.put(buffer);
 		.flip();
		//We will start searching after our residual from last time (we didn't find it there)
		//We will go back far enough to ensure that we will catch partial delimiters
		.position(startPoint - delimiter.length < 0 ? 0 : startPoint - delimiter.length);
		//This is our last delimiter we found
		int lastDelimiter = 0;
		//While we have data
		while (.hasRemaining())
		{
			//Get a byte
			byte b = .get();
			//If this is the start of a delimiter
			if (delimiter[depth] == b)
			{
				//Start searching the next byte next time
				depth++;
				//If we have found the full delimiter
				if (depth == delimiter.length)
				{
					//Get another view of this buffer
					ByteBuffer data = .duplicate();
					//Set its start to where we left off
					data.position(lastDelimiter);
					//Set its limit to before the delimiter
					data.limit(.position() - delimiter.length);
					//Deserialize this section
					try
					{
						List<NioPacketpkts = deserializeBlob(data);
						packets.addAll(pkts);
					}
					{
						.warn("There was a packet of invalid data sent to the deserializer");
					}
					//Set our delimiter for next time we go through
					lastDelimiter = .position();
					depth = 0;
				}
			}
			//If this isn't what we are looking for, reset our search
			else
			{
				depth = 0;
			}
		}
		//If after our whole search, we still have some data left over
		if (.limit() > lastDelimiter)
		{
			//Set the buffers position to the position of the last delimiter
			.position(lastDelimiter);
			//Work out how much data we need
			int requiredSize = .remaining();
			//If we don't have enough
			if ( == null || .capacity() < requiredSize)
			{
				//Get enough to hold it
				 = ByteBuffer.allocate(requiredSize);
			}
			//Store it for next time
		}
		//If we didn't have any data left over, get rid of our residual buffer
		else
		{
			 = null;
		}
		//Return the packets that we got from this
		return packets;
	}

	public void serialize(NioPacket packetthrows IOException
	{
		//Check if the channel is closed
		if (!)
		{
		}
		try
		{
			//Serialize our packets into byte buffers
			ByteBuffer buff = serializeBlob(packet);
			//Add these buffers to the queue
		}
		{
			.warn("There was a packet of invalid data sent to the serializer");
		}
	}

	public void close() throws IOException
	{
		//Clear our variables
		 = null;
		 = null;
		 = false;
	}

	public int read(ByteBuffer bufferthrows IOException
	{
		//Check if the channel is closed
		if (!)
		{
		}
		//This is to store how many bytes we have read
		int read = 0;
		//If we have a rebuffer then add it first
		if ( != null)
		{
			read += .remaining();
			buffer.put();
			 = null;
		}
		//Read as many of our buffers into the passed buffer as we can
		while (!.isEmpty()
			   && buffer.remaining() >= .peek().remaining() + getDelimiter().length)
		{
			read += bb.remaining();
			read += getDelimiter().length;
			buffer.put(bb);
			buffer.put(getDelimiter());
		}
		//Read as much of our remaining buffer as we can
		{
			//Get our next buffer in the queue
			//Note that we don't remove the element here, even if it is empty
			//This is so a delimiter can be added next time (even if there is no data)
			//Create a view of our buffer
			ByteBuffer view = peek.duplicate();
			//Set it's limit to how much free space we have in the buffer
			view.limit(peek.position() + buffer.remaining());
			//Move the position of our byte buffer so that we skip over the bytes we are writing
			peek.position(peek.position() + buffer.remaining());
			//Put as much as we can into the buffer
			buffer.put(view);
		}
		return read;
	}

	public boolean isOpen()
	{
		return ;
	}

	public void setContext(Context context)
	{
		this. = context;
	}

	public boolean hasData() throws IOException
	{
		//Check if the channel is closed
		if (!)
		{
		}
		return !.isEmpty();
	}

	public void rebuffer(ByteBuffer datathrows IOException
	{
		//Check if the channel is closed
		if (!)
		{
		}
		//Get the byte buffer
		 = ByteBuffer.allocate(data.remaining());
	}

This method is used to deserialize a blob of data after we have found our delimiter. It passes a byte buffer with its position and limit set to the data of interest.

Parameters:
blob the java.nio.ByteBuffer with its position and limit set to our point of interest.
Returns:
a list of packets which were found in that delimited blob
Throws:
NioInvalidDataException if the given data was invalid
	protected abstract List<NioPacketdeserializeBlob(ByteBuffer blobthrows NioInvalidDataException;

This method is used to convert a NioPacket object into a serialized byte buffer form. It should accept a packet and convert it into a ByteBuffer containing the data to be sent to the client. When sent to the client a delimiter will be added after this ByteBuffers content.

Parameters:
packet the packet to be serialized
Returns:
a java.nio.ByteBuffer that contains the data to be sent
Throws:
NioInvalidDataException if the given data was invalid
	protected abstract ByteBuffer serializeBlob(NioPacket packetthrows NioInvalidDataException;

This method should return the multi byte delimiter to use when delimiting the incoming data. It should not change as it may miss packets in this case.

Returns:
a multi byte delimiter to search and use to split up the incoming data stream
	protected abstract byte[] getDelimiter();
New to GrepCode? Check out our FAQ X