From 4ac680103bf42956763ac79a8b881ba6044aa3f9 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 5 Nov 2013 13:38:10 +0100 Subject: [PATCH] Only retrieve the FlashMapManager if a non-empty output FlashMap has been found Issue: SPR-10937 --- .../servlet/support/RequestContextUtils.java | 8 +-- .../web/servlet/view/RedirectView.java | 49 +++++++++---------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java index f56a615ec9c..e9c25b93eb4 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java @@ -44,6 +44,7 @@ import org.springframework.web.servlet.ThemeResolver; * Locale, ThemeResolver, Theme, and MultipartResolver. * * @author Juergen Hoeller + * @author Rossen Stoyanchev * @since 03.03.2003 * @see RequestContext * @see org.springframework.web.servlet.DispatcherServlet @@ -191,7 +192,7 @@ public abstract class RequestContextUtils { * Return a read-only {@link Map} with "input" flash attributes saved on a * previous request. * @param request the current request - * @return a read-only Map, or {@code null} + * @return a read-only Map, or {@code null} if not found * @see FlashMap */ @SuppressWarnings("unchecked") @@ -201,8 +202,8 @@ public abstract class RequestContextUtils { /** * Return the "output" FlashMap with attributes to save for a subsequent request. - * @param request current request - * @return a {@link FlashMap} instance, never {@code null} + * @param request the current request + * @return a {@link FlashMap} instance (never {@code null} within a DispatcherServlet request) * @see FlashMap */ public static FlashMap getOutputFlashMap(HttpServletRequest request) { @@ -213,6 +214,7 @@ public abstract class RequestContextUtils { * Return the FlashMapManager instance to save flash attributes with * before a redirect. * @param request the current request + * @return a {@link FlashMapManager} instance (never {@code null} within a DispatcherServlet request) */ public static FlashMapManager getFlashMapManager(HttpServletRequest request) { return (FlashMapManager) request.getAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java index 8813f4172f8..26b7992997c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -33,7 +33,6 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.beans.BeanUtils; import org.springframework.http.HttpStatus; -import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -251,15 +250,15 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { return false; } + /** * Convert model to request parameters and redirect to the given URL. * @see #appendQueryProperties * @see #sendRedirect */ @Override - protected void renderMergedOutputModel( - Map model, HttpServletRequest request, HttpServletResponse response) - throws IOException { + protected void renderMergedOutputModel(Map model, HttpServletRequest request, + HttpServletResponse response) throws IOException { String targetUrl = createTargetUrl(model, request); targetUrl = updateTargetUrl(targetUrl, model, request, response); @@ -269,11 +268,13 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build(); flashMap.setTargetRequestPath(uriComponents.getPath()); flashMap.addTargetRequestParams(uriComponents.getQueryParams()); + FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request); + if (flashMapManager == null) { + throw new IllegalStateException("FlashMapManager not found despite output FlashMap having been set"); + } + flashMapManager.saveOutputFlashMap(flashMap, request, response); } - FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request); - flashMapManager.saveOutputFlashMap(flashMap, request, response); - sendRedirect(request, response, targetUrl, this.http10Compatible); } @@ -305,7 +306,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { Map variables = getCurrentRequestUriVariables(request); targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, enc); } - if (this.exposeModelAttributes) { appendQueryProperties(targetUrl, model, enc); } @@ -328,15 +328,17 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { throws UnsupportedEncodingException { StringBuilder result = new StringBuilder(); - Matcher m = URI_TEMPLATE_VARIABLE_PATTERN.matcher(targetUrl); + Matcher matcher = URI_TEMPLATE_VARIABLE_PATTERN.matcher(targetUrl); int endLastMatch = 0; - while (m.find()) { - String name = m.group(1); - Object value = model.containsKey(name) ? model.remove(name) : currentUriVariables.get(name); - Assert.notNull(value, "Model has no value for '" + name + "'"); - result.append(targetUrl.substring(endLastMatch, m.start())); + while (matcher.find()) { + String name = matcher.group(1); + Object value = (model.containsKey(name) ? model.remove(name) : currentUriVariables.get(name)); + if (value == null) { + throw new IllegalArgumentException("Model has no value for key '" + name + "'"); + } + result.append(targetUrl.substring(endLastMatch, matcher.start())); result.append(UriUtils.encodePathSegment(value.toString(), encodingScheme)); - endLastMatch = m.end(); + endLastMatch = matcher.end(); } result.append(targetUrl.substring(endLastMatch, targetUrl.length())); return result; @@ -345,7 +347,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { @SuppressWarnings("unchecked") private Map getCurrentRequestUriVariables(HttpServletRequest request) { Map uriVars = - (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); return (uriVars != null) ? uriVars : Collections. emptyMap(); } @@ -442,7 +444,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { if (isEligibleValue(value)) { return true; } - if (value.getClass().isArray()) { int length = Array.getLength(value); if (length == 0) { @@ -456,7 +457,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } return true; } - if (value instanceof Collection) { Collection coll = (Collection) value; if (coll.isEmpty()) { @@ -469,7 +469,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } return true; } - return false; } @@ -505,7 +504,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { * @return the updated URL or the same as URL as the one passed in */ protected String updateTargetUrl(String targetUrl, Map model, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { RequestContext requestContext = null; if (getWebApplicationContext() != null) { @@ -517,14 +516,12 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { requestContext = new RequestContext(request, response, wac.getServletContext(), model); } } - if (requestContext != null) { RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor(); if (processor != null) { targetUrl = processor.processUrl(request, targetUrl); } } - return targetUrl; } @@ -536,12 +533,10 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { * @param http10Compatible whether to stay compatible with HTTP 1.0 clients * @throws IOException if thrown by response methods */ - protected void sendRedirect( - HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible) - throws IOException { + protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, + String targetUrl, boolean http10Compatible) throws IOException { String encodedRedirectURL = response.encodeRedirectURL(targetUrl); - if (http10Compatible) { if (this.statusCode != null) { response.setStatus(this.statusCode.value());