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