1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.cometd;
16
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.List;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ConcurrentMap;
22
23 import org.mortbay.log.Log;
24 import org.mortbay.util.LazyList;
25
26 import dojox.cometd.Channel;
27 import dojox.cometd.Client;
28 import dojox.cometd.DataFilter;
29 import dojox.cometd.Message;
30
31
32
33
34
35
36
37 public class ChannelImpl implements Channel
38 {
39 protected AbstractBayeux _bayeux;
40 private ClientImpl[] _subscribers=new ClientImpl[0];
41 private DataFilter[] _dataFilters=new DataFilter[0];
42 private ChannelId _id;
43 private ConcurrentMap<String,ChannelImpl> _children = new ConcurrentHashMap<String, ChannelImpl>();
44 private ChannelImpl _wild;
45 private ChannelImpl _wildWild;
46 private boolean _persistent;
47
48
49 ChannelImpl(String id,AbstractBayeux bayeux)
50 {
51 _id=new ChannelId(id);
52 _bayeux=bayeux;
53 }
54
55
56 public void addChild(ChannelImpl channel)
57 {
58 ChannelId child=channel.getChannelId();
59 if (!_id.isParentOf(child))
60 {
61 throw new IllegalArgumentException(_id+" not parent of "+child);
62 }
63
64 String next = child.getSegment(_id.depth());
65
66 if ((child.depth()-_id.depth())==1)
67 {
68
69 ChannelImpl old = _children.putIfAbsent(next,channel);
70
71 if (old!=null)
72 throw new IllegalArgumentException("Already Exists");
73
74 if (ChannelId.WILD.equals(next))
75 _wild=channel;
76 else if (ChannelId.WILDWILD.equals(next))
77 _wildWild=channel;
78
79 }
80 else
81 {
82 ChannelImpl branch=_children.get(next);
83 branch=(ChannelImpl)_bayeux.getChannel((_id.depth()==0?"/":(_id.toString()+"/"))+next,true);
84
85 branch.addChild(channel);
86 }
87 }
88
89
90
91
92
93 public void addDataFilter(DataFilter filter)
94 {
95 synchronized(this)
96 {
97 _dataFilters=(DataFilter[])LazyList.addToArray(_dataFilters,filter,null);
98 }
99 }
100
101
102
103
104
105
106 public ChannelId getChannelId()
107 {
108 return _id;
109 }
110
111
112 public ChannelImpl getChild(ChannelId id)
113 {
114 String next=id.getSegment(_id.depth());
115 if (next==null)
116 return null;
117
118 ChannelImpl channel = _children.get(next);
119
120 if (channel==null || channel.getChannelId().depth()==id.depth())
121 {
122 return channel;
123 }
124 return channel.getChild(id);
125 }
126
127
128 public void getChannels(List<Channel> list)
129 {
130 list.add(this);
131 for (ChannelImpl channel: _children.values())
132 channel.getChannels(list);
133 }
134
135
136
137
138
139 public String getId()
140 {
141 return _id.toString();
142 }
143
144
145
146 public boolean isPersistent()
147 {
148 return _persistent;
149 }
150
151
152 public void publish(Client fromClient, Object data, String msgId)
153 {
154 _bayeux.doPublish(getChannelId(),fromClient,data,msgId);
155 }
156
157
158 public boolean remove()
159 {
160 return _bayeux.removeChannel(getChannelId());
161 }
162
163
164
165
166
167
168 public DataFilter removeDataFilter(DataFilter filter)
169 {
170 synchronized(this)
171 {
172 _dataFilters=(DataFilter[])LazyList.removeFromArray(_dataFilters,filter);
173 return filter;
174 }
175 }
176
177
178 public void setPersistent(boolean persistent)
179 {
180 _persistent=persistent;
181 }
182
183
184
185
186
187 public void subscribe(Client client)
188 {
189 if (!(client instanceof ClientImpl))
190 throw new IllegalArgumentException("Client instance not obtained from Bayeux.newClient()");
191
192 synchronized (this)
193 {
194 for (ClientImpl c : _subscribers)
195 {
196 if (client.equals(c))
197 return;
198 }
199 _subscribers=(ClientImpl[])LazyList.addToArray(_subscribers,client,null);
200 }
201
202 ((ClientImpl)client).addSubscription(this);
203 }
204
205
206 public String toString()
207 {
208 return _id.toString();
209 }
210
211
212
213
214
215 public void unsubscribe(Client client)
216 {
217 if (!(client instanceof ClientImpl))
218 throw new IllegalArgumentException("Client instance not obtained from Bayeux.newClient()");
219 ((ClientImpl)client).removeSubscription(this);
220 synchronized(this)
221 {
222 _subscribers=(ClientImpl[])LazyList.removeFromArray(_subscribers,client);
223
224 if (!_persistent && _subscribers.length==0 && _children.size()==0)
225 remove();
226 }
227 }
228
229
230 protected void doDelivery(ChannelId to, Client from, Message msg)
231 {
232 int tail = to.depth()-_id.depth();
233
234 Object data = msg.getData();
235 Object old = data;
236
237 DataFilter[] filters=null;
238
239 try
240 {
241 switch(tail)
242 {
243 case 0:
244 {
245 synchronized(this)
246 {
247 filters=_dataFilters;
248 }
249 for (DataFilter filter: filters)
250 data=filter.filter(from,this,data);
251 }
252 break;
253
254 case 1:
255 if (_wild!=null)
256 {
257 synchronized(_wild)
258 {
259 filters=_wild._dataFilters;
260 }
261 for (DataFilter filter: filters)
262 data=filter.filter(from,this,data);
263 }
264
265 default:
266 if (_wildWild!=null)
267 {
268 synchronized(_wildWild)
269 {
270 filters=_wildWild._dataFilters;
271 }
272 for (DataFilter filter: filters)
273 {
274 data=filter.filter(from,this,data);
275 }
276 }
277 }
278 }
279 catch (IllegalStateException e)
280 {
281 Log.debug(e);
282 return;
283 }
284 if (data!=old)
285 msg.put(AbstractBayeux.DATA_FIELD,data);
286
287 ClientImpl[] subscribers;
288
289 switch(tail)
290 {
291 case 0:
292 synchronized (this)
293 {
294 subscribers=_subscribers;
295 }
296 for (ClientImpl client: subscribers)
297 {
298 client.doDelivery(from,msg);
299 }
300
301 break;
302
303 case 1:
304 if (_wild!=null)
305 {
306 synchronized (_wild)
307 {
308 subscribers=_wild._subscribers;
309 }
310 for (ClientImpl client: subscribers)
311 {
312 client.doDelivery(from,msg);
313 }
314 }
315
316 default:
317 {
318 if (_wildWild!=null)
319 {
320 synchronized (_wildWild)
321 {
322 subscribers=_wildWild._subscribers;
323 }
324 for (ClientImpl client: subscribers)
325 {
326 client.doDelivery(from,msg);
327 }
328 }
329 String next = to.getSegment(_id.depth());
330 ChannelImpl channel = _children.get(next);
331 if (channel!=null)
332 channel.doDelivery(to,from,msg);
333 }
334 }
335 }
336
337
338 public Collection<Client> getSubscribers()
339 {
340 synchronized(this)
341 {
342 return Arrays.asList((Client[])_subscribers);
343 }
344 }
345
346
347 public int getSubscriberCount()
348 {
349 synchronized(this)
350 {
351 return _subscribers.length;
352 }
353 }
354
355
356
357
358
359 public Collection<DataFilter> getDataFilters()
360 {
361 synchronized(this)
362 {
363 return Arrays.asList(_dataFilters);
364 }
365 }
366
367
368
369 }