This commit is contained in:
@@ -1,112 +0,0 @@
|
||||
package org.springframework.faces.ui.resource;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Special action for resolving and rendering static resources from within a JAR file.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class RenderResourceAction implements Action {
|
||||
|
||||
private static final String IF_MODIFIED_SINCE_HEADER = "If-Modified-Since";
|
||||
|
||||
private static final String HTTP_CONTENT_LENGTH_HEADER = "Content-Length";
|
||||
|
||||
private static final String HTTP_LAST_MODIFIED_HEADER = "Last-Modified";
|
||||
|
||||
private static final String HTTP_EXPIRES_HEADER = "Expires";
|
||||
|
||||
private static final String HTTP_CACHE_CONTROL_HEADER = "Cache-Control";
|
||||
|
||||
private Map defaultMimeTypes = new HashMap();
|
||||
{
|
||||
defaultMimeTypes.put(".css", "text/css");
|
||||
defaultMimeTypes.put(".gif", "image/gif");
|
||||
defaultMimeTypes.put(".ico", "image/vnd.microsoft.icon");
|
||||
defaultMimeTypes.put(".jpeg", "image/jpeg");
|
||||
defaultMimeTypes.put(".jpg", "image/jpeg");
|
||||
defaultMimeTypes.put(".js", "text/javascript");
|
||||
defaultMimeTypes.put(".png", "image/png");
|
||||
}
|
||||
|
||||
public Event execute(RequestContext context) throws Exception {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
|
||||
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
|
||||
ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
|
||||
|
||||
String localResourcePath = context.getExternalContext().getRequestPath().toString();
|
||||
String jarResourcePath = "META-INF" + context.getExternalContext().getRequestPath().toString();
|
||||
|
||||
URL resource;
|
||||
|
||||
resource = servletContext.getResource(localResourcePath);
|
||||
if (resource == null) {
|
||||
resource = ClassUtils.getDefaultClassLoader().getResource(jarResourcePath);
|
||||
if (resource == null) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return new Event(this, "success");
|
||||
}
|
||||
}
|
||||
|
||||
URLConnection resourceConn = resource.openConnection();
|
||||
long lastModified = resourceConn.getLastModified();
|
||||
|
||||
long ifModifiedSince = request.getDateHeader(IF_MODIFIED_SINCE_HEADER);
|
||||
if (ifModifiedSince > 0 && lastModified / 1000 <= ifModifiedSince / 1000) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return new Event(this, "success");
|
||||
}
|
||||
|
||||
String mimeType = servletContext.getMimeType(jarResourcePath);
|
||||
if (mimeType == null) {
|
||||
String extension = jarResourcePath.substring(jarResourcePath.lastIndexOf('.'));
|
||||
mimeType = (String) defaultMimeTypes.get(extension);
|
||||
}
|
||||
response.setContentType(mimeType);
|
||||
|
||||
response.setHeader(HTTP_CONTENT_LENGTH_HEADER, Long.toString(resourceConn.getContentLength()));
|
||||
response.setDateHeader(HTTP_LAST_MODIFIED_HEADER, lastModified);
|
||||
configureCaching(response, 31556926);
|
||||
|
||||
InputStream in = resourceConn.getInputStream();
|
||||
OutputStream out = response.getOutputStream();
|
||||
try {
|
||||
byte[] buffer = new byte[1024];
|
||||
while (in.available() > 0) {
|
||||
int len = in.read(buffer);
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
} finally {
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
return new Event(this, "success");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTTP headers to allow caching for the given number of seconds.
|
||||
* @param seconds number of seconds into the future that the response should be cacheable for
|
||||
*/
|
||||
private void configureCaching(HttpServletResponse response, int seconds) {
|
||||
// HTTP 1.0 header
|
||||
response.setDateHeader(HTTP_EXPIRES_HEADER, System.currentTimeMillis() + seconds * 1000L);
|
||||
// HTTP 1.1 header
|
||||
response.setHeader(HTTP_CACHE_CONTROL_HEADER, "max-age=" + seconds);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.springframework.faces.ui.resource;
|
||||
|
||||
import org.springframework.webflow.engine.EndState;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder;
|
||||
|
||||
/**
|
||||
* Builder for generating the "resources" flow which is responsible for serving static resources from the classpath.
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class ResourcesFlowBuilder extends AbstractFlowBuilder {
|
||||
public void buildStates() throws FlowBuilderException {
|
||||
EndState renderResource = new EndState(getFlow(), "renderResource");
|
||||
renderResource.setFinalResponseAction(new RenderResourceAction());
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.springframework.faces.ui.resource;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.webflow.context.ExternalContext;
|
||||
import org.springframework.webflow.context.RequestPath;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
public class RenderResourceActionTests extends TestCase {
|
||||
|
||||
ExternalContext externalContext = (ExternalContext) EasyMock.createMock(ExternalContext.class);
|
||||
RequestContext requestContext = (RequestContext) EasyMock.createMock(RequestContext.class);
|
||||
ServletContext servletContext = new ResourceTestMockServletContext();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
RequestPath requestPath;
|
||||
String[] requestElements;
|
||||
|
||||
RenderResourceAction action;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
action = new RenderResourceAction();
|
||||
|
||||
EasyMock.expect(requestContext.getExternalContext()).andStubReturn(externalContext);
|
||||
EasyMock.expect(externalContext.getContext()).andStubReturn(servletContext);
|
||||
EasyMock.expect(externalContext.getResponse()).andStubReturn(response);
|
||||
EasyMock.expect(externalContext.getRequest()).andStubReturn(request);
|
||||
EasyMock.expect(externalContext.getResponseWriter()).andStubReturn(new PrintWriter(new StringWriter()));
|
||||
}
|
||||
|
||||
public final void testExecute() throws Exception {
|
||||
|
||||
requestPath = new RequestPath("/ext/ext.js");
|
||||
|
||||
EasyMock.expect(externalContext.getRequestPath()).andStubReturn(requestPath);
|
||||
|
||||
EasyMock.replay(new Object[] { requestContext, externalContext });
|
||||
|
||||
action.execute(requestContext);
|
||||
}
|
||||
|
||||
public final void testExecute_ResourceNotFound() throws Exception {
|
||||
|
||||
requestPath = new RequestPath("/xxx/xxx.js");
|
||||
|
||||
EasyMock.expect(externalContext.getRequestPath()).andStubReturn(requestPath);
|
||||
|
||||
EasyMock.replay(new Object[] { requestContext, externalContext });
|
||||
|
||||
action.execute(requestContext);
|
||||
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
private class ResourceTestMockServletContext extends MockServletContext {
|
||||
|
||||
public String getMimeType(String filePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.springframework.webflow.context.servlet;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
|
||||
public class DefaultFlowUrlHandler implements FlowUrlHandler {
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING_SCHEME = "UTF-8";
|
||||
|
||||
private String urlEncodingScheme = DEFAULT_URL_ENCODING_SCHEME;
|
||||
|
||||
private UrlPathHelper urlPathHelper;
|
||||
|
||||
public DefaultFlowUrlHandler() {
|
||||
urlPathHelper = new UrlPathHelper();
|
||||
}
|
||||
|
||||
public String getFlowExecutionKey(HttpServletRequest request) {
|
||||
return request.getParameter("execution");
|
||||
}
|
||||
|
||||
public String getFlowId(HttpServletRequest request) {
|
||||
return WebUtils.extractFilenameFromUrlPath(urlPathHelper.getLookupPathForRequest(request));
|
||||
}
|
||||
|
||||
public String createFlowExecutionUrl(String flowId, String flowExecutionKey, HttpServletRequest request) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(request.getContextPath());
|
||||
url.append(request.getServletPath());
|
||||
url.append('/');
|
||||
url.append(encode(flowId));
|
||||
url.append('?');
|
||||
appendQueryParameter(url, "execution", flowExecutionKey);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
public String createFlowDefinitionUrl(String flowId, AttributeMap input, HttpServletRequest request) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(request.getContextPath());
|
||||
url.append(request.getServletPath());
|
||||
url.append('/');
|
||||
url.append(encode(flowId));
|
||||
if (input != null && !input.isEmpty()) {
|
||||
url.append('?');
|
||||
appendQueryParameters(url, input.asMap());
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
private void appendQueryParameters(StringBuffer url, Map parameters) {
|
||||
Iterator entries = parameters.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) entries.next();
|
||||
appendQueryParameter(url, entry.getKey(), entry.getValue());
|
||||
if (entries.hasNext()) {
|
||||
url.append('&');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendQueryParameter(StringBuffer url, Object key, Object value) {
|
||||
String encodedKey = encode(key);
|
||||
String encodedValue = encode(value);
|
||||
url.append(encodedKey).append('=').append(encodedValue);
|
||||
}
|
||||
|
||||
private String encode(Object value) {
|
||||
return value != null ? urlEncode(String.valueOf(value)) : "";
|
||||
}
|
||||
|
||||
private String urlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(String.valueOf(value), urlEncodingScheme);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalArgumentException("Cannot url encode " + value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.webflow.context.servlet;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
|
||||
public interface FlowUrlHandler {
|
||||
|
||||
/**
|
||||
* Extract the flow execution from the request.
|
||||
* @param request the request
|
||||
* @return the flow execution key, or null if no flow execution key is present
|
||||
*/
|
||||
public String getFlowExecutionKey(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Extract the flow id from the request.
|
||||
* @param request the request
|
||||
* @return the flow id, or null if no flow id is present
|
||||
*/
|
||||
public String getFlowId(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Create a URL that when addressed will launch a new execution of a flow.
|
||||
* @param flowId the id of the flow definition
|
||||
* @param input the input to pass the new flow execution
|
||||
* @param request the current request
|
||||
* @return the flow definition url
|
||||
*/
|
||||
public String createFlowDefinitionUrl(String flowId, AttributeMap input, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Create a URL that when addressed will resume an existing execution of a flow.
|
||||
* @param flowExecutionKey the flow execution key that is paused and waiting to be resumed
|
||||
* @param request the current request
|
||||
* @return the flow execution url
|
||||
*/
|
||||
public String createFlowExecutionUrl(String flowId, String flowExecutionKey, HttpServletRequest request);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springframework.webflow.context.servlet;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
|
||||
public class ParameterBasedFlowUrlHandler implements FlowUrlHandler {
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING_SCHEME = "UTF-8";
|
||||
|
||||
private String urlEncodingScheme = DEFAULT_URL_ENCODING_SCHEME;
|
||||
|
||||
public String getFlowExecutionKey(HttpServletRequest request) {
|
||||
return request.getParameter("_flowExecutionKey");
|
||||
}
|
||||
|
||||
public String getFlowId(HttpServletRequest request) {
|
||||
return request.getParameter("_flowId");
|
||||
}
|
||||
|
||||
public String createFlowExecutionUrl(String flowId, String flowExecutionKey, HttpServletRequest request) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(request.getContextPath());
|
||||
url.append(request.getServletPath());
|
||||
if (request.getPathInfo() != null) {
|
||||
url.append(request.getPathInfo());
|
||||
}
|
||||
url.append('?');
|
||||
appendQueryParameter(url, "_flowId", flowId);
|
||||
url.append('&');
|
||||
appendQueryParameter(url, "_flowExecutionKey", flowExecutionKey);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
public String createFlowDefinitionUrl(String flowId, AttributeMap input, HttpServletRequest request) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(request.getContextPath());
|
||||
url.append(request.getServletPath());
|
||||
if (request.getPathInfo() != null) {
|
||||
url.append(request.getPathInfo());
|
||||
}
|
||||
url.append('?');
|
||||
appendQueryParameter(url, "_flowId", flowId);
|
||||
if (input != null && !input.isEmpty()) {
|
||||
url.append('&');
|
||||
appendQueryParameters(url, input.asMap());
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
private void appendQueryParameters(StringBuffer url, Map parameters) {
|
||||
Iterator entries = parameters.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) entries.next();
|
||||
appendQueryParameter(url, entry.getKey(), entry.getValue());
|
||||
if (entries.hasNext()) {
|
||||
url.append('&');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendQueryParameter(StringBuffer url, Object key, Object value) {
|
||||
String encodedKey = encode(key);
|
||||
String encodedValue = encode(value);
|
||||
url.append(encodedKey).append('=').append(encodedValue);
|
||||
}
|
||||
|
||||
private String encode(Object value) {
|
||||
return value != null ? urlEncode(String.valueOf(value)) : "";
|
||||
}
|
||||
|
||||
private String urlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(String.valueOf(value), urlEncodingScheme);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalArgumentException("Cannot url encode " + value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.springframework.webflow.executor;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
|
||||
public class FlowExecutionResult {
|
||||
private String flowId;
|
||||
private String flowExecutionKey;
|
||||
private String outcome;
|
||||
private AttributeMap output;
|
||||
|
||||
private FlowExecutionResult(String flowId, String flowExecutionKey, String outcome, AttributeMap output) {
|
||||
this.flowId = flowId;
|
||||
this.flowExecutionKey = flowExecutionKey;
|
||||
this.outcome = outcome;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public static FlowExecutionResult createPausedResult(String flowId, String flowExecutionKey) {
|
||||
return new FlowExecutionResult(flowId, flowExecutionKey, null, null);
|
||||
}
|
||||
|
||||
public static FlowExecutionResult createEndedResult(String flowId, Event outcome) {
|
||||
return new FlowExecutionResult(flowId, null, outcome.getId(), outcome.getAttributes());
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return flowId;
|
||||
}
|
||||
|
||||
public boolean paused() {
|
||||
return flowExecutionKey != null;
|
||||
}
|
||||
|
||||
public String getPausedKey() {
|
||||
return flowExecutionKey;
|
||||
}
|
||||
|
||||
public boolean ended() {
|
||||
return flowExecutionKey == null;
|
||||
}
|
||||
|
||||
public String getEndedOutcome() {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
public AttributeMap getEndedOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.webflow.mvc;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
|
||||
public interface FlowHandler {
|
||||
public String getFlowId();
|
||||
|
||||
public MutableAttributeMap createExecutionInputMap(HttpServletRequest request);
|
||||
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
HttpServletResponse response);
|
||||
|
||||
public ModelAndView handleException(FlowException e, HttpServletRequest request, HttpServletResponse response);
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.springframework.webflow.mvc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.context.support.WebApplicationObjectSupport;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler;
|
||||
import org.springframework.webflow.context.servlet.FlowUrlHandler;
|
||||
import org.springframework.webflow.context.servlet.ServletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
|
||||
public class FlowHandlerAdapter extends WebApplicationObjectSupport implements HandlerAdapter {
|
||||
|
||||
private FlowExecutor flowExecutor;
|
||||
private FlowUrlHandler urlHandler;
|
||||
|
||||
public FlowHandlerAdapter(FlowExecutor flowExecutor) {
|
||||
this.flowExecutor = flowExecutor;
|
||||
this.urlHandler = new DefaultFlowUrlHandler();
|
||||
}
|
||||
|
||||
public FlowUrlHandler getFlowUrlHandler() {
|
||||
return urlHandler;
|
||||
}
|
||||
|
||||
public void setFlowUrlHandler(FlowUrlHandler urlHandler) {
|
||||
this.urlHandler = urlHandler;
|
||||
}
|
||||
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof FlowHandler;
|
||||
}
|
||||
|
||||
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
FlowHandler flowHandler = (FlowHandler) handler;
|
||||
String flowExecutionKey = urlHandler.getFlowExecutionKey(request);
|
||||
if (flowExecutionKey != null) {
|
||||
try {
|
||||
ServletExternalContext context = createServletExternalContext(request, response);
|
||||
FlowExecutionResult result = flowExecutor.resumeExecution(flowExecutionKey, context);
|
||||
return handleFlowExecutionResult(result, context, request, response, flowHandler);
|
||||
} catch (FlowException e) {
|
||||
return handleFlowException(e, request, response, flowHandler);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
MutableAttributeMap input = flowHandler.createExecutionInputMap(request);
|
||||
ServletExternalContext context = createServletExternalContext(request, response);
|
||||
FlowExecutionResult result = flowExecutor.launchExecution(flowHandler.getFlowId(), input, context);
|
||||
return handleFlowExecutionResult(result, context, request, response, flowHandler);
|
||||
} catch (FlowException e) {
|
||||
return handleFlowException(e, request, response, flowHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// subclassing hooks
|
||||
|
||||
protected ServletExternalContext createServletExternalContext(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return new ServletExternalContext(getServletContext(), request, response, urlHandler);
|
||||
}
|
||||
|
||||
protected MutableAttributeMap defaultFlowExecutionInputMap(HttpServletRequest request) {
|
||||
return new LocalAttributeMap(request.getParameterMap());
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowOutcome(String flowId, String outcome, AttributeMap endedOutput,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
// by default, just start the flow over passing the output as input
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, endedOutput, request));
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowException(String flowId, FlowException e, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
if (e instanceof NoSuchFlowExecutionException && flowId != null) {
|
||||
// by default, attempt to restart the flow
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, null, request));
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private ModelAndView handleFlowExecutionResult(FlowExecutionResult result, ServletExternalContext context,
|
||||
HttpServletRequest request, HttpServletResponse response, FlowHandler handler) throws IOException {
|
||||
if (result.paused()) {
|
||||
if (context.flowExecutionRedirectRequested()) {
|
||||
String url = urlHandler.createFlowExecutionUrl(result.getFlowId(), result.getPausedKey(), request);
|
||||
response.sendRedirect(url);
|
||||
return null;
|
||||
} else if (context.externalRedirectRequested()) {
|
||||
response.sendRedirect(context.getExternalRedirectUrl());
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (result.ended()) {
|
||||
if (context.flowDefinitionRedirectRequested()) {
|
||||
String flowId = context.getFlowRedirectFlowId();
|
||||
AttributeMap input = context.getFlowRedirectFlowInput();
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, input, request));
|
||||
return null;
|
||||
} else if (context.externalRedirectRequested()) {
|
||||
response.sendRedirect(context.getExternalRedirectUrl());
|
||||
return null;
|
||||
} else {
|
||||
ModelAndView mv = handler.handleExecutionOutcome(result.getEndedOutcome(), result.getEndedOutput(),
|
||||
request, response);
|
||||
return mv != null ? mv : defaultHandleFlowOutcome(handler.getFlowId(), result.getEndedOutcome(), result
|
||||
.getEndedOutput(), request, response);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Execution result should have been one of [paused] or [ended]");
|
||||
}
|
||||
}
|
||||
|
||||
private ModelAndView handleFlowException(FlowException e, HttpServletRequest request, HttpServletResponse response,
|
||||
FlowHandler handler) throws IOException {
|
||||
ModelAndView result = handler.handleException(e, request, response);
|
||||
return result != null ? result : defaultHandleFlowException(handler.getFlowId(), e, request, response);
|
||||
}
|
||||
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.webflow.test;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
|
||||
/**
|
||||
* A simple flow execution key implementation. New instances of this class get their values from a sequence encapsulated
|
||||
* as a static private variable of this class.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class GeneratedFlowExecutionKey extends FlowExecutionKey {
|
||||
|
||||
private static int nextKey = 1;
|
||||
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Creates a new mock flow execution key.
|
||||
*/
|
||||
public GeneratedFlowExecutionKey() {
|
||||
this.value = nextKey();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof GeneratedFlowExecutionKey)) {
|
||||
return false;
|
||||
}
|
||||
GeneratedFlowExecutionKey key = (GeneratedFlowExecutionKey) o;
|
||||
return value == key.value;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return value * 29;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
private static int nextKey() {
|
||||
int key = nextKey;
|
||||
nextKey++;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.springframework.webflow.context.servlet;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
|
||||
public class DefaultFlowUrlHandlerTests extends TestCase {
|
||||
private DefaultFlowUrlHandler urlHandler = new DefaultFlowUrlHandler();
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
public void testGetFlowId() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
assertEquals("foo", urlHandler.getFlowId(request));
|
||||
}
|
||||
|
||||
public void testGetFlowExecutionKey() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.addParameter("execution", "12345");
|
||||
assertEquals("12345", urlHandler.getFlowExecutionKey(request));
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrl() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", null, request);
|
||||
assertEquals("/springtravel/app/bookHotel", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrlEmptyInput() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", CollectionUtils.EMPTY_ATTRIBUTE_MAP, request);
|
||||
assertEquals("/springtravel/app/bookHotel", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrlWithFlowInput() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
LocalAttributeMap input = new LocalAttributeMap(new LinkedHashMap());
|
||||
input.put("foo", "bar");
|
||||
input.put("bar", "needs encoding");
|
||||
input.put("baz", new Integer(1));
|
||||
input.put("boop", null);
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", input, request);
|
||||
assertEquals("/springtravel/app/bookHotel?foo=bar&bar=needs+encoding&baz=1&boop=", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowExecutionUrl() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
String url = urlHandler.createFlowExecutionUrl("foo", "12345", request);
|
||||
assertEquals("/springtravel/app/foo?execution=12345", url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.springframework.webflow.context.servlet;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.webflow.context.servlet.ParameterBasedFlowUrlHandler;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
|
||||
public class ParameterBasedFlowUrlHandlerTests extends TestCase {
|
||||
private ParameterBasedFlowUrlHandler urlHandler = new ParameterBasedFlowUrlHandler();
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
public void testGetFlowId() {
|
||||
request.addParameter("_flowId", "foo");
|
||||
assertEquals("foo", urlHandler.getFlowId(request));
|
||||
}
|
||||
|
||||
public void testGetFlowExecutionKey() {
|
||||
request.addParameter("_flowExecutionKey", "12345");
|
||||
assertEquals("12345", urlHandler.getFlowExecutionKey(request));
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrl() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/flows");
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", null, request);
|
||||
assertEquals("/springtravel/app/flows?_flowId=bookHotel", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrlEmptyInput() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/flows");
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", CollectionUtils.EMPTY_ATTRIBUTE_MAP, request);
|
||||
assertEquals("/springtravel/app/flows?_flowId=bookHotel", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowDefinitionUrlWithFlowInput() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/flows");
|
||||
LocalAttributeMap input = new LocalAttributeMap(new LinkedHashMap());
|
||||
input.put("foo", "bar");
|
||||
input.put("bar", "needs encoding");
|
||||
input.put("baz", new Integer(1));
|
||||
input.put("boop", null);
|
||||
String url = urlHandler.createFlowDefinitionUrl("bookHotel", input, request);
|
||||
assertEquals("/springtravel/app/flows?_flowId=bookHotel&foo=bar&bar=needs+encoding&baz=1&boop=", url);
|
||||
}
|
||||
|
||||
public void testCreateFlowExecutionUrl() {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/flows");
|
||||
String url = urlHandler.createFlowExecutionUrl("bookHotel", "12345", request);
|
||||
assertEquals("/springtravel/app/flows?_flowId=bookHotel&_flowExecutionKey=12345", url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
package org.springframework.webflow.mvc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.context.servlet.ServletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.test.MockFlowExecutionKey;
|
||||
|
||||
public class FlowControllerTests extends TestCase {
|
||||
private FlowController controller;
|
||||
private FlowExecutor executor;
|
||||
private MockServletContext servletContext;
|
||||
private MockHttpServletRequest request;
|
||||
private MockHttpServletResponse response;
|
||||
private ServletExternalContext context;
|
||||
|
||||
protected void setUp() {
|
||||
executor = (FlowExecutor) EasyMock.createMock(FlowExecutor.class);
|
||||
controller = new FlowController(executor) {
|
||||
protected ServletExternalContext createServletExternalContext(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return context;
|
||||
}
|
||||
};
|
||||
servletContext = new MockServletContext();
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
context = new ServletExternalContext(servletContext, request, response, controller.getFlowUrlHandler());
|
||||
controller.setApplicationContext(new StaticWebApplicationContext());
|
||||
controller.setServletContext(servletContext);
|
||||
}
|
||||
|
||||
public void testLaunchFlowRequest() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowRequestEndsAfterProcessing() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo?bar=baz", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testResumeFlowRequest() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("POST");
|
||||
request.addParameter("execution", "12345");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.resumeExecution("12345", context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "123456");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testResumeFlowRequestEndsAfterProcessing() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("POST");
|
||||
request.addParameter("execution", "12345");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.resumeExecution("12345", context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo?bar=baz", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithExecutionRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
context.requestFlowExecutionRedirect();
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("/springtravel/app/foo?execution=12345", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithDefinitionRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
LocalAttributeMap input = new LocalAttributeMap();
|
||||
input.put("baz", "boop");
|
||||
context.requestFlowDefinitionRedirect("bar", input);
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("/springtravel/app/bar?baz=boop", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithExternalRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
context.requestExternalRedirect("http://www.paypal.com");
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("http://www.paypal.com", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testDefaultHandleFlowException() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
try {
|
||||
controller.handleRequest(request, response);
|
||||
fail("Should have thrown exception");
|
||||
} catch (FlowException e) {
|
||||
assertEquals(flowException, e);
|
||||
}
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testDefaultHandleNoSuchFlowExecutionException() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
request.addParameter("execution", "12345");
|
||||
executor.resumeExecution("12345", context);
|
||||
FlowException flowException = new NoSuchFlowExecutionException(new MockFlowExecutionKey("12345"), null);
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithCustomFlowHandler() throws Exception {
|
||||
final LocalAttributeMap input = new LocalAttributeMap();
|
||||
input.put("bar", "boop");
|
||||
controller.registerFlowHandler(new FlowHandler() {
|
||||
public String getFlowId() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public MutableAttributeMap createExecutionInputMap(HttpServletRequest request) {
|
||||
return input;
|
||||
}
|
||||
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", input, context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testHandleFlowOutcomeCustomFlowHandler() throws Exception {
|
||||
final LocalAttributeMap input = new LocalAttributeMap();
|
||||
input.put("bar", "boop");
|
||||
controller.registerFlowHandler(new FlowHandler() {
|
||||
public String getFlowId() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public MutableAttributeMap createExecutionInputMap(HttpServletRequest request) {
|
||||
return input;
|
||||
}
|
||||
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
assertEquals("finish", outcome);
|
||||
assertEquals("baz", output.get("bar"));
|
||||
assertEquals(FlowControllerTests.this.request, request);
|
||||
assertEquals(FlowControllerTests.this.response, response);
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", input, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRequest(request, response);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo?bar=baz", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testHandleFlowExceptionCustomFlowHandler() throws Exception {
|
||||
final FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
|
||||
controller.registerFlowHandler(new FlowHandler() {
|
||||
public String getFlowId() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public MutableAttributeMap createExecutionInputMap(HttpServletRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
assertEquals(flowException, e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", null, context);
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
try {
|
||||
controller.handleRequest(request, response);
|
||||
fail("Should have thrown exception");
|
||||
} catch (FlowException e) {
|
||||
assertEquals(flowException, e);
|
||||
}
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package org.springframework.webflow.mvc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.context.servlet.ServletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.test.MockFlowExecutionKey;
|
||||
|
||||
public class FlowHandlerAdapterTests extends TestCase {
|
||||
private FlowHandlerAdapter controller;
|
||||
private FlowExecutor executor;
|
||||
private MockServletContext servletContext;
|
||||
private MockHttpServletRequest request;
|
||||
private MockHttpServletResponse response;
|
||||
private ServletExternalContext context;
|
||||
private FlowHandler flowHandler;
|
||||
private LocalAttributeMap flowInput;
|
||||
private boolean handleException;
|
||||
private boolean handleExecutionOutcome;
|
||||
|
||||
protected void setUp() {
|
||||
executor = (FlowExecutor) EasyMock.createMock(FlowExecutor.class);
|
||||
controller = new FlowHandlerAdapter(executor) {
|
||||
protected ServletExternalContext createServletExternalContext(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return context;
|
||||
}
|
||||
};
|
||||
servletContext = new MockServletContext();
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
context = new ServletExternalContext(servletContext, request, response, controller.getFlowUrlHandler());
|
||||
controller.setApplicationContext(new StaticWebApplicationContext());
|
||||
controller.setServletContext(servletContext);
|
||||
flowHandler = new FlowHandler() {
|
||||
public MutableAttributeMap createExecutionInputMap(HttpServletRequest request) {
|
||||
assertEquals(FlowHandlerAdapterTests.this.request, request);
|
||||
return flowInput;
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
if (handleException) {
|
||||
return new ModelAndView("error");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
if (handleExecutionOutcome) {
|
||||
return new ModelAndView("redirect:/home");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public void testLaunchFlowRequest() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/whatever");
|
||||
request.setRequestURI("/springtravel/app/whatever");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", flowInput, context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowRequestEndsAfterProcessing() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/whatever");
|
||||
request.setRequestURI("/springtravel/app/whatever");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.launchExecution("foo", null, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo?bar=baz", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testResumeFlowRequest() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("POST");
|
||||
request.addParameter("execution", "12345");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.resumeExecution("12345", context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "123456");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testResumeFlowRequestEndsAfterProcessing() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("POST");
|
||||
request.addParameter("execution", "12345");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.resumeExecution("12345", context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo?bar=baz", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithExecutionRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
context.requestFlowExecutionRedirect();
|
||||
executor.launchExecution("foo", null, context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("/springtravel/app/foo?execution=12345", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithDefinitionRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
LocalAttributeMap input = new LocalAttributeMap();
|
||||
input.put("baz", "boop");
|
||||
context.requestFlowDefinitionRedirect("bar", input);
|
||||
executor.launchExecution("foo", null, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("/springtravel/app/bar?baz=boop", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testLaunchFlowWithExternalRedirect() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
context.requestExternalRedirect("http://www.paypal.com");
|
||||
executor.launchExecution("foo", null, context);
|
||||
FlowExecutionResult result = FlowExecutionResult.createPausedResult("foo", "12345");
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
assertEquals("http://www.paypal.com", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testDefaultHandleFlowException() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
Map parameters = new HashMap();
|
||||
request.setParameters(parameters);
|
||||
executor.launchExecution("foo", null, context);
|
||||
FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
try {
|
||||
controller.handle(request, response, flowHandler);
|
||||
fail("Should have thrown exception");
|
||||
} catch (FlowException e) {
|
||||
assertEquals(flowException, e);
|
||||
}
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testDefaultHandleNoSuchFlowExecutionException() throws Exception {
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
request.addParameter("execution", "12345");
|
||||
executor.resumeExecution("12345", context);
|
||||
FlowException flowException = new NoSuchFlowExecutionException(new MockFlowExecutionKey("12345"), null);
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNull(mv);
|
||||
assertEquals("/springtravel/app/foo", response.getRedirectedUrl());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testHandleFlowOutcomeCustomFlowHandler() throws Exception {
|
||||
handleExecutionOutcome = true;
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", flowInput, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNotNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
public void testHandleFlowExceptionCustomFlowHandler() throws Exception {
|
||||
handleException = true;
|
||||
final FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
request.setContextPath("/springtravel");
|
||||
request.setServletPath("/app");
|
||||
request.setPathInfo("/foo");
|
||||
request.setRequestURI("/springtravel/app/foo");
|
||||
request.setMethod("GET");
|
||||
executor.launchExecution("foo", null, context);
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handle(request, response, flowHandler);
|
||||
assertNotNull(mv);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user