1 package org.mortbay.cometd.session;
2
3 import java.io.ByteArrayInputStream;
4 import java.util.Map;
5
6 import javax.servlet.ServletContextAttributeEvent;
7 import javax.servlet.ServletContextAttributeListener;
8 import javax.servlet.http.HttpServletRequest;
9
10 import org.mortbay.cometd.AbstractBayeux;
11 import org.mortbay.jetty.Request;
12 import org.mortbay.jetty.security.B64Code;
13 import org.mortbay.jetty.servlet.AbstractSessionManager;
14 import org.mortbay.jetty.servlet.HashSessionManager;
15 import org.mortbay.log.Log;
16 import org.mortbay.util.ByteArrayOutputStream2;
17
18 import dojox.cometd.Bayeux;
19 import dojox.cometd.Client;
20 import dojox.cometd.Extension;
21 import dojox.cometd.Message;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class BayeuxSessionManager extends HashSessionManager
38 {
39 public final static String BAYEUX_SESSION=Bayeux.SERVICE+"/ext/session";
40 AbstractBayeux _bayeux;
41 private String _secret="Really Private";
42
43
44 protected void initialize(Bayeux bayeux)
45 {
46 Log.info("Bayeux Session Manager initialized for "+_context.getContextPath());
47 _bayeux=(AbstractBayeux)bayeux;
48 _bayeux.setRequestAvailable(true);
49 _bayeux.addExtension(new SessionExt());
50 }
51
52
53 protected AbstractSessionManager.Session newSession(HttpServletRequest request)
54 {
55 return new BayeuxSession(request);
56 }
57
58
59 protected AbstractSessionManager.Session newSession(long created, String clusterId)
60 {
61 return new BayeuxSession(created,clusterId);
62 }
63
64
65
66
67
68 public void doStart() throws Exception
69 {
70 super.doStart();
71
72 _context.getContextHandler().addEventListener(new ServletContextAttributeListener(){
73
74 public void attributeAdded(ServletContextAttributeEvent scab)
75 {
76 if (scab.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX))
77 {
78 Bayeux bayeux=(Bayeux)scab.getValue();
79 initialize(bayeux);
80 }
81 }
82
83 public void attributeRemoved(ServletContextAttributeEvent scab)
84 {
85 }
86
87 public void attributeReplaced(ServletContextAttributeEvent scab)
88 {
89 }
90 });
91
92 }
93
94
95
96 protected class SessionExt implements Extension
97 {
98
99
100 public Message rcv(Message message)
101 {
102 return message;
103 }
104
105
106 public Message rcvMeta(Message message)
107 {
108 if (message.getChannel().equals(Bayeux.META_HANDSHAKE))
109 {
110 Map<String,?> ext = (Map<String,?>)message.get(Bayeux.EXT_FIELD);
111 String session=ext==null?null:(String)ext.get("session");
112 if (session!=null)
113 {
114 byte[] buf = B64Code.decode(session.toCharArray());
115
116 ByteArrayInputStream bin=new ByteArrayInputStream(buf);
117 try
118 {
119 Session s =restoreSession(bin);
120 ((BayeuxSession)s).access(System.currentTimeMillis());
121 ((Request)_bayeux.getCurrentRequest()).setSession(s);
122 String cid=message.getClientId();
123 Client client = _bayeux.getClient(cid);
124 ((BayeuxSession)s).setClient(client);
125 addSession(s);
126 Log.info("Restored session "+s.getId()+" for bayeux client "+cid);
127 }
128 catch(Exception e)
129 {
130 Log.warn(e);
131 }
132 }
133 }
134 return message;
135 }
136
137
138 public Message send(Message message)
139 {
140 return message;
141 }
142
143
144 public Message sendMeta(Message message)
145 {
146 if (message.getChannel().equals(Bayeux.META_HANDSHAKE))
147 {
148 String cid=message.getClientId();
149 Client client = _bayeux.getClient(cid);
150 ((BayeuxSession)_bayeux.getCurrentRequest().getSession(true)).setClient(client);
151 }
152 return message;
153 }
154
155 }
156
157
158 private Object encode(Object o, String valueSecret)
159 {
160 return null;
161 }
162
163
164 private Object decode(String value, String valueSecret)
165 {
166 return null;
167 }
168
169
170
171 protected class BayeuxSession extends HashSessionManager.Session
172 {
173 Client _client;
174 boolean _dirty;
175
176
177 protected BayeuxSession(HttpServletRequest request)
178 {
179 super(request);
180 }
181
182
183 public BayeuxSession(long created, String clusterId)
184 {
185 super(created,clusterId);
186 _dirty=true;
187 }
188
189
190 public void setClient(Client client)
191 {
192 _client=client;
193 }
194
195
196
197
198
199 protected void access(long time)
200 {
201 super.access(time);
202 }
203
204
205
206
207
208 public void invalidate() throws IllegalStateException
209 {
210 super.invalidate();
211 _dirty=true;
212 }
213
214
215
216
217
218 public synchronized void removeAttribute(String name)
219 {
220 super.removeAttribute(name);
221 _dirty=true;
222 }
223
224
225
226
227
228 public synchronized void setAttribute(String name, Object value)
229 {
230 super.setAttribute(name,value);
231 _dirty=true;
232 }
233
234
235
236
237
238 protected void complete()
239 {
240 super.complete();
241
242 if (_dirty && _client!=null)
243 {
244 _dirty=false;
245 Message message=_bayeux.newMessage();
246
247 ByteArrayOutputStream2 bout = new ByteArrayOutputStream2();
248 try
249 {
250 save(bout);
251
252
253 byte[] buf = bout.toByteArray();
254 String encoded=new String(B64Code.encode(buf));
255 message.put(Bayeux.DATA_FIELD,encoded);
256 }
257 catch(Exception e)
258 {
259 Log.warn(e);
260 }
261
262 _bayeux.deliver(_client,_client,BAYEUX_SESSION,message);
263 }
264 }
265 }
266 }