You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ri...@apache.org on 2005/02/03 21:57:53 UTC

svn commit: r151229 [1/2] - in incubator/beehive/trunk/netui: src/compiler/org/apache/beehive/netui/compiler/ src/compiler/org/apache/beehive/netui/compiler/genmodel/ src/compiler/org/apache/beehive/netui/compiler/grammar/ src/pageflow/org/apache/beehive/netui/pageflow/ src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/ src/pageflow/org/apache/beehive/netui/pageflow/handler/ src/pageflow/org/apache/beehive/netui/pageflow/internal/ src/util/org/apache/beehive/netui/util/ src/webapp-template/default/WEB-INF/ test/webapps/drt/coreWeb/WEB-INF/src/mockportal/ test/webapps/drt/coreWeb/miniTests/generics/ test/webapps/drt/coreWeb/miniTests/passAssignableFormBeanToAction/ test/webapps/drt/testRecorder/config/ test/webapps/drt/testRecorder/tests/

Author: rich
Date: Thu Feb  3 12:57:47 2005
New Revision: 151229

URL: http://svn.apache.org/viewcvs?view=rev&rev=151229
Log:
Fixes for:
    - http://issues.apache.org/jira/browse/BEEHIVE-233 : page flow actions can't use generic type-variables as arguments
    - http://issues.apache.org/jira/browse/BEEHIVE-234 : Confusing errors when hitting a page flow whose class is missing or not accessible
    - http://issues.apache.org/jira/browse/BEEHIVE-238 : Invalid error for missing returnAction on an abstract nested page flow

Also, replaced all the static methods in FlowControllerFactory with instance methods (and a static get()), so the factory itself could be plugged in the future.

DRT/BVT: netui (WinXP)
BB: self (linux)


Added:
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/generics/
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/generics/Controller.jpf   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/generics/index.jsp   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/passAssignableFormBeanToAction/
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/passAssignableFormBeanToAction/Controller.jpf   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/passAssignableFormBeanToAction/index.jsp   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/Generics.xml   (with props)
    incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PassAssignableFormBeanToAction.xml   (with props)
