Browse Source

Nullability fine-tuning (RequestContext, LocaleResolver)

Includes page-level JSTL time zone support for JSP tags.

Issue: SPR-15720
Issue: SPR-15746
pull/1472/head
Juergen Hoeller 9 years ago
parent
commit
00f4c36d7a
  1. 7
      spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java
  2. 8
      spring-web/src/main/java/org/springframework/http/server/reactive/DefaultPathContainer.java
  3. 5
      spring-web/src/main/java/org/springframework/http/server/reactive/PathContainer.java
  4. 11
      spring-web/src/main/java/org/springframework/web/util/pattern/CaptureTheRestPathElement.java
  5. 6
      spring-web/src/main/java/org/springframework/web/util/pattern/CaptureVariablePathElement.java
  6. 10
      spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java
  7. 14
      spring-web/src/main/java/org/springframework/web/util/pattern/LiteralPathElement.java
  8. 3
      spring-web/src/main/java/org/springframework/web/util/pattern/PathElement.java
  9. 15
      spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java
  10. 4
      spring-web/src/main/java/org/springframework/web/util/pattern/SeparatorPathElement.java
  11. 2
      spring-web/src/main/java/org/springframework/web/util/pattern/SingleCharWildcardedPathElement.java
  12. 4
      spring-web/src/main/java/org/springframework/web/util/pattern/WildcardPathElement.java
  13. 44
      spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternMatcherTests.java
  14. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java
  15. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java
  16. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/ThemeResolver.java
  17. 11
      spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java
  18. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java
  19. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java
  20. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java
  21. 50
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java
  22. 195
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java
  23. 7
      spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java
  24. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/theme/FixedThemeResolver.java
  25. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/theme/SessionThemeResolver.java

7
spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java

