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/09/27 06:02:45 UTC

svn commit: r291814 [1/2] - in /beehive/trunk/netui: src/pageflow/org/apache/beehive/netui/pageflow/ src/pageflow/org/apache/beehive/netui/pageflow/internal/ test/ant/ test/src/junitTests/org/apache/beehive/netui/test/pageflow/ test/src/junitTests/org/...

Author: rich
Date: Mon Sep 26 21:02:25 2005
New Revision: 291814

URL: http://svn.apache.org/viewcvs?rev=291814&view=rev
Log:
Fix for http://issues.apache.org/jira/browse/BEEHIVE-941 : Need APIs for getUserPrincipal/isUserInRole, when a custom LoginHandler is configured

Also made some fixes/additions to MockPageFlowTestCase, and factored out Page Flow runtime initialization from PageFlowContextListener to an (internal) PageFlowInitialization.

tests: bvt in netui (WinXP)
BB: bvt in netui (linux)


Added:
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/PageFlowInitialization.java   (with props)
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java   (with props)
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginTest.java   (with props)
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/TestLoginHandler.java   (with props)
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/test-beehive-netui-config.xml   (with props)
Modified:
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/LegacySettings.java
    beehive/trunk/netui/test/ant/junitCore.xml
    beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/MockPageFlowTestCase.java

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java Mon Sep 26 21:02:25 2005
@@ -56,7 +56,11 @@
     {
     }
     
