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