polish
This commit is contained in:
@@ -15,6 +15,8 @@ Bug Fixes
|
||||
* Fixed bug where Errors nestedPath attribute was not respected in views rendered by Web Flow (SWF-973)
|
||||
* Fixed bug where Errors nestedPath attribute was not respected when using Errors API programatically within a Validator called by Web Flow (SWF-973)
|
||||
* Made MessageCodesResolver pluggable on MvcViewFactoryCreator; configure a DefaultMessageCodesResolver to resolve error message codes consistent with default Spring MVC behavior (SWF-977)
|
||||
* Made FlowHandlerAdapter#sendRedirect method protected, allowing overriding of web flow system redirect behavior; for example, to redirect to a SSL channel.
|
||||
* Made DefaultFlowUrlHandler consistent with Spring MVC RedirectView behavior for URL encoding of flow URL parameters; URL encoding scheme is also now pluggable.
|
||||
* Introduced createDefaultFlowHandler hook in FlowHandlerMapping, allowing for customizing the Default FlowHandler implementation application wide (SWF-994)
|
||||
|
||||
Improvements
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
|
||||
/**
|
||||
@@ -50,16 +51,23 @@ import org.springframework.webflow.core.collection.AttributeMap;
|
||||
* execution "e1s1" of the "hotels/booking" flow.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*
|
||||
*/
|
||||
public class DefaultFlowUrlHandler implements FlowUrlHandler {
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING_SCHEME = "UTF-8";
|
||||
private static final String FLOW_EXECUTION_KEY_PARAMETER = "execution";
|
||||
|
||||
private String urlEncodingScheme = DEFAULT_URL_ENCODING_SCHEME;
|
||||
private String encodingScheme;
|
||||
|
||||
/**
|
||||
* Set the character encoding scheme for flow urls. Default is the request's encoding scheme (which is ISO-8859-1 if
|
||||
* not specified otherwise).
|
||||
*/
|
||||
public void setEncodingScheme(String encodingScheme) {
|
||||
this.encodingScheme = encodingScheme;
|
||||
}
|
||||
|
||||
public String getFlowExecutionKey(HttpServletRequest request) {
|
||||
return request.getParameter("execution");
|
||||
return request.getParameter(FLOW_EXECUTION_KEY_PARAMETER);
|
||||
}
|
||||
|
||||
public String getFlowId(HttpServletRequest request) {
|
||||
@@ -90,7 +98,7 @@ public class DefaultFlowUrlHandler implements FlowUrlHandler {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(request.getRequestURI());
|
||||
url.append('?');
|
||||
appendQueryParameter(url, "execution", flowExecutionKey);
|
||||
appendQueryParameter(url, FLOW_EXECUTION_KEY_PARAMETER, flowExecutionKey, getEncodingScheme(request));
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
@@ -118,35 +126,49 @@ public class DefaultFlowUrlHandler implements FlowUrlHandler {
|
||||
}
|
||||
if (input != null && !input.isEmpty()) {
|
||||
url.append('?');
|
||||
appendQueryParameters(url, input.asMap());
|
||||
appendQueryParameters(url, input.asMap(), getEncodingScheme(request));
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
private void appendQueryParameters(StringBuffer url, Map parameters) {
|
||||
// internal helpers
|
||||
|
||||
private String getEncodingScheme(HttpServletRequest request) {
|
||||
if (encodingScheme != null) {
|
||||
return encodingScheme;
|
||||
} else {
|
||||
String encodingScheme = request.getCharacterEncoding();
|
||||
if (encodingScheme == null) {
|
||||
encodingScheme = WebUtils.DEFAULT_CHARACTER_ENCODING;
|
||||
}
|
||||
return encodingScheme;
|
||||
}
|
||||
}
|
||||
|
||||
private void appendQueryParameters(StringBuffer url, Map parameters, String encodingScheme) {
|
||||
Iterator entries = parameters.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) entries.next();
|
||||
appendQueryParameter(url, entry.getKey(), entry.getValue());
|
||||
appendQueryParameter(url, entry.getKey(), entry.getValue(), encodingScheme);
|
||||
if (entries.hasNext()) {
|
||||
url.append('&');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendQueryParameter(StringBuffer url, Object key, Object value) {
|
||||
String encodedKey = encode(key);
|
||||
String encodedValue = encode(value);
|
||||
private void appendQueryParameter(StringBuffer url, Object key, Object value, String encodingScheme) {
|
||||
String encodedKey = encode(key, encodingScheme);
|
||||
String encodedValue = encode(value, encodingScheme);
|
||||
url.append(encodedKey).append('=').append(encodedValue);
|
||||
}
|
||||
|
||||
private String encode(Object value) {
|
||||
return value != null ? urlEncode(String.valueOf(value)) : "";
|
||||
private String encode(Object value, String encodingScheme) {
|
||||
return value != null ? urlEncode(value.toString(), encodingScheme) : "";
|
||||
}
|
||||
|
||||
private String urlEncode(String value) {
|
||||
private String urlEncode(String value, String encodingScheme) {
|
||||
try {
|
||||
return URLEncoder.encode(String.valueOf(value), urlEncodingScheme);
|
||||
return URLEncoder.encode(value, encodingScheme);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalArgumentException("Cannot url encode " + value);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FlowHandlerAdapter.class);
|
||||
|
||||
private static final String REFERER_FLOW_EXECUTION_ATTRIBUTE = "refererExecution";
|
||||
|
||||
private static final String SERVLET_RELATIVE_LOCATION_PREFIX = "servletRelative:";
|
||||
|
||||
private static final String CONTEXT_RELATIVE_LOCATION_PREFIX = "contextRelative:";
|
||||
@@ -133,6 +135,14 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
this.ajaxHandler = ajaxHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether redirect sent by this handler adapter should be compatible with HTTP 1.0 clients.
|
||||
* @return true if so, false otherwise
|
||||
*/
|
||||
public boolean getRedirectHttp10Compatible() {
|
||||
return redirectHttp10Compatible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether redirects sent by this handler adapter should be compatible with HTTP 1.0 clients.
|
||||
* <p>
|
||||
@@ -189,6 +199,10 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// subclassing hooks
|
||||
|
||||
/**
|
||||
@@ -206,7 +220,7 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
/**
|
||||
* The default algorithm to determine the id of the flow to launch from the current request. Only called if
|
||||
* {@link FlowHandler#getFlowId()} returns null. This implementation delegates to the configured
|
||||
* {@link FlowUrlHandler#getFlowId(HttpServletRequest)}.
|
||||
* {@link FlowUrlHandler#getFlowId(HttpServletRequest)}. Subclasses may override.
|
||||
* @param request the current request
|
||||
*/
|
||||
protected String defaultGetFlowId(HttpServletRequest request) {
|
||||
@@ -216,7 +230,7 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
/**
|
||||
* The default algorithm to create the flow execution input map. Only called if
|
||||
* {@link FlowHandler#createExecutionInputMap(HttpServletRequest)} returns null. This implementation exposes all
|
||||
* current request parameters as flow execution input attributes.
|
||||
* current request parameters as flow execution input attributes. Subclasses may override.
|
||||
* @param request the current request
|
||||
*/
|
||||
protected MutableAttributeMap defaultCreateFlowExecutionInputMap(HttpServletRequest request) {
|
||||
@@ -243,7 +257,7 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
* The default algorithm for handling a flow execution outcome. Only called if
|
||||
* {@link FlowHandler#handleExecutionOutcome(FlowExecutionOutcome, HttpServletRequest, HttpServletResponse)} returns
|
||||
* null. This implementation attempts to start a new execution of the ended flow. Any flow execution output is
|
||||
* passed as input to the new execution.
|
||||
* passed as input to the new execution. Subclasses may override.
|
||||
* @param flowId the id of the ended flow
|
||||
* @param outcome the flow execution outcome
|
||||
* @param context ServletExternalContext the completed ServletExternalContext
|
||||
@@ -268,6 +282,7 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
* {@link FlowHandler#handleException(FlowException, HttpServletRequest, HttpServletResponse)} returns null. This
|
||||
* implementation rethrows the exception unless it is a {@link NoSuchFlowExecutionException}. If the exception is a
|
||||
* NoSuchFlowExecutionException, this implementation attempts to start a new execution of the ended or expired flow.
|
||||
* Subclasses may override.
|
||||
* @param flowId the id of the ended flow
|
||||
* @param e the flow exception
|
||||
* @param request the current request
|
||||
@@ -288,6 +303,31 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a redirect to the requested url using {@link HttpServletResponse#sendRedirect(String)}.Called to actually
|
||||
* perform flow execution redirects, flow definition redirects, and external redirects. Subclasses may override to
|
||||
* customize general Web Flow system redirect behavior.
|
||||
* @param url the url to redirect to
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @throws IOException an exception occurred
|
||||
*/
|
||||
protected void sendRedirect(String url, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
if (ajaxHandler.isAjaxRequest(request, response)) {
|
||||
ajaxHandler.sendAjaxRedirect(url, request, response, false);
|
||||
} else {
|
||||
if (redirectHttp10Compatible) {
|
||||
// Always send status code 302.
|
||||
response.sendRedirect(response.encodeRedirectURL(url));
|
||||
} else {
|
||||
// Correct HTTP status code is 303, in particular for POST requests.
|
||||
response.setStatus(303);
|
||||
response.setHeader("Location", response.encodeRedirectURL(url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void handleFlowExecutionResult(FlowExecutionResult result, ServletExternalContext context,
|
||||
@@ -336,7 +376,7 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
String flowId = context.getFlowRedirectFlowId();
|
||||
MutableAttributeMap input = context.getFlowRedirectFlowInput();
|
||||
if (result.isPaused()) {
|
||||
input.put("refererExecution", result.getPausedKey());
|
||||
input.put(REFERER_FLOW_EXECUTION_ATTRIBUTE, result.getPausedKey());
|
||||
}
|
||||
String url = flowUrlHandler.createFlowDefinitionUrl(flowId, input, request);
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -385,21 +425,6 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
sendRedirect(url.toString(), request, response);
|
||||
}
|
||||
|
||||
private void sendRedirect(String url, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (ajaxHandler.isAjaxRequest(request, response)) {
|
||||
ajaxHandler.sendAjaxRedirect(url, request, response, false);
|
||||
} else {
|
||||
if (redirectHttp10Compatible) {
|
||||
// Always send status code 302.
|
||||
response.sendRedirect(response.encodeRedirectURL(url));
|
||||
} else {
|
||||
// Correct HTTP status code is 303, in particular for POST requests.
|
||||
response.setStatus(303);
|
||||
response.setHeader("Location", response.encodeRedirectURL(url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFlowException(FlowException e, HttpServletRequest request, HttpServletResponse response,
|
||||
FlowHandler handler) throws IOException {
|
||||
String location = handler.handleException(e, request, response);
|
||||
@@ -410,10 +435,6 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
|
||||
}
|
||||
}
|
||||
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String getFlowId(FlowHandler handler, HttpServletRequest request) {
|
||||
String flowId = handler.getFlowId();
|
||||
if (flowId != null) {
|
||||
|
||||
Reference in New Issue
Block a user