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