LocaleContextHolder allows for independent setting of Locale and TimeZone

Issue: SPR-1528
This commit is contained in:
Juergen Hoeller
2013-11-01 22:41:31 +01:00
parent 1dc7ff8604
commit 7b2ac6d194
2 changed files with 220 additions and 8 deletions

View File

@@ -35,6 +35,7 @@ import org.springframework.core.NamedThreadLocal;
* MessageSourceAccessor automatically use that Locale.
*
* @author Juergen Hoeller
* @author Nicholas Williams
* @since 1.2
* @see LocaleContext
* @see org.springframework.context.support.MessageSourceAccessor
@@ -62,7 +63,8 @@ public abstract class LocaleContextHolder {
* <i>not</i> exposing it as inheritable for child threads.
* <p>The given LocaleContext may be a {@link TimeZoneAwareLocaleContext},
* containing a locale with associated time zone information.
* @param localeContext the current LocaleContext
* @param localeContext the current LocaleContext,
* or {@code null} to reset the thread-bound context
* @see SimpleLocaleContext
* @see SimpleTimeZoneAwareLocaleContext
*/
@@ -110,28 +112,43 @@ public abstract class LocaleContextHolder {
}
/**
* Associate the given Locale with the current thread.
* Associate the given Locale with the current thread,
* preserving any TimeZone that may have been set already.
* <p>Will implicitly create a LocaleContext for the given Locale,
* <i>not</i> exposing it as inheritable for child threads.
* @param locale the current Locale, or {@code null} to reset
* the thread-bound context
* @see SimpleLocaleContext#SimpleLocaleContext(java.util.Locale)
* the locale part of thread-bound context
* @see #setTimeZone(TimeZone)
* @see SimpleLocaleContext#SimpleLocaleContext(Locale)
*/
public static void setLocale(Locale locale) {
setLocale(locale, false);
}
/**
* Associate the given Locale with the current thread.
* Associate the given Locale with the current thread,
* preserving any TimeZone that may have been set already.
* <p>Will implicitly create a LocaleContext for the given Locale.
* @param locale the current Locale, or {@code null} to reset
* the thread-bound context
* the locale part of thread-bound context
* @param inheritable whether to expose the LocaleContext as inheritable
* for child threads (using an {@link InheritableThreadLocal})
* @see SimpleLocaleContext#SimpleLocaleContext(java.util.Locale)
* @see #setTimeZone(TimeZone, boolean)
* @see SimpleLocaleContext#SimpleLocaleContext(Locale)
*/
public static void setLocale(Locale locale, boolean inheritable) {
LocaleContext localeContext = (locale != null ? new SimpleLocaleContext(locale) : null);
LocaleContext localeContext = getLocaleContext();
TimeZone timeZone = (localeContext instanceof TimeZoneAwareLocaleContext ?
((TimeZoneAwareLocaleContext) localeContext).getTimeZone() : null);
if (timeZone != null) {
localeContext = new SimpleTimeZoneAwareLocaleContext(locale, timeZone);
}
else if (locale != null) {
localeContext = new SimpleLocaleContext(locale);
}
else {
localeContext = null;
}
setLocaleContext(localeContext, inheritable);
}
@@ -160,6 +177,46 @@ public abstract class LocaleContextHolder {
return Locale.getDefault();
}
/**
* Associate the given TimeZone with the current thread,
* preserving any Locale that may have been set already.
* <p>Will implicitly create a LocaleContext for the given Locale,
* <i>not</i> exposing it as inheritable for child threads.
* @param timeZone the current TimeZone, or {@code null} to reset
* the time zone part of the thread-bound context
* @see #setLocale(Locale)
* @see SimpleTimeZoneAwareLocaleContext#SimpleTimeZoneAwareLocaleContext(Locale, TimeZone)
*/
public static void setTimeZone(TimeZone timeZone) {
setTimeZone(timeZone, false);
}
/**
* Associate the given TimeZone with the current thread,
* preserving any Locale that may have been set already.
* <p>Will implicitly create a LocaleContext for the given Locale.
* @param timeZone the current TimeZone, or {@code null} to reset
* the time zone part of the thread-bound context
* @param inheritable whether to expose the LocaleContext as inheritable
* for child threads (using an {@link InheritableThreadLocal})
* @see #setLocale(Locale, boolean)
* @see SimpleTimeZoneAwareLocaleContext#SimpleTimeZoneAwareLocaleContext(Locale, TimeZone)
*/
public static void setTimeZone(TimeZone timeZone, boolean inheritable) {
LocaleContext localeContext = getLocaleContext();
Locale locale = (localeContext != null ? localeContext.getLocale() : null);
if (timeZone != null) {
localeContext = new SimpleTimeZoneAwareLocaleContext(locale, timeZone);
}
else if (locale != null) {
localeContext = new SimpleLocaleContext(locale);
}
else {
localeContext = null;
}
setLocaleContext(localeContext, inheritable);
}
/**
* Return the TimeZone associated with the current thread, if any,
* or the system default TimeZone else. This is effectively a

View File

@@ -0,0 +1,155 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.i18n;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Juergen Hoeller
*/
public class LocaleContextHolderTests {
@Test
public void testSetLocaleContext() {
LocaleContext lc = new SimpleLocaleContext(Locale.GERMAN);
LocaleContextHolder.setLocaleContext(lc);
assertSame(lc, LocaleContextHolder.getLocaleContext());
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
lc = new SimpleLocaleContext(Locale.GERMANY);
LocaleContextHolder.setLocaleContext(lc);
assertSame(lc, LocaleContextHolder.getLocaleContext());
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
LocaleContextHolder.resetLocaleContext();
assertNull(LocaleContextHolder.getLocaleContext());
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
}
@Test
public void testSetTimeZoneAwareLocaleContext() {
LocaleContext lc = new SimpleTimeZoneAwareLocaleContext(Locale.GERMANY, TimeZone.getTimeZone("GMT+1"));
LocaleContextHolder.setLocaleContext(lc);
assertSame(lc, LocaleContextHolder.getLocaleContext());
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), LocaleContextHolder.getTimeZone());
LocaleContextHolder.resetLocaleContext();
assertNull(LocaleContextHolder.getLocaleContext());
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
}
@Test
public void testSetLocale() {
LocaleContextHolder.setLocale(Locale.GERMAN);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertFalse(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocaleContext().getLocale());
LocaleContextHolder.setLocale(Locale.GERMANY);
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertFalse(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocaleContext().getLocale());
LocaleContextHolder.setLocale(null);
assertNull(LocaleContextHolder.getLocaleContext());
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
}
@Test
public void testSetTimeZone() {
LocaleContextHolder.setTimeZone(TimeZone.getTimeZone("GMT+1"));
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertNull(LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setTimeZone(TimeZone.getTimeZone("GMT+2"));
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertNull(LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setTimeZone(null);
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertNull(LocaleContextHolder.getLocaleContext());
}
@Test
public void testSetLocaleAndSetTimeZoneMixed() {
LocaleContextHolder.setLocale(Locale.GERMANY);
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertFalse(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocaleContext().getLocale());
LocaleContextHolder.setTimeZone(TimeZone.getTimeZone("GMT+1"));
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMANY, LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setLocale(Locale.GERMAN);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setTimeZone(null);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertFalse(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocaleContext().getLocale());
LocaleContextHolder.setTimeZone(TimeZone.getTimeZone("GMT+2"));
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setLocale(null);
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), LocaleContextHolder.getTimeZone());
assertTrue(LocaleContextHolder.getLocaleContext() instanceof TimeZoneAwareLocaleContext);
assertNull(LocaleContextHolder.getLocaleContext().getLocale());
assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setTimeZone(null);
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertNull(LocaleContextHolder.getLocaleContext());
}
}