From 70907fd3263c2fdb66ac25a8eb86982a47cd722b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 5 Nov 2013 14:18:08 +0100 Subject: [PATCH] Only retrieve the FlashMapManager if a non-empty output FlashMap has been found Issue: SPR-10937 (cherry picked from commit 4ac6801) --- .../servlet/support/RequestContextUtils.java | 9 ++-- .../web/servlet/view/RedirectView.java | 49 +++++++++---------- 2 files changed, 27 insertions(+), 31 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 f9928390466..e0b22a9c875 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 @@ -18,7 +18,6 @@ package org.springframework.web.servlet.support; import java.util.Locale; import java.util.Map; - import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; @@ -41,6 +40,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 @@ -160,7 +160,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") @@ -170,8 +170,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) { @@ -182,6 +182,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 0f96d4832ad..83451c11f73 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; @@ -250,15 +249,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); @@ -268,11 +267,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); } @@ -304,7 +305,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); } @@ -327,15 +327,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; @@ -344,7 +346,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(); } @@ -441,7 +443,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) { @@ -455,7 +456,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } return true; } - if (value instanceof Collection) { Collection coll = (Collection) value; if (coll.isEmpty()) { @@ -468,7 +468,6 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } return true; } - return false; } @@ -504,7 +503,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) { @@ -516,14 +515,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; } @@ -535,12 +532,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());