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 java.io.IOException;
23 import java.io.ObjectStreamException;
24 import java.io.Serializable;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.myfaces.orchestra.FactoryFinder;
33 import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
34 import org.apache.myfaces.orchestra.lib.OrchestraException;
35 import org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterProviderManager;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class ConversationManager implements Serializable
56 {
57 private static final long serialVersionUID = 1L;
58
59 final static String CONVERSATION_CONTEXT_PARAM = "conversationContext";
60
61 private final static String CONVERSATION_MANAGER_KEY = "org.apache.myfaces.ConversationManager";
62 private final static String CONVERSATION_CONTEXT_REQ = "org.apache.myfaces.ConversationManager.conversationContext";
63
64 private static final Iterator EMPTY_ITERATOR = Collections.EMPTY_LIST.iterator();
65
66 private final Log log = LogFactory.getLog(ConversationManager.class);
67
68
69
70
71
72
73
74
75 private long nextConversationContextId = 1;
76
77
78
79 private final Map conversationContexts = new HashMap();
80
81 protected ConversationManager()
82 {
83 }
84
85
86
87
88
89
90
91
92
93
94 public static ConversationManager getInstance()
95 {
96 return getInstance(true);
97 }
98
99
100
101
102
103
104
105
106
107 public static ConversationManager getInstance(boolean create)
108 {
109 FrameworkAdapter frameworkAdapter = FrameworkAdapter.getCurrentInstance();
110 if (frameworkAdapter == null)
111 {
112 if (!create)
113 {
114
115
116 return null;
117 }
118 else
119 {
120 throw new IllegalStateException("FrameworkAdapter not found");
121 }
122 }
123
124 ConversationManager conversationManager = (ConversationManager) frameworkAdapter.getSessionAttribute(
125 CONVERSATION_MANAGER_KEY);
126 if (conversationManager == null && create)
127 {
128 conversationManager = FactoryFinder.getConversationManagerFactory().createConversationManager();
129
130
131 RequestParameterProviderManager.getInstance().register(new ConversationRequestParameterProvider());
132
133
134 FrameworkAdapter.getCurrentInstance().setSessionAttribute(CONVERSATION_MANAGER_KEY, conversationManager);
135 }
136
137 return conversationManager;
138 }
139
140
141
142
143
144
145 private Long findConversationContextId()
146 {
147 FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
148
149
150 Long conversationContextId = (Long)fa.getRequestAttribute(CONVERSATION_CONTEXT_REQ);
151 if (conversationContextId == null)
152 {
153 if (fa.containsRequestParameterAttribute(CONVERSATION_CONTEXT_PARAM))
154 {
155 String urlConversationContextId = fa.getRequestParameterAttribute(
156 CONVERSATION_CONTEXT_PARAM).toString();
157 conversationContextId = new Long(
158 Long.parseLong(urlConversationContextId, Character.MAX_RADIX));
159 }
160 }
161 return conversationContextId;
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 private Long getOrCreateConversationContextId()
182 {
183 Long conversationContextId = findConversationContextId();
184 if (conversationContextId == null)
185 {
186 conversationContextId = createNextConversationContextId();
187 FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
188 fa.setRequestAttribute(CONVERSATION_CONTEXT_REQ, conversationContextId);
189 }
190
191 return conversationContextId;
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 public Long getConversationContextId()
214 {
215 return getOrCreateConversationContextId();
216 }
217
218
219
220
221
222
223
224
225 private Long createNextConversationContextId()
226 {
227 Long conversationContextId;
228 synchronized(this)
229 {
230 conversationContextId = new Long(nextConversationContextId);
231 nextConversationContextId++;
232 }
233 return conversationContextId;
234 }
235
236
237
238
239
240
241
242
243
244
245 public ConversationContext getConversationContext(Long conversationContextId)
246 {
247 synchronized (this)
248 {
249 return (ConversationContext) conversationContexts.get(conversationContextId);
250 }
251 }
252
253
254
255
256
257
258
259
260
261
262 protected ConversationContext getOrCreateConversationContext(Long conversationContextId)
263 {
264 synchronized (this)
265 {
266 ConversationContext conversationContext = (ConversationContext) conversationContexts.get(
267 conversationContextId);
268 if (conversationContext == null)
269 {
270 ConversationContextFactory factory = FactoryFinder.getConversationContextFactory();
271 conversationContext = factory.createConversationContext(null, conversationContextId.longValue());
272 conversationContexts.put(conversationContextId, conversationContext);
273
274
275
276 log.debug("Created context " + conversationContextId);
277 }
278 return conversationContext;
279 }
280 }
281
282
283
284
285
286
287
288
289
290 public ConversationContext createConversationContext(ConversationContext parent)
291 {
292 Long ctxId = createNextConversationContextId();
293 ConversationContextFactory factory = FactoryFinder.getConversationContextFactory();
294 ConversationContext ctx = factory.createConversationContext(parent, ctxId.longValue());
295
296 synchronized(this)
297 {
298 conversationContexts.put(ctxId, ctx);
299 }
300
301 return ctx;
302 }
303
304
305
306
307
308
309
310
311
312 public void activateConversationContext(ConversationContext ctx)
313 {
314 FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
315 fa.setRequestAttribute(CONVERSATION_CONTEXT_REQ, ctx.getIdAsLong());
316 }
317
318
319
320
321 public void clearCurrentConversationContext()
322 {
323 Long conversationContextId = findConversationContextId();
324 if (conversationContextId != null)
325 {
326 ConversationContext conversationContext = getConversationContext(conversationContextId);
327 if (conversationContext != null)
328 {
329 conversationContext.invalidate();
330 }
331 }
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 public void removeAndInvalidateConversationContext(ConversationContext context)
349 {
350 if (context.hasChildren())
351 {
352 throw new OrchestraException("Cannot remove context with children");
353 }
354
355 if (context.getIdAsLong().equals(findConversationContextId()))
356 {
357 throw new OrchestraException("Cannot remove current context");
358 }
359
360 synchronized(conversationContexts)
361 {
362 conversationContexts.remove(context.getIdAsLong());
363 }
364
365 ConversationContext parent = context.getParent();
366 if (parent != null)
367 {
368 parent.removeChild(context);
369 }
370
371 context.invalidate();
372
373
374
375
376
377
378
379
380
381
382
383 }
384
385
386
387
388
389
390
391
392
393 protected void removeConversationContext(Long conversationContextId)
394 {
395 synchronized (this)
396 {
397 conversationContexts.remove(conversationContextId);
398 }
399 }
400
401
402
403
404
405
406 public Conversation startConversation(String name, ConversationFactory factory)
407 {
408 ConversationContext conversationContext = getOrCreateCurrentConversationContext();
409 return conversationContext.startConversation(name, factory);
410 }
411
412
413
414
415
416
417
418
419 protected void removeConversation(String name)
420 {
421 Long conversationContextId = findConversationContextId();
422 if (conversationContextId != null)
423 {
424 ConversationContext conversationContext = getConversationContext(conversationContextId);
425 if (conversationContext != null)
426 {
427 conversationContext.removeConversation(name);
428 }
429 }
430 }
431
432
433
434
435
436
437 public Conversation getConversation(String name)
438 {
439 ConversationContext conversationContext = getCurrentConversationContext();
440 if (conversationContext == null)
441 {
442 return null;
443 }
444 return conversationContext.getConversation(name);
445 }
446
447
448
449
450 public boolean hasConversation(String name)
451 {
452 ConversationContext conversationContext = getCurrentConversationContext();
453 if (conversationContext == null)
454 {
455 return false;
456 }
457 return conversationContext.hasConversation(name);
458 }
459
460
461
462
463
464 public Iterator iterateConversations()
465 {
466 ConversationContext conversationContext = getCurrentConversationContext();
467 if (conversationContext == null)
468 {
469 return EMPTY_ITERATOR;
470 }
471
472 return conversationContext.iterateConversations();
473 }
474
475
476
477
478
479
480
481
482
483
484 public ConversationContext getCurrentConversationContext()
485 {
486 Long ccid = findConversationContextId();
487 if (ccid == null)
488 {
489 return null;
490 }
491 else
492 {
493 ConversationContext ctx = getConversationContext(ccid);
494 if (ctx == null)
495 {
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515 log.warn("ConversationContextId specified but context does not exist");
516 synchronized(this)
517 {
518 if (nextConversationContextId <= ccid.longValue())
519 {
520 nextConversationContextId = ccid.longValue() + 1;
521 }
522 }
523 return null;
524 }
525 return ctx;
526 }
527 }
528
529
530
531
532
533
534
535
536
537
538
539
540 ConversationContext getOrCreateCurrentConversationContext()
541 {
542 Long ccid = getOrCreateConversationContextId();
543 return getOrCreateConversationContext(ccid);
544 }
545
546
547
548
549
550 public boolean hasConversationContext()
551 {
552 return getCurrentConversationContext() == null;
553 }
554
555
556
557
558
559
560
561
562 public ConversationContext getCurrentRootConversationContext()
563 {
564 Long ccid = findConversationContextId();
565 if (ccid == null)
566 {
567 return null;
568 }
569
570 synchronized (this)
571 {
572 ConversationContext conversationContext = getConversationContext(ccid);
573 if (conversationContext == null)
574 {
575 return null;
576 }
577 else
578 {
579 return conversationContext.getRoot();
580 }
581 }
582 }
583
584
585
586
587
588
589
590 public ConversationMessager getMessager()
591 {
592 return FrameworkAdapter.getCurrentInstance().getConversationMessager();
593 }
594
595
596
597
598
599
600
601
602
603
604
605 protected void checkTimeouts()
606 {
607 Map.Entry[] contexts;
608 synchronized (this)
609 {
610 contexts = new Map.Entry[conversationContexts.size()];
611 conversationContexts.entrySet().toArray(contexts);
612 }
613
614 long checkTime = System.currentTimeMillis();
615
616 for (int i = 0; i<contexts.length; i++)
617 {
618 Map.Entry context = contexts[i];
619
620 ConversationContext conversationContext = (ConversationContext) context.getValue();
621 if (conversationContext.hasChildren())
622 {
623
624 continue;
625 }
626
627 conversationContext.checkConversationTimeout();
628
629 if (conversationContext.getTimeout() > -1 &&
630 (conversationContext.getLastAccess() +
631 conversationContext.getTimeout()) < checkTime)
632 {
633 if (log.isDebugEnabled())
634 {
635 log.debug("end conversation context due to timeout: " + conversationContext.getId());
636 }
637
638 removeAndInvalidateConversationContext(conversationContext);
639 }
640 }
641 }
642
643 private void writeObject(java.io.ObjectOutputStream out) throws IOException
644 {
645
646
647 }
648
649 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
650 {
651
652 }
653
654 private Object readResolve() throws ObjectStreamException
655 {
656
657
658
659
660 return FactoryFinder.getConversationManagerFactory().createConversationManager();
661 }
662 }