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