-    static void init( ServletContext servletContext )
+    /**
+     * Initialize an instance of this class in the ServletContext.  This is a framework-invoked method and should
+     * normally be called directly.
+     */
+    public static void init( ServletContext servletContext )
     {
         PageFlowFactoriesConfig factoriesBean = ConfigUtil.getConfig().getPageFlowFactories();
         FacesBackingBeanFactory factory = null;

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java Mon Sep 26 21:02:25 2005
@@ -66,17 +66,17 @@
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
-
+import java.security.Principal;
 
 
 /**
  * Base class for user-written flow controllers - {@link PageFlowController}s and {@link SharedFlowController}s.
- */ 
+ */
 public abstract class FlowController extends PageFlowManagedObject
         implements PageFlowConstants, ActionResolver
 {
     private static final Logger _log = Logger.getInstance( FlowController.class );
-    
+
     private static final String ONCREATE_EXCEPTION_FORWARD = InternalConstants.ATTR_PREFIX + "onCreateException";
     private static final String CACHEID_ACTION_METHODS = InternalConstants.ATTR_PREFIX + "actionMethods";
     private static final int DEFAULT_MAX_CONCURRENT_REQUEST_COUNT = 4;
@@ -85,7 +85,7 @@
     private static final Locale DEFAULT_LOCALE = Locale.getDefault();
     private static final ActionForward NULL_ACTION_FORWARD = new ActionForward();
     private static final TokenProcessor TOKEN_PROCESSOR = TokenProcessor.getInstance();
-    
+
     /**
      * The system default Locale.
      * 
@@ -100,10 +100,10 @@
      * @deprecated This variable will be removed with no replacement.  In most cases,
      *             {@link FlowController#getServletContext()} is sufficient; for other cases, the ActionServlet itself
      *             is in the ServletContext attribute {@link Globals#ACTION_SERVLET_KEY}.
-     */ 
+     */
     protected transient ActionServlet servlet = null;
-    
-    
+
+
     static class PerRequestState
     {
         private HttpServletRequest _request;
@@ -135,35 +135,35 @@
 
     /**
      * Stores per-request state, which is <i>only valid during calls to {@link FlowController#execute} or {@link FlowController#handleException}</i>.
-     */ 
+     */
     private transient PerRequestState _perRequestState;
 
     /**
      * Cached reference to the associated Struts ModuleConfig.
-     */ 
+     */
     private transient ModuleConfig _moduleConfig = null;
 
     /**
      * @see #incrementRequestCount
-     */ 
+     */
     private transient int _requestCount = 0;
-    
+
     /**
      * @see #incrementRequestCount
-     */ 
+     */
     private static int _maxConcurrentRequestCount = -1;
-    
+
 
     /**
      * Default constructor.
-     */ 
+     */
     protected FlowController()
     {
     }
 
     /**
      * Reinitialize the object for a new request.  Used by the framework; normally should not be called directly.
-     */ 
+     */
     public void reinitialize( HttpServletRequest request, HttpServletResponse response, ServletContext servletContext )
     {
         //
@@ -176,7 +176,8 @@
     }
 
     /**
-     * Log in the user, using "weak" username/password authentication.
+     * Log in the user, using "weak" username/password authentication.  Goes through a custom {@link LoginHandler}, if
+     * one has been configured in beehive-netui-config.xml.
      *
      * @param username the user's login name
      * @param password the user's password
@@ -189,9 +190,10 @@
         LoginHandler lh = Handlers.get( getServletContext() ).getLoginHandler();
         lh.login( getHandlerContext(), username, password );
     }
-    
+
     /**
-     * Log out the current user.
+     * Log out the current user.  Goes through a custom {@link LoginHandler}, if one has been configured in
+     * beehive-netui-config.xml.
      * 
      * @param invalidateSessions if true, the session is invalidated (on all single-signon webapps); 
      *            otherwise the session and its data are left intact (except for authentication
@@ -206,6 +208,32 @@
     }
 
     /**
+     * Get the current logged-in user.  Goes through a custom {@link LoginHandler}, if one has been configured in
+     * beehive-netui-config.xml.
+     * 
+     * @return the current logged-in <code>Principal</code>, or <code>null</code> if there is no logged-in user.
+     */
+    public Principal getUserPrincipal()
+    {
+        LoginHandler lh = Handlers.get( getServletContext() ).getLoginHandler();
+        return lh.getUserPrincipal(getHandlerContext());
+    }
+
+    /**
+     * Tell whether the current logged-in user is a member of a given role.  Goes through a custom {@link LoginHandler},
+     * if one has been configured in beehive-netui-config.xml.
+     * 
+     * @param roleName the name of the role to test.
+     * @return <code>true</code> if there is a current logged-in user and the user is a member of the given role.
+     * @see #getUserPrincipal
+     */
+    public boolean isUserInRole(String roleName)
+    {
+        LoginHandler lh = Handlers.get( getServletContext() ).getLoginHandler();
+        return lh.isUserInRole(getHandlerContext(), roleName);
+    }
+    
+    /**
      * Send a Page Flow error to the browser.
      * 
      * @deprecated Use {@link FlowController#sendError(String, HttpServletRequest, HttpServletResponse)} instead.
@@ -217,7 +245,7 @@
     {
         sendError( errText, null, response );
     }
-    
+
     /**
      * Send a Page Flow error to the browser.
      * 
@@ -227,10 +255,10 @@
     protected void sendError( String errText, HttpServletRequest request, HttpServletResponse response )
         throws IOException
     {
-        InternalUtils.sendError( "PageFlow_Custom_Error", null, request, response, 
+        InternalUtils.sendError( "PageFlow_Custom_Error", null, request, response,
                                  new Object[]{ getDisplayName(), errText } );
     }
-    
+
     /**
      * Handle the given exception - invoke user code if appropriate and return a destination URI.
      * 
@@ -241,19 +269,19 @@
      * @param response the current HttpServletResponse.
      * @return a Struts ActionForward object that specifies the URI that should be displayed.
      * @throws ServletException if another Exception is thrown during handling of <code>ex</code>.
-     */ 
+     */
     public synchronized ActionForward handleException( Throwable ex, ActionMapping mapping,
                                                        ActionForm form, HttpServletRequest request,
                                                        HttpServletResponse response )
         throws IOException, ServletException
     {
         PerRequestState prevState = setPerRequestState( new PerRequestState( request, response, mapping ) );
-        
+
         try
         {
             ExceptionsHandler eh = Handlers.get( getServletContext() ).getExceptionsHandler();
             FlowControllerHandlerContext context = getHandlerContext();
-            
+
             // First, put the exception into the request (or other applicable context).
             Throwable unwrapped = eh.unwrapException( context, ex );
             eh.exposeException( context, unwrapped, mapping );
@@ -264,7 +292,7 @@
             setPerRequestState( prevState );
         }
     }
-    
+
     /**
      * Get the name of the current action being executed.  This call is only valid
      * during {@link FlowController#execute} (where any user action method is invoked), and during the lifecycle
@@ -280,7 +308,7 @@
     {
         return InternalUtils.getActionName( getActionMapping() );
     }
-    
+
     /**
      * Perform decision logic to determine the next URI to be displayed.
      * 
@@ -331,20 +359,20 @@
         RequestContext requestContext = new RequestContext( request, response );
         eventReporter.actionRaised( requestContext, this, mapping, form );
         long startTime = System.currentTimeMillis();
-        
+
         //
         // If we handled an exception in onCreate, just forward to the result of that.
         //
         ActionForward onCreateFwd = ( ActionForward ) request.getAttribute( ONCREATE_EXCEPTION_FORWARD );
-        
+
         if ( onCreateFwd != null )
         {
             return onCreateFwd == NULL_ACTION_FORWARD ? null : onCreateFwd;
         }
-        
-        
+
+
         PageFlowUtils.setActionURI( request );
-        
+
         //
         // First change the actionPath (path) so that it lines up with our naming convention
         // for action methods.
@@ -360,11 +388,11 @@
             //
             beforeAction();
             gotPastBeforeAction = true;
-            
+
             PageFlowActionMapping pfActionMapping =
                     mapping instanceof PageFlowActionMapping ? ( PageFlowActionMapping ) mapping : null;
             Object unwrappedForm = InternalUtils.unwrapFormBean( form );
-            
+
             //
             // mapping.isOverloaded() means it's the base mapping for a set of overloaded mappings.
             // Find the one appropriate to the passed-in form.
@@ -382,39 +410,39 @@
                     {
                         String formQualifiedActionPath = getFormQualifiedActionPath( i, mappingPath );
                         ActionConfig cf = pfActionMapping.getModuleConfig().findActionConfig( formQualifiedActionPath );
-                            
+
                         if ( cf != null )
                         {
                             assert cf instanceof PageFlowActionMapping : cf.getClass().getName();
-                                
+
                             if ( _log.isDebugEnabled() )
                             {
                                 _log.debug( "Found form-specific mapping " + cf.getPath() +
                                            " -- choosing this one over current mapping " + mappingPath );
                             }
-                                
+
                             pfActionMapping = ( PageFlowActionMapping ) cf;
                             mapping = pfActionMapping;
                             break;
                         }
                     }
-                }                
+                }
             }
-            
+
             String actionName = InternalUtils.getActionName( mapping );
-            
+
             //
             // Check whether isLoginRequired=true for this action.
             //
             LoginHandler loginHandler = Handlers.get( getServletContext() ).getLoginHandler();
-            
+
             if ( pfActionMapping != null && pfActionMapping.isLoginRequired()
                  && loginHandler.getUserPrincipal( getHandlerContext() ) == null )
             {
                 NotLoggedInException ex = createNotLoggedInException( actionName, request );
                 return handleException( ex, mapping, form, request, response );
             }
-            
+
             //
             // Now delegate to the appropriate action method, or if it's a simple action, handle it that way.
             //
@@ -427,7 +455,7 @@
             {
                 retVal = getActionMethodForward( actionName, unwrappedForm, request, response, mapping );
             }
-            
+
             ActionForward ret = forwardTo( retVal, mapping, request, response, actionName, null, form, servletContext );
             long timeTaken = System.currentTimeMillis() - startTime;
             eventReporter.actionSuccess( requestContext, this, mapping, form, ret, timeTaken );
@@ -449,7 +477,7 @@
             try
             {
                 ActionForward overrideReturn = null;
-                
+
                 if ( gotPastBeforeAction )
                 {
                     //
@@ -463,13 +491,13 @@
                     {
                         overrideReturn = handleException( th, mapping, form, request, response );
                     }
-                }            
-                
+                }
+
                 //
                 // Store information on this action for use with navigateTo=Jpf.NavigateTo.previousAction.
                 //
                 savePreviousActionInfo( form, request, mapping, getServletContext() );
-                
+
                 if ( overrideReturn != null )
                 {
                     return overrideReturn;
@@ -493,7 +521,7 @@
         FlowControllerHandlerContext context = new FlowControllerHandlerContext( request, response, this );
         return handler.doForward( context, fwd, mapping, actionName, altModuleConfig, form );
     }
-    
+
     NotLoggedInException createNotLoggedInException( String actionName, HttpServletRequest request )
     {
         if ( InternalUtils.sessionExpired( request ) )
@@ -505,15 +533,15 @@
             return new NotLoggedInException( actionName, this );
         }
     }
-    
+
     /**
      * Initialize after object creation.  This is a framework-invoked method; it should not normally be called directly.
-     */ 
+     */
     public synchronized void create( HttpServletRequest request, HttpServletResponse response,
                                      ServletContext servletContext )
     {
         PerRequestState prevState = setPerRequestState( new PerRequestState( request, response, null ) );
-        
+
         try
         {
             try
@@ -539,21 +567,21 @@
         {
             setPerRequestState( prevState );
         }
-        
+
         PageFlowEventReporter er = AdapterManager.getServletContainerAdapter( servletContext ).getEventReporter();
         RequestContext requestContext = new RequestContext( request, response );
         er.flowControllerCreated( requestContext, this );
     }
-    
+
     /**
      * Internal destroy method that is invoked when this object is being removed from the session.  This is a
      * framework-invoked method; it should not normally be called directly.
-     */ 
+     */
     void destroy( HttpSession session )
     {
         onDestroy();    // for backwards compatiblity
         super.destroy( session );
-        
+
         //
         // We may have lost our transient ServletContext reference.  Try to get the ServletContext reference from the
         // HttpSession object if necessary.
@@ -567,12 +595,12 @@
             er.flowControllerDestroyed( this, session );
         }
     }
-    
+
     /**
      * Get the Struts module path for this controller.
      * 
      * @return a String that is the Struts module path for this controller.
-     */ 
+     */
     public abstract String getModulePath();
 
     /**
@@ -581,19 +609,19 @@
      * {@link FlowController#getActionMapping} may all be used during this method.  The action to be run can be
      * discovered by calling {@link ActionMapping#getPath} on the value returned from
      * {@link FlowController#getActionMapping}.
-     */ 
+     */
     protected synchronized void beforeAction()
         throws Exception
     {
     }
-    
+
     /**
      * Callback that occurs after any user action method is invoked.  {@link FlowController#getRequest},
      * {@link FlowController#getResponse}, {@link FlowController#getSession}, and 
      * {@link FlowController#getActionMapping} may all be used during this method.  The action that was run can be
      * discovered by calling {@link ActionMapping#getPath} on the value returned from
      * {@link FlowController#getActionMapping}.
-     */ 
+     */
     protected synchronized void afterAction()
         throws Exception
     {
@@ -602,7 +630,7 @@
     /**
      * Callback that is invoked when this controller instance is created.  {@link FlowController#getRequest},
      * {@link FlowController#getResponse}, {@link FlowController#getSession} may all be used during this method.
-     */ 
+     */
     protected void onCreate()
         throws Exception
     {
@@ -620,11 +648,11 @@
      * synchronization here can cause deadlocks.
      *
      * @deprecated {@link FlowController#onDestroy(HttpSession)} should be used instead. 
-     */ 
+     */
     protected void onDestroy()
     {
     }
-    
+
     /**
      * Callback that is invoked when this controller instance is "destroyed", i.e., removed from the user session. 
      * {@link FlowController#getRequest}, {@link FlowController#getResponse}, and {@link FlowController#getActionMapping}
@@ -634,17 +662,17 @@
      * Note that this method is <strong>not synchronized</strong>.  It is dangerous to synchronize your override of
      * this method because it is invoked during a callback from the Servlet container.  Depending on the container,
      * synchronization here can cause deadlocks.
-     */ 
+     */
     protected void onDestroy( HttpSession session )
     {
     }
-    
+
     /**
      * Get a legacy PreviousPageInfo.
      * @deprecated This method will be removed without replacement in a future release.
-     */ 
+     */
     public abstract PreviousPageInfo getPreviousPageInfoLegacy( PageFlowController curJpf, HttpServletRequest request );
-    
+
     /**
      * Get an action handler method of the given name/signature.
      *  
@@ -652,14 +680,14 @@
      * @param argType the type of the argument to the action handler method; if <code>null</code>,
      *            the method takes no arguments.
      * @return the desired Method, or <code>null</code> if it doesn't exist.
-     */ 
+     */
     protected Method getActionMethod( String methodName, Class argType )
     {
         String cacheKey = argType != null ? methodName + '/' + argType.getName() : methodName;
         Class thisClass = getClass();
         ClassLevelCache cache = ClassLevelCache.getCache( thisClass );
         Method actionMethod = ( Method ) cache.get( CACHEID_ACTION_METHODS, cacheKey );
-        
+
         if ( actionMethod != null )
         {
             return actionMethod;
@@ -685,16 +713,16 @@
                 while ( argType != null )
                 {
                     actionMethod = InternalUtils.lookupMethod( thisClass, methodName, new Class[]{ argType } );
-                    
+
                     if ( actionMethod != null )
                     {
                         break;
                     }
-                    
+
                     argType = argType.getSuperclass();
                 }
             }
-                
+
             if ( actionMethod != null && actionMethod.getReturnType().equals( Forward.class ) )
             {
                 if ( ! Modifier.isPublic( actionMethod.getModifiers() ) ) actionMethod.setAccessible( true );
@@ -702,7 +730,7 @@
                 return actionMethod;
             }
         }
-        
+
         return null;
     }
 
@@ -712,16 +740,16 @@
         if ( mapping instanceof PageFlowActionMapping )
         {
             String formClassName = ( ( PageFlowActionMapping ) mapping ).getFormClass();
-            
+
             if ( formClassName != null )
             {
                 return InternalUtils.getReloadableClass( formClassName, getServletContext() );
             }
         }
-        
+
         return form != null ? form.getClass() : null;
     }
-    
+
     /**
      * Get the ActionForward returned by the action handler method that corresponds to the
      * given action name and form-bean, or send an error to the browser if there is no
@@ -734,7 +762,7 @@
      *             there was no matching method (in which case an error was written to the
      *             browser.
      * @throws Exception if an Exception was raised in user code.
-     */ 
+     */
     ActionForward getActionMethodForward( String actionName, Object inputForm,
                                           HttpServletRequest request, HttpServletResponse response,
                                           ActionMapping mapping  )
@@ -753,7 +781,7 @@
         {
             return invokeActionMethod( actionMethod, inputForm, request, mapping );
         }
-        
+
         if ( _log.isWarnEnabled() )
         {
             InternalStringBuilder msg = new InternalStringBuilder( "Could not find matching action method for action=" );
@@ -774,7 +802,7 @@
         ret.append( formClass.getName().replace( '.', '_' ).replace( '$', '_' ) );
         return ret.toString();
     }
-    
+
     /**
      * Invoke the given action handler method, passing it an argument if appropriate.
      * 
@@ -788,7 +816,7 @@
     {
         return invokeActionMethod( method, arg, getRequest(), getActionMapping() );
     }
-    
+
     /**
      * Invoke the given action handler method, passing it an argument if appropriate.
      * 
@@ -811,7 +839,7 @@
                 {
                     _log.debug( "Invoking action method " + method.getName() + '(' + paramTypes[0].getName() + ')' );
                 }
-    
+
                 return ( ActionForward ) method.invoke( this, new Object[]{ arg } );
             }
             else if ( paramTypes.length == 0 )
@@ -820,14 +848,14 @@
                 {
                     _log.debug( "Invoking action method " + method.getName() + "()" );
                 }
-    
+
                 return ( ActionForward ) method.invoke( this, null );
             }
         }
         finally
         {
             boolean readonly = false;
-            
+
             if ( mapping instanceof PageFlowActionMapping )
             {
                 PageFlowActionMapping pfam = ( PageFlowActionMapping ) mapping;
@@ -844,7 +872,7 @@
         {
             _log.warn( "Could not find action method " + method.getName() + " with appropriate signature." );
         }
-        
+
         return null;
     }
 
@@ -961,19 +989,19 @@
 
     /**
      * Get the Struts ModuleConfig object associated with this FlowController.
-     */ 
+     */
     public final ModuleConfig getModuleConfig()
     {
         assert _moduleConfig != null : "no cached ModuleConfig for " + getClass().getName();
         return _moduleConfig;
     }
-    
+
     private void initModuleConfig( ServletContext servletContext, HttpServletRequest request )
     {
         if ( _moduleConfig == null )
         {
             _moduleConfig = InternalUtils.getModuleConfig( getModulePath(), servletContext );
-            
+
             if ( _moduleConfig == null )
             {
                 //
@@ -985,7 +1013,7 @@
                 {
                     try
                     {
-                        AutoRegisterActionServlet servlet = ( AutoRegisterActionServlet ) actionServlet; 
+                        AutoRegisterActionServlet servlet = ( AutoRegisterActionServlet ) actionServlet;
                         _moduleConfig = servlet.ensureModuleRegistered( getModulePath(), request );
                     }
                     catch ( Exception e )
@@ -994,11 +1022,11 @@
                     }
                 }
             }
-            
+
             assert _moduleConfig != null : getModulePath() + "; " + getClass().getName();
         }
     }
-    
+
     /**
      * Gets the Struts module configuration associated with this controller.
      * 
@@ -1016,7 +1044,6 @@
      * class should be {@link PageFlowActionServlet}.
      * Note: this method invokes the full action-processing cycle on a {@link ScopedRequest}.  Use
      *             {@link FlowController#resolveAction} to resolve the URI for an action in the current page flow.
-     * @exclude
      * @deprecated Use {@link PageFlowUtils#strutsLookup} instead.  This method will be removed in v1.1.
      */
     public static ActionResult lookup( String actionName, ServletContext context, HttpServletRequest request,
@@ -1025,12 +1052,11 @@
     {
         return PageFlowUtils.strutsLookup( context, request, response, actionName, null );
     }
-    
+
     /**
      * Resolve the given action name to a URI.
      * Note: this method invokes the full action-processing cycle on a {@link ScopedRequest}.  Use
      *             {@link FlowController#resolveAction} to resolve the URI for an action in the current page flow.
-     * @exclude
      * @deprecated Use {@link PageFlowUtils#strutsLookup} instead.  This method will be removed in v1.1.
      */
     public static ActionResult lookup( String actionName, ServletContext context, HttpServletRequest request,
@@ -1039,7 +1065,7 @@
     {
         return PageFlowUtils.strutsLookup( context, request, response, actionName, null );
     }
-    
+
     /**
      * Call an action and return the result URI.
      * 
@@ -1048,25 +1074,25 @@
      * @return the result webapp-relative URI, as a String.
      * @throws ActionNotFoundException when the given action does not exist in this FlowController.
      * @throws Exception if the action method throws an Exception.
-     */ 
+     */
     public String resolveAction( String actionName, Object form, HttpServletRequest request,
                                  HttpServletResponse response )
         throws Exception
     {
         ActionMapping mapping = ( ActionMapping ) getModuleConfig().findActionConfig( '/' + actionName );
-        
+
         if ( mapping == null )
         {
             InternalUtils.throwPageFlowException( new ActionNotFoundException( actionName, this, form ), request );
         }
-        
+
         ActionForward fwd = getActionMethodForward( actionName, form, request, response, mapping );
-        
+
         if ( fwd instanceof Forward )
         {
             ( ( Forward ) fwd ).initialize( mapping, this, request );
         }
-        
+
         String path = fwd.getPath();
         if ( fwd.getContextRelative() || FileUtils.isAbsoluteURI( path ) )
         {
@@ -1087,7 +1113,7 @@
      * @return the result webapp-relative URI, as a String.
      * @throws ActionNotFoundException when the given action does not exist in this FlowController.
      * @throws Exception if the action method throws an Exception.
-     */ 
+     */
     public String resolveAction( String actionName, Object form )
         throws Exception
     {
@@ -1103,16 +1129,16 @@
     {
         ActionConfig[] actionConfigs = getModuleConfig().findActionConfigs();
         ArrayList actionNames = new ArrayList();
-        
+
         for ( int i = 0; i < actionConfigs.length; i++ )
         {
             ActionConfig ac = actionConfigs[i];
             actionNames.add( ac.getPath().substring( 1 ) ); // every action path has a '/' in front of it
         }
-        
+
         return ( String[] ) actionNames.toArray( new String[0] );
     }
-    
+
     /**
      * Tell whether a given String is the name of an action handled by a method in this PageFlowController.
      * 
@@ -1124,17 +1150,17 @@
     {
         return getModuleConfig().findActionConfig( '/' + name ) != null;
     }
-    
+
     /**
      * Tell whether this is a {@link PageFlowController}.
      * 
      * @return <code>true</code> if this is a {@link PageFlowController}.
-     */ 
+     */
     public boolean isPageFlow()
     {
         return false;
     }
-    
+
     /**
      * Get the current Struts ActionServlet.
      * 
@@ -1142,16 +1168,16 @@
      *             sufficient; for other cases, the ActionServlet itself is in the ServletContext attribute
      *             {@link Globals#ACTION_SERVLET_KEY}.
      * @return the ActionServlet.
-     */ 
+     */
     protected ActionServlet getServlet()
     {
         return InternalUtils.getActionServlet( getServletContext() );
     }
-    
+
     /**
      * Called on this object for non-lookup (refresh) requests.  This is a framework-invoked method that should not
      * normally be called directly.
-     */ 
+     */
     public final synchronized void refresh( HttpServletRequest request, HttpServletResponse response )
     {
         PerRequestState prevState = setPerRequestState( new PerRequestState( request, response, null ) );
@@ -1165,36 +1191,36 @@
             setPerRequestState( prevState );
         }
     }
-    
+
     /**
      * Callback that is invoked when this controller is involved in a refresh request, as can happen in a portal
      * environment on a request where no action is run in the current page flow, but a previously-displayed page in the
      * page flow is re-rendered.
-     */ 
+     */
     protected void onRefresh()
     {
     }
-    
+
     /**
      * Remove this instance from the user session.
-     */ 
+     */
     protected void remove()
     {
         removeFromSession( getRequest() );
     }
-    
+
     /**
      * Used by derived classes to store information on the most recent action executed.
-     */ 
+     */
     void savePreviousActionInfo( ActionForm form, HttpServletRequest request, ActionMapping mapping,
                                  ServletContext servletContext )
     {
     }
-    
+
     /**
      * Store information about recent pages displayed.  This is a framework-invoked method that should not normally be
      * called directly.
-     */ 
+     */
     public void savePreviousPageInfo( ActionForward forward, ActionForm form, ActionMapping mapping,
                                       HttpServletRequest request, ServletContext servletContext,
                                       boolean isSpecialForward )
@@ -1218,13 +1244,13 @@
      * <code>return-to="previousAction"</code> is used.
      * @see PageFlowController#getPreviousActionInfo
      * @see PageFlowController#getPreviousActionURI
-     * @see PageFlowController#getPreviousFormBean        
+     * @see PageFlowController#getPreviousFormBean
      */
     protected boolean alwaysTrackPreviousAction()
     {
         return false;
     }
-    
+
     /**
      * When this FlowController does not use a {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward}
      * annotation with either a
@@ -1270,7 +1296,7 @@
         {
             _maxConcurrentRequestCount = DEFAULT_MAX_CONCURRENT_REQUEST_COUNT;
             String countStr = servletContext.getInitParameter( MAX_CONCURRENT_REQUESTS_PARAM );
-            
+
             if ( countStr != null )
             {
                 try
@@ -1282,7 +1308,7 @@
                     _log.error( "Invalid value for servlet context parameter" + MAX_CONCURRENT_REQUESTS_PARAM
                                 + ": " + countStr, e );
                 }
-                
+
                 if ( _maxConcurrentRequestCount < 1 )
                 {
                     _maxConcurrentRequestCount = DEFAULT_MAX_CONCURRENT_REQUEST_COUNT;
@@ -1291,7 +1317,7 @@
                 }
             }
         }
-        
+
         //
         // Now, if the current count of concurrent requests to this instance is greater than the max,
         // send an error on the response.
@@ -1308,14 +1334,14 @@
             response.sendError( EXCEEDED_MAX_CONCURRENT_REQUESTS_ERRORCODE );
             return false;
         }
-        
+
         //
         // We're ok -- increment the count and continue.
         //
         ++_requestCount;
         return true;
     }
-    
+
     void decrementRequestCount( HttpServletRequest request )
     {
         assert _requestCount > 0 : request.getRequestURI();
@@ -1341,7 +1367,7 @@
         throws IOException, ServletException
     {
         PerRequestState prevState = setPerRequestState( new PerRequestState( request, response, actionMapping ) );
-        
+
         try
         {
             if ( _log.isDebugEnabled() )
@@ -1354,12 +1380,12 @@
             {
                 ActionForward retVal = null;
                 String actionName = InternalUtils.getActionName( actionMapping );
-                
+
                 if ( actionName == null && ex instanceof PageFlowException )
                 {
                     actionName = ( ( PageFlowException ) ex ).getActionName();
                 }
-            
+
                 try
                 {
                     Object[] args = new Object[]{ ex, actionName, message, formBean };
@@ -1372,7 +1398,7 @@
                         ensureFailover( request );
                     }
                 }
-            
+
                 ActionForwardHandler handler = Handlers.get( getServletContext() ).getActionForwardHandler();
                 return handler.doForward( getHandlerContext(), retVal, actionMapping, actionName, getModuleConfig(),
                                           wrappedFormBean );
@@ -1380,7 +1406,7 @@
             catch ( InvocationTargetException e )
             {
                 Throwable target = e.getTargetException();
-            
+
                 if ( target instanceof Exception )
                 {
                     throw ( Exception ) target;
@@ -1395,11 +1421,11 @@
         {
             _log.error( "Exception while handling exception " + ex.getClass().getName()
                         + ".  The original exception will be thrown.", e );
-            
+
             ExceptionsHandler eh = Handlers.get( getServletContext() ).getExceptionsHandler();
             FlowControllerHandlerContext context = new FlowControllerHandlerContext( request, response, this );
             Throwable unwrapped = eh.unwrapException( context, e );
-            
+
             if ( ! eh.eatUnhandledException( context, unwrapped ) )
             {
                 if ( ex instanceof ServletException ) throw ( ServletException ) ex;
@@ -1407,7 +1433,7 @@
                 if ( ex instanceof Error ) throw ( Error ) ex;
                 throw new UnhandledException( ex );
             }
-            
+
             return null;
         }
         finally
@@ -1415,31 +1441,31 @@
             setPerRequestState( prevState );
         }
     }
-    
+
     /**
      * Add a property-related message that will be shown with the Errors and Error tags.
      * 
      * @param propertyName the name of the property with which to associate this error.
      * @param messageKey the message-resources key for the message.
      * @param messageArgs zero or more arguments to the message.
-     */ 
+     */
     protected void addActionError( String propertyName, String messageKey, Object[] messageArgs )
     {
         InternalUtils.addActionError( propertyName, new ActionMessage( messageKey, messageArgs ), getRequest() );
     }
-    
+
     /**
      * Add a property-related message as an expression that will be evaluated and shown with the Errors and Error tags.
      * 
      * @param propertyName the name of the property with which to associate this error.
      * @param expression the expression that will be evaluated to generate the error message.
      * @param messageArgs zero or more arguments to the message; may be expressions.
-     */ 
+     */
     protected void addActionErrorExpression( String propertyName, String expression, Object[] messageArgs )
     {
         PageFlowUtils.addActionErrorExpression( getRequest(), propertyName, expression, messageArgs );
     }
-    
+
     /**
      * Add a validation error that will be shown with the Errors and Error tags.
      * @deprecated Use {@link #addActionError} instead.
@@ -1447,36 +1473,36 @@
      * @param propertyName the name of the property with which to associate this error.
      * @param messageKey the message-resources key for the error message.
      * @param messageArgs an array of arguments for the error message.
-     */ 
+     */
     protected void addValidationError( String propertyName, String messageKey, Object[] messageArgs )
     {
         PageFlowUtils.addValidationError( propertyName, messageKey, messageArgs, getRequest() );
     }
-    
+
     /**
      * Add a validation error that will be shown with the Errors and Error tags.
      * @deprecated Use {@link #addActionError} instead.
      * 
      * @param propertyName the name of the property with which to associate this error.
      * @param messageKey the message-resources key for the error message.
-     */ 
+     */
     protected void addValidationError( String propertyName, String messageKey )
     {
         PageFlowUtils.addValidationError( propertyName, messageKey, getRequest() );
     }
-    
+
     private static ActionForward handleSimpleAction( PageFlowActionMapping mapping,
                                                      ActionForm wrappedFormBean,
                                                      HttpServletRequest request,
                                                      ServletContext servletContext )
     {
-        
+
         Map/*< String, String >*/ conditionalForwards = mapping.getConditionalForwardsMap();
-        
+
         if ( ! conditionalForwards.isEmpty() )
         {
             Object formBean = InternalUtils.unwrapFormBean( wrappedFormBean );
-            
+
             for ( Iterator/*< Map.Entry< String, String > >*/ i = conditionalForwards.entrySet().iterator(); i.hasNext(); )
             {
                 Map.Entry/*< String, String >*/ entry = ( Map.Entry ) i.next();
@@ -1506,30 +1532,30 @@
                 }
             }
         }
-        
-        
+
+
         String defaultForwardName = mapping.getDefaultForward();
         assert defaultForwardName != null : "defaultForwardName is null on Simple Action " + mapping.getPath();
-        
+
         if ( _log.isTraceEnabled() )
         {
             _log.trace( "No expression evaluated to true on simple action " + mapping.getPath()
                         + "; using forward " + defaultForwardName + '.' );
         }
-        
+
         return new Forward( defaultForwardName );
     }
-    
+
     /**
      * Get the system default locale.
      * 
      * @return the system default locale.
-     */ 
+     */
     protected static Locale getDefaultLocale()
     {
         return defaultLocale;
     }
-    
+
     /**
      * Return the default data source for the Struts module associated with this FlowController.
      *
@@ -1627,7 +1653,7 @@
     {
         return getMessageResources( key );
     }
-    
+
     /**
      * Get the default message resources for this FlowController.
      */
@@ -1635,7 +1661,7 @@
     {
         return getMessageResources( Globals.MESSAGES_KEY );
     }
-    
+
     /**
      * Get the specified message resources for this FlowController.
      *
@@ -1679,19 +1705,19 @@
     {
         return TOKEN_PROCESSOR.generateToken( request );
     }
-    
+
     /**
      * Generate a new transaction token, to be used for enforcing a single request for a particular transaction.
      * 
-     * @see #isTokenValid() 
-     * @see #isTokenValid(boolean) 
+     * @see #isTokenValid()
+     * @see #isTokenValid(boolean)
      * @see #resetToken()
      */
     protected String generateToken()
     {
         return TOKEN_PROCESSOR.generateToken( getRequest() );
     }
-    
+
     /**
      * Return <code>true</code> if there is a transaction token stored in
      * the user's current session, and the value submitted as a request
@@ -1710,11 +1736,11 @@
      */
     protected boolean isTokenValid( HttpServletRequest request )
     {
-        
+
         return TOKEN_PROCESSOR.isTokenValid( request, false );
-        
+
     }
-    
+
     /**
      * Return <code>true</code> if there is a transaction token stored in
      * the user's current session, and the value submitted as a request
@@ -1728,7 +1754,7 @@
      * transaction token in the user's session</li>
      * </ul>
      * 
-     * @see #generateToken() 
+     * @see #generateToken()
      * @see #resetToken()
      */
     protected boolean isTokenValid()
@@ -1758,7 +1784,7 @@
     {
         return TOKEN_PROCESSOR.isTokenValid( request, reset );
     }
-    
+
     /**
      * Return <code>true</code> if there is a transaction token stored in
      * the user's current session, and the value submitted as a request
@@ -1772,7 +1798,7 @@
      * </ul>
      *
      * @param reset   Should we reset the token after checking it?
-     * @see #generateToken() 
+     * @see #generateToken()
      * @see #resetToken()
      */
     protected boolean isTokenValid( boolean reset )
@@ -1794,15 +1820,15 @@
     {
         TOKEN_PROCESSOR.resetToken( request );
     }
-    
+
     /**
      * Reset the saved transaction token in the user's session.  This
      * indicates that transactional token checking will not be needed
      * on the next request that is submitted.
      * 
-     * @see #isTokenValid() 
-     * @see #isTokenValid(boolean) 
-     * @see #generateToken() 
+     * @see #isTokenValid()
+     * @see #isTokenValid(boolean)
+     * @see #generateToken()
      */
     protected void resetToken()
     {
@@ -1834,19 +1860,19 @@
      */
     protected void saveMessages( HttpServletRequest request, ActionMessages messages )
     {
-        
+
         // Remove any messages attribute if none are required
         if ( messages == null || messages.isEmpty() )
         {
             request.removeAttribute( Globals.MESSAGE_KEY );
             return;
         }
-        
+
         // Save the messages we need
         request.setAttribute( Globals.MESSAGE_KEY, messages );
-        
+
     }
-    
+
     /**
      * Save the specified messages keys into the request for use by the &lt;netui:error&gt; or &lt;netui:errors&gt; tags.
      *
@@ -1908,18 +1934,18 @@
         if ( locale == null ) locale = getDefaultLocale();
         getSession().setAttribute( Globals.LOCALE_KEY, locale );
     }
-    
+
     /**
      * Get the flow-scoped form bean member associated with the given ActionMapping.  This is a framework-invoked
      * method that should not normally be called directly.
-     */ 
+     */
     public ActionForm getFormBean( ActionMapping mapping )
     {
         if ( mapping instanceof PageFlowActionMapping )
         {
             PageFlowActionMapping pfam = ( PageFlowActionMapping ) mapping;
             String formMember = pfam.getFormMember();
-            
+
             try
             {
                 if ( formMember != null )
@@ -1934,16 +1960,16 @@
                 _log.error( "Could not use member field " + formMember + " as the form bean.", e );
             }
         }
-        
+
         return null;
     }
-    
+
     PageFlowRequestProcessor getRequestProcessor()
     {
         ModuleConfig mc = getModuleConfig();
         String key = Globals.REQUEST_PROCESSOR_KEY + mc.getPrefix();
         RequestProcessor rp = ( RequestProcessor ) getServletContext().getAttribute( key );
-        
+
         //
         // The RequestProcessor may not have been initialized -- if so, just return a new (temporary) one.
         //
@@ -1960,7 +1986,7 @@
                 _log.error( "Could not initialize request processor for module " + mc.getPrefix(), e );
             }
         }
-        
+
         assert rp == null || rp instanceof PageFlowRequestProcessor : rp.getClass().getName();
         return ( PageFlowRequestProcessor ) rp;
     }
@@ -2023,7 +2049,7 @@
         return PageFlowUtils.getRewrittenActionURI( servletContext, request, response,
                                                     actionName, parameters, null, asValidXml );
     }
-    
+
     FlowControllerHandlerContext getHandlerContext()
     {
         return new FlowControllerHandlerContext( getRequest(), getResponse(), this );

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java Mon Sep 26 21:02:25 2005
@@ -67,7 +67,11 @@
     {
     }
 
-    static void init( ServletContext servletContext )
+    /**
+     * Initialize an instance of this class in the ServletContext.  This is a framework-invoked method and should
+     * normally be called directly.
+     */
+    public static void init( ServletContext servletContext )
     {
         PageFlowFactoriesConfig factoriesBean = ConfigUtil.getConfig().getPageFlowFactories();
         FlowControllerFactory factory = null;

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowActionServlet.java Mon Sep 26 21:02:25 2005
@@ -20,6 +20,7 @@
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
+import org.apache.beehive.netui.pageflow.internal.PageFlowInitialization;
 import org.apache.beehive.netui.pageflow.handler.Handlers;
 import org.apache.beehive.netui.pageflow.handler.FlowControllerHandlerContext;
 import org.apache.beehive.netui.pageflow.handler.ForwardRedirectHandler;
@@ -117,14 +118,12 @@
     public void init()
             throws ServletException
     {
-        //
-        // Ensure that PageFlowContextListener gets to do its initializations, even if it's not registered in web.xml.
-        //
+        // Ensure that we get to do our initializations, even if there's no context listener registered in web.xml.
         ServletContext servletContext = getServletContext();
         
-        if ( ! PageFlowContextListener.isInit( servletContext ) )
+        if ( ! PageFlowInitialization.isInit( servletContext ) )
         {
-            PageFlowContextListener.performInitializations( servletContext );
+            PageFlowInitialization.performInitializations(servletContext, null);
         }
         
         _handlers = Handlers.get( servletContext );

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java Mon Sep 26 21:02:25 2005
@@ -17,27 +17,11 @@
  */
 package org.apache.beehive.netui.pageflow;
 
-import org.apache.beehive.netui.core.urls.TemplatedURLFormatter;
-import org.apache.beehive.netui.core.urltemplates.URLTemplatesFactory;
-import org.apache.beehive.netui.pageflow.handler.Handlers;
-import org.apache.beehive.netui.pageflow.internal.AdapterManager;
-import org.apache.beehive.netui.pageflow.internal.DefaultTemplatedURLFormatter;
-import org.apache.beehive.netui.pageflow.internal.InternalConstants;
-import org.apache.beehive.netui.pageflow.internal.LegacySettings;
-import org.apache.beehive.netui.util.config.ConfigInitializationException;
-import org.apache.beehive.netui.util.config.ConfigUtil;
-import org.apache.beehive.netui.util.config.bean.PrefixHandlerConfig;
-import org.apache.beehive.netui.util.config.bean.UrlConfig;
-import org.apache.beehive.netui.util.internal.DiscoveryUtils;
+import org.apache.beehive.netui.pageflow.internal.PageFlowInitialization;
 import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.util.xml.XmlInputStreamResolver;
 
-import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
 
 
 
@@ -47,224 +31,18 @@
 public class PageFlowContextListener
         implements ServletContextListener
 {
-    private static final String ALREADY_INIT_ATTR = InternalConstants.ATTR_PREFIX + "contextInit";
-            
     private static final Logger _log = Logger.getInstance( PageFlowContextListener.class );
     
-    private static class TransientFlag implements Serializable
-    {
-        private transient boolean _flag;
-        
-        public TransientFlag()
-        {
-            _flag = true;
-        }
-        
-        public boolean isSet()
-        {
-            return _flag;
-        }
-    }
-    
     public void contextInitialized( ServletContextEvent event )
     {
-        performInitializations( event.getServletContext() );
-    }
-
-    public void contextDestroyed( ServletContextEvent event )
-    {
-    }
-    
-    static boolean isInit( ServletContext servletContext )
-    {
-        //
-        // If the flag is present, but was serialized, then the webapp was redeployed.  At this point, we want
-        // to go through the init logic again.
-        //
-        TransientFlag flag = ( TransientFlag ) servletContext.getAttribute( ALREADY_INIT_ATTR );
-        return flag != null && flag.isSet();
-    }
-    
-    static void performInitializations( ServletContext servletContext )
-    {
-        servletContext.setAttribute( ALREADY_INIT_ATTR, new TransientFlag() );
-        
-        //
-        // Initialize the config file, unless it's already initialized.  This can happen because the scope for the 
-        // config (static) isn't the same as the scope for PageFlowActionServlet, which may get created and destroyed
-        // within a classloader (which is the case during StrutsTestCase tests).
-        //
-        if ( ! ConfigUtil.isInit() )
-        {
-            try
-            {
-                ConfigUtil.init( new NetUIConfigResolver(servletContext) );
-            }
-            catch ( ConfigInitializationException e )
-            {
-                _log.fatal( "Could not initialize from " + InternalConstants.NETUI_CONFIG_PATH, e );
-                throw new IllegalStateException( "Could not initialize from " + InternalConstants.NETUI_CONFIG_PATH, e );
-            }
-        }
-        
-        AdapterManager.initServletContext( servletContext );
-        LegacySettings.init( servletContext );
-        Handlers.init( servletContext );
-        FlowControllerFactory.init( servletContext );
-        FacesBackingBeanFactory.init( servletContext );
-        initPrefixHandlers();
-        initURLTemplates( servletContext );
-    }
-
-    /**
-     * This method will initialize all of the PrefixHandlers registered in the netui config.
-     * The prefix handlers are registered with ProcessPopulate and are typically implemented as
-     * public inner classes in the tags that require prefix handlers.
-     */
-    private static void initPrefixHandlers()
-    {
-        PrefixHandlerConfig[] prefixHandlers = ConfigUtil.getConfig().getPrefixHandlers();
-        if ( prefixHandlers == null )
-        {
-            return;
-        }
-        for ( int i = 0; i < prefixHandlers.length; i++ )
-        {
-            try
-            {
-                Class prefixClass = Class.forName( prefixHandlers[i].getHandlerClass() );
-                String name = prefixHandlers[i].getName();
-                if ( name == null || name.equals( "" ) )
-                {
-                    _log.warn( "The name for the prefix handler '" + prefixHandlers[i].getHandlerClass()
-                        + "' must not be null" );
-                    continue;
-                }
-                Object o = prefixClass.newInstance();
-                if ( !( o instanceof RequestParameterHandler ) )
-                {
-                    _log.warn( "The class '" + prefixHandlers[i].getHandlerClass()
-                        + "' must be an instance of RequestParameterHandler" );
-                    continue;
-                }
-                ProcessPopulate.registerPrefixHandler( name, ( RequestParameterHandler ) o );
-            }
-            catch ( ClassNotFoundException e )
-            {
-                _log.warn( "Class '" + prefixHandlers[i].getHandlerClass() + "' not found", e );
-            }
-            catch ( IllegalAccessException e )
-            {
-                _log.warn( "Illegal access on Class '" + prefixHandlers[i].getHandlerClass() + "'", e );
-
-            }
-            catch ( InstantiationException e )
-            {
-                _log.warn( "InstantiationException on Class '" + prefixHandlers[i].getHandlerClass() + "'",
-                    e.getCause() );
-            }
+        if (_log.isDebugEnabled()) {
+            _log.debug("In " + getClass().getName() + "; performing initializations.");
         }
+        PageFlowInitialization.performInitializations(event.getServletContext(), null);
     }
 
-    /**
-     * Creates a URLTemplatesFactory (may be container specific from the
-     * ServletContainerAdapter) and the the default TemplatedURLFormatter
-     * (registered in the netui config). These classes are used by the
-     * URLRewriterService.
-     */
-    private static void initURLTemplates( ServletContext servletContext )
-    {
-        TemplatedURLFormatter formatter = TemplatedURLFormatter.getTemplatedURLFormatter( servletContext );
-        if ( formatter == null )
-        {
-            // get the default template formatter class name from the config file
-            formatter = getTemplatedURLFormatter();
-
-            assert formatter != null : "Found a non-null URL formatter";
-            
-            // set the TemplatedURLFormatter attribute on the context.
-            TemplatedURLFormatter.initServletContext( servletContext, formatter );
-        }
-
-        URLTemplatesFactory templatesFactory = URLTemplatesFactory.getURLTemplatesFactory( servletContext );
-        if ( templatesFactory == null )
-        {
-            // URLTemplatesFactory has not been initialized,
-            // get a URLTemplatesFactory object from the containerAdapter.
-            templatesFactory = PageFlowUtils.createURLTemplatesFactory( servletContext );
-
-            // get the known/req tokens from the default formatter for the factory to use to verify templates
-            templatesFactory.setKnownTokens( formatter.getKnownTokens() );
-            templatesFactory.setRequiredTokens( formatter.getRequiredTokens() );
-            templatesFactory.load( servletContext );
-
-            // set the URLTemplatesFactory attribute on the context.
-            URLTemplatesFactory.initServletContext( servletContext, templatesFactory );
-        }
-    }
-
-    private static TemplatedURLFormatter getTemplatedURLFormatter()
+    public void contextDestroyed( ServletContextEvent event )
     {
-        TemplatedURLFormatter formatter = null;
-
-        // check for a default template formatter class name from the config file
-        UrlConfig urlConfig = ConfigUtil.getConfig().getUrlConfig();
-        if ( urlConfig != null )
-        {
-            String className = urlConfig.getTemplatedUrlFormatterClass();
-            if ( className != null )
-            {
-                className = className.trim();
-
-                // create an instance of the def template formatter class
-                ClassLoader cl = DiscoveryUtils.getClassLoader();
-
-                try
-                {
-                    Class formatterClass = cl.loadClass( className );
-                    if ( ! TemplatedURLFormatter.class.isAssignableFrom( formatterClass ) )
-                    {
-                        _log.error( "The templated-url-formatter-class, " + className
-                                    + ", does not extend TemplatedURLFormatter." );
-                    }
-                    else
-                    {
-                        formatter = ( TemplatedURLFormatter ) formatterClass.newInstance();
-                    }
-                }
-                catch ( ClassNotFoundException e )
-                {
-                    _log.error( "Could not find templated-url-formatter-class " + className, e );
-                }
-                catch ( InstantiationException e )
-                {
-                    _log.error( "Could not instantiate templated-url-formatter-class " + className, e );
-                }
-                catch ( IllegalAccessException e )
-                {
-                    _log.error( "Could not instantiate templated-url-formatter-class " + className, e );
-                }
-            }
-        }
-
-        return formatter;
-    }
-
-    private static class NetUIConfigResolver
-        extends XmlInputStreamResolver {
-
-        private ServletContext _servletContext = null;
-
-        private NetUIConfigResolver(ServletContext servletContext) {
-            _servletContext = servletContext;
-        }
-
-        public String getResourcePath() {
-            return InternalConstants.NETUI_CONFIG_PATH;
-        }
-
-        public InputStream getInputStream() {
-            return _servletContext.getResourceAsStream(getResourcePath());
-        }
     }
 }
+

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java Mon Sep 26 21:02:25 2005
@@ -49,6 +49,7 @@
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
+import org.apache.beehive.netui.pageflow.internal.PageFlowInitialization;
 import org.apache.beehive.netui.pageflow.handler.Handlers;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
 
@@ -82,9 +83,9 @@
     {
         _servletContext = filterConfig.getServletContext();
         
-        if ( ! PageFlowContextListener.isInit( _servletContext ) )
+        if ( ! PageFlowInitialization.isInit( _servletContext ) )
         {
-            PageFlowContextListener.performInitializations( _servletContext );
+            PageFlowInitialization.performInitializations(_servletContext, null);
         }
         
         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( _servletContext );

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/LegacySettings.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/LegacySettings.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/LegacySettings.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/LegacySettings.java Mon Sep 26 21:02:25 2005
@@ -35,8 +35,6 @@
     private static final Logger _log = Logger.getInstance( LegacySettings.class );
 
     private static final String CONTEXT_ATTR = InternalConstants.ATTR_PREFIX + "_cache";
-    private static final int DEFAULT_MAX_FORWARDS_PER_REQUEST = 25;
-    private static final int DEFAULT_MAX_NESTING_STACK_DEPTH = 10;
 
     public static final int serialVersionUID = 1;
 

Added: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/PageFlowInitialization.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/PageFlowInitialization.java?rev=291814&view=auto
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/PageFlowInitialization.java (added)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/PageFlowInitialization.java Mon Sep 26 21:02:25 2005
@@ -0,0 +1,258 @@
+/*
+ * 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.internal;
+
+import org.apache.beehive.netui.core.urls.TemplatedURLFormatter;
+import org.apache.beehive.netui.core.urltemplates.URLTemplatesFactory;
+import org.apache.beehive.netui.pageflow.FacesBackingBeanFactory;
+import org.apache.beehive.netui.pageflow.FlowControllerFactory;
+import org.apache.beehive.netui.pageflow.PageFlowUtils;
+import org.apache.beehive.netui.pageflow.ProcessPopulate;
+import org.apache.beehive.netui.pageflow.RequestParameterHandler;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
+import org.apache.beehive.netui.util.config.ConfigInitializationException;
+import org.apache.beehive.netui.util.config.ConfigUtil;
+import org.apache.beehive.netui.util.config.bean.PrefixHandlerConfig;
+import org.apache.beehive.netui.util.config.bean.UrlConfig;
+import org.apache.beehive.netui.util.internal.DiscoveryUtils;
+import org.apache.beehive.netui.util.logging.Logger;
+import org.apache.beehive.netui.util.xml.XmlInputStreamResolver;
+
+import javax.servlet.ServletContext;
+import java.io.InputStream;
+import java.io.Serializable;
+
+/**
+ * Handles initialization of the Page Flow runtime.
+ */
+public class PageFlowInitialization {
+
+    private static final String ALREADY_INIT_ATTR = InternalConstants.ATTR_PREFIX + "contextInit";
+
+    private static final Logger _log = Logger.getInstance( PageFlowInitialization.class );
+
+    private static class TransientFlag implements Serializable
+    {
+        private transient boolean _flag;
+
+        public TransientFlag()
+        {
+            _flag = true;
+        }
+
+        public boolean isSet()
+        {
+            return _flag;
+        }
+    }
+
+    public static boolean isInit( ServletContext servletContext )
+    {
+        //
+        // If the flag is present, but was serialized, then the webapp was redeployed.  At this point, we want
+        // to go through the init logic again.
+        //
+        TransientFlag flag = ( TransientFlag ) servletContext.getAttribute( ALREADY_INIT_ATTR );
+        return flag != null && flag.isSet();
+    }
+
+    public static void performInitializations( ServletContext servletContext, XmlInputStreamResolver overrideConfigInput )
+    {
+        servletContext.setAttribute( ALREADY_INIT_ATTR, new TransientFlag() );
+
+        //
+        // Initialize the config file, unless it's already initialized.  This can happen because the scope for the 
+        // config (static) isn't the same as the scope for PageFlowActionServlet, which may get created and destroyed
+        // within a classloader (which is the case during StrutsTestCase tests).
+        //
+        if ( ! ConfigUtil.isInit() )
+        {
+            XmlInputStreamResolver resolver =
+                    overrideConfigInput != null ? overrideConfigInput : new NetUIConfigResolver(servletContext);
+            try
+            {
+                ConfigUtil.init(resolver);
+            }
+            catch ( ConfigInitializationException e )
+            {
+                _log.fatal( "Could not initialize from " + resolver.getResourcePath(), e );
+                throw new IllegalStateException( "Could not initialize from " + resolver.getResourcePath(), e );
+            }
+        }
+
+        AdapterManager.initServletContext( servletContext );
+        LegacySettings.init( servletContext );
+        Handlers.init( servletContext );
+        FlowControllerFactory.init( servletContext );
+        FacesBackingBeanFactory.init( servletContext );
+        initPrefixHandlers();
+        initURLTemplates( servletContext );
+    }
+
+    /**
+     * This method will initialize all of the PrefixHandlers registered in the netui config.
+     * The prefix handlers are registered with ProcessPopulate and are typically implemented as
+     * public inner classes in the tags that require prefix handlers.
+     */
+    private static void initPrefixHandlers()
+    {
+        PrefixHandlerConfig[] prefixHandlers = ConfigUtil.getConfig().getPrefixHandlers();
+        if ( prefixHandlers == null )
+        {
+            return;
+        }
+        for ( int i = 0; i < prefixHandlers.length; i++ )
+        {
+            try
+            {
+                Class prefixClass = Class.forName( prefixHandlers[i].getHandlerClass() );
+                String name = prefixHandlers[i].getName();
+                if ( name == null || name.equals( "" ) )
+                {
+                    _log.warn( "The name for the prefix handler '" + prefixHandlers[i].getHandlerClass()
+                            + "' must not be null" );
+                    continue;
+                }
+                Object o = prefixClass.newInstance();
+                if ( !( o instanceof RequestParameterHandler ) )
+                {
+                    _log.warn( "The class '" + prefixHandlers[i].getHandlerClass()
+                            + "' must be an instance of RequestParameterHandler" );
+                    continue;
+                }
+                ProcessPopulate.registerPrefixHandler( name, ( RequestParameterHandler ) o );
+            }
+            catch ( ClassNotFoundException e )
+            {
+                _log.warn( "Class '" + prefixHandlers[i].getHandlerClass() + "' not found", e );
+            }
+            catch ( IllegalAccessException e )
+            {
+                _log.warn( "Illegal access on Class '" + prefixHandlers[i].getHandlerClass() + "'", e );
+
+            }
+            catch ( InstantiationException e )
+            {
+                _log.warn( "InstantiationException on Class '" + prefixHandlers[i].getHandlerClass() + "'",
+                        e.getCause() );
+            }
+        }
+    }
+
+    /**
+     * Creates a URLTemplatesFactory (may be container specific from the
+     * ServletContainerAdapter) and the the default TemplatedURLFormatter
+     * (registered in the netui config). These classes are used by the
+     * URLRewriterService.
+     */
+    private static void initURLTemplates( ServletContext servletContext )
+    {
+        TemplatedURLFormatter formatter = TemplatedURLFormatter.getTemplatedURLFormatter( servletContext );
+        if ( formatter == null )
+        {
+            // get the default template formatter class name from the config file
+            formatter = getTemplatedURLFormatter();
+
+            assert formatter != null : "Found a non-null URL formatter";
+
+            // set the TemplatedURLFormatter attribute on the context.
+            TemplatedURLFormatter.initServletContext( servletContext, formatter );
+        }
+
+        URLTemplatesFactory templatesFactory = URLTemplatesFactory.getURLTemplatesFactory( servletContext );
+        if ( templatesFactory == null )
+        {
+            // URLTemplatesFactory has not been initialized,
+            // get a URLTemplatesFactory object from the containerAdapter.
+            templatesFactory = PageFlowUtils.createURLTemplatesFactory( servletContext );
+
+            // get the known/req tokens from the default formatter for the factory to use to verify templates
+            templatesFactory.setKnownTokens( formatter.getKnownTokens() );
+            templatesFactory.setRequiredTokens( formatter.getRequiredTokens() );
+            templatesFactory.load( servletContext );
+
+            // set the URLTemplatesFactory attribute on the context.
+            URLTemplatesFactory.initServletContext( servletContext, templatesFactory );
+        }
+    }
+
+    private static TemplatedURLFormatter getTemplatedURLFormatter()
+    {
+        TemplatedURLFormatter formatter = null;
+
+        // check for a default template formatter class name from the config file
+        UrlConfig urlConfig = ConfigUtil.getConfig().getUrlConfig();
+        if ( urlConfig != null )
+        {
+            String className = urlConfig.getTemplatedUrlFormatterClass();
+            if ( className != null )
+            {
+                className = className.trim();
+
+                // create an instance of the def template formatter class
+                ClassLoader cl = DiscoveryUtils.getClassLoader();
+
+                try
+                {
+                    Class formatterClass = cl.loadClass( className );
+                    if ( ! TemplatedURLFormatter.class.isAssignableFrom( formatterClass ) )
+                    {
+                        _log.error( "The templated-url-formatter-class, " + className
+                                + ", does not extend TemplatedURLFormatter." );
+                    }
+                    else
+                    {
+                        formatter = ( TemplatedURLFormatter ) formatterClass.newInstance();
+                    }
+                }
+                catch ( ClassNotFoundException e )
+                {
+                    _log.error( "Could not find templated-url-formatter-class " + className, e );
+                }
+                catch ( InstantiationException e )
+                {
+                    _log.error( "Could not instantiate templated-url-formatter-class " + className, e );
+                }
+                catch ( IllegalAccessException e )
+                {
+                    _log.error( "Could not instantiate templated-url-formatter-class " + className, e );
+                }
+            }
+        }
+
+        return formatter;
+    }
+
+    private static class NetUIConfigResolver
+            extends XmlInputStreamResolver {
+
+        private ServletContext _servletContext = null;
+
+        private NetUIConfigResolver(ServletContext servletContext) {
+            _servletContext = servletContext;
+        }
+
+        public String getResourcePath() {
+            return InternalConstants.NETUI_CONFIG_PATH;
+        }
+
+        public InputStream getInputStream() {
+            return _servletContext.getResourceAsStream(getResourcePath());
+        }
+    }
+}

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

Modified: beehive/trunk/netui/test/ant/junitCore.xml
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/test/ant/junitCore.xml?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/test/ant/junitCore.xml (original)
+++ beehive/trunk/netui/test/ant/junitCore.xml Mon Sep 26 21:02:25 2005
@@ -36,6 +36,10 @@
   
         <junit printsummary="true" fork="${fail}" haltonfailure="${fail}" haltonerror="${fail}" showOutput="${show.output}">
             <jvmarg value="-ea"/>
+            <!-- Setting the production-mode flag to true will cause unresolvable actions to send
+                 a 404 response instead of the nice dev-mode error pages, which is what we want
+                 to happen here. -->
+            <jvmarg value="-Dbeehive.productionmode=true"/>
             <classpath refid="test.classpath"/>
             <formatter type="${formatter.type}"/>
             <sysproperty key="log4j.configuration" value="file:${log4j.config}"/>

Modified: beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/MockPageFlowTestCase.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/MockPageFlowTestCase.java?rev=291814&r1=291813&r2=291814&view=diff
==============================================================================
--- beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/MockPageFlowTestCase.java (original)
+++ beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/MockPageFlowTestCase.java Mon Sep 26 21:02:25 2005
@@ -18,13 +18,19 @@
 package org.apache.beehive.netui.test.pageflow;
 
 import org.apache.beehive.netui.pageflow.PageFlowActionServlet;
+import org.apache.beehive.netui.pageflow.PageFlowUtils;
+import org.apache.beehive.netui.pageflow.internal.PageFlowInitialization;
+import org.apache.beehive.netui.util.xml.XmlInputStreamResolver;
 import servletunit.struts.MockStrutsTestCase;
 import servletunit.HttpServletRequestSimulator;
 import junit.framework.AssertionFailedError;
 
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
 /**
  * Base class for Page Flow test cases running under StrutsTestCase/JUnit.
- */ 
+ */
 public abstract class MockPageFlowTestCase
         extends MockStrutsTestCase
 {
@@ -32,11 +38,14 @@
         throws Exception
     {
         super.setUp();
-        setActionServlet( new PageFlowActionServlet() );
-        
+        PageFlowInitialization.performInitializations(config.getServletContext(), getOverrideConfigResolver());
+        setActionServlet(new PageFlowActionServlet());
+        getActionServlet();     // causes it to be initialized
+
         // The page flow class must be on classpath; if not, assert.
         try
         {
+            compilePageFlow();
             Class.forName( getPageFlowClassName() );
         }
         catch ( ClassNotFoundException e )
@@ -45,68 +54,149 @@
         }
     }
 
+    /**
+     * This allows overriding of resolution of beehive-netui-config.xml.
+     * @return an {@link XmlInputStreamResolver} that resolves the location of beehive-netui-config.xml.
+     */
+    protected XmlInputStreamResolver getOverrideConfigResolver() {
+        return null;
+    }
+    
+    /**
+     * This is support for compiling page flows from within the test, for use within an IDE.  Set the system
+     * property "mockpageflowtestcase-compile-ide-beehive-root"Z
+     * @throws Exception
+     */
+    protected void compilePageFlow()
+            throws Exception
+    {
+        String beehiveRoot = System.getProperty("mockpageflowtestcase-compile-ide-beehive-root");
+        
+        if (beehiveRoot != null) {
+            // Compile the page flow using apt.
+            String pageFlowClassName = getPageFlowClassName();
+            String junitSourceRoot = beehiveRoot + "/netui/test/src/junitTests";
+            String junitBuildRoot = beehiveRoot + "/netui/build/test-classes/junitTests";
+            String sourceFile = junitSourceRoot + '/' + pageFlowClassName.replace('.', '/') + ".java";
+            Class aptMainClass = Class.forName("com.sun.tools.apt.Main");
+            Method mainMethod = aptMainClass.getMethod("process", new Class[]{ String[].class });
+            ArrayList args = new ArrayList();
+            args.add("-nocompile");
+            args.add("-classpath");
+            args.add(System.getProperty("java.class.path"));
+            args.add("-d");
+            args.add(junitBuildRoot);
+            args.add("-factory");
+            args.add("org.apache.beehive.netui.compiler.apt.PageFlowAnnotationProcessorFactory");
+            args.add("-sourcepath");
+            args.add(junitSourceRoot);
+            args.add("-Aweb.content.root=" + junitSourceRoot);
+            args.add(sourceFile);
+            String[] argsArray = (String[]) args.toArray(new String[args.size()]);
+            System.out.print(MockPageFlowTestCase.class.getName());
+            System.out.print(": invoking apt with command line:");
+            for (int i = 0; i < argsArray.length; i++) {
+                System.out.print(' ');
+                System.out.print(argsArray[i]);
+            }
+            System.out.println();
+            mainMethod.invoke(aptMainClass, new Object[]{ argsArray });
+            
+            
+        }
+    }
+
     protected void tearDown()
             throws Exception
     {
         super.tearDown();
     }
-    
+
     /**
      * Get the fully-qualified class name for the page flow to be tested.
-     */ 
+     */
     protected abstract String getPageFlowClassName();
-    
+
     /**
-     * Get the webapp name, to be used in constructing the request URI.  It is rarely necessary to specify this; it
-     * defaults to "mockPageFlowWebapp".
-     */ 
-    protected String getWebappName()
+     * Get the Struts module path for the page flow.
+     * @return the module path, which is the parent directory path; or "" if the page flow is at the root of the webapp.
+     */
+    protected String getModulePath()
     {
-        return "mockPageFlowWebapp";
+        String modulePath = '/' + getPageFlowClassName().replace( '.', '/' );
+        int lastSlash = modulePath.lastIndexOf( '/' );
+        return modulePath.substring( 0, lastSlash );
     }
     
     /**
      * Run the given action on the page flow determined by {@link #getPageFlowClassName}.
-     */ 
-    protected void runAction( String actionName )
+     */
+    protected void runAction(String actionName)
     {
-        String modulePath = getPageFlowClassName().replace( '.', '/' );
-        int lastSlash = modulePath.lastIndexOf( '/' );
+        String modulePath = getModulePath();
         String actionPath = '/' + actionName + ".do";
         HttpServletRequestSimulator mockRequest = getMockRequest();
-        
-        //
-        // Set up the request path-info and request servlet-path.  The logic differs when the page flow is the root
-        // module (the second case, below.
-        //
-        if ( lastSlash != -1 )
-        {
-            modulePath = modulePath.substring( 0, lastSlash );
-            setRequestPathInfo( modulePath, actionPath );
-            mockRequest.setServletPath( modulePath + actionPath );
-        }
-        else
-        {
-            assertTrue( false );
-            setRequestPathInfo( actionPath );
-            mockRequest.setServletPath( actionPath );
+
+        // Set up the request path-info, servlet-path, URI, etc..
+        setRequestPathInfo(modulePath, actionPath);
+        mockRequest.setServletPath(modulePath + actionPath);
+        mockRequest.setRequestURI(getRequestContextPath() + mockRequest.getServletPath());
+        mockRequest.setContextPath(getRequestContextPath());
+
+        actionPerform();
+    }
+
+    public void verifyForwardPath(String forwardPath) throws AssertionFailedError
+    {
+        // If the forward path is local, prepend the page flow's directory path.
+        if (forwardPath.charAt(0) != '/') {
+            forwardPath = getModulePath() + '/' + forwardPath;
         }
+        super.verifyForwardPath(forwardPath);
+    }
+
+    /**
+     * Verify that a particular action output was added by the action.
+     * 
+     * @param actionOutputName the name of the expected action output.
+     * @param desiredValue the desired value of the expected action output.
+     * @throws AssertionFailedError if the action output was not added, or if it had the wrong value.
+     */
+    public void verifyActionOutput(String actionOutputName, Object desiredValue) throws AssertionFailedError
+    {
+        Object value = PageFlowUtils.getActionOutput(actionOutputName, getMockRequest());
         
-        mockRequest.setRequestURI( '/' + getWebappName() + mockRequest.getServletPath() );
+        if (value == null && desiredValue != null) {
+            throw new AssertionFailedError("Did not find expected action output \"" + actionOutputName
+                                           + "\" (request=" + getMockRequest().getServletPath() + ").");
+        }
         
-        actionPerform();
+        if ((value != null || desiredValue != null) && ! value.equals(desiredValue)) {
+            throw new AssertionFailedError("Wrong value for action output \"" + actionOutputName + "\"; expected "
+                                           + desiredValue + ", got " + value + " (request=" +
+                                           getMockRequest().getServletPath() + ").");
+        }
+    }
+    
+    /**
+     * Get the context path for all requests.  Defaults to "/mockwebapp".  It is rarely necessary to specify this; it
+     * defaults to "mockwebapp".
+     */
+    protected String getRequestContextPath()
+    {
+        return "/mockwebapp";
     }
     
     /**
      * Add an update expression and the value to be set.
      * @param expression the update expression, e.g., "actionForm.foo".
      * @param value the value to be set.
-     */ 
+     */
     protected void addUpdateExpression( String expression, String value )
     {
         addRequestParameter( '{' + expression + '}', new String[]{ value } );
     }
-    
+
     protected MockPageFlowTestCase( String name )
     {
         super( name );

Added: beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java?rev=291814&view=auto
==============================================================================
--- beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java (added)
+++ beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java Mon Sep 26 21:02:25 2005
@@ -0,0 +1,64 @@
+package org.apache.beehive.netui.test.pageflow.login;
+
+import javax.security.auth.login.LoginException;
+import org.apache.beehive.netui.pageflow.Forward;
+import org.apache.beehive.netui.pageflow.PageFlowController;
+import org.apache.beehive.netui.pageflow.annotations.Jpf;
+
+public class LoginController extends PageFlowController
+{
+    public static class LoginForm
+    {
+        private String _username;
+        private String _password;
+
+        public String getUsername() {
+            return _username;
+        }
+
+        public void setUsername(String username) {
+            _username = username;
+        }
+
+        public String getPassword() {
+            return _password;
+        }
+
+        public void setPassword(String password) {
+            _password = password;
+        }
+    }
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="success", path="success.doesnotexist")
+        },
+        catches={
+            @Jpf.Catch(type=LoginException.class, path="failure.doesnotexist")
+        }
+    )
+    public Forward login(LoginForm form)
+        throws LoginException
+    {
+        login(form.getUsername(), form.getPassword());
+        Forward fwd = new Forward("success");
+        fwd.addActionOutput("userPrincipal", getUserPrincipal());
+        fwd.addActionOutput("isUserInGoodrole", Boolean.valueOf(isUserInRole("goodrole")));
+        fwd.addActionOutput("isUserInBadrole", Boolean.valueOf(isUserInRole("badrole")));
+        return fwd;
+    }
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="success", path="success.doesnotexist")
+        }
+    )
+    public Forward logout()
+    {
+        logout(false);
+        Forward fwd = new Forward("success");
+        fwd.addActionOutput("userPrincipal", getUserPrincipal());
+        fwd.addActionOutput("isUserInGoodrole", Boolean.valueOf(isUserInRole("goodrole")));
+        return fwd;
+    }
+}

Propchange: beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/pageflow/login/LoginController.java
------------------------------------------------------------------------------
    svn:eol-style = native