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.EventListener;
20 import java.util.List;
21
22 import org.mortbay.util.LazyList;
23
24 import dojox.cometd.Bayeux;
25 import dojox.cometd.Client;
26 import dojox.cometd.Extension;
27 import dojox.cometd.Listener;
28 import dojox.cometd.Message;
29 import dojox.cometd.MessageListener;
30 import dojox.cometd.RemoveListener;
31
32
33
34
35
36
37
38 public class ClientImpl implements Client
39 {
40 private String _id;
41 private String _type;
42 private Object _messageQ=null;
43 private int _responsesPending;
44 private ChannelImpl[] _subscriptions=new ChannelImpl[0];
45 private boolean _JSONCommented;
46 private Listener _listener;
47 private RemoveListener[] _rListeners=new RemoveListener[0];
48 private MessageListener[] _syncMListeners=new MessageListener[0];
49 private MessageListener[] _asyncMListeners=new MessageListener[0];
50 protected AbstractBayeux _bayeux;
51 private String _browserId;
52 private int _adviseVersion;
53 private int _batch;
54 private int _maxQueue;
55 private long _timeout;
56
57
58 protected ClientImpl(AbstractBayeux bayeux)
59 {
60 _bayeux=bayeux;
61 _maxQueue=-1;
62 _bayeux.addClient(this,null);
63 if (_bayeux.isLogInfo())
64 _bayeux.logInfo("newClient: "+this);
65 }
66
67
68 protected ClientImpl(AbstractBayeux bayeux, String idPrefix)
69 {
70 _bayeux=bayeux;
71 _maxQueue=0;
72
73 _bayeux.addClient(this,idPrefix);
74
75 if (_bayeux.isLogInfo())
76 _bayeux.logInfo("newClient: "+this);
77
78 }
79
80
81
82
83
84 protected ClientImpl(AbstractBayeux bayeux, String idPrefix, Listener listener)
85 {
86 this(bayeux,idPrefix);
87 _listener=listener;
88 }
89
90
91
92
93
94
95
96 public void publish(String toChannel, Object data, String msgId)
97 {
98 _bayeux.getChannel(toChannel).publish(this,data,msgId);
99 }
100
101
102
103
104
105
106 public void subscribe(String toChannel)
107 {
108 _bayeux.subscribe(toChannel,this);
109 }
110
111
112
113
114
115
116 public void unsubscribe(String toChannel)
117 {
118 _bayeux.unsubscribe(toChannel,this);
119 }
120
121
122
123
124
125 public void deliver(Client from, Message message)
126 {
127 for (Extension e:_bayeux._extensions)
128 message=e.send(message);
129 doDelivery(from,message);
130 }
131
132
133 public void deliver(Client from, String toChannel, Object data, String id)
134 {
135
136 Message message=_bayeux.newMessage();
137 message.put(Bayeux.CHANNEL_FIELD,toChannel);
138 message.put(Bayeux.DATA_FIELD,data);
139 if (id!=null)
140 message.put(Bayeux.ID_FIELD,id);
141
142 for (Extension e:_bayeux._extensions)
143 message=e.send(message);
144 doDelivery(from,message);
145
146 ((MessageImpl)message).decRef();
147 }
148
149
150 protected void doDelivery(Client from, Message message)
151 {
152 MessageListener[] alisteners=null;
153 synchronized(this)
154 {
155 ((MessageImpl)message).incRef();
156
157 if (_maxQueue<0)
158 _messageQ=LazyList.add(_messageQ,message);
159 else if (_maxQueue>0)
160 {
161 if (LazyList.size(_messageQ)>=_maxQueue)
162 _messageQ=LazyList.remove(_messageQ,0);
163 _messageQ=LazyList.add(_messageQ,message);
164 }
165
166 if (_batch==0 && _responsesPending<1)
167 resume();
168
169
170 for (MessageListener l:_syncMListeners)
171 l.deliver(from,this,message);
172 alisteners=_asyncMListeners;
173 }
174
175
176 for (MessageListener l:alisteners)
177 l.deliver(from,this,message);
178 }
179
180
181
182 public void startBatch()
183 {
184 synchronized(this)
185 {
186 _batch++;
187 }
188 }
189
190
191 public void endBatch()
192 {
193 synchronized(this)
194 {
195 if (--_batch==0 && LazyList.size(_messageQ)>0 && _responsesPending<1)
196 resume();
197 }
198 }
199
200
201 public String getConnectionType()
202 {
203 return _type;
204 }
205
206
207
208
209
210 public String getId()
211 {
212 return _id;
213 }
214
215
216
217
218
219 public boolean hasMessages()
220 {
221 synchronized(this)
222 {
223 return LazyList.size(_messageQ)>0;
224 }
225 }
226
227
228
229
230
231 public boolean isJSONCommented()
232 {
233 synchronized(this)
234 {
235 return _JSONCommented;
236 }
237 }
238
239
240 public boolean isLocal()
241 {
242 return true;
243 }
244
245
246
247
248
249
250 public void remove(boolean timeout)
251 {
252 synchronized(this)
253 {
254 Client client=_bayeux.removeClient(_id);
255 if (_bayeux.isLogInfo())
256 _bayeux.logInfo("Remove client "+client+" timeout="+timeout);
257 if (_rListeners!=null)
258 for (RemoveListener l:_rListeners)
259 l.removed(_id, timeout);
260 if (_browserId!=null)
261 _bayeux.clientOffBrowser(getBrowserId(),_id);
262 _browserId=null;
263 }
264 resume();
265
266 }
267
268
269 public int responded()
270 {
271 synchronized(this)
272 {
273 return _responsesPending--;
274 }
275 }
276
277
278 public int responsePending()
279 {
280 synchronized(this)
281 {
282 return ++_responsesPending;
283 }
284 }
285
286
287
288
289 public void resume()
290 {
291 }
292
293
294
295
296
297 public void setJSONCommented(boolean commented)
298 {
299 synchronized(this)
300 {
301 _JSONCommented=commented;
302 }
303 }
304
305
306 public void setListener(Listener listener)
307 {
308 synchronized(this)
309 {
310 if (_listener!=null)
311 removeListener(_listener);
312 _listener=listener;
313 if (_listener!=null)
314 addListener(_listener);
315 }
316 }
317
318
319 public Listener getListener()
320 {
321 return _listener;
322 }
323
324
325
326
327
328 public int getMessages()
329 {
330 synchronized(this)
331 {
332 return LazyList.size(_messageQ);
333 }
334 }
335
336
337
338
339
340 public List<Message> takeMessages()
341 {
342 synchronized(this)
343 {
344 switch (LazyList.size(_messageQ))
345 {
346 case 0: return null;
347 case 1:
348 Message message = (Message)LazyList.get(_messageQ,0);
349 _messageQ=null;
350 return Collections.singletonList(message);
351 default:
352 List<Message> messages = LazyList.getList(_messageQ);
353 _messageQ=null;
354 return messages;
355 }
356 }
357 }
358
359
360
361 public void returnMessages(List<Message> messages)
362 {
363 synchronized(this)
364 {
365 switch (LazyList.size(_messageQ))
366 {
367 case 0:
368 _messageQ=messages;
369 break;
370 case 1:
371 default:
372 throw new IllegalStateException();
373 }
374 }
375 }
376
377
378
379
380
381 public Message takeMessage()
382 {
383 synchronized(this)
384 {
385 switch (LazyList.size(_messageQ))
386 {
387 case 0: return null;
388 case 1:
389 {
390 Message message = (Message)LazyList.get(_messageQ,0);
391 _messageQ=null;
392 return message;
393 }
394 default:
395 {
396 Message message = (Message)LazyList.get(_messageQ,0);
397 _messageQ=LazyList.remove(_messageQ,0);
398 return message;
399 }
400 }
401 }
402 }
403
404
405 public void returnMessage(Message message)
406 {
407 synchronized(this)
408 {
409 switch (LazyList.size(_messageQ))
410 {
411 case 0:
412 _messageQ=message;
413 break;
414 case 1:
415 default:
416 throw new IllegalStateException();
417 }
418 }
419 }
420
421
422 public String toString()
423 {
424 return _id;
425 }
426
427
428 protected void addSubscription(ChannelImpl channel)
429 {
430 synchronized (this)
431 {
432 _subscriptions=(ChannelImpl[])LazyList.addToArray(_subscriptions,channel,null);
433 }
434 }
435
436
437 protected void removeSubscription(ChannelImpl channel)
438 {
439 synchronized (this)
440 {
441 _subscriptions=(ChannelImpl[])LazyList.removeFromArray(_subscriptions,channel);
442 }
443 }
444
445
446 protected void setConnectionType(String type)
447 {
448 synchronized (this)
449 {
450 _type=type;
451 }
452 }
453
454
455 protected void setId(String _id)
456 {
457 synchronized (this)
458 {
459 this._id=_id;
460 }
461 }
462
463
464 protected void unsubscribeAll()
465 {
466 ChannelImpl[] subscriptions;
467 synchronized(this)
468 {
469 _messageQ=null;
470 subscriptions=_subscriptions;
471 _subscriptions=new ChannelImpl[0];
472 }
473 for (ChannelImpl channel : subscriptions)
474 channel.unsubscribe(this);
475
476 }
477
478
479 public void setBrowserId(String id)
480 {
481 if (_browserId!=null && !_browserId.equals(id))
482 _bayeux.clientOffBrowser(_browserId,_id);
483 _browserId=id;
484 if (_browserId!=null)
485 _bayeux.clientOnBrowser(_browserId,_id);
486 }
487
488
489 public String getBrowserId()
490 {
491 return _browserId;
492 }
493
494
495 public boolean equals(Object o)
496 {
497 if (!(o instanceof Client))
498 return false;
499 return getId().equals(((Client)o).getId());
500 }
501
502
503
504
505
506 public int getAdviceVersion()
507 {
508 return _adviseVersion;
509 }
510
511
512
513
514
515 public void setAdviceVersion(int version)
516 {
517 _adviseVersion=version;
518 }
519
520
521 public void addListener(EventListener listener)
522 {
523 synchronized(this)
524 {
525 if (listener instanceof MessageListener)
526 {
527 if (listener instanceof MessageListener.Synchronous)
528 _syncMListeners=(MessageListener[])LazyList.addToArray(_syncMListeners,listener,MessageListener.class);
529 else
530 _asyncMListeners=(MessageListener[])LazyList.addToArray(_asyncMListeners,listener,MessageListener.class);
531 }
532
533 if (listener instanceof RemoveListener)
534 _rListeners=(RemoveListener[])LazyList.addToArray(_rListeners,listener,RemoveListener.class);
535 }
536 }
537
538
539 public void removeListener(EventListener listener)
540 {
541 synchronized(this)
542 {
543 if (listener instanceof MessageListener)
544 {
545 _syncMListeners=(MessageListener[])LazyList.removeFromArray(_syncMListeners,listener);
546 _asyncMListeners=(MessageListener[])LazyList.removeFromArray(_asyncMListeners,listener);
547 }
548
549 if (listener instanceof RemoveListener)
550 _rListeners=(RemoveListener[])LazyList.removeFromArray(_rListeners,listener);
551 }
552 }
553
554
555 public long getTimeout()
556 {
557 return _timeout;
558 }
559
560
561 public void setTimeout(long timeoutMS)
562 {
563 _timeout=timeoutMS;
564 }
565
566 }