1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.conversation;
20
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.io.Serializable;
25 import java.io.IOException;
26 import java.io.ObjectStreamException;
27
28 import javax.faces.FacesException;
29 import javax.faces.context.FacesContext;
30 import javax.servlet.http.HttpSession;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.myfaces.custom.requestParameterProvider.RequestParameterProviderManager;
35 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
36
37
38
39
40
41
42
43 public class ConversationManager implements Serializable
44 {
45 private final static Log log = LogFactory.getLog(ConversationManager.class);
46
47 public final static String CONVERSATION_CONTEXT_PARAM = "conversationContext";
48
49 private final static String INIT_PERSISTENCE_MANAGER_FACOTRY = "org.apache.myfaces.conversation.PERSISTENCE_MANAGER_FACTORY";
50 private final static String INIT_MESSAGER = "org.apache.myfaces.conversation.MESSAGER";
51 private final static String INIT_BEAN_ELEVATOR = "org.apache.myfaces.conversation.BEAN_ELEVATOR";
52
53 private final static String CONVERSATION_MANAGER_KEY = "org.apache.myfaces.ConversationManager";
54 private final static String CONVERSATION_CONTEXT_REQ = "org.apache.myfaces.ConversationManager.conversationContext";
55
56 private static long NEXT_CONVERSATION_CONTEXT = 1;
57
58 private PersistenceManagerFactory persistenceManagerFactory;
59 private ConversationMessager conversationMessager;
60 private ConversationBeanElevator conversationBeanElevator;
61
62 private final Map conversationContexts = new HashMap();
63
64
65
66 private class ContextWiperThread extends Thread
67 {
68 private final static long CHECK_TIME = 5 * 60 * 1000;
69 public ContextWiperThread()
70 {
71 setDaemon(true);
72 setName("ConversationManager.ContextWiperThread");
73 }
74
75 public void run()
76 {
77 while (!isInterrupted())
78 {
79 checkContextTimeout();
80
81 try
82 {
83 Thread.sleep(CHECK_TIME);
84 }
85 catch (InterruptedException e)
86 {
87 log.warn(e.getLocalizedMessage(), e);
88 }
89 }
90 }
91 }
92 private ContextWiperThread wiperThread = new ContextWiperThread();
93
94 protected ConversationManager()
95 {
96 wiperThread.start();
97 }
98
99
100
101
102 public static ConversationManager getInstance()
103 {
104 FacesContext context = FacesContext.getCurrentInstance();
105 if (context == null)
106 {
107
108 ConversationManager cm = ConversationServletFilter.getConversationManager();
109 if (cm != null)
110 {
111 return cm;
112 }
113
114 throw new IllegalStateException("no faces context available");
115 }
116 return getInstance(context);
117 }
118
119
120
121
122 public static ConversationManager getInstance(FacesContext context)
123 {
124 ConversationManager conversationManager = (ConversationManager) context.getExternalContext().getSessionMap().get(CONVERSATION_MANAGER_KEY);
125 if (conversationManager == null)
126 {
127 if (!Boolean.TRUE.equals(context.getExternalContext().getRequestMap().get(ConversationServletFilter.CONVERSATION_FILTER_CALLED)))
128 {
129 throw new IllegalStateException("ConversationServletFilter not called. Please configure the filter org.apache.myfaces.custom.conversation.ConversationServletFilter in your web.xml to cover your faces requests.");
130 }
131
132 conversationManager = createConversationManager();
133
134
135 RequestParameterProviderManager.getInstance(context).register(new ConversationRequestParameterProvider());
136
137
138 context.getExternalContext().getSessionMap().put(CONVERSATION_MANAGER_KEY, conversationManager);
139 }
140
141 return conversationManager;
142 }
143
144 protected static ConversationManager createConversationManager()
145 {
146 ConversationManager conversationManager;
147
148
149 conversationManager = new ConversationManager();
150
151
152 conversationManager.createMessager();
153
154
155 conversationManager.createBeanElevator();
156
157 return conversationManager;
158 }
159
160
161
162
163 public static ConversationManager getInstance(HttpSession session)
164 {
165 if (session == null)
166 {
167 return null;
168 }
169 return (ConversationManager) session.getAttribute(CONVERSATION_MANAGER_KEY);
170 }
171
172
173
174
175
176
177 protected Long getConversationContextId()
178 {
179 Map requestMap;
180 Map requestParameterMap;
181
182 FacesContext context = FacesContext.getCurrentInstance();
183 if (context != null)
184 {
185 requestMap = context.getExternalContext().getRequestMap();
186 requestParameterMap = context.getExternalContext().getRequestParameterMap();
187 }
188 else
189 {
190 ConversationExternalContext ccontext = ConversationServletFilter.getConversationExternalContext();
191 if (ccontext != null)
192 {
193 requestMap = ccontext.getRequestMap();
194 requestParameterMap = ccontext.getRequestParameterMap();
195 }
196 else
197 {
198 throw new IllegalStateException("cant find a requestMap or requestParameterMap");
199 }
200 }
201
202 Long conversationContextId = (Long) requestMap.get(CONVERSATION_CONTEXT_REQ);
203 if (conversationContextId == null)
204 {
205 if (requestParameterMap.containsKey(CONVERSATION_CONTEXT_PARAM))
206 {
207 String urlConversationContextId = requestParameterMap.get(CONVERSATION_CONTEXT_PARAM).toString();
208 conversationContextId = new Long(Long.parseLong(urlConversationContextId, Character.MAX_RADIX));
209 }
210 else
211 {
212 synchronized (ConversationManager.class)
213 {
214 conversationContextId = new Long(NEXT_CONVERSATION_CONTEXT);
215 NEXT_CONVERSATION_CONTEXT++;
216 }
217 }
218
219 requestMap.put(CONVERSATION_CONTEXT_REQ, conversationContextId);
220 }
221
222 return conversationContextId;
223 }
224
225
226
227
228 protected ConversationContext getConversationContext(Long conversationContextId)
229 {
230 synchronized (conversationContexts)
231 {
232 return (ConversationContext) conversationContexts.get(conversationContextId);
233 }
234 }
235
236
237
238
239
240 protected ConversationContext getOrCreateConversationContext(Long conversationContextId)
241 {
242 synchronized (conversationContexts)
243 {
244 ConversationContext conversationContext = (ConversationContext) conversationContexts.get(conversationContextId);
245 if (conversationContext == null)
246 {
247 conversationContext = new ConversationContext(conversationContextId.longValue());
248 conversationContexts.put(conversationContextId, conversationContext);
249 }
250
251 return conversationContext;
252 }
253 }
254
255
256
257
258 protected void destroyConversationContext(Long conversationContextId)
259 {
260 synchronized (conversationContexts)
261 {
262 conversationContexts.remove(conversationContextId);
263 }
264 }
265
266
267
268
269
270 public void startConversation(String name, boolean persistence)
271 {
272 Long conversationContextId = getConversationContextId();
273 ConversationContext conversationContext = getOrCreateConversationContext(conversationContextId);
274 conversationContext.startConversation(name, persistence);
275 }
276
277
278
279
280
281 public void endConversation(String name, boolean regularEnd)
282 {
283 Long conversationContextId = getConversationContextId();
284 ConversationContext conversationContext = getConversationContext(conversationContextId);
285 if (conversationContext != null)
286 {
287 conversationContext.endConversation(name, regularEnd);
288
289 if (!conversationContext.hasConversations())
290 {
291 destroyConversationContext(conversationContextId);
292 }
293 }
294 }
295
296
297
298
299
300
301 public Conversation getConversation(String name)
302 {
303 ConversationContext conversationContext = getConversationContext();
304 if (conversationContext == null)
305 {
306 return null;
307 }
308 return conversationContext.getConversation(name);
309 }
310
311
312
313
314
315
316 public Conversation findConversation(Object instance)
317 {
318 ConversationContext conversationContext = getConversationContext();
319 if (conversationContext == null)
320 {
321 return null;
322 }
323 return conversationContext.findConversation(instance);
324 }
325
326
327
328
329 public boolean hasConversation(String name)
330 {
331 ConversationContext conversationContext = getConversationContext();
332 if (conversationContext == null)
333 {
334 return false;
335 }
336 return conversationContext.hasConversation(name);
337 }
338
339
340
341
342
343 protected ConversationContext getConversationContext()
344 {
345 Long conversationContextId = getConversationContextId();
346 ConversationContext conversationContext = getConversationContext(conversationContextId);
347 return conversationContext;
348 }
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372 public boolean hasConversationContext()
373 {
374 FacesContext context = FacesContext.getCurrentInstance();
375
376 return
377 (context.getExternalContext().getRequestMap().containsKey(CONVERSATION_CONTEXT_REQ) ||
378 context.getExternalContext().getRequestParameterMap().containsKey(CONVERSATION_CONTEXT_PARAM)) &&
379 getConversationContext() != null;
380 }
381
382
383
384
385 public PersistenceManager getPersistenceManager()
386 {
387 ConversationContext conversationContext = getConversationContext();
388 if (conversationContext == null)
389 {
390 return null;
391 }
392
393 return conversationContext.getPersistenceManager();
394 }
395
396
397
398
399 protected PersistenceManager createPersistenceManager()
400 {
401 return getPersistenceManagerFactory().create();
402 }
403
404
405
406
407
408
409 protected ConversationMessager getMessager()
410 {
411 return conversationMessager;
412 }
413
414
415
416
417
418
419 protected void createMessager()
420 {
421 String conversationMessagerName = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(INIT_MESSAGER);
422 if (conversationMessagerName == null)
423 {
424 conversationMessager = new DefaultConversationMessager();
425 }
426 else
427 {
428 try
429 {
430 conversationMessager = (ConversationMessager) ClassUtils.classForName(conversationMessagerName).newInstance();
431 }
432 catch (InstantiationException e)
433 {
434 throw new FacesException("error creating messager: " + conversationMessagerName, e);
435 }
436 catch (IllegalAccessException e)
437 {
438 throw new FacesException("error creating messager: " + conversationMessagerName, e);
439 }
440 catch (ClassNotFoundException e)
441 {
442 throw new FacesException("error creating messager: " + conversationMessagerName, e);
443 }
444 }
445 }
446
447
448
449
450
451
452
453 protected void createBeanElevator()
454 {
455 String conversationBeanElevatorName = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(INIT_BEAN_ELEVATOR);
456 if (conversationBeanElevatorName == null)
457 {
458 conversationBeanElevator = new DefaultConversationBeanElevator();
459 }
460 else
461 {
462 try
463 {
464 conversationBeanElevator = (DefaultConversationBeanElevator) ClassUtils.classForName(conversationBeanElevatorName).newInstance();
465 }
466 catch (InstantiationException e)
467 {
468 throw new FacesException("error creating bean elevator: " + conversationBeanElevatorName, e);
469 }
470 catch (IllegalAccessException e)
471 {
472 throw new FacesException("error creating bean elevator: " + conversationBeanElevatorName, e);
473 }
474 catch (ClassNotFoundException e)
475 {
476 throw new FacesException("error creating bean elevator: " + conversationBeanElevatorName, e);
477 }
478 }
479 }
480
481
482
483
484
485
486 protected PersistenceManagerFactory getPersistenceManagerFactory()
487 {
488 if (persistenceManagerFactory == null)
489 {
490 String persistenceManagerFactoryName = (String) ConversationServletFilter.getConversationExternalContext().getInitParameterMap().get(INIT_PERSISTENCE_MANAGER_FACOTRY);
491 if (persistenceManagerFactoryName == null)
492 {
493 throw new IllegalArgumentException("please configure '" + INIT_PERSISTENCE_MANAGER_FACOTRY + "' in your web.xml");
494 }
495 try
496 {
497 persistenceManagerFactory = (PersistenceManagerFactory) ClassUtils.classForName(persistenceManagerFactoryName).newInstance();
498 }
499 catch (InstantiationException e)
500 {
501 throw new FacesException("error creating persistenceManagerFactory named: " + persistenceManagerFactoryName, e);
502 }
503 catch (IllegalAccessException e)
504 {
505 throw new FacesException("error creating persistenceManagerFactory named: " + persistenceManagerFactoryName, e);
506 }
507 catch (ClassNotFoundException e)
508 {
509 throw new FacesException("error creating persistenceManagerFactory named: " + persistenceManagerFactoryName, e);
510 }
511 }
512
513 return persistenceManagerFactory;
514 }
515
516 protected void attachPersistence()
517 {
518 ConversationContext conversationContext = getConversationContext();
519 if (conversationContext != null)
520 {
521 conversationContext.attachPersistence();
522 }
523 }
524
525 protected void detachPersistence()
526 {
527 ConversationContext conversationContext = getConversationContext();
528 if (conversationContext != null)
529 {
530 conversationContext.detachPersistence();
531 }
532 }
533
534 protected void purgePersistence()
535 {
536 ConversationContext conversationContext = getConversationContext();
537 if (conversationContext != null)
538 {
539 conversationContext.purgePersistence();
540 }
541 }
542
543 protected void checkContextTimeout()
544 {
545 synchronized (conversationContexts)
546 {
547 long timeToLive = 30 * 60 * 1000;
548 long checkTime = System.currentTimeMillis();
549
550 Iterator iterContexts = conversationContexts.values().iterator();
551 while (iterContexts.hasNext())
552 {
553 ConversationContext conversationContext = (ConversationContext) iterContexts.next();
554 if (conversationContext.getLastAccess() + timeToLive < checkTime)
555 {
556 if (log.isDebugEnabled())
557 {
558 log.debug("end conversation context due to timeout: " + conversationContext.getId());
559 }
560 conversationContext.shutdownContext();
561 iterContexts.remove();
562 }
563 }
564 }
565 }
566
567
568
569
570
571 public ConversationBeanElevator getConversationBeanElevator()
572 {
573 return conversationBeanElevator;
574 }
575
576 private void writeObject(java.io.ObjectOutputStream out) throws IOException
577 {
578
579
580 }
581
582 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
583 {
584
585 }
586
587 private Object readResolve() throws ObjectStreamException
588 {
589
590 return null;
591 }
592 }