View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.orchestra.conversation.jsf;
21  
22  import org.apache.myfaces.orchestra.conversation.Conversation;
23  import org.apache.myfaces.orchestra.conversation.ConversationFlashLifetimeAspect;
24  import org.apache.myfaces.orchestra.conversation.ConversationManager;
25  import org.apache.myfaces.orchestra.conversation.FlashScopeManager;
26  
27  import javax.faces.event.PhaseEvent;
28  import javax.faces.event.PhaseId;
29  import javax.faces.event.PhaseListener;
30  import java.util.Iterator;
31  import java.util.Set;
32  
33  /***
34   * Handle Flash conversations.
35   * <p>
36   * At the end of request processing, delete any flash-scope conversations for which no
37   * bean in that scope has been accessed during the request.
38   */
39  public class FlashScopePhaseListener implements PhaseListener
40  {
41  	private static final long serialVersionUID = 1L;
42  
43  	public void afterPhase(PhaseEvent event)
44  	{
45  		if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
46  		{
47  			invalidateFlashConversations(event.getFacesContext().getViewRoot().getViewId());
48  		}
49  	}
50  
51  	public void beforePhase(PhaseEvent event)
52  	{
53  	}
54  
55  	/***
56  	 * Invalidates any conversation with aspect {@link ConversationFlashLifetimeAspect}
57  	 * which has not been accessed during a http request
58  	 */
59  	protected void invalidateFlashConversations(String viewId)
60  	{
61  		FlashScopeManager flashManager = FlashScopeManager.getInstance();
62  		if (flashManager.isIgnoreRequest())
63  		{
64  			return;
65  		}
66  
67  		if (flashManager.getFlashScopeManagerConfiguration() != null)
68  		{
69  			Set ignoredViewIds = flashManager.getFlashScopeManagerConfiguration().getIgnoreViewIds();
70  			if (ignoredViewIds != null && ignoredViewIds.contains(viewId))
71  			{
72  				// The flash configuration has explicitly stated that no conversations should be
73  				// terminated when processing this specific view, so just return.
74  				// 
75  				// Special "ignored views" are useful when dealing with things like nested
76  				// frames within a page that periodically refresh themselves while the "main"
77  				// part of the page remains unsubmitted.
78  				return;
79  			}
80  		}
81  
82  		ConversationManager conversationManager = ConversationManager.getInstance(false);
83  		if (conversationManager == null)
84  		{
85  			return;
86  		}
87  
88  		Iterator iterConversations = conversationManager.iterateConversations();
89  		while (iterConversations.hasNext())
90  		{
91  			Conversation conversation = (Conversation) iterConversations.next();
92  			
93  			// This conversation has "flash" scope if it has an attached Aspect
94  			// of type ConversationFlashLifetimeAspect. All other conversations
95  			// are not flash-scoped and should be ignored here.
96  			ConversationFlashLifetimeAspect aspect =
97  				(ConversationFlashLifetimeAspect)
98  					conversation.getAspect(ConversationFlashLifetimeAspect.class);
99  
100 			if (aspect != null && !aspect.isAccessed())
101 			{
102 				conversation.invalidate();
103 			}
104 		}
105 	}
106 
107 	public PhaseId getPhaseId()
108 	{
109 		return PhaseId.RENDER_RESPONSE;
110 	}
111 }