package org.mortbay.cometd.ext;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import org.cometd.Bayeux;
import org.cometd.Client;
import org.cometd.Extension;
import org.cometd.Message;
import org.mortbay.cometd.MessageImpl;
import org.mortbay.util.ArrayIdQueue;
import org.mortbay.util.ArrayIdQueue.ArrayIdIterator;
public class AcknowledgedMessagesClientExtension implements Extension
{
private final ArrayIdQueue<Message> _unackedQueue=new ArrayIdQueue<Message>(8,16,this);
public Message rcv(Client from, Message message)
{
return message;
}
public Message rcvMeta(Client from, Message message)
{
if (message.getChannel().equals(Bayeux.META_CONNECT))
{
Map<String, Object> ext=(Map<String, Object>) message.get(Bayeux.EXT_FIELD);
if (ext != null)
{
Long acked=(Long) ext.get("ack");
if (acked != null)
{
ArrayIdIterator it=_unackedQueue.idIterator();
MessageImpl queuedMessage=null;
while (it.hasNext())
{
queuedMessage=(MessageImpl)it.next();
long messageBatchId=it.associatedId();
if (acked >= messageBatchId)
{
queuedMessage.decRef();
it.remove();
}
}
}
}
Queue<Message> messages=from.getQueue();
messages.addAll(_unackedQueue);
_unackedQueue.clear();
}
return message;
}
public Message send(Client from, Message message)
{
if(!_unackedQueue.contains(message))
{
_unackedQueue.add(message);
// prevent the message from being erased
((MessageImpl) message).incRef();
}
return message;
}
public Message sendMeta(Client from, Message message)
{
if ( message.getChannel().equals(Bayeux.META_CONNECT) && from.getQueue().size()>0 )
{
_unackedQueue.incrementCurrentId();
Map<String, Object> ext= message.getExt(true);
ext.put("ack",_unackedQueue.getCurrentId());
message.put(Bayeux.EXT_FIELD,ext);
}
return message;
}
}