View Javadoc

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     /* (non-Javadoc)
150      * @see java.util.HashMap#clear()
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     /* (non-Javadoc)
186      * @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
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     /* (non-Javadoc)
208      * @see java.util.HashMap#putAll(java.util.Map)
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     /* (non-Javadoc)
224      * @see java.util.HashMap#remove(java.lang.Object)
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     /* (non-Javadoc)
244      * @see java.util.HashMap#entrySet()
245      */
246     @Override
247     public Set<java.util.Map.Entry<String, Object>> entrySet()
248     {
249         return Collections.unmodifiableSet(super.entrySet());
250     }
251 
252     /* ------------------------------------------------------------ */
253     /* (non-Javadoc)
254      * @see java.util.HashMap#keySet()
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      * @param buffer A cached buffer containing HTTP response headers 
284      * and message content, to be reused when sending one message
285      * to multiple clients 
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 }