1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.orchestra.conversation;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.myfaces.orchestra.lib._ReentrantLock;
25
26 import java.util.Arrays;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.TreeMap;
30
31
32
33
34
35
36
37
38
39
40
41 public class ConversationContext
42 {
43 private final Log log = LogFactory.getLog(ConversationContext.class);
44
45
46
47
48
49
50
51
52
53 private final Long id;
54
55
56 private final Map attributes = new TreeMap();
57
58
59 private final ConversationContext parent;
60
61
62 private final Map conversations = new TreeMap();
63
64
65
66
67 private String name;
68
69
70 private long lastAccess;
71
72
73 private long timeoutMillis = 30 * 60 * 1000;
74
75 private final _ReentrantLock lock = new _ReentrantLock();
76
77
78
79
80 protected ConversationContext(long id)
81 {
82 this(null, id);
83 }
84
85
86
87
88
89
90 protected ConversationContext(ConversationContext parent, long id)
91 {
92 this.parent = parent;
93 this.id = Long.valueOf(id);
94
95 touch();
96 }
97
98
99
100
101
102
103 public String getName()
104 {
105 return name;
106 }
107
108
109
110
111
112
113 public void setName(String name)
114 {
115 this.name = name;
116 }
117
118
119
120
121 public long getId()
122 {
123 return id.longValue();
124 }
125
126
127
128
129 public Long getIdAsLong()
130 {
131 return id;
132 }
133
134
135
136
137
138
139 public ConversationContext getParent()
140 {
141 return parent;
142 }
143
144
145
146
147 protected void touch()
148 {
149 lastAccess = System.currentTimeMillis();
150
151 if (getParent() != null)
152 {
153 getParent().touch();
154 }
155 }
156
157
158
159
160 public long getLastAccess()
161 {
162 return lastAccess;
163 }
164
165
166
167
168
169
170 public long getTimeout()
171 {
172 return timeoutMillis;
173 }
174
175
176
177
178
179
180 public void setTimeout(long timeoutMillis)
181 {
182 this.timeoutMillis = timeoutMillis;
183 }
184
185
186
187
188 protected void clear()
189 {
190 synchronized (this)
191 {
192 Conversation[] convArray = new Conversation[conversations.size()];
193 conversations.values().toArray(convArray);
194
195 for (int i = 0; i < convArray.length; i++)
196 {
197 Conversation conversation = convArray[i];
198 conversation.invalidate();
199 }
200
201 conversations.clear();
202 }
203 }
204
205
206
207
208 protected Conversation startConversation(String name, ConversationFactory factory)
209 {
210 synchronized (this)
211 {
212 touch();
213 Conversation conversation = (Conversation) conversations.get(name);
214 if (conversation == null)
215 {
216 conversation = factory.createConversation(this, name);
217
218 conversations.put(name, conversation);
219 }
220 return conversation;
221 }
222 }
223
224
225
226
227
228
229 protected void removeConversation(Conversation conversation)
230 {
231 synchronized (this)
232 {
233 touch();
234 conversations.remove(conversation.getName());
235 }
236 }
237
238
239
240
241
242
243 protected void removeConversation(String name)
244 {
245 synchronized (this)
246 {
247 touch();
248 Conversation conversation = (Conversation) conversations.get(name);
249 if (conversation != null)
250 {
251 removeConversation(conversation);
252 }
253 }
254 }
255
256
257
258
259 protected boolean hasConversations()
260 {
261 synchronized (this)
262 {
263 touch();
264 return conversations.size() > 0;
265 }
266 }
267
268
269
270
271 protected boolean hasConversation(String name)
272 {
273 synchronized (this)
274 {
275 touch();
276 return conversations.get(name) != null;
277 }
278 }
279
280
281
282
283 protected Conversation getConversation(String name)
284 {
285 synchronized (this)
286 {
287 touch();
288
289 Conversation conv = (Conversation) conversations.get(name);
290 if (conv != null)
291 {
292 conv.touch();
293 }
294
295 return conv;
296 }
297 }
298
299
300
301
302
303
304
305 public Iterator iterateConversations()
306 {
307 synchronized (this)
308 {
309 touch();
310
311 Conversation[] convs = (Conversation[]) conversations.values().toArray(
312 new Conversation[conversations.size()]);
313 return Arrays.asList(convs).iterator();
314 }
315 }
316
317
318
319
320
321
322 protected void checkConversationTimeout()
323 {
324 synchronized (this)
325 {
326 Conversation[] convArray = new Conversation[conversations.size()];
327 conversations.values().toArray(convArray);
328
329 for (int i = 0; i < convArray.length; i++)
330 {
331 Conversation conversation = convArray[i];
332
333 ConversationTimeoutableAspect timeoutAspect =
334 (ConversationTimeoutableAspect)
335 conversation.getAspect(ConversationTimeoutableAspect.class);
336
337 if (timeoutAspect != null && timeoutAspect.isTimeoutReached())
338 {
339 if (log.isDebugEnabled())
340 {
341 log.debug("end conversation due to timeout: " + conversation.getName());
342 }
343
344 conversation.invalidate();
345 }
346 }
347 }
348 }
349
350
351
352
353
354
355
356 public void setAttribute(String name, Object attribute)
357 {
358 synchronized(attributes)
359 {
360 attributes.remove(name);
361 attributes.put(name, attribute);
362 }
363 }
364
365
366
367
368 public boolean hasAttribute(String name)
369 {
370 synchronized(attributes)
371 {
372 return attributes.containsKey(name);
373 }
374 }
375
376
377
378
379 public Object getAttribute(String name)
380 {
381 synchronized(attributes)
382 {
383 return attributes.get(name);
384 }
385 }
386
387
388
389
390 public Object removeAttribute(String name)
391 {
392 synchronized(attributes)
393 {
394 return attributes.remove(name);
395 }
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 public void lockInterruptablyForCurrentThread() throws InterruptedException
414 {
415 if (log.isDebugEnabled())
416 {
417 log.debug("Locking context " + this.id);
418 }
419 lock.lockInterruptibly();
420 }
421
422
423
424
425
426
427
428
429
430
431 public void unlockForCurrentThread()
432 {
433 if (log.isDebugEnabled())
434 {
435 log.debug("Unlocking context " + this.id);
436 }
437 lock.unlock();
438 }
439
440
441
442
443
444
445 public boolean isLockedForCurrentThread()
446 {
447 return lock.isHeldByCurrentThread();
448 }
449
450
451
452
453
454
455
456
457
458
459 public ConversationContext getRoot()
460 {
461 ConversationContext cctx = this;
462 while (cctx != null && cctx.getParent() != null)
463 {
464 cctx = getParent();
465 }
466
467 return cctx;
468 }
469 }