2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.view.faces;
19
20 import java.util.ArrayList;
21 import java.util.Enumeration;
22 import java.util.Iterator;
23 import java.util.List;
24 import javax.faces.context.FacesContext;
25 import javax.servlet.ServletContextAttributeEvent;
26 import javax.servlet.ServletContextAttributeListener;
27 import javax.servlet.ServletContextEvent;
28 import javax.servlet.ServletContextListener;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletRequestAttributeEvent;
31 import javax.servlet.ServletRequestAttributeListener;
32 import javax.servlet.ServletRequestEvent;
33 import javax.servlet.ServletRequestListener;
34 import javax.servlet.http.HttpSessionActivationListener;
35 import javax.servlet.http.HttpSessionAttributeListener;
36 import javax.servlet.http.HttpSessionBindingEvent;
37 import javax.servlet.http.HttpSessionEvent;
38 import javax.servlet.http.HttpSessionListener;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.shale.view.AbstractApplicationBean;
42 import org.apache.shale.view.AbstractRequestBean;
43 import org.apache.shale.view.AbstractSessionBean;
44 import org.apache.shale.view.Constants;
45 import org.apache.shale.view.ExceptionHandler;
46 import org.apache.shale.view.ViewController;
47
48
49 /***
50 * <p><strong>LifecycleListener</strong> implements the lifecycle startup
51 * and shutdown calls (<code>init()</code> and <code>destroy()</code>) for
52 * subclasses of {@link AbstractApplicationBean}, {@link AbstractRequestBean},
53 * and {@link AbstractSessionBean}.</p>
54 *
55 * <p>It must be registered with the servlet container as a listener,
56 * through an entry in either the <code>/WEB-INF/web.xml</code> resource
57 * or a tag library descriptor included in the web application.</p>
58 *
59 * $Id: LifecycleListener.java 489966 2006-12-24 01:43:42Z craigmcc $
60 *
61 * @since 1.0.3
62 */
63 public class LifecycleListener
64 implements ServletContextAttributeListener,
65 ServletContextListener,
66 HttpSessionActivationListener,
67 HttpSessionAttributeListener,
68 HttpSessionListener,
69 ServletRequestAttributeListener,
70 ServletRequestListener {
71
72
73
74
75
76 /***
77 * <p>Create a new lifecycle listener.</p>
78 */
79 public LifecycleListener() {
80 if (log.isInfoEnabled()) {
81 log.info("Initializing org.apache.shale.view.faces.LifecycleListener");
82 }
83 }
84
85
86
87
88
89 /***
90 * <p>The <code>Log</code> instance for this class.</p>
91 */
92 private static final Log log = LogFactory.getLog(LifecycleListener.class);
93
94
95
96
97
98 /***
99 * <p>The fully qualified class name of the <em>Tiger Extensions</em>
100 * verison of this listener class.</p>
101 */
102 private static final String TIGER_LISTENER =
103 "org.apache.shale.tiger.view.faces.LifecycleListener2";
104
105
106
107
108
109 /***
110 * <p>The <em>Tiger Extensions</em> implementation of this listener, if
111 * such a class exists in the application classpath. This value is lazily
112 * instantiated.</p>
113 */
114 private LifecycleListener tiger = null;
115
116
117 /***
118 * <p>Flag indicating whether the <code>tiger</code> value has been calculated
119 * already.</p>
120 */
121 private boolean tigerInitialized = false;
122
123
124
125
126
127 /***
128 * <p>Respond to a context created event. No special processing
129 * is required.</p>
130 *
131 * @param event Event to be processed
132 */
133 public void contextInitialized(ServletContextEvent event) {
134
135
136 LifecycleListener tiger = tiger();
137 if (tiger != null) {
138 tiger.contextInitialized(event);
139 }
140
141 }
142
143
144 /***
145 * <p>Respond to a context destroyed event. Causes any application
146 * scope attribute that implements {@link AbstractApplicationBean}
147 * to be removed, triggering an <code>attributeRemoved()</code> event.</p>
148 *
149 * @param event Event to be processed
150 */
151 public void contextDestroyed(ServletContextEvent event) {
152
153
154 LifecycleListener tiger = tiger();
155 if (tiger != null) {
156 tiger.contextDestroyed(event);
157 }
158
159
160
161 List list = new ArrayList();
162 Enumeration names = event.getServletContext().getAttributeNames();
163 while (names.hasMoreElements()) {
164 String name = (String) names.nextElement();
165 list.add(name);
166 }
167 Iterator keys = list.iterator();
168 while (keys.hasNext()) {
169 String key = (String) keys.next();
170 event.getServletContext().removeAttribute(key);
171 }
172
173 }
174
175
176
177
178
179 /***
180 * <p>Respond to an application scope attribute being added. If the
181 * value is an {@link AbstractApplicationBean}, call its
182 * <code>init()</code> method.</p>
183 *
184 * @param event Event to be processed
185 */
186 public void attributeAdded(ServletContextAttributeEvent event) {
187
188
189 LifecycleListener tiger = tiger();
190 if (tiger != null) {
191 tiger.attributeAdded(event);
192 return;
193 }
194
195
196 Object value = event.getValue();
197 if (value != null) {
198 fireApplicationInit(value);
199 }
200
201 }
202
203
204 /***
205 * <p>Respond to an application scope attribute being replaced.
206 * If the old value was an {@link AbstractApplicationBean}, call
207 * its <code>destroy()</code> method. If the new value is an
208 * {@link AbstractApplicationBean}, call its <code>init()</code>
209 * method.</p>
210 *
211 * @param event Event to be processed
212 */
213 public void attributeReplaced(ServletContextAttributeEvent event) {
214
215
216 LifecycleListener tiger = tiger();
217 if (tiger != null) {
218 tiger.attributeReplaced(event);
219 return;
220 }
221
222
223 Object value = event.getValue();
224 if (value != null) {
225 fireApplicationDestroy(value);
226 }
227
228
229 value = event.getServletContext().getAttribute(event.getName());
230 if (value != null) {
231 fireApplicationInit(value);
232 }
233
234 }
235
236
237 /***
238 * <p>Respond to an application scope attribute being removed.
239 * If the old value was an {@link AbstractApplicationBean}, call
240 * its <code>destroy()</code> method.</p>
241 *
242 * @param event Event to be processed
243 */
244 public void attributeRemoved(ServletContextAttributeEvent event) {
245
246
247 LifecycleListener tiger = tiger();
248 if (tiger != null) {
249 tiger.attributeRemoved(event);
250 return;
251 }
252
253
254 Object value = event.getValue();
255 if (value != null) {
256 fireApplicationDestroy(value);
257 }
258
259 }
260
261
262
263
264
265 /***
266 * <p>Respond to a session created event. No special processing
267 * is required.</p>
268 *
269 * @param event Event to be processed
270 */
271 public void sessionCreated(HttpSessionEvent event) {
272
273
274 LifecycleListener tiger = tiger();
275 if (tiger != null) {
276 tiger.sessionCreated(event);
277 }
278
279 }
280
281
282 /***
283 * <p>Respond to a session destroyed event. Causes any session
284 * scope attribute that implements {@link AbstractSessionBean}
285 * to be removed, triggering an <code>attributeRemoved()</code> event.</p>
286 *
287 * @param event Event to be processed
288 */
289 public void sessionDestroyed(HttpSessionEvent event) {
290
291
292 LifecycleListener tiger = tiger();
293 if (tiger != null) {
294 tiger.sessionDestroyed(event);
295 }
296
297
298
299 List list = new ArrayList();
300 try {
301 Enumeration names = event.getSession().getAttributeNames();
302 while (names.hasMoreElements()) {
303 String name = (String) names.nextElement();
304 list.add(name);
305 }
306 Iterator keys = list.iterator();
307 while (keys.hasNext()) {
308 String key = (String) keys.next();
309 event.getSession().removeAttribute(key);
310 }
311 } catch (IllegalStateException e) {
312
313
314
315
316 ;
317 }
318
319 }
320
321
322
323
324
325 /***
326 * <p>Respond to a "session will passivate" event. Notify all session
327 * scope attributes that are {@link AbstractSessionBean}s.</p>
328 *
329 * @param event Event to be processed
330 */
331 public void sessionWillPassivate(HttpSessionEvent event) {
332
333
334 LifecycleListener tiger = tiger();
335 if (tiger != null) {
336 tiger.sessionWillPassivate(event);
337 return;
338 }
339
340
341 Enumeration names = event.getSession().getAttributeNames();
342 while (names.hasMoreElements()) {
343 String name = (String) names.nextElement();
344 Object value = event.getSession().getAttribute(name);
345 if (value != null) {
346 fireSessionPassivate(value);
347 }
348 }
349
350 }
351
352
353 /***
354 * <p>Respond to a "session did activate" event. Notify all session
355 * scope attributes that are {@link AbstractSessionBean}s.</p>
356 *
357 * @param event Event to be processed
358 */
359 public void sessionDidActivate(HttpSessionEvent event) {
360
361
362 LifecycleListener tiger = tiger();
363 if (tiger != null) {
364 tiger.sessionDidActivate(event);
365 return;
366 }
367
368
369 Enumeration names = event.getSession().getAttributeNames();
370 while (names.hasMoreElements()) {
371 String name = (String) names.nextElement();
372 Object value = event.getSession().getAttribute(name);
373 if (value != null) {
374 fireSessionActivate(value);
375 }
376 }
377
378 }
379
380
381
382
383
384 /***
385 * <p>Respond to a session scope attribute being added. If the
386 * value is an {@link AbstractSessionBean}, call its
387 * <code>init()</code> method.</p>
388 *
389 * @param event Event to be processed
390 */
391 public void attributeAdded(HttpSessionBindingEvent event) {
392
393
394 LifecycleListener tiger = tiger();
395 if (tiger != null) {
396 tiger.attributeAdded(event);
397 return;
398 }
399
400
401 Object value = event.getValue();
402 if (value != null) {
403 fireSessionInit(value);
404 }
405
406 }
407
408
409 /***
410 * <p>Respond to a session scope attribute being replaced.
411 * If the old value was an {@link AbstractSessionBean}, call
412 * its <code>destroy()</code> method. If the new value is an
413 * {@link AbstractSessionBean}, call its <code>init()</code>
414 * method.</p>
415 *
416 * @param event Event to be processed
417 */
418 public void attributeReplaced(HttpSessionBindingEvent event) {
419
420
421 LifecycleListener tiger = tiger();
422 if (tiger != null) {
423 tiger.attributeReplaced(event);
424 return;
425 }
426
427
428 Object value = event.getValue();
429 if (value != null) {
430 fireSessionDestroy(value);
431 }
432
433
434 value = event.getSession().getAttribute(event.getName());
435 if (value != null) {
436 fireSessionInit(value);
437 }
438
439 }
440
441
442 /***
443 * <p>Respond to a session scope attribute being removed.
444 * If the old value was an {@link AbstractSessionBean}, call
445 * its <code>destroy()</code> method.</p>
446 *
447 * @param event Event to be processed
448 */
449 public void attributeRemoved(HttpSessionBindingEvent event) {
450
451
452 LifecycleListener tiger = tiger();
453 if (tiger != null) {
454 tiger.attributeRemoved(event);
455 return;
456 }
457
458
459 Object value = event.getValue();
460 if (value != null) {
461 fireSessionDestroy(value);
462 }
463
464 }
465
466
467
468
469
470 /***
471 * <p>Respond to a request created event. No special processing
472 * is required.</p>
473 *
474 * @param event Event to be processed
475 */
476 public void requestInitialized(ServletRequestEvent event) {
477
478
479 LifecycleListener tiger = tiger();
480 if (tiger != null) {
481 tiger.requestInitialized(event);
482 }
483
484 }
485
486
487 /***
488 * <p>Respond to a request destroyed event. Causes any request
489 * scope attribute that implements {@link AbstractRequestBean}
490 * or {@link AbstractFragmentBean} to be removed, triggering an
491 * <code>attributeRemoved()</code> event.</p>
492 *
493 * @param event Event to be processed
494 */
495 public void requestDestroyed(ServletRequestEvent event) {
496
497
498 LifecycleListener tiger = tiger();
499 if (tiger != null) {
500 tiger.requestDestroyed(event);
501 return;
502 }
503
504
505
506 List list = new ArrayList();
507 ServletRequest request = event.getServletRequest();
508 Enumeration names = request.getAttributeNames();
509 while (names.hasMoreElements()) {
510 String name = (String) names.nextElement();
511 Object value = request.getAttribute(name);
512 if ((value instanceof AbstractRequestBean) || (value instanceof ViewController)) {
513 list.add(name);
514 }
515 }
516 Iterator keys = list.iterator();
517 while (keys.hasNext()) {
518 String key = (String) keys.next();
519 event.getServletRequest().removeAttribute(key);
520 }
521
522 }
523
524
525
526
527
528 /***
529 * <p>Respond to a request scope attribute being added. If the
530 * value is an {@link AbstractRequestBean}, call its <code>init()</code> method.
531 * </p>
532 *
533 * @param event Event to be processed
534 */
535 public void attributeAdded(ServletRequestAttributeEvent event) {
536
537 if (log.isDebugEnabled()) {
538 log.debug("ServletRequestAttributeAdded(" + event.getName()
539 + "," + event.getValue() + ")");
540 }
541
542
543 LifecycleListener tiger = tiger();
544 if (tiger != null) {
545 tiger.attributeAdded(event);
546 return;
547 }
548
549 Object value = event.getValue();
550 if (value != null) {
551 fireRequestInit(value);
552 }
553
554 }
555
556
557 /***
558 * <p>Respond to a request scope attribute being replaced.
559 * If the old value was an {@link AbstractRequestBean},
560 * call its <code>destroy()</code> method. If the new value is an
561 * {@link AbstractRequestBean}, call its <code>init()</code> method.</p>
562 *
563 * @param event Event to be processed
564 */
565 public void attributeReplaced(ServletRequestAttributeEvent event) {
566
567 if (log.isDebugEnabled()) {
568 log.debug("ServletRequestAttributeReplaced(" + event.getName()
569 + "," + event.getValue()
570 + "," + event.getServletRequest().getAttribute(event.getName())
571 + ")");
572 }
573
574
575 LifecycleListener tiger = tiger();
576 if (tiger != null) {
577 tiger.attributeReplaced(event);
578 return;
579 }
580
581 Object value = event.getValue();
582 if (value != null) {
583 fireRequestDestroy(value);
584 }
585
586 value = event.getServletRequest().getAttribute(event.getName());
587 if (value != null) {
588 fireRequestInit(value);
589 }
590
591 }
592
593
594 /***
595 * <p>Respond to a request scope attribute being removed.
596 * If the old value was an {@link AbstractRequestBean},
597 * call its <code>destroy()</code> method.</p>
598 *
599 * @param event Event to be processed
600 */
601 public void attributeRemoved(ServletRequestAttributeEvent event) {
602
603 if (log.isDebugEnabled()) {
604 log.debug("ServletRequestAttributeRemoved(" + event.getName()
605 + "," + event.getValue() + ")");
606 }
607
608
609 LifecycleListener tiger = tiger();
610 if (tiger != null) {
611 tiger.attributeRemoved(event);
612 return;
613 }
614
615 Object value = event.getValue();
616 if (value != null) {
617 fireRequestDestroy(value);
618 }
619
620 }
621
622
623
624
625
626 /***
627 * <p>Fire a destroy event on an @{link AbstractApplicationBean}.</p>
628 *
629 * @param bean {@link AbstractApplicationBean} to fire event on
630 */
631 protected void fireApplicationDestroy(Object bean) {
632
633 try {
634 if (bean instanceof AbstractApplicationBean) {
635 ((AbstractApplicationBean) bean).destroy();
636 }
637 } catch (Exception e) {
638 handleException(FacesContext.getCurrentInstance(), e);
639 }
640
641 }
642
643
644 /***
645 * <p>Fire an init event on an {@link AbstractApplicationBean}.</p>
646 *
647 * @param bean {@link AbstractApplicationBean} to fire event on
648 */
649 protected void fireApplicationInit(Object bean) {
650
651 try {
652 if (bean instanceof AbstractApplicationBean) {
653 ((AbstractApplicationBean) bean).init();
654 }
655 } catch (Exception e) {
656 handleException(FacesContext.getCurrentInstance(), e);
657 }
658
659 }
660
661
662 /***
663 * <p>Fire a destroy event on an @{link AbstractRequestBean}.</p>
664 *
665 * @param bean {@link AbstractRequestBean} to fire event on
666 */
667 protected void fireRequestDestroy(Object bean) {
668
669 try {
670 if (bean instanceof AbstractRequestBean) {
671 ((AbstractRequestBean) bean).destroy();
672 } else if (bean instanceof ViewController) {
673 ((ViewController) bean).destroy();
674 }
675 } catch (Exception e) {
676 handleException(FacesContext.getCurrentInstance(), e);
677 }
678
679 }
680
681
682 /***
683 * <p>Fire an init event on an {@link AbstractRequestBean}.</p>
684 *
685 * @param bean {@link AbstractRequestBean} to fire event on
686 */
687 protected void fireRequestInit(Object bean) {
688
689 try {
690 if (bean instanceof AbstractRequestBean) {
691 ((AbstractRequestBean) bean).init();
692 } else if (bean instanceof ViewController) {
693 ((ViewController) bean).init();
694 }
695 } catch (Exception e) {
696 handleException(FacesContext.getCurrentInstance(), e);
697 }
698
699 }
700
701
702 /***
703 * <p>Fire an activate event on an @{link AbstractSessionBean}.</p>
704 *
705 * @param bean {@link AbstractSessionBean} to fire event on
706 */
707 protected void fireSessionActivate(Object bean) {
708
709 try {
710 if (bean instanceof AbstractSessionBean) {
711 ((AbstractSessionBean) bean).activate();
712 }
713 } catch (Exception e) {
714 handleException(FacesContext.getCurrentInstance(), e);
715 }
716
717 }
718
719
720 /***
721 * <p>Fire a destroy event on an @{link AbstractSessionBean}.</p>
722 *
723 * @param bean {@link AbstractSessionBean} to fire event on
724 */
725 protected void fireSessionDestroy(Object bean) {
726
727 try {
728 if (bean instanceof AbstractSessionBean) {
729 ((AbstractSessionBean) bean).destroy();
730 }
731 } catch (Exception e) {
732 handleException(FacesContext.getCurrentInstance(), e);
733 }
734
735 }
736
737
738 /***
739 * <p>Fire an init event on an {@link AbstractSessionBean}.</p>
740 *
741 * @param bean {@link AbstractSessionBean} to fire event on
742 */
743 protected void fireSessionInit(Object bean) {
744
745 try {
746 if (bean instanceof AbstractSessionBean) {
747 ((AbstractSessionBean) bean).init();
748 }
749 } catch (Exception e) {
750 handleException(FacesContext.getCurrentInstance(), e);
751 }
752
753 }
754
755
756 /***
757 * <p>Fire an passivate event on an @{link AbstractSessionBean}.</p>
758 *
759 * @param bean {@link AbstractSessionBean} to fire event on
760 */
761 protected void fireSessionPassivate(Object bean) {
762
763 try {
764 if (bean instanceof AbstractSessionBean) {
765 ((AbstractSessionBean) bean).passivate();
766 }
767 } catch (Exception e) {
768 handleException(FacesContext.getCurrentInstance(), e);
769 }
770
771 }
772
773
774 /***
775 * <p>Handle the specified exception according to the strategy
776 * defined by our current {@link ExceptionHandler}.</p>
777 *
778 * @param context FacesContext for the current request
779 * @param exception Exception to be handled
780 */
781 protected void handleException(FacesContext context, Exception exception) {
782
783 if (context == null) {
784 exception.printStackTrace(System.out);
785 return;
786 }
787 ExceptionHandler handler = (ExceptionHandler)
788 context.getApplication().getVariableResolver().resolveVariable
789 (context, Constants.EXCEPTION_HANDLER);
790 handler.handleException(exception);
791
792 }
793
794
795
796
797
798 /***
799 * <p>Return the <em>Tiger Extensions</em> implementation of this listener
800 * if one exists; otherwise, return <code>null</code>.</p>
801 */
802 private LifecycleListener tiger() {
803
804
805
806 if (tigerInitialized) {
807 return tiger;
808 }
809
810
811
812 try {
813 Class clazz = this.getClass().getClassLoader().loadClass(TIGER_LISTENER);
814 tiger = (LifecycleListener) clazz.newInstance();
815 } catch (Exception e) {
816 ;
817 }
818
819
820 tigerInitialized = true;
821 return tiger;
822
823 }
824
825
826 }