From a1ed5ac6d92e1ec41b5d985411100adc4b37a3cd Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Mon, 6 Apr 2009 19:55:09 +0000 Subject: [PATCH] response complete status tracking --- .../webflow/context/ExternalContext.java | 23 ++-- .../portlet/PortletExternalContext.java | 66 ++++++----- .../servlet/ServletExternalContext.java | 52 +++++--- .../webflow/test/MockExternalContext.java | 44 +++++-- .../portlet/PortletExternalContextTests.java | 85 ++++++++++++- .../servlet/ServletExternalContextTests.java | 112 +++++++++++++++++- 6 files changed, 306 insertions(+), 76 deletions(-) diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java index 3b74ee01..ada58225 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java @@ -134,11 +134,14 @@ public interface ExternalContext { /** * Get a writer for writing out a response. * @return the writer + * @throws IllegalStateException if the response has completed or is not allowed */ - public Writer getResponseWriter(); + public Writer getResponseWriter() throws IllegalStateException; /** - * Is a response allowed to be written for this request? + * Is a render response allowed to be written for this request? Always return false after a response has been + * completed. May return false before that to indicate a response is not allowed to be completed. For example, in a + * Portlet environment, render responses are only allowed in render requests. * @return true if yes, false otherwise */ public boolean isResponseAllowed(); @@ -148,8 +151,9 @@ public interface ExternalContext { * flow execution to request a refresh operation, usually to support "refresh after event processing" behavior. * Calling this method also sets responseComplete status to true. * @see #isResponseComplete() + * @throws IllegalStateException if the response has completed or is not allowed */ - public void requestFlowExecutionRedirect(); + public void requestFlowExecutionRedirect() throws IllegalStateException; /** * Request that a flow definition redirect be performed by the calling environment. Typically called from within a @@ -158,25 +162,28 @@ public interface ExternalContext { * @see #isResponseComplete() * @param flowId the id of the flow definition to redirect to * @param input input to pass the flow; this input is generally encoded the url to launch the flow + * @throws IllegalStateException if the response has completed or is not allowed */ - public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input); + public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) throws IllegalStateException; /** * Request a redirect to an arbitrary resource location. May not be supported in some environments. Calling this * method also sets responseComplete status to true. * @see #isResponseComplete() * @param location the location of the resource to redirect to + * @throws IllegalStateException if the response has completed or is not allowed */ - public void requestExternalRedirect(String location); + public void requestExternalRedirect(String location) throws IllegalStateException; /** - * Request that the redirect response requested be sent to the client in a manner that causes the client to issue - * the redirect from a popup dialog. Calling this method only has an effect when a redirect has been requested. + * Request that the current redirect requested be sent to the client in a manner that causes the client to issue the + * redirect from a popup dialog. Only call this method after a redirect has been requested. * @see #requestFlowExecutionRedirect() * @see #requestFlowDefinitionRedirect(String, MutableAttributeMap) * @see #requestExternalRedirect(String) + * @throws IllegalStateException if a redirect has not been requested */ - public void requestRedirectInPopup(); + public void requestRedirectInPopup() throws IllegalStateException; /** * Called by flow artifacts such as View states and end states to indicate they handled the response, typically by diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java index 7ad674f2..af16eaea 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java @@ -202,17 +202,15 @@ public class PortletExternalContext implements ExternalContext { } public String getFlowExecutionUrl(String flowId, String flowExecutionKey) { - if (isRenderPhase()) { - return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, (RenderResponse) response); - } else { - throw new IllegalStateException("You can only obtain a flow execution URL in a RenderRequest"); + if (!isRenderPhase()) { + throw new IllegalStateException( + "A flow execution action URL can only be obtained in a RenderRequest using a RenderResponse"); } + return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, (RenderResponse) response); } - public Writer getResponseWriter() { - if (!isRenderPhase()) { - throw new IllegalStateException("You can only access a response Writer in a RenderRequest"); - } + public Writer getResponseWriter() throws IllegalStateException { + assertResponseAllowed(); try { return ((RenderResponse) response).getWriter(); } catch (IOException e) { @@ -223,7 +221,7 @@ public class PortletExternalContext implements ExternalContext { } public boolean isResponseAllowed() { - return isRenderPhase(); + return isRenderPhase() && !responseComplete; } public boolean isResponseComplete() { @@ -234,39 +232,32 @@ public class PortletExternalContext implements ExternalContext { responseComplete = true; } - public void requestFlowExecutionRedirect() { - if (isRenderPhase()) { - throw new IllegalStateException("Redirects are not allowed durring the portlet render phase"); - } - assertResponseNotAlreadyCompleted(); + public void requestFlowExecutionRedirect() throws IllegalStateException { + assertRedirectResponseAllowed(); flowExecutionRedirectRequested = true; recordResponseComplete(); } - public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) { - if (isRenderPhase()) { - throw new IllegalStateException("Redirects are not allowed durring the portlet render phase"); - } - assertResponseNotAlreadyCompleted(); + public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) throws IllegalStateException { + assertRedirectResponseAllowed(); flowDefinitionRedirectFlowId = flowId; flowDefinitionRedirectFlowInput = input; recordResponseComplete(); } - public void requestExternalRedirect(String uri) { - if (isRenderPhase()) { - throw new IllegalStateException("Redirects are not allowed durring the portlet render phase"); - } - assertResponseNotAlreadyCompleted(); + public void requestExternalRedirect(String uri) throws IllegalStateException { + assertRedirectResponseAllowed(); externalRedirectUrl = uri; recordResponseComplete(); } - public void requestRedirectInPopup() { - if (isRenderPhase()) { - throw new IllegalStateException("Redirects are not allowed durring the portlet render phase"); + public void requestRedirectInPopup() throws IllegalStateException { + if (isRedirectRequested()) { + redirectInPopup = true; + } else { + throw new IllegalStateException( + "Only call requestRedirectInPopup after a redirect has been requested by calling requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); } - redirectInPopup = true; } public boolean isRedirectRequested() { @@ -362,10 +353,25 @@ public class PortletExternalContext implements ExternalContext { } } - private void assertResponseNotAlreadyCompleted() { + private void assertResponseAllowed() throws IllegalStateException { + if (!isRenderPhase()) { + throw new IllegalStateException( + "A response is not allowed because the current PortletRequest is not a RenderRequest"); + } if (responseComplete) { throw new IllegalStateException( - "The ExternalContext response has already been completed; this would have been done with a previous call to recordResponseComplete, requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); + "A response is not allowed because recordResponseComplete() has already been called on this ExternalContext"); + } + } + + private void assertRedirectResponseAllowed() throws IllegalStateException { + if (!isActionPhase()) { + throw new IllegalStateException( + "A redirect is not allowed because the current PortletRequest is not a ActionRequest"); + } + if (responseComplete) { + throw new IllegalStateException( + "A redirect is not allowed because a response has already been completed on this ExternalContext"); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java index 7e3b4bda..c660d400 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java @@ -205,7 +205,8 @@ public class ServletExternalContext implements ExternalContext { return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, request); } - public Writer getResponseWriter() { + public Writer getResponseWriter() throws IllegalStateException { + assertResponseAllowed(); try { return response.getWriter(); } catch (IOException e) { @@ -216,7 +217,7 @@ public class ServletExternalContext implements ExternalContext { } public boolean isResponseAllowed() { - return true; + return !responseComplete; } public boolean isResponseComplete() { @@ -227,27 +228,32 @@ public class ServletExternalContext implements ExternalContext { responseComplete = true; } - public void requestFlowExecutionRedirect() { - assertResponseNotAlreadyCompleted(); + public void requestFlowExecutionRedirect() throws IllegalStateException { + assertResponseAllowed(); flowExecutionRedirectRequested = true; recordResponseComplete(); } - public void requestExternalRedirect(String location) { - assertResponseNotAlreadyCompleted(); - externalRedirectUrl = location; - recordResponseComplete(); - } - - public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) { - assertResponseNotAlreadyCompleted(); + public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) throws IllegalStateException { + assertResponseAllowed(); flowDefinitionRedirectFlowId = flowId; flowDefinitionRedirectFlowInput = input; recordResponseComplete(); } - public void requestRedirectInPopup() { - redirectInPopup = true; + public void requestExternalRedirect(String location) throws IllegalStateException { + assertResponseAllowed(); + externalRedirectUrl = location; + recordResponseComplete(); + } + + public void requestRedirectInPopup() throws IllegalStateException { + if (isRedirectRequested()) { + redirectInPopup = true; + } else { + throw new IllegalStateException( + "Only call requestRedirectInPopup after a redirect has been requested by calling requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); + } } public boolean isRedirectRequested() { @@ -352,10 +358,22 @@ public class ServletExternalContext implements ExternalContext { this.flowUrlHandler = flowUrlHandler; } - private void assertResponseNotAlreadyCompleted() { - if (responseComplete) { + private void assertResponseAllowed() throws IllegalStateException { + if (!isResponseAllowed()) { + if (getFlowExecutionRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because a redirect has already been requested on this ExternalContext"); + } + if (getFlowDefinitionRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because a flowRedirect has already been requested on this ExternalContext"); + } + if (getExternalRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because an externalRedirect has already been requested on this ExternalContext"); + } throw new IllegalStateException( - "The ExternalContext response has already been completed; this would have been done with a previous call to recordResponseComplete, requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); + "A response is not allowed because one has already been completed on this ExternalContext"); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java index a985975a..0dd55f04 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java @@ -147,42 +147,48 @@ public class MockExternalContext implements ExternalContext { } public Writer getResponseWriter() { + assertResponseAllowed(); return responseWriter; } public boolean isResponseAllowed() { - return true; + return !responseComplete; } public boolean isResponseComplete() { return responseComplete; } - public void recordResponseComplete() throws IllegalStateException { + public void recordResponseComplete() { responseComplete = true; } - public void requestFlowExecutionRedirect() { - assertResponseNotAlreadyCompleted(); + public void requestFlowExecutionRedirect() throws IllegalStateException { + assertResponseAllowed(); flowExecutionRedirectRequested = true; recordResponseComplete(); } - public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) { - assertResponseNotAlreadyCompleted(); + public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) throws IllegalStateException { + assertResponseAllowed(); flowDefinitionRedirectFlowId = flowId; flowDefinitionRedirectFlowInput = input; recordResponseComplete(); } - public void requestExternalRedirect(String uri) { - assertResponseNotAlreadyCompleted(); + public void requestExternalRedirect(String uri) throws IllegalStateException { + assertResponseAllowed(); externalRedirectUrl = uri; recordResponseComplete(); } - public void requestRedirectInPopup() { - redirectInPopup = true; + public void requestRedirectInPopup() throws IllegalStateException { + if (isRedirectRequested()) { + redirectInPopup = true; + } else { + throw new IllegalStateException( + "Only call requestRedirectInPopup after a redirect has been requested by calling requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); + } } public boolean isRedirectRequested() { @@ -400,10 +406,22 @@ public class MockExternalContext implements ExternalContext { return redirectInPopup; } - private void assertResponseNotAlreadyCompleted() { - if (responseComplete) { + private void assertResponseAllowed() throws IllegalStateException { + if (!isResponseAllowed()) { + if (getFlowExecutionRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because a redirect has already been requested on this ExternalContext"); + } + if (getFlowDefinitionRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because a flowRedirect has already been requested on this ExternalContext"); + } + if (getExternalRedirectRequested()) { + throw new IllegalStateException( + "A response is not allowed because an externalRedirect has already been requested on this ExternalContext"); + } throw new IllegalStateException( - "The ExternalContext response has already been completed; this would have been done with a previous call to recordResponseComplete, requestFlowExecutionRedirect, requestFlowDefinitionRedirect, or requestExternalRedirect"); + "A response is not allowed because one has already been completed on this ExternalContext"); } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java b/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java index f31cb01a..34efe634 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java @@ -15,13 +15,14 @@ */ package org.springframework.webflow.context.portlet; +import java.io.IOException; +import java.io.Writer; + import junit.framework.TestCase; import org.springframework.mock.web.portlet.MockActionRequest; import org.springframework.mock.web.portlet.MockActionResponse; import org.springframework.mock.web.portlet.MockPortletContext; -import org.springframework.mock.web.portlet.MockPortletRequest; -import org.springframework.mock.web.portlet.MockPortletResponse; import org.springframework.mock.web.portlet.MockRenderRequest; import org.springframework.mock.web.portlet.MockRenderResponse; import org.springframework.webflow.context.servlet.ServletExternalContext; @@ -33,15 +34,15 @@ public class PortletExternalContextTests extends TestCase { private MockPortletContext portletContext; - private MockPortletRequest request; + private MockActionRequest request; - private MockPortletResponse response; + private MockActionResponse response; private PortletExternalContext context; - private MockPortletRequest renderRequest; + private MockRenderRequest renderRequest; - private MockPortletResponse renderResponse; + private MockRenderResponse renderResponse; private PortletExternalContext renderContext; @@ -83,8 +84,11 @@ public class PortletExternalContextTests extends TestCase { } public void testCommitExecutionRedirect() { + assertFalse(context.isResponseAllowed()); context.requestFlowExecutionRedirect(); assertTrue(context.getFlowExecutionRedirectRequested()); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); } public void testCommitExecutionRedirectRenderRequest() { @@ -97,9 +101,12 @@ public class PortletExternalContextTests extends TestCase { } public void testCommitFlowRedirect() { + assertFalse(context.isResponseAllowed()); context.requestFlowDefinitionRedirect("foo", null); assertTrue(context.getFlowDefinitionRedirectRequested()); assertEquals("foo", context.getFlowRedirectFlowId()); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); } public void testCommitFlowRedirectRenderRequest() { @@ -112,9 +119,11 @@ public class PortletExternalContextTests extends TestCase { } public void testCommitExternalRedirect() { + assertFalse(context.isResponseAllowed()); context.requestExternalRedirect("foo"); assertTrue(context.getExternalRedirectRequested()); assertEquals("foo", context.getExternalRedirectUrl()); + assertTrue(context.isResponseComplete()); } public void testCommitExternalRedirectRenderRequest() { @@ -127,10 +136,12 @@ public class PortletExternalContextTests extends TestCase { } public void testCommitExecutionRedirectPopup() { + assertFalse(context.isResponseAllowed()); context.requestFlowExecutionRedirect(); context.requestRedirectInPopup(); assertTrue(context.getFlowExecutionRedirectRequested()); assertTrue(context.getRedirectInPopup()); + assertTrue(context.isResponseComplete()); } public void testCommitFlowRedirectPopup() { @@ -139,6 +150,7 @@ public class PortletExternalContextTests extends TestCase { assertTrue(context.getFlowDefinitionRedirectRequested()); assertEquals("foo", context.getFlowRedirectFlowId()); assertTrue(context.getRedirectInPopup()); + assertTrue(context.isResponseComplete()); } public void testCommitExternalRedirectPopup() { @@ -147,6 +159,7 @@ public class PortletExternalContextTests extends TestCase { assertTrue(context.getExternalRedirectRequested()); assertEquals("foo", context.getExternalRedirectUrl()); assertTrue(context.getRedirectInPopup()); + assertTrue(context.isResponseComplete()); } public void testExecutionRedirectPopupRenderRequest() { @@ -170,4 +183,64 @@ public class PortletExternalContextTests extends TestCase { assertFalse(context.isRenderPhase()); } + public void testRecordResponseComplete() { + context.recordResponseComplete(); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); + } + + public void testDoubleCommitResponse() { + context.recordResponseComplete(); + try { + context.requestExternalRedirect("foo"); + } catch (IllegalStateException e) { + } + try { + context.requestFlowExecutionRedirect(); + fail("Should have failed"); + } catch (IllegalStateException e) { + + } + try { + context.requestFlowDefinitionRedirect("foo", null); + fail("Should have failed"); + } catch (IllegalStateException e) { + + } + } + + public void testRedirectInPopup() { + assertFalse(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); + context.requestFlowExecutionRedirect(); + assertTrue(context.isResponseComplete()); + context.requestRedirectInPopup(); + assertTrue(context.getRedirectInPopup()); + assertFalse(context.isResponseAllowed()); + assertTrue(context.getRedirectInPopup()); + } + + public void testRedirectInPopupNoRedirectRequested() { + try { + context.requestRedirectInPopup(); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + + public void testGetResponseWriter() throws IOException { + Writer writer = renderContext.getResponseWriter(); + writer.append('t'); + assertEquals("t", renderResponse.getContentAsString()); + } + + public void testGetResponseWriterResponseComplete() throws IOException { + context.recordResponseComplete(); + try { + context.getResponseWriter(); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java b/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java index 5568a48c..1afd6740 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java @@ -15,6 +15,9 @@ */ package org.springframework.webflow.context.servlet; +import java.io.IOException; +import java.io.Writer; + import junit.framework.TestCase; import org.springframework.mock.web.MockHttpServletRequest; @@ -36,7 +39,10 @@ public class ServletExternalContextTests extends TestCase { protected void setUp() { servletContext = new MockServletContext(); + servletContext.setAttribute("aFoo", "bar"); request = new MockHttpServletRequest(); + request.setAttribute("rFoo", "bar"); + request.getSession(true).setAttribute("sFoo", "bar"); response = new MockHttpServletResponse(); context = new ServletExternalContext(servletContext, request, response); } @@ -50,6 +56,18 @@ public class ServletExternalContextTests extends TestCase { assertTrue(context.getRequestParameterMap().isEmpty()); } + public void testGetAppAttribute() { + assertEquals("bar", context.getApplicationMap().get("aFoo")); + } + + public void testGetSessionAttribute() { + assertEquals("bar", context.getSessionMap().get("sFoo")); + } + + public void testGetRequestAttribute() { + assertEquals("bar", context.getRequestMap().get("rFoo")); + } + public void testGetNativeObjects() { assertEquals(servletContext, context.getNativeContext()); assertEquals(request, context.getNativeRequest()); @@ -72,18 +90,22 @@ public class ServletExternalContextTests extends TestCase { public void testCommitExecutionRedirect() { context.requestFlowExecutionRedirect(); assertTrue(context.getFlowExecutionRedirectRequested()); + assertTrue(context.isResponseComplete()); } public void testCommitFlowRedirect() { context.requestFlowDefinitionRedirect("foo", null); assertTrue(context.getFlowDefinitionRedirectRequested()); assertEquals("foo", context.getFlowRedirectFlowId()); + assertTrue(context.isResponseComplete()); } public void testCommitExternalRedirect() { context.requestExternalRedirect("foo"); assertTrue(context.getExternalRedirectRequested()); assertEquals("foo", context.getExternalRedirectUrl()); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); } public void testCommitExecutionRedirectPopup() { @@ -91,6 +113,8 @@ public class ServletExternalContextTests extends TestCase { context.requestRedirectInPopup(); assertTrue(context.getFlowExecutionRedirectRequested()); assertTrue(context.getRedirectInPopup()); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); } public void testCommitFlowRedirectPopup() { @@ -99,6 +123,8 @@ public class ServletExternalContextTests extends TestCase { assertTrue(context.getFlowDefinitionRedirectRequested()); assertEquals("foo", context.getFlowRedirectFlowId()); assertTrue(context.getRedirectInPopup()); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); } public void testCommitExternalRedirectPopup() { @@ -107,10 +133,92 @@ public class ServletExternalContextTests extends TestCase { assertTrue(context.getExternalRedirectRequested()); assertEquals("foo", context.getExternalRedirectUrl()); assertTrue(context.getRedirectInPopup()); + assertFalse(context.isResponseAllowed()); } - public void testResponseAllowed() { - assertTrue(context.isResponseAllowed()); + public void testRecordResponseComplete() { + context.recordResponseComplete(); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); + } + + public void testDoubleCommitResponse() { + context.recordResponseComplete(); + try { + context.requestFlowExecutionRedirect(); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + try { + context.requestFlowDefinitionRedirect("foo", null); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + try { + context.requestExternalRedirect("foo"); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + + public void testDoubleCommitResponseExecutionRedirectFirst() { + context.requestFlowExecutionRedirect(); + try { + context.requestFlowDefinitionRedirect("foo", null); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + + public void testDoubleCommitResponseDefinitionRedirectFirst() { + context.requestFlowDefinitionRedirect("foo", null); + try { + context.requestFlowDefinitionRedirect("foo", null); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + + public void testDoubleCommitResponseExternalRedirectFirst() { + context.requestExternalRedirect("foo"); + try { + context.requestFlowDefinitionRedirect("foo", null); + fail("Should have failed"); + } catch (IllegalStateException e) { + } + } + + public void testRedirectInPopup() { + context.requestFlowExecutionRedirect(); + assertTrue(context.isResponseComplete()); + assertFalse(context.isResponseAllowed()); + context.requestRedirectInPopup(); + assertTrue(context.getRedirectInPopup()); + } + + public void testRedirectInPopupNoRedirectRequested() { + try { + context.requestRedirectInPopup(); + fail("Should have failed"); + } catch (IllegalStateException e) { + + } + } + + public void testGetResponseWriter() throws IOException { + Writer writer = context.getResponseWriter(); + writer.append('t'); + assertEquals("t", response.getContentAsString()); + } + + public void testGetResponseWriterResponseComplete() throws IOException { + context.recordResponseComplete(); + try { + context.getResponseWriter(); + fail("Should have failed"); + } catch (IllegalStateException e) { + + } } } \ No newline at end of file