View Javadoc

1   package org.mortbay.cometd;
2   
3   import java.io.IOException;
4   import java.io.Reader;
5   import java.util.HashMap;
6   import java.util.List;
7   import java.util.Map;
8   
9   import org.cometd.Bayeux;
10  import org.cometd.Message;
11  import org.mortbay.util.ArrayQueue;
12  import org.mortbay.util.StringMap;
13  import org.mortbay.util.ajax.JSON;
14  
15  
16  public class MessagePool 
17  {
18      final private ArrayQueue<MessageImpl> _messagePool;
19      final private ArrayQueue<JSON.ReaderSource> _readerPool;
20  
21      /* ------------------------------------------------------------ */
22      public MessagePool()
23      {
24          this(50);
25      }
26  
27      /* ------------------------------------------------------------ */
28      public MessagePool(int capacity)
29      {
30          _messagePool=new ArrayQueue<MessageImpl>(capacity,capacity);
31          _readerPool=new ArrayQueue<JSON.ReaderSource>(capacity,capacity);
32      }
33      
34      /* ------------------------------------------------------------ */
35      /**
36       * @return the {@link JSON} instance used to convert data and ext fields
37       */
38      public JSON getJSON()
39      {
40          return _json;
41      }
42  
43      /* ------------------------------------------------------------ */
44      /**
45       * @param json the {@link JSON} instance used to convert data and ext fields
46       */
47      public void setJSON(JSON json)
48      {
49          _json=json;
50      }
51  
52      /* ------------------------------------------------------------ */
53      /**
54       * @return the {@link JSON} instance used to serialize and deserialize bayeux bayeux messages
55       */
56      public JSON getMsgJSON()
57      {
58          return _msgJSON;
59      }
60  
61      /* ------------------------------------------------------------ */
62      /**
63       * @param msgJSON the {@link JSON} instance used to serialize and deserialize bayeux messages
64       */
65      public void setMsgJSON(JSON msgJSON)
66      {
67          _msgJSON=msgJSON;
68      }
69  
70      /* ------------------------------------------------------------ */
71      /**
72       * @return the {@link JSON} instance used to deserialize batches of bayeux messages
73       */
74      public JSON getBatchJSON()
75      {
76          return _batchJSON;
77      }
78  
79      /* ------------------------------------------------------------ */
80      /**
81       * @param batchJSON the {@link JSON} instance used to convert batches of bayeux messages
82       */
83      public void setBatchJSON(JSON batchJSON)
84      {
85          _batchJSON=batchJSON;
86      }
87  
88  
89      /* ------------------------------------------------------------ */
90      public MessageImpl newMessage()
91      {
92          MessageImpl message=_messagePool.poll();
93          if (message==null)
94          {
95              message=new MessageImpl(this);
96          }
97          message.incRef();
98          return message;
99      }
100 
101     /* ------------------------------------------------------------ */
102     public MessageImpl newMessage(Message associated)
103     {
104         MessageImpl message=_messagePool.poll();
105         if (message==null)
106         {
107             message=new MessageImpl(this);
108         }
109         message.incRef();
110         if (associated!=null)
111             message.setAssociated(associated);
112         return message;
113     }
114 
115     /* ------------------------------------------------------------ */
116     void recycleMessage(MessageImpl message)
117     {
118         message.clear();
119         _messagePool.offer(message);
120     }
121 
122     /* ------------------------------------------------------------ */
123     public Message[] parse(Reader reader) throws IOException
124     {
125         JSON.ReaderSource source =_readerPool.poll();
126         if (source==null)
127             source=new JSON.ReaderSource(reader);
128         else
129             source.setReader(reader);
130         
131         Object batch=_batchJSON.parse(source);
132         _readerPool.offer(source);
133 
134         if (batch==null)
135             return new Message[0]; 
136         if (batch.getClass().isArray())
137             return (Message[])batch;
138         return new Message[]{(Message)batch};
139     }
140 
141     /* ------------------------------------------------------------ */
142     public Message[] parse(String s) throws IOException
143     {
144         Object batch=_batchJSON.parse(new JSON.StringSource(s));
145         if (batch==null)
146             return new Message[0]; 
147         if (batch.getClass().isArray())
148             return (Message[])batch;
149         return new Message[]{(Message)batch};
150     }
151 
152     /* ------------------------------------------------------------ */
153     public void parseTo(String fodder, List<Message> messages)
154     {
155         Object batch=_batchJSON.parse(new JSON.StringSource(fodder));
156         if (batch==null)
157             return;
158         if (batch.getClass().isArray())
159         {
160             Message[] msgs=(Message[])batch;
161             for (int m=0;m<msgs.length;m++)
162                 messages.add(msgs[m]);
163         }
164         else
165             messages.add((Message)batch);
166     }
167 
168     /* ------------------------------------------------------------ */
169     public String toString()
170     {
171         return "MessagePool:"+_messagePool.size()+"/"+_messagePool.getCapacity();
172         
173     }
174     
175     /* ------------------------------------------------------------ */
176     /* ------------------------------------------------------------ */
177     private StringMap _fieldStrings = new StringMap();
178     private StringMap _valueStrings = new StringMap();
179     {
180         _fieldStrings.put(Bayeux.ADVICE_FIELD,Bayeux.ADVICE_FIELD);
181         _fieldStrings.put(Bayeux.CHANNEL_FIELD,Bayeux.CHANNEL_FIELD);
182         _fieldStrings.put(Bayeux.CLIENT_FIELD,Bayeux.CLIENT_FIELD);
183         _fieldStrings.put(Bayeux.DATA_FIELD,Bayeux.DATA_FIELD);
184         _fieldStrings.put(Bayeux.ERROR_FIELD,Bayeux.ERROR_FIELD);
185         _fieldStrings.put(Bayeux.EXT_FIELD,Bayeux.EXT_FIELD);
186         _fieldStrings.put(Bayeux.ID_FIELD,Bayeux.ID_FIELD);
187         _fieldStrings.put(Bayeux.SUBSCRIPTION_FIELD,Bayeux.SUBSCRIPTION_FIELD);
188         _fieldStrings.put(Bayeux.SUCCESSFUL_FIELD,Bayeux.SUCCESSFUL_FIELD);
189         _fieldStrings.put(Bayeux.TIMESTAMP_FIELD,Bayeux.TIMESTAMP_FIELD);
190         _fieldStrings.put(Bayeux.TRANSPORT_FIELD,Bayeux.TRANSPORT_FIELD);
191         _fieldStrings.put("connectionType","connectionType");
192         
193         _valueStrings.put(Bayeux.META_CLIENT,Bayeux.META_CLIENT);
194         _valueStrings.put(Bayeux.META_CONNECT,Bayeux.META_CONNECT);
195         _valueStrings.put(Bayeux.META_DISCONNECT,Bayeux.META_DISCONNECT);
196         _valueStrings.put(Bayeux.META_HANDSHAKE,Bayeux.META_HANDSHAKE);
197         _valueStrings.put(Bayeux.META_SUBSCRIBE,Bayeux.META_SUBSCRIBE);
198         _valueStrings.put(Bayeux.META_UNSUBSCRIBE,Bayeux.META_UNSUBSCRIBE);
199         _valueStrings.put("long-polling","long-polling");
200     }
201     
202 
203     /* ------------------------------------------------------------ */
204     /* ------------------------------------------------------------ */
205     private JSON _json = new JSON()
206     {
207         @Override
208         protected Map newMap()
209         {
210             return new HashMap(8);
211         }
212         
213         @Override
214         protected String toString(char[] buffer, int offset, int length)
215         {
216             Map.Entry entry = _valueStrings.getEntry(buffer,offset,length);
217             if (entry!=null)
218                 return (String)entry.getValue();
219             String s= new String(buffer,offset,length);
220             return s;
221         }
222     };
223 
224     /* ------------------------------------------------------------ */
225     /* ------------------------------------------------------------ */
226     private JSON _msgJSON = new JSON()
227     {
228         @Override
229         protected Map newMap()
230         {
231             return newMessage();
232         }
233 
234         @Override
235         protected String toString(char[] buffer, int offset, int length)
236         {
237             Map.Entry entry = _fieldStrings.getEntry(buffer,offset,length);
238             if (entry!=null)
239                 return (String)entry.getValue();
240             
241             String s= new String(buffer,offset,length);
242             return s;
243         }
244 
245         @Override
246         protected JSON contextFor(String field)
247         {
248             return _json;
249         }
250     };
251 
252     /* ------------------------------------------------------------ */
253     /* ------------------------------------------------------------ */
254     private JSON _batchJSON = new JSON()
255     {
256         @Override
257         protected Map newMap()
258         {
259             return newMessage();
260         }
261 
262         @Override
263         protected Object[] newArray(int size)
264         {
265             return new Message[size]; // todo recycle
266         }
267 
268         @Override
269         protected JSON contextFor(String field)
270         {
271             return _json;
272         }
273 
274         @Override
275         protected JSON contextForArray()
276         {
277             return _msgJSON;
278         }
279     };
280 
281 }