@ -50,9 +50,6 @@ class WiretapConnector implements ClientHttpConnector { @@ -50,9 +50,6 @@ class WiretapConnector implements ClientHttpConnector {
this.delegate = delegate;
}
public ClientHttpConnector getDelegate() {
return this.delegate;
}
@Override
public Mono<ClientHttpResponse> connect(HttpMethod method, URI uri,
@ -69,7 +66,7 @@ class WiretapConnector implements ClientHttpConnector { @@ -69,7 +66,7 @@ class WiretapConnector implements ClientHttpConnector {
.map(response -> {
WiretapClientHttpRequest wrappedRequest = requestRef.get();
String requestId = wrappedRequest.getHeaders().getFirst(WebTestClient.WEBTESTCLIENT_REQUEST_ID);
Assert.notNull(requestId, "No \"" + WebTestClient.WEBTESTCLIENT_REQUEST_ID + "\" header");
Assert.state(requestId != null, () -> "No \"" + WebTestClient.WEBTESTCLIENT_REQUEST_ID + "\" header");
WiretapClientHttpResponse wrappedResponse = new WiretapClientHttpResponse(response);
ExchangeResult result = new ExchangeResult(wrappedRequest, wrappedResponse);
this.exchanges.put(requestId, result);
@ -82,7 +79,7 @@ class WiretapConnector implements ClientHttpConnector { @@ -82,7 +79,7 @@ class WiretapConnector implements ClientHttpConnector {
*/
public ExchangeResult claimRequest(String requestId) {
ExchangeResult result = this.exchanges.remove(requestId);
Assert.notNull(result, "No match for " + WebTestClient.WEBTESTCLIENT_REQUEST_ID + "=" + requestId);
Assert.state(result != null, () -> "No match for " + WebTestClient.WEBTESTCLIENT_REQUEST_ID + "=" + requestId);
return result;
}

8
spring-web/src/main/java/org/springframework/http/server/reactive/DefaultPathContainer.java

@ -175,9 +175,9 @@ class DefaultPathContainer implements PathContainer { @@ -175,9 +175,9 @@ class DefaultPathContainer implements PathContainer {
return EMPTY_PATH;
}
Assert.isTrue(fromIndex < toIndex, "fromIndex: " + fromIndex + " should be < toIndex " + toIndex);
Assert.isTrue(fromIndex >= 0 && fromIndex < elements.size(), "Invalid fromIndex: " + fromIndex);
Assert.isTrue(toIndex >= 0 && toIndex <= elements.size(), "Invalid toIndex: " + toIndex);
Assert.isTrue(fromIndex < toIndex, () -> "fromIndex: " + fromIndex + " should be < toIndex " + toIndex);
Assert.isTrue(fromIndex >= 0 && fromIndex < elements.size(), () -> "Invalid fromIndex: " + fromIndex);
Assert.isTrue(toIndex >= 0 && toIndex <= elements.size(), () -> "Invalid toIndex: " + toIndex);
List<Element> subList = elements.subList(fromIndex, toIndex);
String path = subList.stream().map(Element::value).collect(Collectors.joining(""));
@ -200,7 +200,7 @@ class DefaultPathContainer implements PathContainer { @@ -200,7 +200,7 @@ class DefaultPathContainer implements PathContainer {
DefaultPathSegment(String value, String valueDecoded, String semicolonContent,
MultiValueMap<String, String> params) {
Assert.isTrue(!value.contains("/"), "Invalid path segment value: " + value);
Assert.isTrue(!value.contains("/"), () -> "Invalid path segment value: " + value);
this.value = value;
this.valueDecoded = valueDecoded;
this.valueDecodedChars = valueDecoded.toCharArray();

5
spring-web/src/main/java/org/springframework/http/server/reactive/PathContainer.java

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.server.reactive;
import java.nio.charset.Charset;
@ -69,15 +70,16 @@ public interface PathContainer { @@ -69,15 +70,16 @@ public interface PathContainer {
* Return the original, raw (encoded) value for the path component.
*/
String value();
}
/**
* A path separator element.
*/
interface Separator extends Element {
}
/**
* A path segment element.
*/
@ -104,7 +106,6 @@ public interface PathContainer { @@ -104,7 +106,6 @@ public interface PathContainer {
* Path parameters parsed from the path segment.
*/
MultiValueMap<String, String> parameters();
}
}

11
spring-web/src/main/java/org/springframework/web/util/pattern/CaptureTheRestPathElement.java

@ -16,14 +16,13 @@ @@ -16,14 +16,13 @@
package org.springframework.web.util.pattern;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
import java.util.List;
import org.springframework.http.server.reactive.PathContainer.Element;
import org.springframework.http.server.reactive.PathContainer.Segment;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
/**
* A path element representing capturing the rest of a path. In the pattern
@ -67,8 +66,8 @@ class CaptureTheRestPathElement extends PathElement { @@ -67,8 +66,8 @@ class CaptureTheRestPathElement extends PathElement {
for (int i = pathIndex; i < matchingContext.pathLength; i++) {
Element element = matchingContext.pathElements.get(i);
if (element instanceof Segment) {
MultiValueMap<String, String> parameters = ((Segment)element).parameters();
if (parameters != null && parameters.size()!=0) {
MultiValueMap<String, String> parameters = ((Segment) element).parameters();
if (!parameters.isEmpty()) {
if (parametersCollector == null) {
parametersCollector = new LinkedMultiValueMap<>();
}

6
spring-web/src/main/java/org/springframework/web/util/pattern/CaptureVariablePathElement.java

@ -16,13 +16,11 @@ @@ -16,13 +16,11 @@
package org.springframework.web.util.pattern;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.lang.Nullable;
import org.springframework.web.util.UriUtils;
import org.springframework.http.server.reactive.PathContainer.Segment;
import org.springframework.lang.Nullable;
/**
* A path element representing capturing a piece of the path as a variable. In the pattern
@ -116,7 +114,7 @@ class CaptureVariablePathElement extends PathElement { @@ -116,7 +114,7 @@ class CaptureVariablePathElement extends PathElement {
if (matchingContext.isMatchStartMatching && pathIndex == matchingContext.pathLength) {
match = true; // no more data but matches up to this point
}
else {
else if (this.next != null) {
match = this.next.matches(pathIndex, matchingContext);
}
}

10
spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java

@ -16,13 +16,12 @@ @@ -16,13 +16,12 @@
package org.springframework.web.util.pattern;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.PatternSyntaxException;
import org.springframework.lang.Nullable;
import org.springframework.web.util.UriUtils;
import org.springframework.util.Assert;
import org.springframework.web.util.pattern.PatternParseException.PatternMessage;
/**
@ -117,11 +116,10 @@ class InternalPathPatternParser { @@ -117,11 +116,10 @@ class InternalPathPatternParser {
* @throws PatternParseException in case of parse errors
*/
public PathPattern parse(String pathPattern) throws PatternParseException {
if (pathPattern == null) {
pathPattern = "";
}
Assert.notNull(pathPattern, "Path pattern must not be null");
this.pathPatternData = pathPattern.toCharArray();
this.pathPatternLength = pathPatternData.length;
this.pathPatternLength = this.pathPatternData.length;
this.headPE = null;
this.currentPE = null;
this.capturedVariableNames = null;

14
spring-web/src/main/java/org/springframework/web/util/pattern/LiteralPathElement.java

@ -34,6 +34,7 @@ class LiteralPathElement extends PathElement { @@ -34,6 +34,7 @@ class LiteralPathElement extends PathElement {
private boolean caseSensitive;
public LiteralPathElement(int pos, char[] literalText, boolean caseSensitive, char separator) {
super(pos, separator);
this.len = literalText.length;
@ -50,6 +51,7 @@ class LiteralPathElement extends PathElement { @@ -50,6 +51,7 @@ class LiteralPathElement extends PathElement {
}
}
@Override
public boolean matches(int pathIndex, MatchingContext matchingContext) {
if (pathIndex >= matchingContext.pathLength) {
@ -104,22 +106,22 @@ class LiteralPathElement extends PathElement { @@ -104,22 +106,22 @@ class LiteralPathElement extends PathElement {
if (matchingContext.isMatchStartMatching && pathIndex == matchingContext.pathLength) {
return true; // no more data but everything matched so far
}
return this.next.matches(pathIndex, matchingContext);
return (this.next != null && this.next.matches(pathIndex, matchingContext));
}
}
@Override
public int getNormalizedLength() {
return len;
return this.len;
}
public char[] getChars() {
return this.text;
}
public String toString() {
return "Literal(" + String.valueOf(this.text) + ")";
}
public char[] getChars() {
return this.text;
}
}

3
spring-web/src/main/java/org/springframework/web/util/pattern/PathElement.java

@ -16,12 +16,9 @@ @@ -16,12 +16,9 @@
package org.springframework.web.util.pattern;
import java.nio.charset.StandardCharsets;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
/**

15
spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java

@ -16,14 +16,13 @@ @@ -16,14 +16,13 @@
package org.springframework.web.util.pattern;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
import org.springframework.http.server.reactive.PathContainer.Segment;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
/**
* A regex path element. Used to represent any complicated element of the path.
@ -36,9 +35,9 @@ import org.springframework.http.server.reactive.PathContainer.Segment; @@ -36,9 +35,9 @@ import org.springframework.http.server.reactive.PathContainer.Segment;
*/
class RegexPathElement extends PathElement {
private final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
private final String DEFAULT_VARIABLE_PATTERN = "(.*)";
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
private char[] regex;
@ -145,9 +144,9 @@ class RegexPathElement extends PathElement { @@ -145,9 +144,9 @@ class RegexPathElement extends PathElement {
// No more pattern, is there more data?
// If pattern is capturing variables there must be some actual data to bind to them
matches = (pathIndex + 1) >= matchingContext.pathLength &&
((this.variableNames.size() == 0) ? true : textToMatch.length() > 0);
(this.variableNames.isEmpty() || textToMatch.length() > 0);
if (!matches && matchingContext.isAllowOptionalTrailingSlash()) {
matches = ((this.variableNames.size() == 0) ? true : textToMatch.length() > 0) &&
matches = (this.variableNames.isEmpty() || textToMatch.length() > 0) &&
(pathIndex + 2) >= matchingContext.pathLength &&
matchingContext.isSeparator(pathIndex + 1);
}
@ -155,9 +154,9 @@ class RegexPathElement extends PathElement { @@ -155,9 +154,9 @@ class RegexPathElement extends PathElement {
}
else {
if (matchingContext.isMatchStartMatching && (pathIndex + 1 >= matchingContext.pathLength)) {
return true; // no more data but matches up to this point
return true; // no more data but matches up to this point
}
matches = this.next.matches(pathIndex + 1, matchingContext);
matches = (this.next != null && this.next.matches(pathIndex + 1, matchingContext));
}
}

4
spring-web/src/main/java/org/springframework/web/util/pattern/SeparatorPathElement.java

@ -52,9 +52,9 @@ class SeparatorPathElement extends PathElement { @@ -52,9 +52,9 @@ class SeparatorPathElement extends PathElement {
else {
pathIndex++;
if (matchingContext.isMatchStartMatching && pathIndex == matchingContext.pathLength) {
return true; // no more data but matches up to this point
return true; // no more data but matches up to this point
}
return this.next.matches(pathIndex, matchingContext);
return (this.next != null && this.next.matches(pathIndex, matchingContext));
}
}
return false;

2
spring-web/src/main/java/org/springframework/web/util/pattern/SingleCharWildcardedPathElement.java

@ -114,7 +114,7 @@ class SingleCharWildcardedPathElement extends PathElement { @@ -114,7 +114,7 @@ class SingleCharWildcardedPathElement extends PathElement {
if (matchingContext.isMatchStartMatching && pathIndex == matchingContext.pathLength) {
return true; // no more data but everything matched so far
}
return this.next.matches(pathIndex, matchingContext);
return (this.next != null && this.next.matches(pathIndex, matchingContext));
}
}

4
spring-web/src/main/java/org/springframework/web/util/pattern/WildcardPathElement.java

@ -16,9 +16,9 @@ @@ -16,9 +16,9 @@
package org.springframework.web.util.pattern;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
import org.springframework.http.server.reactive.PathContainer.Element;
import org.springframework.http.server.reactive.PathContainer.Segment;
import org.springframework.web.util.pattern.PathPattern.MatchingContext;
/**
* A wildcard path element. In the pattern '/foo/&ast;/goo' the * is
@ -80,7 +80,7 @@ class WildcardPathElement extends PathElement { @@ -80,7 +80,7 @@ class WildcardPathElement extends PathElement {
if (segmentData == null || segmentData.length() == 0) {
return false;
}
return this.next.matches(pathIndex, matchingContext);
return (this.next != null && this.next.matches(pathIndex, matchingContext));
}
}

44
spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternMatcherTests.java

@ -36,7 +36,7 @@ import org.springframework.util.AntPathMatcher; @@ -36,7 +36,7 @@ import org.springframework.util.AntPathMatcher;
import org.springframework.web.util.pattern.PathPattern.PathMatchResult;
import org.springframework.web.util.pattern.PathPattern.PathRemainingMatchInfo;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
@ -48,6 +48,7 @@ public class PathPatternMatcherTests { @@ -48,6 +48,7 @@ public class PathPatternMatcherTests {
private char separator = PathPatternParser.DEFAULT_SEPARATOR;
@Test
public void pathContainer() {
assertEquals("[/][abc][/][def]",elementsToString(toPathContainer("/abc/def").elements()));
@ -1044,16 +1045,15 @@ public class PathPatternMatcherTests { @@ -1044,16 +1045,15 @@ public class PathPatternMatcherTests {
assertEquals("/*.html", pathMatcher.combine("/**", "/*.html"));
assertEquals("/*.html", pathMatcher.combine("/*", "/*.html"));
assertEquals("/*.html", pathMatcher.combine("/*.*", "/*.html"));
assertEquals("/{foo}/bar", pathMatcher.combine("/{foo}", "/bar")); // SPR-8858
assertEquals("/user/user", pathMatcher.combine("/user", "/user")); // SPR-7970
assertEquals("/{foo}/bar", pathMatcher.combine("/{foo}", "/bar")); // SPR-8858
assertEquals("/user/user", pathMatcher.combine("/user", "/user")); // SPR-7970
assertEquals("/{foo:.*[^0-9].*}/edit/",
pathMatcher.combine("/{foo:.*[^0-9].*}", "/edit/")); // SPR-10062
pathMatcher.combine("/{foo:.*[^0-9].*}", "/edit/")); // SPR-10062
assertEquals("/1.0/foo/test", pathMatcher.combine("/1.0", "/foo/test"));
// SPR-10554
assertEquals("/hotel", pathMatcher.combine("/", "/hotel")); // SPR-12975
assertEquals("/hotel/booking", pathMatcher.combine("/hotel/", "/booking")); // SPR-12975
assertEquals("/hotel", pathMatcher.combine("/", "/hotel")); // SPR-12975
assertEquals("/hotel/booking", pathMatcher.combine("/hotel/", "/booking")); // SPR-12975
assertEquals("/hotel", pathMatcher.combine("", "/hotel"));
assertEquals("/hotel", pathMatcher.combine("/hotel", null));
assertEquals("/hotel", pathMatcher.combine("/hotel", ""));
// TODO Do we need special handling when patterns contain multiple dots?
}
@ -1254,7 +1254,7 @@ public class PathPatternMatcherTests { @@ -1254,7 +1254,7 @@ public class PathPatternMatcherTests {
paths.clear();
}
@Test // SPR-13286
@Test // SPR-13286
public void caseInsensitive() {
PathPatternParser pp = new PathPatternParser();
pp.setCaseSensitive(false);
@ -1264,7 +1264,6 @@ public class PathPatternMatcherTests { @@ -1264,7 +1264,6 @@ public class PathPatternMatcherTests {
assertMatches(p,"/group/Sales/members");
}
@Test
public void parameters() {
// CaptureVariablePathElement
@ -1297,7 +1296,6 @@ public class PathPatternMatcherTests { @@ -1297,7 +1296,6 @@ public class PathPatternMatcherTests {
assertNull(result.getMatrixVariables().get("var"));
}
// ---
private PathMatchResult matchAndExtract(String pattern, String path) {
return parse(pattern).matchAndExtract(PathPatternMatcherTests.toPathContainer(path));
@ -1374,19 +1372,6 @@ public class PathPatternMatcherTests { @@ -1374,19 +1372,6 @@ public class PathPatternMatcherTests {
assertEquals(expected, s);
}
static class TestPathCombiner {
PathPatternParser pp = new PathPatternParser();
public String combine(String string1, String string2) {
PathPattern pattern1 = pp.parse(string1);
PathPattern pattern2 = pp.parse(string2);
return pattern1.combine(pattern2).getPatternString();
}
}
private PathRemainingMatchInfo getPathRemaining(String pattern, String path) {
return parse(pattern).getPathRemaining(toPathContainer(path));
}
@ -1407,4 +1392,17 @@ public class PathPatternMatcherTests { @@ -1407,4 +1392,17 @@ public class PathPatternMatcherTests {
return s.toString();
}
static class TestPathCombiner {
PathPatternParser pp = new PathPatternParser();
public String combine(String string1, String string2) {
PathPattern pattern1 = pp.parse(string1);
PathPattern pattern2 = pp.parse(string2);
return pattern1.combine(pattern2).getPatternString();
}
}
}

6
spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.web.servlet;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -70,6 +69,7 @@ public interface LocaleContextResolver extends LocaleResolver { @@ -70,6 +69,7 @@ public interface LocaleContextResolver extends LocaleResolver {
* @see org.springframework.context.i18n.SimpleLocaleContext
* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext
*/
void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext);
void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext);
}

5
spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.web.servlet;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -69,6 +68,6 @@ public interface LocaleResolver { @@ -69,6 +68,6 @@ public interface LocaleResolver {
* @throws UnsupportedOperationException if the LocaleResolver
* implementation does not support dynamic changing of the locale
*/
void setLocale(HttpServletRequest request, HttpServletResponse response, @Nullable Locale locale);
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}

4
spring-webmvc/src/main/java/org/springframework/web/servlet/ThemeResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@ -64,6 +64,6 @@ public interface ThemeResolver { @@ -64,6 +64,6 @@ public interface ThemeResolver {
* @throws UnsupportedOperationException if the ThemeResolver implementation
* does not support dynamic changing of the theme
*/
void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName);
void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName);
}

11
spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java

@ -26,6 +26,7 @@ import org.springframework.context.i18n.LocaleContext; @@ -26,6 +26,7 @@ import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleContextResolver;
import org.springframework.web.servlet.LocaleResolver;
@ -84,8 +85,10 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte @@ -84,8 +85,10 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
private boolean languageTagCompliant = false;
@Nullable
private Locale defaultLocale;
@Nullable
private TimeZone defaultTimeZone;
@ -224,12 +227,16 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte @@ -224,12 +227,16 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, @Nullable Locale locale) {
public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
Assert.notNull(response, "HttpServletResponse is required for CookieLocaleResolver");
Locale locale = null;
TimeZone timeZone = null;
if (localeContext != null) {

6
spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@ -93,7 +93,9 @@ public class FixedLocaleResolver extends AbstractLocaleContextResolver { @@ -93,7 +93,9 @@ public class FixedLocaleResolver extends AbstractLocaleContextResolver {
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext( HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");
}

5
spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java

@ -18,7 +18,6 @@ package org.springframework.web.servlet.i18n; @@ -18,7 +18,6 @@ package org.springframework.web.servlet.i18n;
import java.util.Locale;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -139,7 +138,9 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver { @@ -139,7 +138,9 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
}
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, @Nullable LocaleContext localeContext) {
public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext) {
Locale locale = null;
TimeZone timeZone = null;
if (localeContext != null) {

4
spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java

@ -93,9 +93,7 @@ public class BindStatus { @@ -93,9 +93,7 @@ public class BindStatus {
* @param htmlEscape whether to HTML-escape error messages and string values
* @throws IllegalStateException if no corresponding Errors object found
*/
public BindStatus(RequestContext requestContext, String path, boolean htmlEscape)
throws IllegalStateException {
public BindStatus(RequestContext requestContext, String path, boolean htmlEscape) throws IllegalStateException {
this.requestContext = requestContext;
this.path = path;
this.htmlEscape = htmlEscape;

50
spring-webmvc/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@ -18,7 +18,7 @@ package org.springframework.web.servlet.support; @@ -18,7 +18,7 @@ package org.springframework.web.servlet.support;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
@ -48,7 +48,7 @@ public class JspAwareRequestContext extends RequestContext { @@ -48,7 +48,7 @@ public class JspAwareRequestContext extends RequestContext {
* @param pageContext current JSP page context
*/
public JspAwareRequestContext(PageContext pageContext) {
initContext(pageContext, null);
this(pageContext, null);
}
/**
@ -59,23 +59,9 @@ public class JspAwareRequestContext extends RequestContext { @@ -59,23 +59,9 @@ public class JspAwareRequestContext extends RequestContext {
* (can be {@code null}, using the request attributes for Errors retrieval)
*/
public JspAwareRequestContext(PageContext pageContext, @Nullable Map<String, Object> model) {
initContext(pageContext, model);
}
/**
* Initialize this context with the given page context,
* using the given model attributes for Errors retrieval.
* @param pageContext current JSP page context
* @param model the model attributes for the current view
* (can be {@code null}, using the request attributes for Errors retrieval)
*/
protected void initContext(PageContext pageContext, @Nullable Map<String, Object> model) {
if (!(pageContext.getRequest() instanceof HttpServletRequest)) {
throw new IllegalArgumentException("RequestContext only supports HTTP requests");
}
this.pageContext = pageContext;
initContext((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(),
super((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(),
pageContext.getServletContext(), model);
this.pageContext = pageContext;
}
@ -88,9 +74,9 @@ public class JspAwareRequestContext extends RequestContext { @@ -88,9 +74,9 @@ public class JspAwareRequestContext extends RequestContext {
}
/**
* This implementation checks for a JSTL locale attribute
* in page, request, session or application scope; if not found,
* returns the {@code HttpServletRequest.getLocale()}.
* This implementation checks for a JSTL locale attribute in page,
* request, session or application scope; if not found, returns the
* {@code HttpServletRequest.getLocale()}.
*/
@Override
protected Locale getFallbackLocale() {
@ -103,6 +89,21 @@ public class JspAwareRequestContext extends RequestContext { @@ -103,6 +89,21 @@ public class JspAwareRequestContext extends RequestContext {
return getRequest().getLocale();
}
/**
* This implementation checks for a JSTL time zone attribute in page,
* request, session or application scope; if not found, returns {@code null}.
*/
@Override
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlPageLocaleResolver.getJstlTimeZone(getPageContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
* Inner class that isolates the JSTL dependency.
@ -114,6 +115,11 @@ public class JspAwareRequestContext extends RequestContext { @@ -114,6 +115,11 @@ public class JspAwareRequestContext extends RequestContext {
Object localeObject = Config.find(pageContext, Config.FMT_LOCALE);
return (localeObject instanceof Locale ? (Locale) localeObject : null);
}
public static TimeZone getJstlTimeZone(PageContext pageContext) {
Object timeZoneObject = Config.find(pageContext, Config.FMT_TIME_ZONE);
return (timeZoneObject instanceof TimeZone ? (TimeZone) timeZoneObject : null);
}
}
}

195
spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java

@ -73,7 +73,6 @@ import org.springframework.web.util.WebUtils; @@ -73,7 +73,6 @@ import org.springframework.web.util.WebUtils;
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.servlet.view.AbstractView#setRequestContextAttribute
* @see org.springframework.web.servlet.view.UrlBasedViewResolver#setRequestContextAttribute
* @see #getFallbackLocale()
*/
public class RequestContext {
@ -95,7 +94,6 @@ public class RequestContext { @@ -95,7 +94,6 @@ public class RequestContext {
protected static final boolean jstlPresent = ClassUtils.isPresent(
"javax.servlet.jsp.jstl.core.Config", RequestContext.class.getClassLoader());
@Nullable
private HttpServletRequest request;
@Nullable
@ -104,7 +102,6 @@ public class RequestContext { @@ -104,7 +102,6 @@ public class RequestContext {
@Nullable
private Map<String, Object> model;
@Nullable
private WebApplicationContext webApplicationContext;
@Nullable
@ -122,7 +119,6 @@ public class RequestContext { @@ -122,7 +119,6 @@ public class RequestContext {
@Nullable
private Boolean responseEncodedHtmlEscape;
@Nullable
private UrlPathHelper urlPathHelper;
@Nullable
@ -143,7 +139,7 @@ public class RequestContext { @@ -143,7 +139,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.ServletContext)
*/
public RequestContext(HttpServletRequest request) {
initContext(request, null, null, null);
this(request, null, null, null);
}
/**
@ -158,7 +154,7 @@ public class RequestContext { @@ -158,7 +154,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, Map)
*/
public RequestContext(HttpServletRequest request, HttpServletResponse response) {
initContext(request, response, null, null);
this(request, response, null, null);
}
/**
@ -174,7 +170,7 @@ public class RequestContext { @@ -174,7 +170,7 @@ public class RequestContext {
* @see org.springframework.web.servlet.DispatcherServlet
*/
public RequestContext(HttpServletRequest request, @Nullable ServletContext servletContext) {
initContext(request, null, servletContext, null);
this(request, null, servletContext, null);
}
/**
@ -189,7 +185,7 @@ public class RequestContext { @@ -189,7 +185,7 @@ public class RequestContext {
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, Map)
*/
public RequestContext(HttpServletRequest request, @Nullable Map<String, Object> model) {
initContext(request, null, null, model);
this(request, null, null, model);
}
/**
@ -206,34 +202,7 @@ public class RequestContext { @@ -206,34 +202,7 @@ public class RequestContext {
* @see org.springframework.web.context.WebApplicationContext
* @see org.springframework.web.servlet.DispatcherServlet
*/
public RequestContext(HttpServletRequest request, HttpServletResponse response, @Nullable ServletContext servletContext,
@Nullable Map<String, Object> model) {
initContext(request, response, servletContext, model);
}
/**
* Default constructor for subclasses.
*/
protected RequestContext() {
}
/**
* Initialize this context with the given request, using the given model attributes for Errors retrieval.
* <p>Delegates to {@code getFallbackLocale} and {@code getFallbackTheme} for determining the fallback
* locale and theme, respectively, if no LocaleResolver and/or ThemeResolver can be found in the request.
* @param request current HTTP request
* @param servletContext the servlet context of the web application (can be {@code null}; necessary for
* fallback to root WebApplicationContext)
* @param model the model attributes for the current view (can be {@code null}, using the request
* attributes for Errors retrieval)
* @see #getFallbackLocale
* @see #getFallbackTheme
* @see org.springframework.web.servlet.DispatcherServlet#LOCALE_RESOLVER_ATTRIBUTE
* @see org.springframework.web.servlet.DispatcherServlet#THEME_RESOLVER_ATTRIBUTE
*/
protected void initContext(HttpServletRequest request, @Nullable HttpServletResponse response,
public RequestContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable ServletContext servletContext, @Nullable Map<String, Object> model) {
this.request = request;
@ -242,36 +211,35 @@ public class RequestContext { @@ -242,36 +211,35 @@ public class RequestContext {
// Fetch WebApplicationContext, either from DispatcherServlet or the root context.
// ServletContext needs to be specified to be able to fall back to the root context!
this.webApplicationContext = (WebApplicationContext) request.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (this.webApplicationContext == null) {
this.webApplicationContext = RequestContextUtils.findWebApplicationContext(request, servletContext);
if (this.webApplicationContext == null) {
WebApplicationContext wac = (WebApplicationContext) request.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (wac == null) {
wac = RequestContextUtils.findWebApplicationContext(request, servletContext);
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: not in a DispatcherServlet " +
"request and no ContextLoaderListener registered?");
}
}
this.webApplicationContext = wac;
Locale locale = null;
TimeZone timeZone = null;
// Determine locale to use for this RequestContext.
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver instanceof LocaleContextResolver) {
LocaleContext localeContext = ((LocaleContextResolver) localeResolver).resolveLocaleContext(request);
this.locale = localeContext.getLocale();
locale = localeContext.getLocale();
if (localeContext instanceof TimeZoneAwareLocaleContext) {
this.timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
}
}
else if (localeResolver != null) {
// Try LocaleResolver (we're within a DispatcherServlet request).
this.locale = localeResolver.resolveLocale(request);
locale = localeResolver.resolveLocale(request);
}
// Try JSTL fallbacks if necessary.
if (this.locale == null) {
this.locale = getFallbackLocale();
}
if (this.timeZone == null) {
this.timeZone = getFallbackTimeZone();
}
this.locale = locale;
this.timeZone = timeZone;
// Determine default HTML escape setting from the "defaultHtmlEscape"
// context-param in web.xml, if any.
@ -290,57 +258,6 @@ public class RequestContext { @@ -290,57 +258,6 @@ public class RequestContext {
}
}
/**
* Determine the fallback locale for this context.
* <p>The default implementation checks for a JSTL locale attribute in request, session
* or application scope; if not found, returns the {@code HttpServletRequest.getLocale()}.
* @return the fallback locale (never {@code null})
* @see javax.servlet.http.HttpServletRequest#getLocale()
*/
protected Locale getFallbackLocale() {
if (jstlPresent) {
Locale locale = JstlLocaleResolver.getJstlLocale(getRequest(), getServletContext());
if (locale != null) {
return locale;
}
}
return getRequest().getLocale();
}
/**
* Determine the fallback time zone for this context.
* <p>The default implementation checks for a JSTL time zone attribute in request,
* session or application scope; returns {@code null} if not found.
* @return the fallback time zone (or {@code null} if none derivable from the request)
*/
@Nullable
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlLocaleResolver.getJstlTimeZone(getRequest(), getServletContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
* Determine the fallback theme for this context.
* <p>The default implementation returns the default theme (with name "theme").
* @return the fallback theme (never {@code null})
*/
protected Theme getFallbackTheme() {
ThemeSource themeSource = RequestContextUtils.getThemeSource(getRequest());
if (themeSource == null) {
themeSource = new ResourceBundleThemeSource();
}
Theme theme = themeSource.getTheme(DEFAULT_THEME_NAME);
if (theme == null) {
throw new IllegalStateException("No theme defined and no fallback theme found");
}
return theme;
}
/**
* Return the underlying HttpServletRequest. Only intended for cooperating classes in this package.
@ -387,7 +304,7 @@ public class RequestContext { @@ -387,7 +304,7 @@ public class RequestContext {
* @see RequestContextUtils#getLocale
*/
public final Locale getLocale() {
return this.locale;
return (this.locale != null ? this.locale : getFallbackLocale());
}
/**
@ -398,7 +315,41 @@ public class RequestContext { @@ -398,7 +315,41 @@ public class RequestContext {
*/
@Nullable
public TimeZone getTimeZone() {
return this.timeZone;
return (this.timeZone != null ? this.timeZone : getFallbackTimeZone());
}
/**
* Determine the fallback locale for this context.
* <p>The default implementation checks for a JSTL locale attribute in request, session
* or application scope; if not found, returns the {@code HttpServletRequest.getLocale()}.
* @return the fallback locale (never {@code null})
* @see javax.servlet.http.HttpServletRequest#getLocale()
*/
protected Locale getFallbackLocale() {
if (jstlPresent) {
Locale locale = JstlLocaleResolver.getJstlLocale(getRequest(), getServletContext());
if (locale != null) {
return locale;
}
}
return getRequest().getLocale();
}
/**
* Determine the fallback time zone for this context.
* <p>The default implementation checks for a JSTL time zone attribute in request,
* session or application scope; returns {@code null} if not found.
* @return the fallback time zone (or {@code null} if none derivable from the request)
*/
@Nullable
protected TimeZone getFallbackTimeZone() {
if (jstlPresent) {
TimeZone timeZone = JstlLocaleResolver.getJstlTimeZone(getRequest(), getServletContext());
if (timeZone != null) {
return timeZone;
}
}
return null;
}
/**
@ -452,6 +403,23 @@ public class RequestContext { @@ -452,6 +403,23 @@ public class RequestContext {
return this.theme;
}
/**
* Determine the fallback theme for this context.
* <p>The default implementation returns the default theme (with name "theme").
* @return the fallback theme (never {@code null})
*/
protected Theme getFallbackTheme() {
ThemeSource themeSource = RequestContextUtils.getThemeSource(getRequest());
if (themeSource == null) {
themeSource = new ResourceBundleThemeSource();
}
Theme theme = themeSource.getTheme(DEFAULT_THEME_NAME);
if (theme == null) {
throw new IllegalStateException("No theme defined and no fallback theme found");
}
return theme;
}
/**
* Change the current theme to the specified one,
* storing the new theme name through the configured {@link ThemeResolver}.
@ -524,6 +492,7 @@ public class RequestContext { @@ -524,6 +492,7 @@ public class RequestContext {
* @return whether default use of response encoding HTML escaping is enabled (null = no explicit default)
* @since 4.1.2
*/
@Nullable
public Boolean getResponseEncodedHtmlEscape() {
return this.responseEncodedHtmlEscape;
}
@ -683,7 +652,7 @@ public class RequestContext { @@ -683,7 +652,7 @@ public class RequestContext {
* @return the message
*/
public String getMessage(String code, @Nullable Object[] args, String defaultMessage, boolean htmlEscape) {
String msg = this.webApplicationContext.getMessage(code, args, defaultMessage, this.locale);
String msg = this.webApplicationContext.getMessage(code, args, defaultMessage, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@ -728,7 +697,7 @@ public class RequestContext { @@ -728,7 +697,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(String code, @Nullable Object[] args, boolean htmlEscape) throws NoSuchMessageException {
String msg = this.webApplicationContext.getMessage(code, args, this.locale);
String msg = this.webApplicationContext.getMessage(code, args, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@ -750,7 +719,7 @@ public class RequestContext { @@ -750,7 +719,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(MessageSourceResolvable resolvable, boolean htmlEscape) throws NoSuchMessageException {
String msg = this.webApplicationContext.getMessage(resolvable, this.locale);
String msg = this.webApplicationContext.getMessage(resolvable, getLocale());
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@ -763,7 +732,7 @@ public class RequestContext { @@ -763,7 +732,7 @@ public class RequestContext {
* @return the message
*/
public String getThemeMessage(String code, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, null, defaultMessage, this.locale);
return getTheme().getMessageSource().getMessage(code, null, defaultMessage, getLocale());
}
/**
@ -776,7 +745,7 @@ public class RequestContext { @@ -776,7 +745,7 @@ public class RequestContext {
* @return the message
*/
public String getThemeMessage(String code, @Nullable Object[] args, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, args, defaultMessage, this.locale);
return getTheme().getMessageSource().getMessage(code, args, defaultMessage, getLocale());
}
/**
@ -790,7 +759,7 @@ public class RequestContext { @@ -790,7 +759,7 @@ public class RequestContext {
*/
public String getThemeMessage(String code, @Nullable List<?> args, String defaultMessage) {
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null),
defaultMessage, this.locale);
defaultMessage, getLocale());
}
/**
@ -802,7 +771,7 @@ public class RequestContext { @@ -802,7 +771,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, null, this.locale);
return getTheme().getMessageSource().getMessage(code, null, getLocale());
}
/**
@ -815,7 +784,7 @@ public class RequestContext { @@ -815,7 +784,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code, @Nullable Object[] args) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, args, this.locale);
return getTheme().getMessageSource().getMessage(code, args, getLocale());
}
/**
@ -828,7 +797,7 @@ public class RequestContext { @@ -828,7 +797,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(String code, @Nullable List<?> args) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null), this.locale);
return getTheme().getMessageSource().getMessage(code, (args != null ? args.toArray() : null), getLocale());
}
/**
@ -840,7 +809,7 @@ public class RequestContext { @@ -840,7 +809,7 @@ public class RequestContext {
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getThemeMessage(MessageSourceResolvable resolvable) throws NoSuchMessageException {
return getTheme().getMessageSource().getMessage(resolvable, this.locale);
return getTheme().getMessageSource().getMessage(resolvable, getLocale());
}
/**

7
spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java

@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest; @@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.util.CookieGenerator;
@ -104,7 +105,11 @@ public class CookieThemeResolver extends CookieGenerator implements ThemeResolve @@ -104,7 +105,11 @@ public class CookieThemeResolver extends CookieGenerator implements ThemeResolve
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
Assert.notNull(response, "HttpServletResponse is required for CookieThemeResolver");
if (StringUtils.hasText(themeName)) {
// Set request attribute and add cookie.
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);

4
spring-webmvc/src/main/java/org/springframework/web/servlet/theme/FixedThemeResolver.java

@ -42,7 +42,9 @@ public class FixedThemeResolver extends AbstractThemeResolver { @@ -42,7 +42,9 @@ public class FixedThemeResolver extends AbstractThemeResolver {
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy");
}

4
spring-webmvc/src/main/java/org/springframework/web/servlet/theme/SessionThemeResolver.java

@ -58,7 +58,9 @@ public class SessionThemeResolver extends AbstractThemeResolver { @@ -58,7 +58,9 @@ public class SessionThemeResolver extends AbstractThemeResolver {
}
@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, @Nullable String themeName) {
public void setThemeName(
HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
WebUtils.setSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME,
(StringUtils.hasText(themeName) ? themeName : null));
}

Loading…
Cancel
Save