1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.cometd;
16
17 import java.io.FileNotFoundException;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.servlet.GenericServlet;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.Cookie;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.cometd.Bayeux;
34 import org.cometd.DataFilter;
35 import org.cometd.Message;
36 import org.mortbay.cometd.filter.JSONDataFilter;
37 import org.mortbay.log.Log;
38 import org.mortbay.util.ajax.JSON;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public abstract class AbstractCometdServlet extends GenericServlet
105 {
106 public static final String CLIENT_ATTR="org.mortbay.cometd.client";
107 public static final String TRANSPORT_ATTR="org.mortbay.cometd.transport";
108 public static final String MESSAGE_PARAM="message";
109 public static final String TUNNEL_INIT_PARAM="tunnelInit";
110 public static final String HTTP_CLIENT_ID="BAYEUX_HTTP_CLIENT";
111 public final static String BROWSER_ID="BAYEUX_BROWSER";
112
113 protected AbstractBayeux _bayeux;
114 public final static int __DEFAULT_REFS_THRESHOLD = 10;
115 protected int _refsThreshold=__DEFAULT_REFS_THRESHOLD;
116
117 public AbstractBayeux getBayeux()
118 {
119 return _bayeux;
120 }
121
122 protected abstract AbstractBayeux newBayeux();
123
124 @Override
125 public void init() throws ServletException
126 {
127 synchronized (AbstractCometdServlet.class)
128 {
129 _bayeux=(AbstractBayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX);
130 if (_bayeux==null)
131 {
132 _bayeux=newBayeux();
133 }
134 }
135
136 synchronized(_bayeux)
137 {
138 boolean was_initialized=_bayeux.isInitialized();
139 _bayeux.initialize(getServletContext());
140
141 if (!was_initialized)
142 {
143 String filters=getInitParameter("filters");
144 if (filters!=null)
145 {
146 try
147 {
148 InputStream is = getServletContext().getResourceAsStream(filters);
149 if (is==null)
150 throw new FileNotFoundException(filters);
151
152 Object[] objects=(Object[])JSON.parse(new InputStreamReader(getServletContext().getResourceAsStream(filters),"utf-8"));
153 for (int i=0; objects!=null&&i<objects.length; i++)
154 {
155 Map<?,?> filter_def=(Map<?,?>)objects[i];
156
157 String fc = (String)filter_def.get("class");
158 if (fc!=null)
159 Log.warn(filters+" file uses deprecated \"class\" name. Use \"filter\" instead");
160 else
161 fc=(String)filter_def.get("filter");
162 Class<?> c=Thread.currentThread().getContextClassLoader().loadClass(fc);
163 DataFilter filter=(DataFilter)c.newInstance();
164
165 if (filter instanceof JSONDataFilter)
166 ((JSONDataFilter)filter).init(filter_def.get("init"));
167
168 _bayeux.getChannel((String)filter_def.get("channels"),true).addDataFilter(filter);
169 }
170 }
171 catch (Exception e)
172 {
173 getServletContext().log("Could not parse: "+filters,e);
174 throw new ServletException(e);
175 }
176 }
177
178 String timeout=getInitParameter("timeout");
179 if (timeout!=null)
180 _bayeux.setTimeout(Long.parseLong(timeout));
181
182 String maxInterval=getInitParameter("maxInterval");
183 if (maxInterval!=null)
184 _bayeux.setMaxInterval(Long.parseLong(maxInterval));
185
186 String commentedJSON=getInitParameter("JSONCommented");
187 _bayeux.setJSONCommented(commentedJSON!=null && Boolean.parseBoolean(commentedJSON));
188
189 String l=getInitParameter("logLevel");
190 if (l!=null&&l.length()>0)
191 _bayeux.setLogLevel(Integer.parseInt(l));
192
193 String interval=getInitParameter("interval");
194 if (interval!=null)
195 _bayeux.setInterval(Long.parseLong(interval));
196
197 String mfInterval=getInitParameter("multiFrameInterval");
198 if (mfInterval!=null)
199 _bayeux.setMultiFrameInterval(Integer.parseInt(mfInterval));
200
201 String requestAvailable=getInitParameter("requestAvailable");
202 _bayeux.setRequestAvailable(requestAvailable!=null && Boolean.parseBoolean(requestAvailable));
203
204 String direct=getInitParameter("directDeliver");
205 if (direct!=null)
206 _bayeux.setDirectDeliver(Boolean.parseBoolean(direct));
207
208 String async=getInitParameter("asyncDeliver");
209 if (async!=null)
210 getServletContext().log("asyncDeliver no longer supported");
211
212 String refsThreshold=getInitParameter("refsThreshold");
213 if (refsThreshold!=null)
214 _refsThreshold=Integer.parseInt(refsThreshold);
215
216 _bayeux.generateAdvice();
217
218 if (_bayeux.isLogInfo())
219 {
220 getServletContext().log("timeout="+timeout);
221 getServletContext().log("interval="+interval);
222 getServletContext().log("maxInterval="+maxInterval);
223 getServletContext().log("multiFrameInterval="+mfInterval);
224 getServletContext().log("filters="+filters);
225 getServletContext().log("refsThreshold="+refsThreshold);
226 }
227 }
228 }
229
230 getServletContext().setAttribute(Bayeux.DOJOX_COMETD_BAYEUX,_bayeux);
231 }
232
233 protected abstract void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
234
235 @Override
236 public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException
237 {
238 HttpServletRequest request=(HttpServletRequest)req;
239 HttpServletResponse response=(HttpServletResponse)resp;
240
241 if (_bayeux.isRequestAvailable())
242 _bayeux.setCurrentRequest(request);
243 try
244 {
245 service(request,response);
246 }
247 finally
248 {
249 if (_bayeux.isRequestAvailable())
250 _bayeux.setCurrentRequest(null);
251 }
252 }
253
254
255 protected String browserId(HttpServletRequest request)
256 {
257 Cookie[] cookies = request.getCookies();
258 if (cookies!=null)
259 {
260 for (Cookie cookie : cookies)
261 {
262 if (BROWSER_ID.equals(cookie.getName()))
263 return cookie.getValue();
264 }
265 }
266
267 return null;
268 }
269
270 protected String newBrowserId(HttpServletRequest request,HttpServletResponse response)
271 {
272 String browser_id=Long.toHexString(request.getRemotePort())+
273 Long.toString(_bayeux.getRandom(),36)+
274 Long.toString(System.currentTimeMillis(),36)+
275 Long.toString(request.getRemotePort(),36);
276
277 Cookie cookie = new Cookie(BROWSER_ID,browser_id);
278 cookie.setPath("/");
279 cookie.setMaxAge(-1);
280 response.addCookie(cookie);
281 return browser_id;
282 }
283
284 private static Message[] __EMPTY_BATCH=new Message[0];
285
286 protected Message[] getMessages(HttpServletRequest request) throws IOException
287 {
288 String fodder=null;
289 try
290 {
291
292 if (request.getContentType() != null && !request.getContentType().startsWith("application/x-www-form-urlencoded"))
293 {
294 return _bayeux.parse(request.getReader());
295 }
296
297 String[] batches=request.getParameterValues(MESSAGE_PARAM);
298
299 if (batches==null || batches.length==0)
300 return __EMPTY_BATCH;
301
302 if (batches.length==0)
303 {
304 fodder=batches[0];
305 return _bayeux.parse(fodder);
306 }
307
308 List<Message> messages = new ArrayList<Message>();
309 for (int i=0;i<batches.length;i++)
310 {
311 if (batches[i]==null)
312 continue;
313
314 fodder=batches[i];
315 _bayeux.parseTo(fodder,messages);
316 }
317
318 return messages.toArray(new Message[messages.size()]);
319 }
320 catch(IOException e)
321 {
322 throw e;
323 }
324 catch(Exception e)
325 {
326 throw new Error(fodder,e);
327 }
328 }
329
330 }