1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.statelessfilter.wrappers;
17
18 import java.io.IOException;
19 import java.security.NoSuchAlgorithmException;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletRequestWrapper;
27 import javax.servlet.http.HttpServletResponse;
28 import javax.servlet.http.HttpSession;
29
30 import net.sourceforge.statelessfilter.backend.ISessionBackend;
31 import net.sourceforge.statelessfilter.backend.ISessionData;
32 import net.sourceforge.statelessfilter.filter.Configuration;
33 import net.sourceforge.statelessfilter.session.SessionData;
34 import net.sourceforge.statelessfilter.session.StatelessSession;
35
36 import org.apache.commons.lang.StringUtils;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43
44
45
46 public class StatelessRequestWrapper extends HttpServletRequestWrapper {
47 private static final String INFO_USES = "{} uses {}";
48 private static final String INFO_USES_DEFAULT = "{} uses default {}";
49
50 Configuration backends = null;
51 Logger logger = LoggerFactory.getLogger(StatelessRequestWrapper.class);
52 HttpServletRequest originalRequest = null;
53
54 StatelessSession session = null;
55
56 private boolean sessionWritten;
57
58 public boolean isSessionWritten() {
59 return sessionWritten;
60 }
61
62
63
64
65
66
67
68 public StatelessRequestWrapper(HttpServletRequest request,
69 Configuration backends) {
70 super(request);
71 originalRequest = request;
72 this.backends = backends;
73 }
74
75
76
77
78
79
80
81
82
83
84
85 public HttpSession getServerSession() {
86 return super.getSession();
87 }
88
89
90
91
92
93
94
95
96 @Override
97 public HttpSession getSession() {
98 if (session == null) {
99 try {
100 session = createSession();
101 } catch (NoSuchAlgorithmException e) {
102 throw new RuntimeException(e);
103 }
104 }
105 return session;
106 }
107
108
109
110
111
112
113 @Override
114 public HttpSession getSession(boolean create) {
115 if (create) {
116 return getSession();
117 }
118
119 if (session == null) {
120 try {
121 session = restoreSession();
122 } catch (NoSuchAlgorithmException e) {
123 throw new RuntimeException(e);
124 }
125 }
126
127 return session;
128 }
129
130
131
132
133
134
135
136
137 public void writeSession(HttpServletRequest myrequest,
138 HttpServletResponse myresponse) throws IOException {
139
140
141 if (session != null) {
142
143
144 if (backends.useDirty && !session.isDirty()) {
145 if (logger.isDebugEnabled()) {
146 logger.debug("Session has not changed.");
147 }
148 return;
149 }
150
151 long requestId = System.currentTimeMillis();
152 session.setNew(false);
153
154
155
156
157 Map<String, Object> sessionAttributes = session.getContent();
158
159 List<String> modifiedAttributes = session.getDirtyAttributes();
160
161
162 List<String> modifiedBackends = new ArrayList<String>();
163
164
165 List<String> remainingModifiedAttributes = new ArrayList<String>(
166 modifiedAttributes);
167
168 Map<String, ISessionData> attributesDispatched = new HashMap<String, ISessionData>();
169 Map<String, List<String>> modifiedAttributesDispatched = new HashMap<String, List<String>>();
170
171 for (String name : sessionAttributes.keySet()) {
172 if (isAttributeMapped(name)) {
173 getBackendSessionData(attributesDispatched,
174 backends.backendsAttributeMapping.get(name),
175 requestId).getContent().put(name,
176 sessionAttributes.get(name));
177
178 setModified(modifiedBackends, modifiedAttributes, name);
179
180 logger.info(INFO_USES, name,
181 backends.backendsAttributeMapping.get(name));
182
183 } else {
184 getBackendSessionData(attributesDispatched,
185 backends.defaultBackend, requestId).getContent()
186 .put(name, sessionAttributes.get(name));
187
188 setModified(modifiedBackends, modifiedAttributes, name);
189 logger.info(INFO_USES_DEFAULT, name,
190 backends.defaultBackend);
191
192 }
193
194
195 remainingModifiedAttributes.remove(name);
196 }
197
198
199 for (String name : remainingModifiedAttributes) {
200 if (isAttributeMapped(name)) {
201 setModified(modifiedBackends, modifiedAttributes, name);
202 logger.info(INFO_USES, name,
203 backends.backendsAttributeMapping.get(name));
204 } else {
205 setModified(modifiedBackends, modifiedAttributes, name);
206 logger.info(INFO_USES_DEFAULT, name,
207 backends.defaultBackend);
208 }
209 }
210
211 if (session.isPropertyDirty()) {
212
213 logger.info("Session properties have changed. Forcing update on all backends.");
214
215 for (String back : backends.backends.keySet()) {
216 ISessionBackend backend = backends.backends.get(back);
217 backend.save(
218 getBackendSessionData(attributesDispatched, back,
219 requestId), modifiedAttributesDispatched
220 .get(back), originalRequest, myresponse);
221 }
222 } else {
223
224 for (String back : modifiedBackends) {
225 ISessionBackend backend = backends.backends.get(back);
226 backend.save(
227 getBackendSessionData(attributesDispatched, back,
228 requestId), modifiedAttributesDispatched
229 .get(back), originalRequest, myresponse);
230 }
231 }
232 }
233
234 sessionWritten = true;
235 }
236
237
238
239
240
241
242
243 private StatelessSession createSession() throws NoSuchAlgorithmException {
244
245 StatelessSession s = restoreSession();
246
247 if (s == null) {
248 s = new StatelessSession(this);
249 s.init(true);
250 }
251
252 return s;
253 }
254
255
256
257
258
259
260
261
262
263
264 private ISessionData getBackendSessionData(
265 Map<String, ISessionData> dispatched, String name, long requestId) {
266
267 if (dispatched.containsKey(name)) {
268 return dispatched.get(name);
269 }
270
271 SessionData data = new SessionData();
272 data.setId(session.getId());
273 data.setCreationTime(session.getCreationTime());
274 data.setValid(session.isValid());
275 data.setRequestId(requestId);
276 dispatched.put(name, data);
277 return data;
278 }
279
280
281
282
283
284
285
286
287
288
289 private boolean isAttributeMapped(String attrName) {
290 if (backends != null && backends.backendsAttributeMapping != null) {
291 return backends.backendsAttributeMapping.containsKey(attrName);
292 }
293
294 return false;
295 }
296
297 private StatelessSession restoreSession() throws NoSuchAlgorithmException {
298 StatelessSession s = new StatelessSession(this);
299 ISessionData data = null;
300 boolean restored = false;
301
302
303 s.init(false);
304 for (ISessionBackend back : backends.backends.values()) {
305 data = back.restore(originalRequest);
306
307
308 if (data != null) {
309 restored = true;
310 s.merge(data);
311 }
312 }
313
314
315 if (!restored) {
316 return null;
317 }
318 return s;
319 }
320
321
322
323
324
325
326
327
328
329 private void setModified(List<String> modifiedBackends,
330 List<String> modifiedAttributes, String attributeName) {
331 String backend = backends.backendsAttributeMapping.get(attributeName);
332
333 if (StringUtils.isEmpty(backend)) {
334 backend = backends.defaultBackend;
335 }
336
337 if (modifiedAttributes.contains(attributeName)
338 && !modifiedBackends.contains(backend)) {
339
340 modifiedBackends.add(backend);
341
342 if (logger.isDebugEnabled()) {
343 logger.info("Flagging backend {} as modified", backend);
344 }
345 }
346 }
347 }