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