1 package org.mortbay.cometd.ext;
2
3 import java.util.HashMap;
4 import java.util.Iterator;
5 import java.util.Map;
6 import java.util.Queue;
7
8 import javax.servlet.UnavailableException;
9
10 import org.cometd.Bayeux;
11 import org.cometd.Client;
12 import org.cometd.Extension;
13 import org.cometd.Message;
14 import org.mortbay.cometd.MessageImpl;
15 import org.mortbay.util.ArrayQueue;
16
17
18
19
20
21
22
23 public class AcknowledgedMessagesClientExtension implements Extension
24 {
25 private final Client _client;
26 private final ArrayIdQueue<Message> _unackedQueue;
27
28 public AcknowledgedMessagesClientExtension(Client client)
29 {
30 _client=client;
31 _unackedQueue=new ArrayIdQueue<Message>(8,16,client);
32 _unackedQueue.setCurrentId(1);
33 }
34
35 public Message rcv(Client from, Message message)
36 {
37 return message;
38 }
39
40
41
42
43
44
45
46 public Message rcvMeta(Client from, Message message)
47 {
48 if (message.getChannel().equals(Bayeux.META_CONNECT))
49 {
50 synchronized (_client)
51 {
52 Map<String, Object> ext=message.getExt(false);
53 if (ext != null)
54 {
55 Long acked=(Long) ext.get("ack");
56 if (acked != null)
57 {
58
59 final int s=_unackedQueue.size();
60 if (s>0)
61 {
62 if (_unackedQueue.getAssociatedIdUnsafe(s-1)<=acked)
63 {
64
65 for (int i=0;i<s;i++)
66 {
67 final Message q = _unackedQueue.getUnsafe(i);
68 if (q instanceof MessageImpl)
69 ((MessageImpl)q).decRef();
70 }
71 _unackedQueue.clear();
72 }
73 else
74 {
75
76 for (int i=0;i<s;i++)
77 {
78 if (_unackedQueue.getAssociatedIdUnsafe(0)<=acked)
79 {
80 final Message q = _unackedQueue.remove();
81 if (q instanceof MessageImpl)
82 ((MessageImpl)q).decRef();
83 continue;
84 }
85 break;
86 }
87 }
88 }
89 }
90 }
91
92
93 final ArrayQueue<Message> messages=(ArrayQueue)from.getQueue();
94 final int cid=_unackedQueue.getCurrentId();
95 final int s=_unackedQueue.size();
96 for (int i=0;i<s;i++)
97 {
98 if (_unackedQueue.getAssociatedIdUnsafe(0)<cid)
99 messages.add(i,_unackedQueue.remove());
100 else
101 break;
102 }
103 }
104 }
105
106 return message;
107 }
108
109 public Message send(Client from, Message message)
110 {
111 synchronized (_client)
112 {
113 _unackedQueue.add(message);
114
115 ((MessageImpl) message).incRef();
116 }
117 return message;
118 }
119
120 public Message sendMeta(Client from, Message message)
121 {
122 if ( message.getChannel().equals(Bayeux.META_CONNECT) )
123 {
124 synchronized (_client)
125 {
126 Map<String, Object> ext= message.getExt(true);
127 ext.put("ack",_unackedQueue.getCurrentId());
128 _unackedQueue.incrementCurrentId();
129 }
130 }
131 return message;
132 }
133 }