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