1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.cometd;
16
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Queue;
21 import java.util.concurrent.CopyOnWriteArrayList;
22
23 import org.cometd.Bayeux;
24 import org.cometd.Client;
25 import org.cometd.DeliverListener;
26 import org.cometd.Extension;
27 import org.cometd.ClientListener;
28 import org.cometd.Message;
29 import org.cometd.MessageListener;
30 import org.cometd.QueueListener;
31 import org.cometd.RemoveListener;
32 import org.mortbay.util.ArrayQueue;
33 import org.mortbay.util.LazyList;
34 import org.mortbay.util.ajax.JSON;
35
36
37
38
39
40
41
42
43 public class ClientImpl implements Client
44 {
45 private String _id;
46 private String _type;
47 private int _responsesPending;
48 private ChannelImpl[] _subscriptions=new ChannelImpl[0];
49 private RemoveListener[] _rListeners;
50 private MessageListener[] _syncMListeners;
51 private MessageListener[] _asyncMListeners;
52 private QueueListener[] _qListeners;
53 private DeliverListener[] _dListeners;
54 protected AbstractBayeux _bayeux;
55 private String _browserId;
56 private JSON.Literal _advice;
57 private int _batch;
58 private int _maxQueue;
59 private ArrayQueue<Message> _queue=new ArrayQueue<Message>(8,16,this);
60 private long _timeout;
61 protected Extension[] _extensions;
62 ;
63
64 int _adviseVersion;
65
66
67 protected ClientImpl(AbstractBayeux bayeux)
68 {
69 _bayeux=bayeux;
70 _maxQueue=bayeux.getMaxClientQueue();
71 _bayeux.addClient(this,null);
72 if (_bayeux.isLogInfo())
73 _bayeux.logInfo("newClient: "+this);
74 }
75
76
77 protected ClientImpl(AbstractBayeux bayeux, String idPrefix)
78 {
79 _bayeux=bayeux;
80 _maxQueue=0;
81
82 _bayeux.addClient(this,idPrefix);
83
84 if (_bayeux.isLogInfo())
85 _bayeux.logInfo("newClient: "+this);
86 }
87
88
89 public void addExtension(Extension ext)
90 {
91 _extensions = (Extension[])LazyList.addToArray(_extensions,ext,Extension.class);
92 }
93
94
95 Extension[] getExtensions()
96 {
97 return _extensions;
98 }
99
100
101 public void deliver(Client from, String toChannel, Object data, String id)
102 {
103
104 Message message=_bayeux.newMessage();
105 message.put(Bayeux.CHANNEL_FIELD,toChannel);
106 message.put(Bayeux.DATA_FIELD,data);
107 if (id!=null)
108 message.put(Bayeux.ID_FIELD,id);
109
110 message=_bayeux.extendSendBayeux(from,message);
111 if (message!=null)
112 doDelivery(from,message);
113
114 ((MessageImpl)message).decRef();
115 }
116
117
118 protected void doDelivery(Client from, Message message)
119 {
120 message=_bayeux.extendSendClient(from,this,message);
121 if (message==null)
122 return;
123
124 MessageListener[] alisteners=null;
125 synchronized(this)
126 {
127 ((MessageImpl)message).incRef();
128
129 if (_maxQueue<0)
130 {
131 _queue.addUnsafe(message);
132 }
133 else
134 {
135 boolean add;
136 if (_queue.size()>=_maxQueue)
137 {
138 if (_qListeners!=null && _qListeners.length>0)
139 {
140 add=true;
141 for (QueueListener l : _qListeners)
142 add &= l.queueMaxed(from,this,message);
143 }
144 else
145 add=false;
146 }
147 else
148 add=true;
149
150 if (add)
151 _queue.addUnsafe(message);
152 }
153
154
155 if (_syncMListeners!=null)
156 for (MessageListener l:_syncMListeners)
157 l.deliver(from,this,message);
158 alisteners=_asyncMListeners;
159
160 if (_batch==0 && _responsesPending<1 && _queue.size()>0)
161 resume();
162 }
163
164
165 if (alisteners!=null)
166 for (MessageListener l:alisteners)
167 l.deliver(from,this,message);
168 }
169
170
171 public void doDeliverListeners()
172 {
173 synchronized (this)
174 {
175 if (_dListeners!=null)
176 for (DeliverListener l:_dListeners)
177 l.deliver(this,_queue);
178 }
179 }
180
181
182
183 public void startBatch()
184 {
185 synchronized(this)
186 {
187 _batch++;
188 }
189 }
190
191
192 public void endBatch()
193 {
194 synchronized(this)
195 {
196 if (--_batch==0 && _queue.size()>0 && _responsesPending<1)
197 resume();
198 }
199 }
200
201
202 public String getConnectionType()
203 {
204 return _type;
205 }
206
207
208
209
210
211 public String getId()
212 {
213 return _id;
214 }
215
216
217 public boolean hasMessages()
218 {
219 return _queue.size()>0;
220 }
221
222
223 public boolean isLocal()
224 {
225 return true;
226 }
227
228
229
230
231
232 public void disconnect()
233 {
234 synchronized(this)
235 {
236 if (_bayeux.hasClient(_id))
237 remove(false);
238 }
239 }
240
241
242
243
244
245 public void remove(boolean timeout)
246 {
247 synchronized(this)
248 {
249 Client client=_bayeux.removeClient(_id);
250 if (_bayeux.isLogInfo())
251 _bayeux.logInfo("Remove client "+client+" timeout="+timeout);
252 if (_browserId!=null)
253 _bayeux.clientOffBrowser(getBrowserId(),_id);
254 _browserId=null;
255
256 if (_rListeners!=null)
257 for (RemoveListener l:_rListeners)
258 l.removed(_id, timeout);
259 }
260 resume();
261 }
262
263
264 public int responded()
265 {
266 synchronized(this)
267 {
268 return _responsesPending--;
269 }
270 }
271
272
273 public int responsePending()
274 {
275 synchronized(this)
276 {
277 return ++_responsesPending;
278 }
279 }
280
281
282
283
284 public void resume()
285 {
286 }
287
288
289
290
291
292 public int getMessages()
293 {
294 return _queue.size();
295 }
296
297
298 public List<Message> takeMessages()
299 {
300 synchronized(this)
301 {
302 ArrayList<Message> list = new ArrayList<Message>(_queue);
303 _queue.clear();
304 return list;
305 }
306 }
307
308
309
310 public void returnMessages(List<Message> messages)
311 {
312 synchronized(this)
313 {
314 _queue.addAll(0,messages);
315 }
316 }
317
318
319 @Override
320 public String toString()
321 {
322 return _id;
323 }
324
325
326 protected void addSubscription(ChannelImpl channel)
327 {
328 synchronized (this)
329 {
330 _subscriptions=(ChannelImpl[])LazyList.addToArray(_subscriptions,channel,null);
331 }
332 }
333
334
335 protected void removeSubscription(ChannelImpl channel)
336 {
337 synchronized (this)
338 {
339 _subscriptions=(ChannelImpl[])LazyList.removeFromArray(_subscriptions,channel);
340 }
341 }
342
343
344 protected void setConnectionType(String type)
345 {
346 synchronized (this)
347 {
348 _type=type;
349 }
350 }
351
352
353 protected void setId(String _id)
354 {
355 synchronized (this)
356 {
357 this._id=_id;
358 }
359 }
360
361
362 protected void unsubscribeAll()
363 {
364 ChannelImpl[] subscriptions;
365 synchronized(this)
366 {
367 _queue.clear();
368 subscriptions=_subscriptions;
369 _subscriptions=new ChannelImpl[0];
370 }
371 for (ChannelImpl channel : subscriptions)
372 channel.unsubscribe(this);
373
374 }
375
376
377 public void setBrowserId(String id)
378 {
379 if (_browserId!=null && !_browserId.equals(id))
380 _bayeux.clientOffBrowser(_browserId,_id);
381 _browserId=id;
382 if (_browserId!=null)
383 _bayeux.clientOnBrowser(_browserId,_id);
384 }
385
386
387 public String getBrowserId()
388 {
389 return _browserId;
390 }
391
392
393 @Override
394 public boolean equals(Object o)
395 {
396 if (!(o instanceof Client))
397 return false;
398 return getId().equals(((Client)o).getId());
399 }
400
401
402
403
404
405
406 public JSON.Literal getAdvice()
407 {
408 return _advice;
409 }
410
411
412
413
414
415 public void setAdvice(JSON.Literal advice)
416 {
417 _advice=advice;
418 }
419
420
421
422 public void addListener(ClientListener listener)
423 {
424 synchronized(this)
425 {
426 if (listener instanceof MessageListener)
427 {
428 if (listener instanceof MessageListener.Synchronous)
429 _syncMListeners=(MessageListener[])LazyList.addToArray(_syncMListeners,listener,MessageListener.class);
430 else
431 _asyncMListeners=(MessageListener[])LazyList.addToArray(_asyncMListeners,listener,MessageListener.class);
432 }
433
434 if (listener instanceof RemoveListener)
435 _rListeners=(RemoveListener[])LazyList.addToArray(_rListeners,listener,RemoveListener.class);
436
437 if (listener instanceof QueueListener)
438 _qListeners=(QueueListener[])LazyList.addToArray(_qListeners,listener,QueueListener.class);
439
440 if (listener instanceof DeliverListener)
441 _dListeners=(DeliverListener[])LazyList.addToArray(_dListeners,listener,DeliverListener.class);
442 }
443 }
444
445
446 public void removeListener(ClientListener listener)
447 {
448 synchronized(this)
449 {
450 if (listener instanceof MessageListener)
451 {
452 _syncMListeners=(MessageListener[])LazyList.removeFromArray(_syncMListeners,listener);
453 _asyncMListeners=(MessageListener[])LazyList.removeFromArray(_asyncMListeners,listener);
454 }
455
456 if (listener instanceof RemoveListener)
457 _rListeners=(RemoveListener[])LazyList.removeFromArray(_rListeners,listener);
458
459 if (listener instanceof QueueListener)
460 _qListeners=(QueueListener[])LazyList.removeFromArray(_qListeners,listener);
461 }
462 }
463
464
465 public long getTimeout()
466 {
467 return _timeout;
468 }
469
470
471 public void setTimeout(long timeoutMS)
472 {
473 _timeout=timeoutMS;
474 }
475
476
477 public void setMaxQueue(int maxQueue)
478 {
479 _maxQueue=maxQueue;
480 }
481
482
483 public int getMaxQueue()
484 {
485 return _maxQueue;
486 }
487
488
489 public Queue<Message> getQueue()
490 {
491 return _queue;
492 }
493 }