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
37
38 public JSON getJSON()
39 {
40 return _json;
41 }
42
43
44
45
46
47 public void setJSON(JSON json)
48 {
49 _json=json;
50 }
51
52
53
54
55
56 public JSON getMsgJSON()
57 {
58 return _msgJSON;
59 }
60
61
62
63
64
65 public void setMsgJSON(JSON msgJSON)
66 {
67 _msgJSON=msgJSON;
68 }
69
70
71
72
73
74 public JSON getBatchJSON()
75 {
76 return _batchJSON;
77 }
78
79
80
81
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];
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 }