1 package org.mortbay.cometd;
2
3 import java.nio.ByteBuffer;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.concurrent.atomic.AtomicInteger;
10
11 import org.cometd.Bayeux;
12 import org.cometd.Message;
13 import org.mortbay.util.ajax.JSON;
14
15 public class MessageImpl extends HashMap<String,Object> implements Message, org.mortbay.util.ajax.JSON.Generator
16 {
17 Message _associated;
18 ByteBuffer _buffer;
19 String _channel;
20 String _clientId;
21 Object _data;
22 Object _ext;
23 String _id;
24 String _json;
25 boolean _lazy=false;
26 final MessagePool _pool;
27 AtomicInteger _refs=new AtomicInteger();
28
29
30 public MessageImpl()
31 {
32 super(8);
33 _pool=null;
34 }
35
36
37 public MessageImpl(MessagePool bayeux)
38 {
39 super(8);
40 _pool=bayeux;
41 }
42
43
44 public void addJSON(StringBuffer buffer)
45 {
46 buffer.append(getJSON());
47 }
48
49
50
51
52
53
54
55 @Override
56 public void clear()
57 {
58 setAssociated(null);
59 _buffer=null;
60 _channel=null;
61 _clientId=null;
62 _data=null;
63 _ext=null;
64 _id=null;
65 _json=null;
66 _lazy=false;
67 _ext=null;
68 _refs.set(0);
69
70 Iterator<Map.Entry<String,Object>> iterator=super.entrySet().iterator();
71 while(iterator.hasNext())
72 {
73 Map.Entry<String,Object> entry=iterator.next();
74 String key=entry.getKey();
75 if (Bayeux.CHANNEL_FIELD.equals(key))
76 entry.setValue(null);
77 else if (Bayeux.ID_FIELD.equals(key))
78 entry.setValue(null);
79 else if (Bayeux.TIMESTAMP_FIELD.equals(key))
80 entry.setValue(null);
81 else if (Bayeux.DATA_FIELD.equals(key))
82 entry.setValue(null);
83 else if (Bayeux.EXT_FIELD.equals(key))
84 entry.setValue(null);
85 else
86 iterator.remove();
87 }
88 super.clear();
89 }
90
91
92 public Object clone()
93 {
94 MessageImpl msg=new MessageImpl();
95 msg.putAll(this);
96 msg._channel=_channel;
97 msg._clientId=_clientId;
98 msg._id=_id;
99 return msg;
100 }
101
102
103 public void decRef()
104 {
105 int r=_refs.decrementAndGet();
106 if (r == 0 && _pool != null)
107 {
108 setAssociated(null);
109 _pool.recycleMessage(this);
110 }
111 else if (r < 0)
112 throw new IllegalStateException();
113 }
114
115
116
117
118
119
120
121 @Override
122 public Set<java.util.Map.Entry<String,Object>> entrySet()
123 {
124 return Collections.unmodifiableSet(super.entrySet());
125 }
126
127
128 public Message getAssociated()
129 {
130 return _associated;
131 }
132
133
134 public ByteBuffer getBuffer()
135 {
136 return _buffer;
137 }
138
139
140 public String getChannel()
141 {
142 return _channel;
143 }
144
145
146 public String getClientId()
147 {
148 if (_clientId == null)
149 _clientId=(String)get(Bayeux.CLIENT_FIELD);
150 return _clientId;
151 }
152
153
154 public Object getData()
155 {
156 return _data;
157 }
158
159
160 public Map<String,Object> getExt(boolean create)
161 {
162 Object ext=_ext == null?get(Bayeux.EXT_FIELD):_ext;
163 if (ext instanceof Map)
164 return (Map<String,Object>)ext;
165 if (ext instanceof JSON.Literal)
166 {
167 JSON json=_pool == null?JSON.getDefault():_pool.getMsgJSON();
168 _ext=ext=json.fromJSON(ext.toString());
169 super.put(Bayeux.EXT_FIELD,ext);
170 return (Map<String,Object>)ext;
171 }
172
173 if (!create)
174 return null;
175
176 _ext=ext=new HashMap<String,Object>();
177 super.put(Bayeux.EXT_FIELD,ext);
178 return (Map<String,Object>)ext;
179
180 }
181
182
183 public String getId()
184 {
185 return _id;
186 }
187
188
189 public String getJSON()
190 {
191 if (_json == null)
192 {
193 JSON json=_pool == null?JSON.getDefault():_pool.getMsgJSON();
194 StringBuffer buf=new StringBuffer(json.getStringBufferSize());
195 synchronized(buf)
196 {
197 json.appendMap(buf,this);
198 _json=buf.toString();
199 }
200 }
201 return _json;
202 }
203
204
205 public int getRefs()
206 {
207 return _refs.get();
208 }
209
210
211 public void incRef()
212 {
213 _refs.incrementAndGet();
214 }
215
216
217
218
219
220
221
222 public boolean isLazy()
223 {
224 return _lazy;
225 }
226
227
228 public boolean isSuccessful()
229 {
230 Boolean bool=(Boolean)get(Bayeux.SUCCESSFUL_FIELD);
231 return bool != null && bool.booleanValue();
232 }
233
234
235
236
237
238
239
240 @Override
241 public Set<String> keySet()
242 {
243 return Collections.unmodifiableSet(super.keySet());
244 }
245
246
247
248
249
250
251
252 @Override
253 public Object put(String key, Object value)
254 {
255 _json=null;
256 _buffer=null;
257 if (Bayeux.CHANNEL_FIELD.equals(key))
258 _channel=(String)value;
259 else if (Bayeux.ID_FIELD.equals(key))
260 _id=value.toString();
261 else if (Bayeux.CLIENT_FIELD.equals(key))
262 _clientId=(String)value;
263 else if (Bayeux.DATA_FIELD.equals(key))
264 _data=value;
265 else if (Bayeux.EXT_FIELD.equals(key))
266 _ext=value;
267 return super.put(key,value);
268 }
269
270
271
272
273
274
275
276 @Override
277 public void putAll(Map<? extends String,? extends Object> m)
278 {
279 _json=null;
280 _buffer=null;
281 super.putAll(m);
282 _channel=(String)get(Bayeux.CHANNEL_FIELD);
283 Object id=get(Bayeux.ID_FIELD);
284 _id=id == null?null:id.toString();
285 _data=get(Bayeux.DATA_FIELD);
286 }
287
288
289
290
291
292
293
294 @Override
295 public Object remove(Object key)
296 {
297 _json=null;
298 _buffer=null;
299 if (Bayeux.CHANNEL_FIELD.equals(key))
300 _channel=null;
301 else if (Bayeux.ID_FIELD.equals(key))
302 _id=null;
303 else if (Bayeux.DATA_FIELD.equals(key))
304 _data=null;
305 else if (Bayeux.EXT_FIELD.equals(key))
306 _ext=null;
307 return super.remove(key);
308 }
309
310
311 public void setAssociated(Message associated)
312 {
313 if (_associated != associated)
314 {
315 if (_associated != null)
316 ((MessageImpl)_associated).decRef();
317 _associated=associated;
318 if (_associated != null)
319 ((MessageImpl)_associated).incRef();
320 }
321 }
322
323
324
325
326
327
328
329
330 public void setBuffer(ByteBuffer buffer)
331 {
332 _buffer=buffer;
333 }
334
335
336
337
338
339
340
341
342 public void setLazy(boolean lazy)
343 {
344 _lazy=lazy;
345 }
346
347
348 public String toString()
349 {
350 return getJSON();
351 }
352 }