Modified:
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/CompilerUtils.java
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/FlowControllerChecker.java
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/PageFlowChecker.java
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/diagnostics.properties
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionModel.java
    incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/grammar/MemberFieldType.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/DynamicSubappActionServlet.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/RequestContext.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/PageFlowNavigationHandler.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/FlowControllerHandlerContext.java
    incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
    incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/util/netui.properties
    incubator/beehive/trunk/netui/src/webapp-template/default/WEB-INF/netui-validator-rules.xml
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortletTag.java
    incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/CompilerUtils.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/CompilerUtils.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/CompilerUtils.java (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/CompilerUtils.java Thu Feb  3 12:57:47 2005
@@ -28,6 +28,7 @@
 import com.sun.mirror.type.DeclaredType;
 import com.sun.mirror.type.InterfaceType;
 import com.sun.mirror.type.ArrayType;
+import com.sun.mirror.type.TypeVariable;
 import com.sun.mirror.util.SourcePosition;
 import com.sun.mirror.util.DeclarationVisitor;
 import com.sun.mirror.util.Declarations;
@@ -1171,5 +1172,16 @@
         {
             return _val;
         }
+    }
+    
+    public static TypeMirror getGenericBoundsType( TypeMirror type )
+    {
+        if ( type instanceof TypeVariable )
+        {
+            Collection< ReferenceType > bounds = ( ( TypeVariable ) type ).getDeclaration().getBounds();
+            return bounds.size() > 0 ? bounds.iterator().next() : type;
+        }
+        
+        return type;
     }
 }

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/FlowControllerChecker.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/FlowControllerChecker.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/FlowControllerChecker.java (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/FlowControllerChecker.java Thu Feb  3 12:57:47 2005
@@ -28,6 +28,8 @@
 import com.sun.mirror.type.TypeMirror;
 import com.sun.mirror.type.DeclaredType;
 import com.sun.mirror.type.ClassType;
+import com.sun.mirror.type.TypeVariable;
+import com.sun.mirror.type.ReferenceType;
 
 import java.io.File;
 import java.io.IOException;
@@ -436,7 +438,7 @@
         
         if ( nParameters > 0 )
         {
-            TypeMirror argType = parameters.iterator().next().getType();
+            TypeMirror argType = CompilerUtils.getGenericBoundsType( parameters.iterator().next().getType() );
 
             if ( ! ( argType instanceof DeclaredType ) )
             {
@@ -504,7 +506,8 @@
 
             if ( memberForm != null )
             {
-                TypeMirror memberFormType = memberForm.getType();
+                TypeMirror memberFormType = CompilerUtils.getGenericBoundsType( memberForm.getType() );
+                
                 String memberFormTypeName =
                         memberFormType instanceof DeclaredType
                         ? CompilerUtils.getDeclaration( ( DeclaredType ) memberFormType ).getQualifiedName()
@@ -517,7 +520,7 @@
                 }
                 else
                 {
-                    if ( ! CompilerUtils.isAssignableFrom( argTypeDecl, memberForm.getType() ))
+                    if ( ! CompilerUtils.isAssignableFrom( argTypeDecl, memberFormType ))
                     {
                         getDiagnostics().addError( method, "error.action-mismatched-form", USE_FORM_BEAN_ATTR,
                                                    formMemberName, memberFormTypeName );

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/PageFlowChecker.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/PageFlowChecker.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/PageFlowChecker.java (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/PageFlowChecker.java Thu Feb  3 12:57:47 2005
@@ -236,8 +236,10 @@
         //
         // Make sure every .jpf has a begin action if the class isn't abstract.
         //
+        boolean isAbstract = CompilerUtils.hasModifier( jpfClass, Modifier.ABSTRACT );
+        
         if ( ! WebappPathOrActionType.actionExists( BEGIN_ACTION_NAME, jpfClass, null, getEnv(), getFlowControllerInfo(), true )
-             && ! CompilerUtils.hasModifier( jpfClass, Modifier.ABSTRACT ) )
+             && ! isAbstract )
         {
             getDiagnostics().addError( jpfClass, "error.no-begin-action" );
         }
@@ -247,10 +249,11 @@
         //
         if ( getFlowControllerInfo().isNested() )
         {
-            if ( getFlowControllerInfo().countReturnActions() == 0 )
+            if ( ! isAbstract && getFlowControllerInfo().countReturnActions() == 0 )
             {
                 getDiagnostics().addError( jpfClass, "error.no-return-action",
-                                           ANNOTATION_INTERFACE_PREFIX + FORWARD_TAG_NAME );
+                                           ANNOTATION_INTERFACE_PREFIX + FORWARD_TAG_NAME,
+                                           RETURN_ACTION_ATTR );
             }                
         }        
     }

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/diagnostics.properties
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/diagnostics.properties?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/diagnostics.properties (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/diagnostics.properties Thu Feb  3 12:57:47 2005
@@ -21,7 +21,7 @@
 error.no-begin-action = There is no begin action defined for this PageFlowController.
 
 error.no-return-action = \
-There is no {0} annotation with the returnAction attribute defined for this nested PageFlowController.
+There is no {0} annotation with the {1} attribute defined for this nested PageFlowController.
 
 warning.file-not-found = File "{0}" could not be found in the web application.
 error.file-not-found = File "{0}" could not be found in the web application.

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionModel.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionModel.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionModel.java (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionModel.java Thu Feb  3 12:57:47 2005
@@ -185,7 +185,8 @@
         if ( params.size() > 0 )
         {
             assert params.size() == 1 : params.size();  // checker should catch this
-            formBeanName = addFormBean( params.iterator().next().getType(), parentApp );
+            TypeMirror paramType = CompilerUtils.getGenericBoundsType( params.iterator().next().getType() );
+            formBeanName = addFormBean( paramType, parentApp );
         }
         
         return formBeanName;
@@ -193,6 +194,7 @@
     
     protected String addFormBean( TypeMirror paramType, GenStrutsApp parentApp )
     {
+        paramType = CompilerUtils.getGenericBoundsType( paramType );
         assert paramType instanceof DeclaredType : paramType.getClass().getName();  // checker should enforce this
         TypeDeclaration decl = CompilerUtils.getDeclaration( ( DeclaredType ) paramType );
         String formBeanName = parentApp.addFormBean( decl, this );

Modified: incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/grammar/MemberFieldType.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/grammar/MemberFieldType.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/grammar/MemberFieldType.java (original)
+++ incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/grammar/MemberFieldType.java Thu Feb  3 12:57:47 2005
@@ -25,6 +25,7 @@
 import com.sun.mirror.declaration.MemberDeclaration;
 import com.sun.mirror.declaration.FieldDeclaration;
 import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
+import com.sun.mirror.type.TypeMirror;
 
 import java.util.Collection;
 
@@ -53,11 +54,12 @@
         {
             if ( field.getSimpleName().equals( fieldName ) )
             {
+                TypeMirror fieldType = CompilerUtils.getGenericBoundsType( field.getType() );
+                
                 if ( _requiredSuperclassName != null
-                     && ! CompilerUtils.isAssignableFrom( _requiredSuperclassName, field.getType(), getEnv() ) )
+                     && ! CompilerUtils.isAssignableFrom( _requiredSuperclassName, fieldType, getEnv() ) )
                 {
-                    addError( member, "error.wrong-field-type",
-                              new Object[]{ fieldName, _requiredSuperclassName } );
+                    addError( member, "error.wrong-field-type", new Object[]{ fieldName, _requiredSuperclassName } );
                     return null;
                 }
                 

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java Thu Feb  3 12:57:47 2005
@@ -92,15 +92,15 @@
     private static final ModuleConfig NONEXISTANT_MODULE_CONFIG = new NonexistantModuleConfig();
     
     
-    public void init( ServletConfig servletConfig )
+    public void init()
         throws ServletException
     {
-        super.init( servletConfig );
-        _handlers = Handlers.get( servletConfig.getServletContext() );
-        setupModuleConfigLocators( servletConfig );
+        super.init();
+        _handlers = Handlers.get( getServletContext() );
+        setupModuleConfigLocators();
     }
     
-    private void setupModuleConfigLocators( ServletConfig servletConfig )
+    private void setupModuleConfigLocators()
     {
         ModuleConfigLocator[] defaultLocators = getDefaultModuleConfigLocators();
         ArrayList< ModuleConfigLocator > locators = new ArrayList< ModuleConfigLocator >();
@@ -133,7 +133,7 @@
         //
         // Look for ModuleConfigLocators specified in web.xml (deprecated method for specifying them).
         //
-        String configLocatorList = servletConfig.getInitParameter( MODULE_CONFIG_LOCATOR_CLASS_ATTR );
+        String configLocatorList = getServletConfig().getInitParameter( MODULE_CONFIG_LOCATOR_CLASS_ATTR );
         
         if ( configLocatorList != null )
         {
@@ -669,6 +669,7 @@
                 //
                 // If we're not in production mode, send a diagnostic on the response; otherwise, simply send a 404.
                 //
+                if ( modulePath.length() == 0 ) modulePath = "/";
                 InternalUtils.sendDevTimeError( "PageFlow_NoModuleConf", null, HttpServletResponse.SC_NOT_FOUND, 
                                                 request, response, servletContext, relativeURI, modulePath );
             }

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/DynamicSubappActionServlet.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/DynamicSubappActionServlet.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/DynamicSubappActionServlet.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/DynamicSubappActionServlet.java Thu Feb  3 12:57:47 2005
@@ -37,9 +37,9 @@
 {
     private static final Logger _log = Logger.getInstance( DynamicSubappActionServlet.class );
     
-    public void init( ServletConfig config ) throws ServletException
+    public void init() throws ServletException
     {
-        super.init( config );
+        super.init();
         
         if ( _log.isWarnEnabled() )
         {

Added: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java?view=auto&rev=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java (added)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java Thu Feb  3 12:57:47 2005
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.pageflow;
+
+import javax.servlet.ServletContext;
+
+public abstract class Factory
+{
+    private ServletContext _servletContext;
+
+    protected Factory( ServletContext servletContext )
+    {
+        _servletContext = servletContext;
+    }
+
+    protected ServletContext getServletContext()
+    {
+        return _servletContext;
+    }
+}

Propchange: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/Factory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java Thu Feb  3 12:57:47 2005
@@ -22,11 +22,14 @@
 import org.apache.beehive.netui.util.config.bean.PageflowConfig;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.config.PageFlowControllerConfig;
+import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
 
 import org.apache.struts.config.ModuleConfig;
 import org.apache.struts.config.ControllerConfig;
@@ -38,57 +41,63 @@
 
 
 /**
- * Factory for creating {@link FlowController}s - user {@link PageFlowController}s and
- * Global.app.
+ * Factory for creating {@link FlowController}s - user {@link PageFlowController}s and {@link SharedFlowController}s.
  */ 
 public class FlowControllerFactory
+        extends Factory
 {
     private static final Logger _log = Logger.getInstance( FlowControllerFactory.class );
     
+    private ReloadableClassHandler _rch;
+    
+    protected FlowControllerFactory( ServletContext servletContext )
+    {
+        super( servletContext );
+        _rch = Handlers.get( servletContext ).getReloadableClassHandler();
+    }
     
     /**
-     * Get the {@link PageFlowController} instance that should be associated with the given request,
-     * based on the path of the request URI.  If it doesn't exist, create it.
-     * The PageFlowController stack (for nesting) will be cleared or pushed, and the new instance
-     * will be stored as the current PageFlowController.
+     * Get a FlowControllerFactory.
      * 
-     * @param request the current HttpServletRequest.
      * @param servletContext the current ServletContext.
-     * @return the PageFlowController for the request, or <code>null</code> if none was found
-     *             and none could be created.
-     */
-    public static PageFlowController getPageFlowForRequest( HttpServletRequest request,  HttpServletResponse response,
-                                                            ServletContext servletContext )
+     * @return a FlowControllerFactory for the given ServletContext.  It may or may not be a cached instance.
+     */ 
+    public static FlowControllerFactory get( ServletContext servletContext )
     {
-        return getPageFlowForRelativeURI( request, response, InternalUtils.getDecodedServletPath( request ), servletContext );
-    }    
+        return new FlowControllerFactory( servletContext );
+    }
     
-    public static PageFlowController getPageFlowForURI( HttpServletRequest request, HttpServletResponse response,
-                                                        String uri, ServletContext servletContext )
+    /**
+     * Get the page flow instance that should be associated with the given request.  If it doesn't exist, create it. 
+     * If one is created, the page flow stack (for nesting) will be cleared or pushed, and the new instance will be
+     * stored as the current page flow.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @return the {@link PageFlowController} for the request, or <code>null</code> if none was found.
+     */
+    public PageFlowController getPageFlowForRequest( RequestContext context )
+            throws InstantiationException, IllegalAccessException
     {
-        return getPageFlowForRelativeURI( request, response, PageFlowUtils.getRelativeURI( request, uri, null ),
-                                          servletContext );
-    }
+        String servletPath = InternalUtils.getDecodedServletPath( context.getHttpRequest() );
+        return getPageFlowForPath( context, servletPath );
+    }     
     
     /**
-     * Get the {@link PageFlowController} instance that should be associated with the given URI.
-     * If it doesn't exist, create it.  The PageFlowController stack (for
-     * nesting) will be cleared or pushed, and the new instance will be stored as the current
-     * PageFlowController.
+     * Get the page flow instance that should be associated with the given path.  If it doesn't exist, create it. 
+     * If one is created, the page flow stack (for nesting) will be cleared or pushed, and the new instance will be
+     * stored as the current page flow.
      * 
-     * @param request the current HttpServletRequest.
-     * @param response the current HttpServletResponse.
-     * @param relativeURI the webapp-relative URI for the page flow.
-     * @param servletContext the current ServletContext.
-     * @return the PageFlowController for the request, or <code>null</code> if none was found
-     *             and none could be created.
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param path a <strong>webapp-relative</strong> path.  The path should not contain the webapp context path.
+     * @return the {@link PageFlowController} for the given path, or <code>null</code> if none was found.
      */
-    public static PageFlowController getPageFlowForRelativeURI( HttpServletRequest request,
-                                                                HttpServletResponse response, String relativeURI,
-                                                                ServletContext servletContext )
+    public PageFlowController getPageFlowForPath( RequestContext context, String path )
+        throws InstantiationException, IllegalAccessException
     {
+        HttpServletRequest request = context.getHttpRequest();
+        HttpServletResponse response = context.getHttpResponse();
         PageFlowController cur = PageFlowUtils.getCurrentPageFlow( request );
-        String parentDir = PageFlowUtils.getModulePathForRelativeURI( relativeURI );
+        String parentDir = PageFlowUtils.getModulePathForRelativeURI( path );
         
         //
         // If there's no current PageFlow, or if the current PageFlowController has a module path that
@@ -96,32 +105,302 @@
         //
         if ( cur == null || ! PageFlowUtils.getModulePathForRelativeURI( cur.getURI() ).equals( parentDir ) )
         {
-            String jpfClassName = InternalUtils.getFlowControllerClassName( parentDir, request, servletContext );
-            return jpfClassName != null ? getPageFlow( jpfClassName, request, response, servletContext ) : null;
+            try
+            {
+                String className = InternalUtils.getFlowControllerClassName( parentDir, request, getServletContext() );
+                return className != null ? createPageFlow( context, className ) : null;
+            }
+            catch ( ClassNotFoundException e )
+            {
+                if ( _log.isInfoEnabled() ) _log.info( "No page flow exists for path " + path );
+                return null;
+            }
         }
         
         //
         // Reinitialize transient data that may have been lost on session failover.
         //
-        cur.reinitialize( request, response, servletContext );
+        cur.reinitialize( request, response, getServletContext() );
         return cur;
+    }     
+    
+    /**
+     * Create a page flow of the given type.  The page flow stack (for nesting) will be cleared or pushed, and the new
+     * instance will be stored as the current page flow.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param pageFlowClassName the type name of the desired page flow.
+     * @return the newly-created {@link PageFlowController}, or <code>null</code> if none was found.
+     */
+    public PageFlowController createPageFlow( RequestContext context, String pageFlowClassName )
+        throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        Class pageFlowClass = getFlowControllerClass( pageFlowClassName );
+        return createPageFlow( context, pageFlowClass );
     }    
     
-    public static Map<String, SharedFlowController> getSharedFlowsForRequest( HttpServletRequest request,
-                                                                              HttpServletResponse response,
-                                                                              ServletContext servletContext )
+    /**
+     * Create a {@link PageFlowController} of the given type.  The PageFlowController stack (for
+     * nesting) will be cleared or pushed, and the new instance will be stored as the current
+     * PageFlowController.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param pageFlowClass the type of the desired PageFlowController.
+     * @return the newly-created PageFlowController, or <code>null</code> if none was found.
+     */
+    public PageFlowController createPageFlow( RequestContext context, Class pageFlowClass )
+            throws InstantiationException, IllegalAccessException
     {
-        String relativeURI = InternalUtils.getDecodedServletPath( request );
-        return getSharedFlowsForRelativeURI( request, response, relativeURI, servletContext );
+        if ( ! PageFlowController.class.isAssignableFrom( pageFlowClass ) )
+        {
+            return null;
+        }
+        
+        //
+        // First check if this is a request for a "long lived" page flow.  If so, try
+        // PageFlowUtils.getCurrentPageFlow again, with the longLived flag.
+        //
+        HttpServletRequest request = context.getHttpRequest();
+        HttpServletResponse response = context.getHttpResponse();
+        ServletContext servletContext = getServletContext();
+        PageFlowController retVal = null;
+        String modulePath = InternalUtils.inferModulePathFromClassName( pageFlowClass.getName() );
+        ModuleConfig mc = ensureModule( modulePath, request, servletContext );
+        
+        if ( mc == null )
+        {
+            _log.error( "Struts module " + modulePath + " not found for " + pageFlowClass.getName()
+                        + "; cannot create page flow.");
+            return null;
+        }
+        
+        if ( InternalUtils.isLongLived( mc ) )
+        {
+            retVal = PageFlowUtils.getLongLivedPageFlow( modulePath, request );
+            
+            if ( _log.isDebugEnabled() )
+            {
+                if ( retVal != null )
+                {
+                    _log.debug( "Using long lived PageFlowController of type " + pageFlowClass.getName() );
+                }
+            }
+        }
+        
+        //
+        // First, see if this is a nested page flow that's already on the stack.  Unless "renesting" is explicitly
+        // enabled, we don't want to allow another instance of this page flow to be nested.  This is a common
+        // browser back-button problem:
+        //    1) request nested page flow A
+        //    2) request nested page flow B
+        //    3) press back button, and execute an action on A.
+        //
+        // This logic does not deal with immediate self-nesting (A->A), which is taken care of in
+        // PageFlowController.forwardTo().  Nested page flows can only self-nest by forwarding to the .jpf URI, not
+        // indirectly by executing actions on themselves (think about it -- that would be a disaster).
+        //
+        boolean createdNew = false;
+        boolean isNestable = InternalUtils.isNestable( mc );
+        PageFlowStack pfStack = PageFlowStack.get( request, false );
+        
+        if ( isNestable && pfStack != null )
+        {
+            PageflowConfig options = ConfigUtil.getConfig().getPageflowConfig();
+            
+            if ( options == null || ! options.getEnableRenesting() )
+            {
+                int lastIndexOfJpfClass = pfStack.lastIndexOf( request, pageFlowClass );
+                
+                if ( lastIndexOfJpfClass != -1 )
+                {
+                    retVal = pfStack.popUntil( request, lastIndexOfJpfClass );
+                    retVal.persistInSession( request, response );
+                    return retVal;
+                }
+            }
+        }
+        
+        //
+        // OK, if it's not an existing long lived page flow, and if this wasn't a nested page flow already on the
+        // stack, then create a new instance.
+        //
+        if ( retVal == null )
+        {
+            if ( _log.isDebugEnabled() )
+            {
+                _log.debug( "Creating PageFlowController of type " + pageFlowClass.getName() );
+            }
+            
+            retVal = ( PageFlowController ) pageFlowClass.newInstance();
+            createdNew = true;
+        }
+        
+        //
+        // Store the previous PageFlowController on the nesting stack (if this one is nestable),
+        // or destroy the nesting stack.
+        //
+        if ( isNestable )
+        {
+            //
+            // Call create() on the newly-created page flow.
+            //
+            retVal.create( request, response, servletContext );
+            PageFlowController current = PageFlowUtils.getCurrentPageFlow( request );
+            
+            if ( current != null )
+            {
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Pushing PageFlowController " + current + " onto the nesting stack" );
+                }
+                
+                if ( pfStack == null ) pfStack = PageFlowStack.get( request, true );
+                pfStack.push( current, request );
+            }
+            
+            retVal.persistInSession( request, response );
+        }
+        else
+        {
+            //
+            // Going to a non-nested pageflow.  Blow away the pageflow stack.
+            //
+            if ( pfStack != null )
+            {
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Destroying the PageFlowController stack." );
+                }
+                
+                //
+                // Start popping page flows until 1) there are none left on the stack, or 2) we find
+                // one of the type we're returning.  If (2), we'll use that one (this means that executing
+                // an action on a nesting page flow while in a nested one will not destroy the nesting
+                // page flow only to create a new instance of it).
+                //
+                PageFlowController onStackAlready = pfStack.popUntil( request, retVal.getClass() );
+                
+                if ( onStackAlready != null )
+                {
+                    if ( _log.isDebugEnabled() )
+                    {
+                        _log.debug( "Found a page flow of type " + retVal.getClass() + " in the stack; "
+                                    + "using that instance and stopping destruction of the nesting stack." );
+                    }
+                    
+                    retVal = onStackAlready;
+                    retVal.persistInSession( request, response );
+                }
+                else
+                {
+                    //
+                    // We're actually using the newly-created page flow, so call create() on it.
+                    // Note that we make the call to persistInSession *before* create, so the previous flow's
+                    // onDestroy() gets called before the new one's onCreate().
+                    //
+                    retVal.reinitialize( request, response, servletContext );
+                    retVal.persistInSession( request, response );
+                    retVal.create( request, response, servletContext );
+                }
+            }
+            else
+            {
+                //
+                // We're actually using the newly-created page flow, so call create() on it (*after* persisting
+                // in the session so the previous page flow's onDestroy() gets called before the new one's
+                // onCreate()).
+                //
+                retVal.reinitialize( request, response, servletContext );
+                retVal.persistInSession( request, response );
+                if ( createdNew ) retVal.create( request, response, servletContext );
+            }
+        }
+        
+        return retVal;
     }
     
-    public static Map<String, SharedFlowController> getSharedFlowsForRelativeURI( HttpServletRequest request,
-                                                                                  HttpServletResponse response,
-                                                                                  String relativeURI,
-                                                                                  ServletContext servletContext )
+    /**
+     * Create a {@link SharedFlowController} of the given type.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param sharedFlowClassName the type name of the desired SharedFlowController.
+     * @return the newly-created SharedFlowController, or <code>null</code> if none was found.
+     */
+    public SharedFlowController createSharedFlow( RequestContext context, String sharedFlowClassName )
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        Class sharedFlowClass = getFlowControllerClass( sharedFlowClassName );
+        return createSharedFlow( context, sharedFlowClass );
+    }    
+    
+    /**
+     * Create a {@link SharedFlowController} of the given type.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param sharedFlowClass the type of the desired SharedFlowController.
+     * @return the newly-created SharedFlowController, or <code>null</code> if none was found.
+     */
+    public SharedFlowController createSharedFlow( RequestContext context, Class sharedFlowClass )
+            throws InstantiationException, IllegalAccessException
+    {
+        assert SharedFlowController.class.isAssignableFrom( sharedFlowClass ) : sharedFlowClass.getName();
+        
+        if ( _log.isDebugEnabled() )
+        {
+            _log.debug( "Creating SharedFlowController of type " + sharedFlowClass.getName() );
+        }
+        
+        SharedFlowController retVal = ( SharedFlowController ) sharedFlowClass.newInstance();
+        HttpServletRequest request = context.getHttpRequest();
+        HttpServletResponse response = context.getHttpResponse();
+        retVal.create( request, response, getServletContext() );
+        
+        if ( _log.isDebugEnabled() )
+        {
+            _log.debug( "Storing " + retVal + " in the session..." );
+        }
+        
+        retVal.persistInSession( request, response );
+        return retVal;
+    }
+    
+    /**
+     * Get the map of shared flows for the given request.  The map is derived from the shared flows
+     * that are declared (through the <code>sharedFlowRefs</code> attribute of
+     * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller}) in the page flow for the request.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @return a Map of shared-flow-name (String) to {@link SharedFlowController}.
+     * @throws ClassNotFoundException if a declared shared flow class could not be found.
+     * @throws InstantiationException if a declared shared flow class could not be instantiated.
+     * @throws IllegalAccessException if a declared shared flow class was not accessible.
+     */ 
+    public Map< String, SharedFlowController > getSharedFlowsForRequest( RequestContext context )
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException
     {
-        String parentDir = PageFlowUtils.getModulePathForRelativeURI( relativeURI );
-        ModuleConfig mc = InternalUtils.ensureModuleConfig( parentDir, request, servletContext );
+        String path = InternalUtils.getDecodedServletPath( context.getHttpRequest() );
+        return getSharedFlowsForPath( context, path );
+    }
+    
+    /**
+     * Get the map of shared flows for the given path.  The map is derived from the shared flows
+     * that are declared (through the <code>sharedFlowRefs</code> attribute of
+     * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller}) in the page flow for the path.
+     * 
+     * @param context a {@link RequestContext} object which contains the current request and response.
+     * @param path a <strong>webapp-relative</strong> path.  The path should not contain the webapp context path.
+     * @return a Map of shared-flow-name (String) to {@link SharedFlowController}.
+     * @throws ClassNotFoundException if a declared shared flow class could not be found.
+     * @throws InstantiationException if a declared shared flow class could not be instantiated.
+     * @throws IllegalAccessException if a declared shared flow class was not accessible.
+     */ 
+    public Map< String, SharedFlowController > getSharedFlowsForPath( RequestContext context, String path )
+        throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        String parentDir = PageFlowUtils.getModulePathForRelativeURI( path );
+        HttpServletRequest request = context.getHttpRequest();
+        HttpServletResponse response = context.getHttpResponse();
+        ModuleConfig mc = InternalUtils.ensureModuleConfig( parentDir, request, getServletContext() );
         
         if ( mc != null )
         {
@@ -147,21 +426,14 @@
                         //
                         if ( sf != null )
                         {
-                            sf.reinitialize( request, response, servletContext );
+                            sf.reinitialize( request, context.getHttpResponse(), getServletContext() );
                         }
                         else
                         {
-                            try
-                            {
-                                sf = getSharedFlow( className, request, response, servletContext );
-                            }
-                            catch ( ClassNotFoundException e )
-                            {
-                                _log.error( "Requested shared flow class " + className + " not found." );
-                            }
+                            sf = createSharedFlow( context, className );
                         }
                         
-                        if ( sf != null && ! ( sf instanceof GlobalApp ) ) sharedFlows.put( name, sf );
+                        if ( ! ( sf instanceof GlobalApp ) ) sharedFlows.put( name, sf );
                     }
                     
                     return sharedFlows;
@@ -176,48 +448,140 @@
         
         if ( ga != null )
         {
-            ga.reinitialize( request, response, servletContext );
+            ga.reinitialize( request, response, getServletContext() );
         }
         else
         {
-            getGlobalApp( request, response, servletContext );
+            getGlobalApp( request, response, getServletContext() );
         }
         
         return null;
     }    
     
     /**
-     * Get the {@link PageFlowController} for the given type.  The PageFlowController stack (for
-     * nesting) will be cleared or pushed, and the new instance will be stored as the current
-     * PageFlowController.
+     * Get a FlowController class.  By default, this loads the class using the thread context class loader.
+     * @param className the name of the {@link FlowController} class to load.
+     * @return the loaded {@link FlowController} class.
+     * @throws ClassNotFoundException if the requested class could not be found.
+     */ 
+    public Class getFlowControllerClass( String className )
+        throws ClassNotFoundException
+    {
+        return _rch.loadClass( className );
+    }
+    
+    /**
+     * Get the page flow instance that should be associated with the given request.  If it doesn't exist, create it. 
+     * If one is created, the page flow stack (for nesting) will be cleared or pushed, and the new instance will be
+     * stored as the current page flow.
+     * @deprecated Use {@link #getPageFlowForRequest(RequestContext)} instead.
+     * 
+     * @param request the current HttpServletRequest.
+     * @param response the current HttpServletResponse.
+     * @param servletContext the current ServletContext.
+     * @return the {@link PageFlowController} for the request, or <code>null</code> if none was found.
+     */
+    public static PageFlowController getPageFlowForRequest( HttpServletRequest request,  HttpServletResponse response,
+                                                            ServletContext servletContext )
+    {
+        return getPageFlowForRelativeURI( request, response, InternalUtils.getDecodedServletPath( request ), servletContext );
+    }    
+    
+    /**
+     * Get the page flow instance that should be associated with the given URI.  If it doesn't exist, create it. 
+     * If one is created, the page flow stack (for nesting) will be cleared or pushed, and the new instance will be
+     * stored as the current page flow.
+     * @deprecated Use {@link #getPageFlowForPath(RequestContext, String)} instead.  The URI must be stripped of the
+     *     webapp context path before being passed.
      * 
-     * @param jpfClassName the name of the desired PageFlowController class.
      * @param request the current HttpServletRequest.
-     * @return the current user session's PageFlowController if it is of the requested type,
-     *         or a newly-created one, or <code>null</code> if none could be found or created.
+     * @param response the current HttpServletResponse.
+     * @param uri a server-relative URI.  The URI should contain the webapp context path.
+     * @param servletContext the current ServletContext.
+     * @return the {@link PageFlowController} for the given URI, or <code>null</code> if none was found.
      */
-    public static PageFlowController getPageFlow( String jpfClassName, HttpServletRequest request,
+    public static PageFlowController getPageFlowForURI( HttpServletRequest request, HttpServletResponse response,
+                                                        String uri, ServletContext servletContext )
+    {
+        return getPageFlowForRelativeURI( request, response, PageFlowUtils.getRelativeURI( request, uri, null ),
+                                          servletContext );
+    }
+    
+    /**
+     * Get the page flow instance that should be associated with the given path.  If it doesn't exist, create it. 
+     * If one is created, the page flow stack (for nesting) will be cleared or pushed, and the new instance will be
+     * stored as the current page flow.
+     * @deprecated Use {@link #getPageFlowForPath(RequestContext, String)} instead.
+     * 
+     * @param request the current HttpServletRequest.
+     * @param response the current HttpServletResponse.
+     * @param path a <strong>webapp-relative</strong> path.  The path should not contain the webapp context path.
+     * @param servletContext the current ServletContext.
+     * @return the {@link PageFlowController} for the given path, or <code>null</code> if none was found.
+     */
+    public static PageFlowController getPageFlowForRelativeURI( HttpServletRequest request,
+                                                                HttpServletResponse response, String path,
+                                                                ServletContext servletContext )
+    {
+        try
+        {
+            return get( servletContext ).getPageFlowForPath( new RequestContext( request, response ), path );
+        }
+        catch ( InstantiationException e )
+        {
+            _log.error( "Could not instantiate PageFlowController for request " + request.getRequestURI(), e );
+            return null;
+        }
+        catch ( IllegalAccessException e )
+        {
+            _log.error( "Could not instantiate PageFlowController for request " + request.getRequestURI(), e );
+            return null;
+        }
+    }    
+    
+    /**
+     * Create a page flow of the given type.  The page flow stack (for nesting) will be cleared or pushed, and the new
+     * instance will be stored as the current page flow.
+     * @deprecated Use {@link #createPageFlow(RequestContext, String)} instead.
+     * 
+     * @param request the current HttpServletRequest.
+     * @param response the current HttpServletResponse.
+     * @param pageFlowClassName the type name of the desired page flow.
+     * @param servletContext the current ServletContext.
+     * @return the newly-created {@link PageFlowController}, or <code>null</code> if none was found.
+     */
+    public static PageFlowController getPageFlow( String pageFlowClassName, HttpServletRequest request,
                                                   HttpServletResponse response, ServletContext servletContext )
     {
         try
         {
-            Class jpfClass = InternalUtils.getReloadableClass( jpfClassName, servletContext );
-            return getPageFlow( jpfClass, request, response, servletContext );
+            return get( servletContext ).createPageFlow( new RequestContext( request, response ), pageFlowClassName );
         }
         catch ( ClassNotFoundException e)
         {
-            if ( _log.isErrorEnabled() ) _log.error( "Requested page flow class " + jpfClassName + " not found." );
+            if ( _log.isErrorEnabled() ) _log.error( "Requested page flow class " + pageFlowClassName + " not found." );
+            return null;
+        }
+        catch ( InstantiationException e )
+        {
+            _log.error( "Could not instantiate PageFlowController of type " + pageFlowClassName, e );
+            return null;
+        }
+        catch ( IllegalAccessException e )
+        {
+            _log.error( "Could not instantiate PageFlowController of type " + pageFlowClassName, e );
             return null;
         }
     }    
     
     /**
      * Get or create the current user session's GlobalApp instance (from the Global.app file).
+     * @deprecated Global.app is deprecated; use shared flows and {@link #getSharedFlowsForRequest(RequestContext)}.
      * 
      * @param request the current HttpServletRequest.
-     * @return the current session's GlobalApp instance, or a new one (based on Global.app)
-     *         if none is found.  If Global.app does not exist in the current webapp,
-     *         <code>null</code> is returned.
+     * @param response the current HttpServletResponse.
+     * @return the current session's {@link GlobalApp} instance, or a new one (based on Global.app) if none is found.
+     *     If Global.app does not exist in the current webapp, <code>null</code> is returned.
      */
     public static GlobalApp getGlobalApp( HttpServletRequest request, HttpServletResponse response,
                                           ServletContext servletContext )
@@ -227,17 +591,31 @@
         
         try
         {
-            SharedFlowController sf =
-                    getSharedFlow( PageFlowConstants.GLOBALAPP_CLASSNAME, request, response, servletContext );
-            
-            if ( ! ( sf instanceof GlobalApp ) )
+            try
+            {
+                FlowControllerFactory factory = get( servletContext );
+                SharedFlowController sf =
+                    factory.createSharedFlow( new RequestContext( request, response ), PageFlowConstants.GLOBALAPP_CLASSNAME );
+                
+                if ( ! ( sf instanceof GlobalApp ) )
+                {
+                    _log.error( "Class " + PageFlowConstants.GLOBALAPP_CLASSNAME + " is not an instance of "
+                                + GlobalApp.class.getName() );
+                    return null;
+                }
+                
+                return ( GlobalApp ) sf;
+            }
+            catch ( InstantiationException e )
             {
-                _log.error( "Class " + PageFlowConstants.GLOBALAPP_CLASSNAME + " is not an instance of "
-                            + GlobalApp.class.getName() );
+                _log.error( "Could not instantiate Global.app.", e );
+                return null;
+            }
+            catch ( IllegalAccessException e )
+            {
+                _log.error( "Could not instantiate Global.app", e );
                 return null;
             }
-            
-            return ( GlobalApp ) sf;
         }
         catch ( ClassNotFoundException e )
         {
@@ -246,15 +624,7 @@
         }
     }    
     
-    public static SharedFlowController getSharedFlow( String sharedFlowClassName, HttpServletRequest request,
-                                                      HttpServletResponse response, ServletContext servletContext )
-        throws ClassNotFoundException
-    {
-        Class sfClass = InternalUtils.getReloadableClass( sharedFlowClassName, servletContext );
-        return getSharedFlow( sfClass, request, response, servletContext );
-    }    
-    
-    private static ModuleConfig ensureModule( String modulePath, HttpServletRequest request,
+    private static ModuleConfig ensureModule( String modulePath, ServletRequest request,
                                               ServletContext servletContext )
     {
         ModuleConfig mc = InternalUtils.getModuleConfig( modulePath, servletContext );        
@@ -286,227 +656,32 @@
     }
     
     /**
-     * Get the {@link PageFlowController} for the given type.  The PageFlowController stack (for
-     * nesting) will be cleared or pushed, and the new instance will be stored as the current
-     * PageFlowController.
+     * Create a page flow of the given type.  The page flow stack (for nesting) will be cleared or pushed, and the new
+     * instance will be stored as the current page flow.
+     * @deprecated Use {@link #createPageFlow(RequestContext, Class)} instead.
      * 
-     * @param jpfClass the desired PageFlowController class.
      * @param request the current HttpServletRequest.
-     * @return the current user session's PageFlowController if it is of the requested type,
-     *         or a newly-created one, or <code>null</code> if none could be found or created.
+     * @param response the current HttpServletResponse.
+     * @param pageFlowClass the type of the desired page flow.
+     * @param servletContext the current ServletContext.
+     * @return the newly-created {@link PageFlowController}, or <code>null</code> if none was found.
      */
-    public static PageFlowController getPageFlow( Class jpfClass, HttpServletRequest request,
+    public static PageFlowController getPageFlow( Class pageFlowClass, HttpServletRequest request,
                                                   HttpServletResponse response, ServletContext servletContext )
     {
-        if ( ! PageFlowController.class.isAssignableFrom( jpfClass ) )
-        {
-            return null;
-        }
-        
         try
         {
-            //
-            // First check if this is a request for a "long lived" page flow.  If so, try
-            // PageFlowUtils.getCurrentPageFlow again, with the longLived flag.
-            //
-            PageFlowController retVal = null;
-            String modulePath = InternalUtils.inferModulePathFromClassName( jpfClass.getName() );
-            ModuleConfig mc = ensureModule( modulePath, request, servletContext );
-            
-            if ( mc == null )
-            {
-                _log.error( "Struts module " + modulePath + " not found for " + jpfClass.getName()
-                            + "; cannot create page flow.");
-                return null;
-            }
-            
-            if ( InternalUtils.isLongLived( mc ) )
-            {
-                retVal = PageFlowUtils.getLongLivedPageFlow( modulePath, request );
-                
-                if ( _log.isDebugEnabled() )
-                {
-                    if ( retVal != null )
-                    {
-                        _log.debug( "Using long lived PageFlowController of type " + jpfClass.getName() );
-                    }
-                }
-            }
-            
-            //
-            // First, see if this is a nested page flow that's already on the stack.  Unless "renesting" is explicitly
-            // enabled, we don't want to allow another instance of this page flow to be nested.  This is a common
-            // browser back-button problem:
-            //    1) request nested page flow A
-            //    2) request nested page flow B
-            //    3) press back button, and execute an action on A.
-            //
-            // This logic does not deal with immediate self-nesting (A->A), which is taken care of in
-            // PageFlowController.forwardTo().  Nested page flows can only self-nest by forwarding to the .jpf URI, not
-            // indirectly by executing actions on themselves (think about it -- that would be a disaster).
-            //
-            boolean createdNew = false;
-            boolean isNestable = InternalUtils.isNestable( mc );
-            PageFlowStack pfStack = PageFlowStack.get( request, false );
-            
-            if ( isNestable && pfStack != null )
-            {
-                PageflowConfig options = ConfigUtil.getConfig().getPageflowConfig();
-                
-                if ( options == null || ! options.getEnableRenesting() )
-                {
-                    int lastIndexOfJpfClass = pfStack.lastIndexOf( request, jpfClass );
-                    
-                    if ( lastIndexOfJpfClass != -1 )
-                    {
-                        retVal = pfStack.popUntil( request, lastIndexOfJpfClass );
-                        retVal.persistInSession( request, response );
-                        return retVal;
-                    }
-                }
-            }
-            
-            //
-            // OK, if it's not an existing long lived page flow, and if this wasn't a nested page flow already on the
-            // stack, then create a new instance.
-            //
-            if ( retVal == null )
-            {
-                if ( _log.isDebugEnabled() )
-                {
-                    _log.debug( "Creating PageFlowController of type " + jpfClass.getName() );
-                }
-
-                retVal = ( PageFlowController ) jpfClass.newInstance();
-                createdNew = true;
-            }
-            
-            //
-            // Store the previous PageFlowController on the nesting stack (if this one is nestable),
-            // or destroy the nesting stack.
-            //
-            if ( isNestable )
-            {
-                //
-                // Call create() on the newly-created page flow.
-                //
-                retVal.create( request, response, servletContext );
-                PageFlowController current = PageFlowUtils.getCurrentPageFlow( request );
-                
-                if ( current != null )
-                {
-                    if ( _log.isDebugEnabled() )
-                    {
-                        _log.debug( "Pushing PageFlowController " + current + " onto the nesting stack" );
-                    }
-
-                    if ( pfStack == null ) pfStack = PageFlowStack.get( request, true );
-                    pfStack.push( current, request );
-                }
-                
-                retVal.persistInSession( request, response );
-            }
-            else
-            {
-                //
-                // Going to a non-nested pageflow.  Blow away the pageflow stack.
-                //
-                if ( pfStack != null )
-                {
-                    if ( _log.isDebugEnabled() )
-                    {
-                        _log.debug( "Destroying the PageFlowController stack." );
-                    }
-                 
-                    //
-                    // Start popping page flows until 1) there are none left on the stack, or 2) we find
-                    // one of the type we're returning.  If (2), we'll use that one (this means that executing
-                    // an action on a nesting page flow while in a nested one will not destroy the nesting
-                    // page flow only to create a new instance of it).
-                    //
-                    PageFlowController onStackAlready = pfStack.popUntil( request, retVal.getClass() );
-
-                    if ( onStackAlready != null )
-                    {
-                        if ( _log.isDebugEnabled() )
-                        {
-                            _log.debug( "Found a page flow of type " + retVal.getClass() + " in the stack; "
-                                       + "using that instance and stopping destruction of the nesting stack." );
-                        }
-
-                        retVal = onStackAlready;
-                        retVal.persistInSession( request, response );
-                    }
-                    else
-                    {
-                        //
-                        // We're actually using the newly-created page flow, so call create() on it.
-                        // Note that we make the call to persistInSession *before* create, so the previous flow's
-                        // onDestroy() gets called before the new one's onCreate().
-                        //
-                        retVal.reinitialize( request, response, servletContext );
-                        retVal.persistInSession( request, response );
-                        retVal.create( request, response, servletContext );
-                    }
-                }
-                else
-                {
-                    //
-                    // We're actually using the newly-created page flow, so call create() on it (*after* persisting
-                    // in the session so the previous page flow's onDestroy() gets called before the new one's
-                    // onCreate()).
-                    //
-                    retVal.reinitialize( request, response, servletContext );
-                    retVal.persistInSession( request, response );
-                    if ( createdNew ) retVal.create( request, response, servletContext );
-                }
-            }
-                            
-            return retVal;
-        }
-        catch ( InstantiationException e )
-        {
-            _log.error( "Could not instantiate PageFlowController of type " + jpfClass.getName(), e );
-            return null;
-        }
-        catch ( IllegalAccessException e )
-        {
-            _log.error( "Could not instantiate PageFlowController of type " + jpfClass.getName(), e );
-            return null;
-        }
-    }        
-    
-    public static SharedFlowController getSharedFlow( Class sfClass, HttpServletRequest request,
-                                                      HttpServletResponse response, ServletContext servletContext )
-    {
-        assert SharedFlowController.class.isAssignableFrom( sfClass ) : sfClass.getName();
-        
-        if ( _log.isDebugEnabled() )
-        {
-            _log.debug( "Creating SharedFlowController of type " + sfClass.getName() );
-        }
-
-        try
-        {
-            SharedFlowController retVal = ( SharedFlowController ) sfClass.newInstance();
-            retVal.create( request, response, servletContext );
-            
-            if ( _log.isDebugEnabled() )
-            {
-                _log.debug( "Storing " + retVal + " in the session..." );
-            }
-            
-            retVal.persistInSession( request, response );
-            return retVal;
+            FlowControllerFactory factory = get( servletContext );
+            return factory.createPageFlow( new RequestContext( request, response ), pageFlowClass );
         }
         catch ( InstantiationException e )
         {
-            _log.error( "Could not instantiate SharedFlowController of type " + sfClass.getName(), e );
+            _log.error( "Could not instantiate PageFlowController of type " + pageFlowClass.getName(), e );
             return null;
         }
         catch ( IllegalAccessException e )
         {
-            _log.error( "Could not instantiate SharedFlowController of type " + sfClass.getName(), e );
+            _log.error( "Could not instantiate PageFlowController of type " + pageFlowClass.getName(), e );
             return null;
         }
     }

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java Thu Feb  3 12:57:47 2005
@@ -98,19 +98,20 @@
         }
     }
 
-    public void init( ServletConfig config )
+    public void init()
             throws ServletException
     {
+        super.init();
+        
         //
         // Ensure that PageFlowContextListener gets to do its initializations, even if it's not registered in web.xml.
         //
-        ServletContext servletContext = config.getServletContext();
+        ServletContext servletContext = getServletContext();
+        
         if ( ! PageFlowContextListener.isInit( servletContext ) )
         {
             PageFlowContextListener.performInitializations( servletContext );
         }
-        
-        super.init( config );
     }
 
     /**

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java Thu Feb  3 12:57:47 2005
@@ -824,8 +824,22 @@
                     _log.debug( "Self-nesting page flow " + getURI() );
                 }
                 
-                // This will cause the right pageflow stack stuff to happen.
-                FlowControllerFactory.getPageFlow( getClass(), request, response, getServletContext() );
+                try
+                {
+                    // This will cause the right pageflow stack stuff to happen.
+                    RequestContext rc = new RequestContext( request, response );
+                    FlowControllerFactory.get( getServletContext() ).createPageFlow( rc, getClass() );
+                }
+                catch ( IllegalAccessException e )
+                {
+                    // This should never happen -- if we successfully created this page flow once, we can do it again.
+                    assert false : e;
+                    _log.error( e );
+                }
+                catch ( InstantiationException e )
+                {
+                    _log.error( "Could not create PageFlowController instance of type " + getClass().getName(), e );
+                }
             }
         }
         

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java Thu Feb  3 12:57:47 2005
@@ -36,7 +36,6 @@
 import org.apache.struts.action.ActionMapping;
 import org.apache.struts.action.ActionForm;
 import org.apache.struts.action.ActionForward;
-import org.apache.struts.action.RequestProcessor;
 import org.apache.struts.config.ModuleConfig;
 import org.apache.struts.Globals;
 
@@ -59,6 +58,7 @@
 {
     private ServletContext _servletContext;
     private ServletContainerAdapter _servletContainerAdapter;
+    private FlowControllerFactory _flowControllerFactory;
     
     private static final Logger _log = Logger.getInstance( PageFlowPageFilter.class );
     
@@ -73,6 +73,7 @@
     {
         _servletContext = servletContext;
         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( _servletContext );
+        _flowControllerFactory = FlowControllerFactory.get( servletContext );
     }
 
     public void init( FilterConfig filterConfig ) throws ServletException
@@ -85,6 +86,7 @@
         }
         
         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( _servletContext );
+        _flowControllerFactory = FlowControllerFactory.get( _servletContext );
     }
     
     protected abstract Set getValidFileExtensions();
@@ -170,38 +172,53 @@
                 MessageResources prevMessageResources = ( MessageResources ) request.getAttribute( Globals.MESSAGES_KEY );
                 initializeModule( httpRequest, httpResponse );
                 
-                //
-                // Initialize shared flows for the current request.
-                //
-                Map< String, SharedFlowController > sharedFlows =
-                        FlowControllerFactory.getSharedFlowsForRequest( httpRequest, httpResponse, _servletContext );
-                ImplicitObjectUtil.loadSharedFlow( request, sharedFlows );
-                ImplicitObjectUtil.loadGlobalApp( request, PageFlowUtils.getGlobalApp( httpRequest ) );
-                
-                //
-                // Make sure that the current PageFlowController is set up for this request.
-                //
-                PageFlowController curJpf = 
-                        FlowControllerFactory.getPageFlowForRequest( httpRequest, httpResponse, _servletContext );
-                
-                //
-                // If there is no pageflow for the current Struts module, than fall back to default
-                // Struts behavior, which is *not* to allow a page request to set the current module.
-                //
-                if ( curJpf == null )
+                try
                 {
-                    InternalUtils.setCurrentModule( prevModuleConfig, request );
-                    request.setAttribute( Globals.MESSAGES_KEY, prevMessageResources );
+                    //
+                    // Initialize shared flows for the current request.
+                    //
+                    RequestContext requestContext = new RequestContext( request, response );
+                    Map< String, SharedFlowController > sharedFlows =
+                            _flowControllerFactory.getSharedFlowsForRequest( requestContext );
+                    ImplicitObjectUtil.loadSharedFlow( request, sharedFlows );
+                    ImplicitObjectUtil.loadGlobalApp( request, PageFlowUtils.getGlobalApp( httpRequest ) );
+                    
+                    //
+                    // Make sure that the current PageFlowController is set up for this request.
+                    //
+                    PageFlowController curJpf = _flowControllerFactory.getPageFlowForRequest( requestContext );
+                    
+                    //
+                    // If there is no pageflow for the current Struts module, than fall back to default
+                    // Struts behavior, which is *not* to allow a page request to set the current module.
+                    //
+                    if ( curJpf == null )
+                    {
+                        InternalUtils.setCurrentModule( prevModuleConfig, request );
+                        request.setAttribute( Globals.MESSAGES_KEY, prevMessageResources );
+                    }
+                    
+                    
+                    if ( _log.isDebugEnabled() )
+                    {
+                        _log.debug( "Current PageFlowController is: " + curJpf );
+                        _log.debug( "Continuing with filter chain..." );
+                    }
+                    
+                    runPage( curJpf, httpRequest, httpResponse, chain );
                 }
-                
-                
-                if ( _log.isDebugEnabled() )
+                catch ( ClassNotFoundException e )
                 {
-                    _log.debug( "Current PageFlowController is: " + curJpf );
-                    _log.debug( "Continuing with filter chain..." );
+                    throw new ServletException( e );
+                }
+                catch ( InstantiationException e )
+                {
+                    throw new ServletException( e );
+                }
+                catch ( IllegalAccessException e )
+                {
+                    throw new ServletException( e );
                 }
-                
-                runPage( curJpf, httpRequest, httpResponse, chain );
             }
             finally
             {

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java Thu Feb  3 12:57:47 2005
@@ -126,6 +126,7 @@
     private Map< String, List< ActionMapping > > _overloadedActions = new HashMap< String, List< ActionMapping > >();
     private ServletContainerAdapter _servletContainerAdapter;
     private Handlers _handlers;
+    private FlowControllerFactory _flowControllerFactory;
     private LegacySettings _legacySettings;
     private ConcurrentHashMap< String, Class > _pageServletClasses = new ConcurrentHashMap< String, Class >();
     private PageFlowPageFilter _pageServletFilter;
@@ -538,30 +539,40 @@
             _log.info( "Attempting to instantiate SharedFlowControllers for request " + request.getRequestURI() );
         }
         
-        Map< String, SharedFlowController > sharedFlows =
-                FlowControllerFactory.getSharedFlowsForRequest( request, response, servletContext );
-        ImplicitObjectUtil.loadSharedFlow( request, sharedFlows );
-        ImplicitObjectUtil.loadGlobalApp( request, PageFlowUtils.getGlobalApp( request ) );
-        
         FlowController currentFlowController = null;
         
-        if ( flowControllerClassName != null )
+        try
         {
-            try
+            RequestContext requestContext = new RequestContext( request, response );
+            Map< String, SharedFlowController > sharedFlows =
+                    _flowControllerFactory.getSharedFlowsForRequest( requestContext );
+            ImplicitObjectUtil.loadSharedFlow( request, sharedFlows );
+            ImplicitObjectUtil.loadGlobalApp( request, PageFlowUtils.getGlobalApp( request ) );
+            
+            if ( flowControllerClassName != null )
             {
-                currentFlowController = 
-                        InternalUtils.getFlowController( flowControllerClassName, request,  response, servletContext );
+                currentFlowController = getFlowController( requestContext, flowControllerClassName );
                 RequestValues.setCurrentFlowController( request, currentFlowController );
             }
-            catch ( ClassNotFoundException e )
+            else
             {
-                _log.error( "Could not find FlowController class " + flowControllerClassName, e );
-                throw new ServletException( e );
+                RequestValues.removeCurrentFlowController( request );
             }
         }
-        else
+        catch ( ClassNotFoundException e )
         {
-            RequestValues.removeCurrentFlowController( request );
+            _log.error( "Could not find FlowController class " + flowControllerClassName, e );
+            throw new ServletException( e );
+        }
+        catch ( InstantiationException e )
+        {
+            _log.error( "Could not instantiate FlowController of type " + flowControllerClassName, e );
+            throw new ServletException( e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            _log.error( "Could not instantiate FlowController of type " + flowControllerClassName, e );
+            throw new ServletException( e );
         }
         
         //
@@ -595,6 +606,49 @@
         }
     }
     
+    private FlowController getFlowController( RequestContext requestContext, String fcClassName )
+        throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        Class fcClass = _flowControllerFactory.getFlowControllerClass( fcClassName );
+        HttpServletRequest request = requestContext.getHttpRequest();
+        HttpServletResponse response = requestContext.getHttpResponse();
+        
+        if ( PageFlowController.class.isAssignableFrom( fcClass ) )
+        {
+            PageFlowController current = PageFlowUtils.getCurrentPageFlow( request );
+            
+            if ( current != null && current.getClass().equals( fcClass ) )
+            {
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Using current page flow: " + current );
+                }
+                
+                //
+                // Reinitialize transient data that may have been lost on session failover.
+                //
+                current.reinitialize( request, response, getServletContext() );
+                return current;
+            }
+            
+            return _flowControllerFactory.createPageFlow( new RequestContext( request, response ), fcClass );
+        }
+        else
+        {
+            assert SharedFlowController.class.isAssignableFrom( fcClass ) : fcClass.getName();
+            
+            SharedFlowController current = PageFlowUtils.getSharedFlow( fcClass.getName(), request );
+            
+            if ( current != null )
+            {
+                current.reinitialize( request, response, getServletContext() );
+                return current;
+            }
+            
+            return _flowControllerFactory.createSharedFlow( new RequestContext( request, response ), fcClass );
+        }
+    }
+    
     private boolean handleException( Throwable th, FlowController fc, HttpServletRequest request,
                                      HttpServletResponse response )
     {
@@ -651,6 +705,7 @@
                     _log.error( msg.toString() );
                 }
 
+                if ( modulePath.length() == 0 ) modulePath = "/";
                 InternalUtils.sendDevTimeError( "PageFlow_NoModuleConf", null,
                                                 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, request, response,
                                                 getServletContext(), uri, modulePath );
@@ -1001,6 +1056,7 @@
         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( getServletContext() );
         _legacySettings = LegacySettings.get( getServletContext() );
         _handlers = Handlers.get( getServletContext() );
+        _flowControllerFactory = FlowControllerFactory.get( getServletContext() );
         
         //
         // Cache a list of overloaded actions for each overloaded action path (actions are overloaded by form bean type).
@@ -1563,8 +1619,7 @@
         Map attrs = new HashMap();
         String queryString = null;
         ServletContext servletContext = getServletContext();
-        assert context.getRequest() instanceof HttpServletRequest : "don't support ServletRequest currently.";
-        HttpServletRequest request = ( HttpServletRequest ) context.getRequest();
+        HttpServletRequest request = ( ( RequestContext ) context ).getHttpRequest();
         
         for ( Enumeration e = request.getAttributeNames(); e.hasMoreElements(); )
         {

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java Thu Feb  3 12:57:47 2005
@@ -1003,8 +1003,23 @@
     public static GlobalApp ensureGlobalApp( HttpServletRequest request, HttpServletResponse response,
                                              ServletContext servletContext )
     {
-        Map< String, SharedFlowController > sf =
-                FlowControllerFactory.getSharedFlowsForRequest( request, response, servletContext );
+        try
+        {
+            FlowControllerFactory.get( servletContext ).getSharedFlowsForRequest( new RequestContext( request, response ) );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            _log.error( e );
+        }
+        catch ( InstantiationException e )
+        {
+            _log.error( e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            _log.error( e );
+        }
+        
         return getGlobalApp( request );
     }
     
@@ -1092,7 +1107,21 @@
                                                                   HttpServletResponse response,
                                                                   ServletContext servletContext )
     {
-        return FlowControllerFactory.getPageFlowForRequest( request, response, servletContext );
+        try
+        {
+            FlowControllerFactory factory = FlowControllerFactory.get( servletContext );
+            return factory.getPageFlowForRequest( new RequestContext( request, response ) );
+        }
+        catch ( InstantiationException e )
+        {
+            _log.error( "Could not instantiate PageFlowController for request " + request.getRequestURI(), e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            _log.error( "Could not instantiate PageFlowController for request " + request.getRequestURI(), e );
+        }
+        
+        return null;
     }
     
     /**
@@ -1108,7 +1137,7 @@
             _log.warn( "could not get ServletContext from request " + request );
         }
         
-        return FlowControllerFactory.getPageFlowForRequest( request, response, servletContext );
+        return ensureCurrentPageFlow( request, response, servletContext );
     }
     
     /**

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/RequestContext.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/RequestContext.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/RequestContext.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/RequestContext.java Thu Feb  3 12:57:47 2005
@@ -19,6 +19,8 @@
 
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 public class RequestContext
 {
@@ -39,5 +41,17 @@
     public ServletResponse getResponse()
     {
         return _response;
+    }
+    
+    HttpServletRequest getHttpRequest()
+    {
+        assert _request instanceof HttpServletRequest : "HttpServletRequest is currently required";
+        return ( HttpServletRequest ) _request;
+    }
+    
+    HttpServletResponse getHttpResponse()
+    {
+        assert _response instanceof HttpServletResponse : "HttpServletResponse is currently required";
+        return ( HttpServletResponse ) _response;
     }
 }

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/PageFlowNavigationHandler.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/PageFlowNavigationHandler.java?view=diff&r1=151228&r2=151229
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/PageFlowNavigationHandler.java (original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/faces/internal/PageFlowNavigationHandler.java Thu Feb  3 12:57:47 2005
@@ -30,6 +30,7 @@
 import org.apache.beehive.netui.pageflow.PageFlowUtils;
 import org.apache.beehive.netui.pageflow.PageFlowConstants;
 import org.apache.beehive.netui.pageflow.FlowControllerFactory;
+import org.apache.beehive.netui.pageflow.RequestContext;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.util.logging.Logger;
 
@@ -76,39 +77,53 @@
                 return;
             }
             
-            ServletContext servletContext = ( ServletContext ) extContext;
-            PageFlowController pfc = FlowControllerFactory.getPageFlowForRequest( httpRequest, httpResponse, servletContext );
-            PageFlowUtils.getCurrentPageFlow( httpRequest );
-
-            if ( pfc != null )
+            try
             {
-                if ( outcome != null )
+                ServletContext servletContext = ( ServletContext ) extContext;
+                FlowControllerFactory fcFactory = FlowControllerFactory.get( servletContext );
+                PageFlowController pfc = fcFactory.getPageFlowForRequest( new RequestContext( httpRequest, httpResponse ) );
+                PageFlowUtils.getCurrentPageFlow( httpRequest );
+    
+                if ( pfc != null )
                 {
-                    String actionURI = outcome + PageFlowConstants.ACTION_EXTENSION;
-                    
-                    if ( _log.isDebugEnabled() )
-                    {
-                        _log.debug( "Forwarding to " + actionURI );
-                    }
-                    
-                    context.responseComplete();
-                    context.setViewRoot( null );
-                    httpRequest.setAttribute( ALREADY_FORWARDED_ATTR, Boolean.TRUE );
-                    
-                    try
-                    {
-                        httpRequest.getRequestDispatcher( actionURI ).forward( httpRequest, httpResponse );
-                    }
-                    catch ( IOException e )
-                    {
-                        _log.error( "Could not forward to " + actionURI, e );
-                    }
-                    catch ( ServletException e )
+                    if ( outcome != null )
                     {
-                        _log.error( "Could not forward to " + actionURI, e.getRootCause() );
+                        String actionURI = outcome + PageFlowConstants.ACTION_EXTENSION;
+                        
+                        if ( _log.isDebugEnabled() )
+                        {
+                            _log.debug( "Forwarding to " + actionURI );
+                        }
+                        
+                        context.responseComplete();
+                        context.setViewRoot( null );
+                        httpRequest.setAttribute( ALREADY_FORWARDED_ATTR, Boolean.TRUE );
+                        
+                        try
+                        {
+                            httpRequest.getRequestDispatcher( actionURI ).forward( httpRequest, httpResponse );
+                        }
+                        catch ( IOException e )
+                        {
+                            _log.error( "Could not forward to " + actionURI, e );
+                        }
+                        catch ( ServletException e )
+                        {
+                            _log.error( "Could not forward to " + actionURI, e.getRootCause() );
+                        }
                     }
+    
+                    return;
                 }
-
+            }
+            catch ( InstantiationException e )
+            {
+                _log.error( "Could not instantiate PageFlowController for request " + httpRequest.getRequestURI(), e );
+                return;
+            }
+            catch ( IllegalAccessException e )
+            {
+                _log.error( "Could not instantiate PageFlowController for request " + httpRequest.getRequestURI(), e );
                 return;
             }
         }