diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java index 6fcd7c8924..5ae5652c40 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java @@ -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. @@ -189,9 +189,24 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte localePart = value.substring(0, spaceIndex); timeZonePart = value.substring(spaceIndex + 1); } - locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); - if (timeZonePart != null) { - timeZone = StringUtils.parseTimeZoneString(timeZonePart); + try { + locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); + if (timeZonePart != null) { + timeZone = StringUtils.parseTimeZoneString(timeZonePart); + } + } + catch (IllegalArgumentException ex) { + if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { + // Error dispatch: ignore locale/timezone parse exceptions + if (logger.isDebugEnabled()) { + logger.debug("Ignoring invalid locale cookie '" + getCookieName() + + "' with value [" + value + "] due to error dispatch: " + ex.getMessage()); + } + } + else { + throw new IllegalStateException("Invalid locale cookie '" + getCookieName() + + "' with value [" + value + "]: " + ex.getMessage()); + } } if (logger.isDebugEnabled()) { logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale + diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java index 270f6ab03b..37f8c9b38a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 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,6 +18,7 @@ package org.springframework.web.servlet.i18n; import java.util.Locale; import java.util.TimeZone; +import javax.servlet.ServletException; import javax.servlet.http.Cookie; import org.junit.Test; @@ -28,6 +29,7 @@ import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.web.util.WebUtils; import static org.junit.Assert.*; @@ -45,7 +47,6 @@ public class CookieLocaleResolverTests { request.setCookies(cookie); CookieLocaleResolver resolver = new CookieLocaleResolver(); - // yup, koekje is the Dutch name for Cookie ;-) resolver.setCookieName("LanguageKoekje"); Locale loc = resolver.resolveLocale(request); assertEquals(loc.getLanguage(), "nl"); @@ -58,7 +59,6 @@ public class CookieLocaleResolverTests { request.setCookies(cookie); CookieLocaleResolver resolver = new CookieLocaleResolver(); - // yup, koekje is the Dutch name for Cookie ;-) resolver.setCookieName("LanguageKoekje"); LocaleContext loc = resolver.resolveLocaleContext(request); assertEquals("nl", loc.getLocale().getLanguage()); @@ -73,7 +73,6 @@ public class CookieLocaleResolverTests { request.setCookies(cookie); CookieLocaleResolver resolver = new CookieLocaleResolver(); - // yup, koekje is the Dutch name for Cookie ;-) resolver.setCookieName("LanguageKoekje"); LocaleContext loc = resolver.resolveLocaleContext(request); assertEquals("nl", loc.getLocale().getLanguage()); @@ -81,6 +80,75 @@ public class CookieLocaleResolverTests { assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) loc).getTimeZone()); } + @Test + public void testResolveLocaleContextWithInvalidLocale() { + MockHttpServletRequest request = new MockHttpServletRequest(); + Cookie cookie = new Cookie("LanguageKoekje", "n-x GMT+1"); + request.setCookies(cookie); + + CookieLocaleResolver resolver = new CookieLocaleResolver(); + resolver.setCookieName("LanguageKoekje"); + try { + resolver.resolveLocaleContext(request); + fail("Should have thrown IllegalStateException"); + } + catch (IllegalStateException ex) { + assertTrue(ex.getMessage().contains("LanguageKoekje")); + assertTrue(ex.getMessage().contains("n-x GMT+1")); + } + } + + @Test + public void testResolveLocaleContextWithInvalidLocaleOnErrorDispatch() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addPreferredLocale(Locale.GERMAN); + request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, new ServletException()); + Cookie cookie = new Cookie("LanguageKoekje", "n-x GMT+1"); + request.setCookies(cookie); + + CookieLocaleResolver resolver = new CookieLocaleResolver(); + resolver.setDefaultTimeZone(TimeZone.getTimeZone("GMT+2")); + resolver.setCookieName("LanguageKoekje"); + LocaleContext loc = resolver.resolveLocaleContext(request); + assertEquals(Locale.GERMAN, loc.getLocale()); + assertTrue(loc instanceof TimeZoneAwareLocaleContext); + assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) loc).getTimeZone()); + } + + @Test + public void testResolveLocaleContextWithInvalidTimeZone() { + MockHttpServletRequest request = new MockHttpServletRequest(); + Cookie cookie = new Cookie("LanguageKoekje", "nl X-MT"); + request.setCookies(cookie); + + CookieLocaleResolver resolver = new CookieLocaleResolver(); + resolver.setCookieName("LanguageKoekje"); + try { + resolver.resolveLocaleContext(request); + fail("Should have thrown IllegalStateException"); + } + catch (IllegalStateException ex) { + assertTrue(ex.getMessage().contains("LanguageKoekje")); + assertTrue(ex.getMessage().contains("nl X-MT")); + } + } + + @Test + public void testResolveLocaleContextWithInvalidTimeZoneOnErrorDispatch() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, new ServletException()); + Cookie cookie = new Cookie("LanguageKoekje", "nl X-MT"); + request.setCookies(cookie); + + CookieLocaleResolver resolver = new CookieLocaleResolver(); + resolver.setDefaultTimeZone(TimeZone.getTimeZone("GMT+2")); + resolver.setCookieName("LanguageKoekje"); + LocaleContext loc = resolver.resolveLocaleContext(request); + assertEquals("nl", loc.getLocale().getLanguage()); + assertTrue(loc instanceof TimeZoneAwareLocaleContext); + assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) loc).getTimeZone()); + } + @Test public void testSetAndResolveLocale() { MockHttpServletRequest request = new MockHttpServletRequest();