KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > pageflow > PageFlowStack


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18 package org.apache.beehive.netui.pageflow;
19
20 import org.apache.beehive.netui.util.logging.Logger;
21 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
22 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
23 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
24 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
25 import org.apache.beehive.netui.pageflow.interceptor.action.InterceptorForward;
26 import org.apache.beehive.netui.pageflow.interceptor.action.ActionInterceptor;
27 import org.apache.beehive.netui.pageflow.interceptor.action.ActionInterceptorContext;
28
29 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
30 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
31 import javax.servlet.http.HttpServletRequest JavaDoc;
32 import javax.servlet.ServletContext JavaDoc;
33 import java.util.Stack JavaDoc;
34 import java.io.Serializable JavaDoc;
35
36
37 /**
38  * Stack for keeping track of a series of nested page flows. When a nested page flow is entered,
39  * the previous page flow is pushed onto this stack, which is kept in the user session.
40  */

41 public class PageFlowStack
42         implements HttpSessionBindingListener JavaDoc, Serializable JavaDoc
43 {
44     private static final Logger _log = Logger.getInstance( PageFlowStack.class );
45     private static final String JavaDoc JPF_STACK_ATTR = InternalConstants.ATTR_PREFIX + "nestingStack";
46     
47     private Stack JavaDoc _stack = new Stack JavaDoc();
48     
49     
50     /**
51      * Wrapper that contains a pushed page flow and information related to it.
52      */

53     public static class PushedPageFlow implements Serializable JavaDoc
54     {
55         private PageFlowController _pageFlow;
56         private ActionInterceptor _interceptor;
57         private InterceptorForward _interceptedForward;
58         private String JavaDoc _interceptedActionName;
59
60         public PushedPageFlow( PageFlowController pageFlow )
61         {
62             _pageFlow = pageFlow;
63         }
64         
65         public PushedPageFlow( PageFlowController pageFlow, ActionInterceptor interceptor,
66                                InterceptorForward interceptedFwd, String JavaDoc interceptedActionName )
67         {
68             this( pageFlow );
69             _interceptor = interceptor;
70             _interceptedForward = interceptedFwd;
71             _interceptedActionName = interceptedActionName;
72         }
73
74         public PageFlowController getPageFlow()
75         {
76             return _pageFlow;
77         }
78
79         public ActionInterceptor getInterceptor()
80         {
81             return _interceptor;
82         }
83
84         public InterceptorForward getInterceptedForward()
85         {
86             return _interceptedForward;
87         }
88
89         public String JavaDoc getInterceptedActionName()
90         {
91             return _interceptedActionName;
92         }
93     }
94     
95    /**
96      * Get the stack of nested page flows for the current user session. Create and store an empty
97      * stack if none exists.
98      *
99      * @param request the current HttpServletRequest
100      * @return the stack of nested page flows {@link PushedPageFlow}s) for the current user session.
101      */

102     public static final PageFlowStack get( HttpServletRequest JavaDoc request )
103     {
104         return get( request, true );
105     }
106
107     /**
108      * Get the stack of nested page flows for the current user session. Create and store an empty
109      * stack if none exists.
110      *
111      * @param request the current HttpServletRequest
112      * @return a {@link PageFlowStack} of nested page flows ({@link PageFlowController}s) for the current user session.
113      */

114     public static PageFlowStack get( HttpServletRequest JavaDoc request, boolean createIfNotExist )
115     {
116         PageFlowStack jpfStack =
117                 ( PageFlowStack ) ScopedServletUtils.getScopedSessionAttr( JPF_STACK_ATTR,
118                                                                            PageFlowUtils.unwrapMultipart( request ) );
119
120         if ( jpfStack == null && createIfNotExist )
121         {
122             jpfStack = new PageFlowStack();
123             jpfStack.save( request );
124         }
125
126         return jpfStack;
127     }
128     
129     /**
130      * Destroy the stack of {@link PageFlowController}s that have invoked nested page flows.
131      *
132      * @param request the current HttpServletRequest.
133      */

134     public static void destroy( HttpServletRequest JavaDoc request )
135     {
136         ScopedServletUtils.removeScopedSessionAttr( JPF_STACK_ATTR, PageFlowUtils.unwrapMultipart( request ) );
137     }
138     
139     /**
140      * Pop page flows from the nesting stack until one of the given type is found.
141      *
142      * @return the last popped page flow if one of the given type was found, or <code>null</code>
143      * if none was found.
144      */

145     PageFlowController popUntil( HttpServletRequest JavaDoc request, Class JavaDoc stopAt )
146     {
147         while ( ! isEmpty() )
148         {
149             PageFlowController popped = pop( request ).getPageFlow();
150             
151             if ( popped.getClass().equals( stopAt ) )
152             {
153                 //
154
// If we've popped everything from the stack, remove the stack attribute from the session.
155
//
156
if ( isEmpty() ) destroy( request );
157                 return popped;
158             }
159             else
160             {
161                 //
162
// We're discarding the popped page flow. Invoke its destroy() callback, unless it's longLived.
163
//
164
if ( ! popped.isLongLived() ) popped.destroy( request.getSession() );
165             }
166         }
167
168         destroy( request ); // we're empty -- remove the attribute from the session.
169
return null;
170     }
171     
172     /**
173      * Pop page flows from the nesting stack until the given index.
174      * @return the last popped page flow of the given type.
175      */

176     PageFlowController popUntil( HttpServletRequest JavaDoc request, int index )
177     {
178         for ( int i = _stack.size() - 1; i > index; --i )
179         {
180             pop( request );
181         }
182         
183         return pop( request ).getPageFlow();
184     }
185     
186     int lastIndexOf( HttpServletRequest JavaDoc request, Class JavaDoc target )
187     {
188         for ( int i = _stack.size() - 1; i >= 0; --i )
189         {
190             if ( ( ( PushedPageFlow ) _stack.elementAt( i ) ).getPageFlow().getClass().equals( target ) )
191             {
192                 return i;
193             }
194         }
195         
196         return -1;
197     }
198     
199     void ensureFailover( HttpServletRequest JavaDoc request, ServletContext JavaDoc servletContext )
200     {
201         String JavaDoc name =
202             ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, PageFlowUtils.unwrapMultipart( request ) );
203         AdapterManager.getServletContainerAdapter( servletContext ).ensureFailover( name, this, request );
204     }
205     
206     void save( HttpServletRequest JavaDoc request )
207     {
208         ScopedServletUtils.setScopedSessionAttr( JPF_STACK_ATTR, this, PageFlowUtils.unwrapMultipart( request ) );
209     }
210     
211     PageFlowStack()
212     {
213     }
214     
215     /**
216      * Push a page flow onto the stack of nested page flows in the session.
217      *
218      * @param pageFlow the page flow to push.
219      * @param request the current HttpServletRequest.
220      */

