Author: rich
Date: Wed Jul 21 14:18:00 2004
New Revision: 23124
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowJspFilter.java
Log:
Fixed a nasty assert in PageFlowJspFilter, which occurred when a JSP in a page
flow directory forwarded to another page flow or JSP.
DRT: netui
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
Wed Jul 21 14:18:00 2004
@@ -84,23 +84,39 @@
private static final String DEFAULT_SIMPLE_ACTION_FORWARD_NAME =
"_defaultForward";
- /**
- * This member variable stores a reference to the current ServletRequest,
which is <i>only valid
- * during a call to [EMAIL PROTECTED] #execute} or [EMAIL PROTECTED]
#handleException}</i>.
- */
- private transient HttpServletRequest _request = null;
+ static class PerRequestState
+ {
+ private HttpServletRequest _request;
+ private HttpServletResponse _response;
+ private ActionMapping _actionMapping;
+
+ public PerRequestState( HttpServletRequest request,
HttpServletResponse response, ActionMapping actionMapping )
+ {
+ _request = request;
+ _response = response;
+ _actionMapping = actionMapping;
+ }
+
+ public HttpServletRequest getRequest()
+ {
+ return _request;
+ }
+
+ public HttpServletResponse getResponse()
+ {
+ return _response;
+ }
+
+ public ActionMapping getActionMapping()
+ {
+ return _actionMapping;
+ }
+ }
/**
- * This member variable stores a reference to the current ServletResponse,
which is <i>only valid
- * during a call to [EMAIL PROTECTED] #execute} or [EMAIL PROTECTED]
#handleException}</i>.
+ * Stores per-request state, which is <i>only valid during calls to [EMAIL
PROTECTED] #execute} or [EMAIL PROTECTED] #handleException}</i>.
*/
- private transient HttpServletResponse _response = null;
-
- /**
- * This member variable stores a reference to the current ActionMapping,
which is <i>only valid
- * during a call to [EMAIL PROTECTED] #execute} or [EMAIL PROTECTED]
#handleException}</i>.
- */
- private transient ActionMapping _mapping = null;
+ private transient PerRequestState _perRequestState;
/**
* We prevent the base class from storing a reference to ActionServlet in
the non-transient
@@ -215,7 +231,7 @@
HttpServletResponse
response )
throws Exception
{
- setRequestMembers( request, response, mapping );
+ PerRequestState prevState = setPerRequestState( new PerRequestState(
request, response, mapping ) );
try
{
@@ -228,7 +244,7 @@
}
finally
{
- nullRequestMembers( request );
+ setPerRequestState( prevState );
}
}
@@ -313,11 +329,10 @@
String actionName = PageFlowUtils.getActionName( mapping );
boolean gotPastBeforeAction = false;
ServletContext servletContext = getServlet().getServletContext();
-
+ PerRequestState prevState = setPerRequestState( new PerRequestState(
request, response, mapping ) );
+
try
{
- setRequestMembers( request, response, mapping );
-
//
// beforeAction callback
//
@@ -462,35 +477,38 @@
}
finally
{
- nullRequestMembers( request );
-
- ActionForward overrideReturn = null;
-
- if ( gotPastBeforeAction )
+ try
{
+ ActionForward overrideReturn = null;
+
+ if ( gotPastBeforeAction )
+ {
+ //
+ // afterAction callback
+ //
+ try
+ {
+ afterAction();
+ }
+ catch ( Throwable th )
+ {
+ overrideReturn = handleException( th, mapping,
actionName, form, request, response );
+ }
+ }
+
//
- // afterAction callback
+ // Store information on this action for use with
navigateTo=Jpf.NavigateTo.previousAction.
//
- try
- {
- setRequestMembers( request, response, mapping );
- afterAction();
- }
- catch ( Throwable th )
+ savePreviousActionInfo( form, request, mapping,
getServlet().getServletContext() );
+
+ if ( overrideReturn != null )
{
- overrideReturn = handleException( th, mapping, actionName,
form, request, response );
+ return overrideReturn;
}
- }
-
-
- //
- // Store information on this action for use with return-to="action"
- //
- savePreviousActionInfo( form, request, mapping,
getServlet().getServletContext() );
-
- if ( overrideReturn != null )
+ }
+ finally
{
- return overrideReturn;
+ setPerRequestState( prevState );
}
}
}
@@ -576,7 +594,6 @@
ServletContext servletContext )
{
setServlet( InternalUtils.getActionServlet( servletContext ) );
- setRequestMembers( request, response, null );
//
// Cache the associated ModuleConfig. This is used throughout the
code, in places where the request
@@ -589,7 +606,8 @@
//
initJavaControls( request, response );
-
+ PerRequestState prevState = setPerRequestState( new PerRequestState(
request, response, null ) );
+
try
{
try
@@ -612,7 +630,7 @@
}
finally
{
- nullRequestMembers( request );
+ setPerRequestState( prevState );
}
}
@@ -884,15 +902,12 @@
*/
protected final HttpServletRequest getRequest()
{
- if ( _request == null )
+ if ( _perRequestState == null )
{
- String message = "getRequest was called outside of a valid
context.";
- LocalizedIllegalStateException ex = new
LocalizedIllegalStateException( message );
- ex.setLocalizedMessage( Bundle.getString(
"PageFlow_IllegalStateGet", "getRequest" ) );
- throw ex;
+ throw new IllegalStateException( "getRequest was called outside of
a valid context." );
}
- return _request;
+ return _perRequestState.getRequest();
}
/**
@@ -907,15 +922,12 @@
*/
protected final HttpServletResponse getResponse()
{
- if ( _response == null )
+ if ( _perRequestState == null )
{
- String message = "getResponse was called outside of a valid
context.";
- LocalizedIllegalStateException ex = new
LocalizedIllegalStateException( message );
- ex.setLocalizedMessage( Bundle.getString(
"PageFlow_IllegalStateGet", "getResponse" ) );
- throw ex;
+ throw new IllegalStateException( "getResponse was called outside
of a valid context." );
}
- return _response;
+ return _perRequestState.getResponse();
}
/**
@@ -923,6 +935,7 @@
* tag that corresponds to the current page flow action being executed.
This call is only valid
* during [EMAIL PROTECTED] #execute} (where any user action method is
invoked), and during the lifecycle
* methods [EMAIL PROTECTED] #beforeAction} and [EMAIL PROTECTED]
#afterAction}.
+ * @deprecated Use [EMAIL PROTECTED] #getActionMapping} instead.
*
* @return the current Struts ActionMapping.
* @throws IllegalStateException if this method is invoked outside of
action method
@@ -931,15 +944,28 @@
*/
protected final ActionMapping getMapping()
{
- if ( _mapping == null )
+ return getActionMapping();
+ }
+
+ /**
+ * Get the current Struts ActionMapping, which is information from the
Struts-XML <action>
+ * tag that corresponds to the current page flow action being executed.
This call is only valid
+ * during [EMAIL PROTECTED] #execute} (where any user action method is
invoked), and during the lifecycle
+ * methods [EMAIL PROTECTED] #beforeAction} and [EMAIL PROTECTED]
#afterAction}.
+ *
+ * @return the current Struts ActionMapping.
+ * @throws IllegalStateException if this method is invoked outside of
action method
+ * execution (i.e., outside of the call to [EMAIL PROTECTED]
#execute}, and outside of
+ * [EMAIL PROTECTED] #onCreate}, [EMAIL PROTECTED]
#beforeAction}, [EMAIL PROTECTED] #afterAction}.
+ */
+ protected final ActionMapping getActionMapping()
+ {
+ if ( _perRequestState == null )
{
- String message = "getMapping was called outside of a valid
context.";
- LocalizedIllegalStateException ex = new
LocalizedIllegalStateException( message );
- ex.setLocalizedMessage( Bundle.getString(
"PageFlow_IllegalStateGet", "getMapping" ) );
- throw ex;
+ throw new IllegalStateException( "getActionMapping was called
outside of a valid context." );
}
- return _mapping;
+ return _perRequestState.getActionMapping();
}
/**
@@ -954,39 +980,27 @@
*/
protected final HttpSession getSession()
{
- if ( _request == null )
+ if ( _perRequestState == null )
{
- String message = "getSession was called outside of a valid
context.";
- LocalizedIllegalStateException ex = new
LocalizedIllegalStateException( message );
- ex.setLocalizedMessage( Bundle.getString(
"PageFlow_IllegalStateGet", "getSession" ) );
- throw ex;
+ throw new IllegalStateException( "getSession was called outside of
a valid context." );
}
- return _request.getSession( true );
+ return _perRequestState.getRequest().getSession( true );
}
- void setRequestMembers( HttpServletRequest request, HttpServletResponse
response, ActionMapping mapping )
- {
- assert request != null;
- assert response != null;
-
- _request = request;
- _response = response;
- _mapping = mapping;
- }
-
- void nullRequestMembers( HttpServletRequest request )
+ PerRequestState setPerRequestState( PerRequestState state )
{
- assert request == _request : "old request: " + _request + ", new
request: " + request;
-
- if ( request == _request )
+ if ( state != null )
{
- _request = null;
- _response = null;
- _mapping = null;
+ assert state.getRequest() != null;
+ assert state.getResponse() != null;
}
+
+ PerRequestState prevState = _perRequestState;
+ _perRequestState = state;
+ return prevState;
}
-
+
/**
* @exclude
*/
@@ -1005,7 +1019,7 @@
//
// We'll get into this next block if the requested module path
differs in case from
// the "natural" module path for this file (Windows only). If so,
we'll parse the
- // module path from the request. Note that the request (which
comes from _request)
+ // module path from the request. Note that the request (which
comes from _perRequestState)
// may be null for Global.app, but because we create the
Global.app URIs ("/-global"
// module path), we'll never have a case issue.
//
@@ -1217,9 +1231,16 @@
*/
public synchronized final void refresh( HttpServletRequest request,
HttpServletResponse response )
{
- setRequestMembers( request, response, null );
- onRefresh();
- nullRequestMembers( request );
+ PerRequestState prevState = setPerRequestState( new PerRequestState(
request, response, null ) );
+
+ try
+ {
+ onRefresh();
+ }
+ finally
+ {
+ setPerRequestState( prevState );
+ }
}
/**
@@ -1535,10 +1556,9 @@
ActionMapping actionMapping, HttpServletRequest request,
HttpServletResponse response, boolean readonly )
throws Exception
{
- setRequestMembers( request, response, actionMapping );
-
ActionForward result = null;
-
+ PerRequestState prevState = setPerRequestState( new PerRequestState(
request, response, actionMapping ) );
+
try
{
if ( _log.isDebugEnabled() )
@@ -1588,7 +1608,7 @@
}
finally
{
- nullRequestMembers( request );
+ setPerRequestState( prevState );
}
return result;
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowJspFilter.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowJspFilter.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowJspFilter.java
Wed Jul 21 14:18:00 2004
@@ -175,34 +175,36 @@
_log.debug( "Continuing with filter chain..." );
}
- try
+ //
+ // Make sure that the pageflow's getRequest() and
getResponse() will work while the JSP
+ // is being rendered, since methods on the pageflow may be
called (through databinding
+ // or tags, or through direct reference).
+ //
+ if ( curJpf != null )
{
//
- // Make sure that the pageflow's getRequest() and
getResponse() will work while the JSP
- // is being rendered, since methods on the pageflow may be
called (through databinding
- // or tags, or through direct reference).
+ // We're going to bail out if there are too many
concurrent requests for the same JPF.
+ // This prevents an attack that takes advantage of the
fact that we serialize requests
+ // to the same pageflow.
//
- if ( curJpf != null )
+ if ( curJpf.incrementRequestCount( httpRequest,
httpResponse, _servletContext ) )
{
- //
- // We're going to bail out if there are too many
concurrent requests for the same JPF.
- // This prevents an attack that takes advantage of the
fact that we serialize requests
- // to the same pageflow.
- //
- if ( curJpf.incrementRequestCount( httpRequest,
httpResponse, _servletContext ) )
+ try
{
- try
+ //
+ // Any databinding calls, indirect calls to
getRequest(), etc. must be protected
+ // against conflicts from running action methods
at the same time as rendering
+ // the JSP here. Synchronize on the JPF.
+ //
+ synchronized ( curJpf )
{
- //
- // Any databinding calls, indirect calls to
getRequest(), etc. must be protected
- // against conflicts from running action
methods at the same time as rendering
- // the JSP here. Synchronize on the JPF.
- //
- synchronized ( curJpf )
- {
- curJpf.setServlet(
InternalUtils.getActionServlet( _servletContext ) );
- curJpf.setRequestMembers( httpRequest,
httpResponse, null );
+ FlowController.PerRequestState newState =
+ new FlowController.PerRequestState(
httpRequest, httpResponse, null );
+ FlowController.PerRequestState prevState =
curJpf.setPerRequestState( newState );
+ curJpf.setServlet(
InternalUtils.getActionServlet( _servletContext ) );
+ try
+ {
// @todo: need to wrap this in checks for
JSP 1.2
// @todo: feature: need to add support for
chaining in user-code to
// run when setting implicit
objects on the request
@@ -215,39 +217,29 @@
chain.doFilter( request, response );
}
- }
- finally
- {
- curJpf.decrementRequestCount( httpRequest );
+ finally
+ {
+ curJpf.setPerRequestState( prevState );
+ }
}
}
- else
+ finally
{
- curJpf = null; // avoid synchronization in
finally block below
+ curJpf.decrementRequestCount( httpRequest );
}
}
- else
- {
- // @todo: need to wrap this in checks for JSP 1.2
- // @todo: feature: need to add support for chaining in
user-code to
- // run when setting implicit objects on the
request
- InternalUtils.ensureGlobalApp(httpRequest,
httpResponse);
- httpRequest.setAttribute("globalApp",
PageFlowUtils.getGlobalApp(httpRequest));
- BundleMap bundleMap = new BundleMap(httpRequest,
_servletContext, null);
- httpRequest.setAttribute("bundle", bundleMap);
-
- chain.doFilter( request, response );
- }
}
- finally
+ else
{
- if ( curJpf != null )
- {
- synchronized ( curJpf )
- {
- curJpf.nullRequestMembers( httpRequest );
- }
- }
+ // @todo: need to wrap this in checks for JSP 1.2
+ // @todo: feature: need to add support for chaining in
user-code to
+ // run when setting implicit objects on the request
+ InternalUtils.ensureGlobalApp(httpRequest, httpResponse);
+ httpRequest.setAttribute("globalApp",
PageFlowUtils.getGlobalApp(httpRequest));
+ BundleMap bundleMap = new BundleMap(httpRequest,
_servletContext, null);
+ httpRequest.setAttribute("bundle", bundleMap);
+
+ chain.doFilter( request, response );
}
}
finally