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.List;
19 import java.util.Queue;
20
21 import org.cometd.Bayeux;
22 import org.cometd.Client;
23 import org.cometd.ClientListener;
24 import org.cometd.DeliverListener;
25 import org.cometd.Extension;
26 import org.cometd.Message;
27 import org.cometd.MessageListener;
28 import org.cometd.QueueListener;
29 import org.cometd.RemoveListener;
30 import org.mortbay.util.ArrayQueue;
31 import org.mortbay.util.LazyList;
32 import org.mortbay.util.ajax.JSON;
33
34
35
36
37
38
39
40
41 public class ClientImpl implements Client
42 {
43 private String _id;
44 private String _type;
45 private int _responsesPending;
46 private ChannelImpl[] _subscriptions=new ChannelImpl[0];
47 private RemoveListener[] _rListeners;
48 private MessageListener[] _syncMListeners;
49 private MessageListener[] _asyncMListeners;
50 private QueueListener[] _qListeners;
51 private DeliverListener[] _dListeners;
52 protected AbstractBayeux _bayeux;
53 private String _browserId;
54 private JSON.Literal _advice;
55 private int _batch;
56 private int _maxQueue;
57 private ArrayQueue<Message> _queue=new ArrayQueue<Message>(8,16,this);
58 private long _timeout;
59 protected Extension[] _extensions;
60
61 protected boolean _deliverViaMetaConnectOnly;
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 public void setDeliverViaMetaConnectOnly(boolean deliverViaMetaConnectOnly)
183 {
184 _deliverViaMetaConnectOnly = deliverViaMetaConnectOnly;
185 }
186
187
188 public boolean isDeliverViaMetaConnectOnly()
189 {
190 return _deliverViaMetaConnectOnly;
191 }
192
193
194 public void startBatch()
195 {
196 synchronized(this)
197 {
198 _batch++;
199 }
200 }
201
202
203 public void endBatch()
204 {
205 synchronized(this)
206 {
207 if (--_batch==0 && _queue.size()>0 && _responsesPending<1)
208 resume();
209 }
210 }
211
212
213 public String getConnectionType()
214 {
215 return _type;
216 }
217
218
219
220
221
222 public String getId()
223 {
224 return _id;
225 }
226
227
228 public boolean hasMessages()
229 {
230 return _queue.size()>0;
231 }
232
233
234 public boolean isLocal()
235 {
236 return true;
237 }
238
239
240
241
242
243 public void disconnect()
244 {
245 synchronized(this)
246 {
247 if (_bayeux.hasClient(_id))
248 remove(false);
249 }
250 }
251
252
253
254
255
256 public void remove(boolean timeout)
257 {
258 synchronized(this)
259 {
260 Client client=_bayeux.removeClient(_id);
261 if (_bayeux.isLogInfo())
262 _bayeux.logInfo("Remove client "+client+" timeout="+timeout);
263 if (_browserId!=null)
264 _bayeux.clientOffBrowser(getBrowserId(),_id);
265 _browserId=null;
266
267 if (_rListeners!=null)
268 for (RemoveListener l:_rListeners)
269 l.removed(_id, timeout);
270 }
271 resume();
272 }
273
274
275 public int responded()
276 {
277 synchronized(this)
278 {
279 return _responsesPending--;
280 }
281 }
282
283
284 public int responsePending()
285 {
286 synchronized(this)
287 {
288 return ++_responsesPending;
289 }
290 }
291
292
293
294
295 public void resume()
296 {
297 }
298
299
300
301
302
303 public int getMessages()
304 {
305 return _queue.size();
306 }
307
308
309 public List<Message> takeMessages()
310 {
311 synchronized(this)
312 {
313 ArrayList<Message> list = new ArrayList<Message>(_queue);
314 _queue.clear();
315 return list;
316 }
317 }
318
319
320
321 public void returnMessages(List<Message> messages)
322 {
323 synchronized(this)
324 {
325 _queue.addAll(0,messages);
326 }
327 }
328
329
330 @Override
331 public String toString()
332 {
333 return _id;
334 }
335
336
337 protected void addSubscription(ChannelImpl channel)
338 {
339 synchronized (this)
340 {
341 _subscriptions=(ChannelImpl[])LazyList.addToArray(_subscriptions,channel,null);
342 }
343 }
344
345
346 protected void removeSubscription(ChannelImpl channel)
347 {
348 synchronized (this)
349 {
350 _subscriptions=(ChannelImpl[])LazyList.removeFromArray(_subscriptions,channel);
351 }
352 }
353
354
355 protected void setConnectionType(String type)
356 {
357 synchronized (this)
358 {
359 _type=type;
360 }
361 }
362
363
364 protected void setId(String _id)
365 {
366 synchronized (this)
367 {
368 this._id=_id;
369 }
370 }
371
372
373 protected void unsubscribeAll()
374 {
375 ChannelImpl[] subscriptions;
376 synchronized(this)
377 {
378 _queue.clear();
379 subscriptions=_subscriptions;
380 _subscriptions=new ChannelImpl[0];
381 }
382 for (ChannelImpl channel : subscriptions)
383 channel.unsubscribe(this);
384
385 }
386
387
388 public void setBrowserId(String id)
389 {
390 if (_browserId!=null && !_browserId.equals(id))
391 _bayeux.clientOffBrowser(_browserId,_id);
392 _browserId=id;
393 if (_browserId!=null)
394 _bayeux.clientOnBrowser(_browserId,_id);
395 }
396
397
398 public String getBrowserId()
399 {
400 return _browserId;
401 }
402
403
404 @Override
405 public boolean equals(Object o)
406 {
407 if (!(o instanceof Client))
408 return false;
409 return getId().equals(((Client)o).getId());
410 }
411
412
413
414
415
416
417 public JSON.Literal getAdvice()
418 {
419 return _advice;
420 }
421
422
423
424
425
426 public void setAdvice(JSON.Literal advice)
427 {
428 _advice=advice;
429 }
430
431
432
433 public void addListener(ClientListener listener)
434 {
435 synchronized(this)
436 {
437 if (listener instanceof MessageListener)
438 {
439 if (listener instanceof MessageListener.Synchronous)
440 _syncMListeners=(MessageListener[])LazyList.addToArray(_syncMListeners,listener,MessageListener.class);
441 else
442 _asyncMListeners=(MessageListener[])LazyList.addToArray(_asyncMListeners,listener,MessageListener.class);
443 }
444
445 if (listener instanceof RemoveListener)
446 _rListeners=(RemoveListener[])LazyList.addToArray(_rListeners,listener,RemoveListener.class);
447
448 if (listener instanceof QueueListener)
449 _qListeners=(QueueListener[])LazyList.addToArray(_qListeners,listener,QueueListener.class);
450
451 if (listener instanceof DeliverListener)
452 _dListeners=(DeliverListener[])LazyList.addToArray(_dListeners,listener,DeliverListener.class);
453 }
454 }
455
456
457 public void removeListener(ClientListener listener)
458 {
459 synchronized(this)
460 {
461 if (listener instanceof MessageListener)
462 {
463 _syncMListeners=(MessageListener[])LazyList.removeFromArray(_syncMListeners,listener);
464 _asyncMListeners=(MessageListener[])LazyList.removeFromArray(_asyncMListeners,listener);
465 }
466
467 if (listener instanceof RemoveListener)
468 _rListeners=(RemoveListener[])LazyList.removeFromArray(_rListeners,listener);
469
470 if (listener instanceof QueueListener)
471 _qListeners=(QueueListener[])LazyList.removeFromArray(_qListeners,listener);
472 }
473 }
474
475
476 public long getTimeout()
477 {
478 return _timeout;
479 }
480
481
482 public void setTimeout(long timeoutMS)
483 {
484 _timeout=timeoutMS;
485 }
486
487
488 public void setMaxQueue(int maxQueue)
489 {
490 _maxQueue=maxQueue;
491 }
492
493
494 public int getMaxQueue()
495 {
496 return _maxQueue;
497 }
498
499
500 public Queue<Message> getQueue()
501 {
502 return _queue;
503 }
504 }