221     public void push( PageFlowController pageFlow, HttpServletRequest JavaDoc request )
222     {
223         ActionInterceptorContext interceptorContext = ActionInterceptorContext.getActiveContext( request, true );
224         
225         if ( interceptorContext != null )
226         {
227             ActionInterceptor interceptor = interceptorContext.getOverridingActionInterceptor();
228             InterceptorForward originalForward = interceptorContext.getOriginalForward();
229             String JavaDoc actionName = interceptorContext.getActionName();
230             _stack.push( new PushedPageFlow( pageFlow, interceptor, originalForward, actionName ) );
231         }
232         else
233         {
234             _stack.push( new PushedPageFlow( pageFlow ) );
235         }
236         
237         // Tell the page flow that it is on the nesting stack.
238
pageFlow.setIsOnNestingStack( true );
239         
240         // To ensure that this attribute is replicated for session failover...
241
ensureFailover( request, pageFlow.getServletContext() );
242     }
243     
244     /**
245      * Pop the most recently-pushed page flow from the stack of nested page flows in the session.
246      *
247      * @param request the current HttpServletRequest.
248      * @return a {@link PushedPageFlow} that represents the popped page flow.
249      */

250     public PushedPageFlow pop( HttpServletRequest JavaDoc request )
251     {
252         PushedPageFlow ppf = ( PushedPageFlow ) _stack.pop();
253         PageFlowController pfc = ppf.getPageFlow();
254         pfc.setIsOnNestingStack( false );
255         
256         if ( request != null ) // may be null if we're called from valueUnbound()
257
{
258             ServletContext JavaDoc servletContext = pfc.getServletContext();
259             
260             // The ServletContext reference will be null if the page flow has been serialized/deserialized.
261
if ( servletContext == null )
262             {
263                 servletContext = InternalUtils.getServletContext( request );
264                 pfc.reinitialize( request, null, servletContext );
265             }
266             
267             ensureFailover( request, servletContext ); // to ensure that this attribute is replicated for session failover
268
}
269         
270         return ppf;
271     }
272     
273     /**
274      * Get the most recently-pushed page flow from the stack of nested page flows in the session.
275      *
276      * @return a {@link PushedPageFlow} that represents the page flow at the top of the stack.
277      */

278     public PushedPageFlow peek()
279     {
280         return ( PushedPageFlow ) _stack.peek();
281     }
282     
283     /**
284      * Tell whether the stack of nested page flows is empty.
285      *
286      * @return <code>true</code> if there are no nested page flows on the stack.
287      */

288     public boolean isEmpty()
289     {
290         return _stack.isEmpty();
291     }
292     
293     /**
294      * Get the size of the stack of nested page flows.
295      *
296      * @return the number of page flows that are currently (hidden away) on the stack.
297      */

298     public int size()
299     {
300         return _stack.size();
301     }
302     
303     /**
304      * @exclude
305      */

306     public void valueBound( HttpSessionBindingEvent JavaDoc event )
307     {
308     }
309
310     /**
311      * @exclude
312      */

313     public void valueUnbound( HttpSessionBindingEvent JavaDoc event )
314     {
315         if ( _log.isDebugEnabled() )
316         {
317             _log.debug( "The page flow stack is being unbound from the session." );
318         }
319         
320         while ( ! isEmpty() )
321         {
322             PageFlowController jpf = pop( null ).getPageFlow();
323             
324             // Note that this page flow may have been serialized/deserialized, which will cause its transient info
325
// to be lost. Rehydrate it.
326
if ( jpf.getServletContext() == null )
327             {
328                 jpf.reinitialize( null, null, event.getSession().getServletContext() );
329             }
330             
331             if ( ! jpf.isLongLived() ) jpf.destroy( event.getSession() );
332         }
333     }
334     
335     /**
336      * Get a stack of PageFlowControllers, not of PushedPageFlows.
337      */

338     Stack JavaDoc getLegacyStack()
339     {
340         Stack JavaDoc ret = new Stack JavaDoc();
341         
342         for ( int i = 0; i < _stack.size(); ++i )
343         {
344             ret.push( ( ( PushedPageFlow ) _stack.get( i ) ).getPageFlow() );
345         }
346         
347         return ret;
348     }
349 }
350
Popular Tags