Comprehensive update to the framework's TimeZone handling, including a new TimeZoneAwareLocaleContext and a LocaleContextResolver for Spring MVC
A few noteworthy minor changes: LocaleContext.getLocale() may return null in special cases (not by default), which our own accessing classes are able to handle now. If there is a non-null TimeZone user setting, we're exposing it to all collaborating libraries, in particular to JSTL, Velocity and JasperReports. Our JSR-310 and Joda-Time support falls back to checking the general LocaleContext TimeZone now, adapting it to their time zone types, if no more specific setting has been provided. Our DefaultConversionService has TimeZone<->ZoneId converters registered. And finally, we're using a custom parseTimeZoneString method now that doesn't accept the TimeZone.getTimeZone(String) GMT fallback for an invalid time zone id anymore. Issue: SPR-1528
This commit is contained in:
parent
52cca48f40
commit
4574528a27
|
@ -19,6 +19,8 @@ package org.springframework.beans.propertyeditors;
|
|||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Editor for {@code java.util.TimeZone}, translating timezone IDs into
|
||||
* {@code TimeZone} objects. Exposes the {@code TimeZone} ID as a text
|
||||
|
@ -33,7 +35,7 @@ public class TimeZoneEditor extends PropertyEditorSupport {
|
|||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
setValue(TimeZone.getTimeZone(text));
|
||||
setValue(StringUtils.parseTimeZoneString(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.beans.propertyeditors;
|
||||
|
||||
import java.time.ZoneId;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Nicholas Williams
|
||||
*/
|
||||
public class ZoneIdEditorTests extends TestCase {
|
||||
|
||||
public void testAmericaChicago() {
|
||||
ZoneIdEditor editor = new ZoneIdEditor();
|
||||
editor.setAsText("America/Chicago");
|
||||
|
||||
ZoneId zoneId = (ZoneId) editor.getValue();
|
||||
assertNotNull("The zone ID should not be null.", zoneId);
|
||||
assertEquals("The zone ID is not correct.", ZoneId.of("America/Chicago"), zoneId);
|
||||
|
||||
assertEquals("The text version is not correct.", "America/Chicago", editor.getAsText());
|
||||
}
|
||||
|
||||
public void testAmericaLosAngeles() {
|
||||
ZoneIdEditor editor = new ZoneIdEditor();
|
||||
editor.setAsText("America/Los_Angeles");
|
||||
|
||||
ZoneId zoneId = (ZoneId) editor.getValue();
|
||||
assertNotNull("The zone ID should not be null.", zoneId);
|
||||
assertEquals("The zone ID is not correct.", ZoneId.of("America/Los_Angeles"), zoneId);
|
||||
|
||||
assertEquals("The text version is not correct.", "America/Los_Angeles", editor.getAsText());
|
||||
}
|
||||
|
||||
public void testGetNullAsText() {
|
||||
ZoneIdEditor editor = new ZoneIdEditor();
|
||||
|
||||
assertEquals("The returned value is not correct.", "", editor.getAsText());
|
||||
}
|
||||
|
||||
public void testGetValueAsText() {
|
||||
ZoneIdEditor editor = new ZoneIdEditor();
|
||||
editor.setValue(ZoneId.of("America/New_York"));
|
||||
|
||||
assertEquals("The text version is not correct.", "America/New_York", editor.getAsText());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2005 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.
|
||||
|
@ -26,14 +26,15 @@ import java.util.Locale;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocaleContextHolder
|
||||
* @see java.util.Locale
|
||||
* @see LocaleContextHolder#getLocale()
|
||||
* @see TimeZoneAwareLocaleContext
|
||||
*/
|
||||
public interface LocaleContext {
|
||||
|
||||
/**
|
||||
* Return the current Locale, which can be fixed or determined dynamically,
|
||||
* depending on the implementation strategy.
|
||||
* @return the current Locale, or {@code null} if no specific Locale associated
|
||||
*/
|
||||
Locale getLocale();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.context.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.core.NamedInheritableThreadLocal;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
@ -59,7 +60,11 @@ public abstract class LocaleContextHolder {
|
|||
/**
|
||||
* Associate the given LocaleContext with the current thread,
|
||||
* <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
|
||||
* @see SimpleLocaleContext
|
||||
* @see SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
public static void setLocaleContext(LocaleContext localeContext) {
|
||||
setLocaleContext(localeContext, false);
|
||||
|
@ -67,10 +72,14 @@ public abstract class LocaleContextHolder {
|
|||
|
||||
/**
|
||||
* Associate the given LocaleContext with the current thread.
|
||||
* <p>The given LocaleContext may be a {@link TimeZoneAwareLocaleContext},
|
||||
* containing a locale with associated time zone information.
|
||||
* @param localeContext the current LocaleContext,
|
||||
* or {@code null} to reset the thread-bound context
|
||||
* @param inheritable whether to expose the LocaleContext as inheritable
|
||||
* for child threads (using an {@link InheritableThreadLocal})
|
||||
* @see SimpleLocaleContext
|
||||
* @see SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
public static void setLocaleContext(LocaleContext localeContext, boolean inheritable) {
|
||||
if (localeContext == null) {
|
||||
|
@ -128,7 +137,13 @@ public abstract class LocaleContextHolder {
|
|||
|
||||
/**
|
||||
* Return the Locale associated with the current thread, if any,
|
||||
* or the system default Locale else.
|
||||
* or the system default Locale else. This is effectively a
|
||||
* replacement for {@link java.util.Locale#getDefault()},
|
||||
* able to optionally respect a user-level Locale setting.
|
||||
* <p>Note: This method has a fallback to the system default Locale.
|
||||
* If you'd like to check for the raw LocaleContext content
|
||||
* (which may indicate no specific locale through {@code null}, use
|
||||
* {@link #getLocaleContext()} and call {@link LocaleContext#getLocale()}
|
||||
* @return the current Locale, or the system default Locale if no
|
||||
* specific Locale has been associated with the current thread
|
||||
* @see LocaleContext#getLocale()
|
||||
|
@ -136,7 +151,39 @@ public abstract class LocaleContextHolder {
|
|||
*/
|
||||
public static Locale getLocale() {
|
||||
LocaleContext localeContext = getLocaleContext();
|
||||
return (localeContext != null ? localeContext.getLocale() : Locale.getDefault());
|
||||
if (localeContext != null) {
|
||||
Locale locale = localeContext.getLocale();
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the TimeZone associated with the current thread, if any,
|
||||
* or the system default TimeZone else. This is effectively a
|
||||
* replacement for {@link java.util.TimeZone#getDefault()},
|
||||
* able to optionally respect a user-level TimeZone setting.
|
||||
* <p>Note: This method has a fallback to the system default Locale.
|
||||
* If you'd like to check for the raw LocaleContext content
|
||||
* (which may indicate no specific time zone through {@code null}, use
|
||||
* {@link #getLocaleContext()} and call {@link TimeZoneAwareLocaleContext#getTimeZone()}
|
||||
* after downcasting to {@link TimeZoneAwareLocaleContext}.
|
||||
* @return the current TimeZone, or the system default TimeZone if no
|
||||
* specific TimeZone has been associated with the current thread
|
||||
* @see TimeZoneAwareLocaleContext#getTimeZone()
|
||||
* @see java.util.TimeZone#getDefault()
|
||||
*/
|
||||
public static TimeZone getTimeZone() {
|
||||
LocaleContext localeContext = getLocaleContext();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
TimeZone timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
if (timeZone != null) {
|
||||
return timeZone;
|
||||
}
|
||||
}
|
||||
return TimeZone.getDefault();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -18,14 +18,15 @@ package org.springframework.context.i18n;
|
|||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of the {@link LocaleContext} interface,
|
||||
* always returning a specified {@code Locale}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocaleContextHolder#setLocaleContext
|
||||
* @see LocaleContextHolder#getLocale()
|
||||
* @see SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
public class SimpleLocaleContext implements LocaleContext {
|
||||
|
||||
|
@ -34,11 +35,10 @@ public class SimpleLocaleContext implements LocaleContext {
|
|||
|
||||
/**
|
||||
* Create a new SimpleLocaleContext that exposes the specified Locale.
|
||||
* Every {@code getLocale()} will return this Locale.
|
||||
* Every {@link #getLocale()} call will return this Locale.
|
||||
* @param locale the Locale to expose
|
||||
*/
|
||||
public SimpleLocaleContext(Locale locale) {
|
||||
Assert.notNull(locale, "Locale must not be null");
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Simple implementation of the {@link TimeZoneAwareLocaleContext} interface,
|
||||
* always returning a specified {@code Locale} and {@code TimeZone}.
|
||||
*
|
||||
* <p>Note: Prefer the use of {@link SimpleLocaleContext} when only setting
|
||||
* a Locale but no TimeZone.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see LocaleContextHolder#setLocaleContext
|
||||
* @see LocaleContextHolder#getTimeZone()
|
||||
*/
|
||||
public class SimpleTimeZoneAwareLocaleContext extends SimpleLocaleContext implements TimeZoneAwareLocaleContext {
|
||||
|
||||
private final TimeZone timeZone;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SimpleTimeZoneAwareLocaleContext that exposes the specified
|
||||
* Locale and TimeZone. Every {@link #getLocale()} call will return the given
|
||||
* Locale, and every {@link #getTimeZone()} call will return the given TimeZone.
|
||||
* @param locale the Locale to expose
|
||||
* @param timeZone the TimeZone to expose
|
||||
*/
|
||||
public SimpleTimeZoneAwareLocaleContext(Locale locale, TimeZone timeZone) {
|
||||
super(locale);
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
|
||||
public TimeZone getTimeZone() {
|
||||
return this.timeZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " " + this.timeZone.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.TimeZone;
|
||||
|
||||
/**
|
||||
* Extension of {@link LocaleContext}, adding awareness of the current time zone.
|
||||
*
|
||||
* <p>Having this variant of LocaleContext set to {@link LocaleContextHolder} means
|
||||
* that some TimeZone-aware infrastructure has been configured, even if it may not
|
||||
* be able to produce a non-null TimeZone at the moment.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see LocaleContextHolder#getTimeZone()
|
||||
*/
|
||||
public interface TimeZoneAwareLocaleContext extends LocaleContext {
|
||||
|
||||
/**
|
||||
* Return the current TimeZone, which can be fixed or determined dynamically,
|
||||
* depending on the implementation strategy.
|
||||
* @return the current TimeZone, or {@code null} if no specific TimeZone associated
|
||||
*/
|
||||
TimeZone getTimeZone();
|
||||
|
||||
}
|
|
@ -16,10 +16,16 @@
|
|||
|
||||
package org.springframework.format.datetime.joda;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.joda.time.Chronology;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
|
||||
/**
|
||||
* A context that holds user-specific Joda-Time settings such as the user's
|
||||
* Chronology (calendar system) and time zone.
|
||||
|
@ -53,6 +59,11 @@ public class JodaTimeContext {
|
|||
|
||||
/**
|
||||
* Set the user's time zone.
|
||||
* <p>Alternatively, set a {@link TimeZoneAwareLocaleContext} on
|
||||
* {@link LocaleContextHolder}. This context class will fall back to
|
||||
* checking the locale context if no setting has been provided here.
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#getTimeZone()
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#setLocaleContext
|
||||
*/
|
||||
public void setTimeZone(DateTimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
|
@ -80,6 +91,15 @@ public class JodaTimeContext {
|
|||
if (this.timeZone != null) {
|
||||
formatter = formatter.withZone(this.timeZone);
|
||||
}
|
||||
else {
|
||||
LocaleContext localeContext = LocaleContextHolder.getLocaleContext();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
TimeZone timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
if (timeZone != null) {
|
||||
formatter = formatter.withZone(DateTimeZone.forTimeZone(timeZone));
|
||||
}
|
||||
}
|
||||
}
|
||||
return formatter;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@ package org.springframework.format.datetime.standard;
|
|||
import java.time.ZoneId;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
|
||||
/**
|
||||
* A context that holds user-specific <code>java.time</code> (JSR-310) settings
|
||||
|
@ -52,6 +57,11 @@ public class DateTimeContext {
|
|||
|
||||
/**
|
||||
* Set the user's time zone.
|
||||
* <p>Alternatively, set a {@link TimeZoneAwareLocaleContext} on
|
||||
* {@link LocaleContextHolder}. This context class will fall back to
|
||||
* checking the locale context if no setting has been provided here.
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#getTimeZone()
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#setLocaleContext
|
||||
*/
|
||||
public void setTimeZone(ZoneId timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
|
@ -79,6 +89,15 @@ public class DateTimeContext {
|
|||
if (this.timeZone != null) {
|
||||
formatter = formatter.withZone(this.timeZone);
|
||||
}
|
||||
else {
|
||||
LocaleContext localeContext = LocaleContextHolder.getLocaleContext();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
TimeZone timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
if (timeZone != null) {
|
||||
formatter = formatter.withZone(timeZone.toZoneId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return formatter;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.springframework.scheduling.support.ScheduledMethodRunnable;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
|
@ -192,11 +193,7 @@ public class ScheduledAnnotationBeanPostProcessor
|
|||
}
|
||||
TimeZone timeZone;
|
||||
if (!"".equals(zone)) {
|
||||
timeZone = TimeZone.getTimeZone(zone);
|
||||
// Check for that silly TimeZone fallback...
|
||||
if ("GMT".equals(timeZone.getID()) && !zone.startsWith("GMT")) {
|
||||
throw new IllegalArgumentException("Invalid time zone id '" + zone + "'");
|
||||
}
|
||||
timeZone = StringUtils.parseTimeZoneString(zone);
|
||||
}
|
||||
else {
|
||||
timeZone = TimeZone.getDefault();
|
||||
|
|
|
@ -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.
|
||||
|
@ -21,6 +21,7 @@ import java.util.UUID;
|
|||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A specialization of {@link GenericConversionService} configured by default with
|
||||
|
@ -31,10 +32,16 @@ import org.springframework.core.convert.converter.ConverterRegistry;
|
|||
* {@code ConverterRegistry} instance.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class DefaultConversionService extends GenericConversionService {
|
||||
|
||||
/** Java 8's java.time package available? */
|
||||
private static final boolean zoneIdAvailable =
|
||||
ClassUtils.isPresent("java.time.ZoneId", DefaultConversionService.class.getClassLoader());
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DefaultConversionService} with the set of
|
||||
* {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}.
|
||||
|
@ -43,46 +50,55 @@ public class DefaultConversionService extends GenericConversionService {
|
|||
addDefaultConverters(this);
|
||||
}
|
||||
|
||||
|
||||
// static utility methods
|
||||
|
||||
/**
|
||||
* Add converters appropriate for most environments.
|
||||
* @param converterRegistry the registry of converters to add to (must also be castable to ConversionService)
|
||||
* @throws ClassCastException if the converterRegistry could not be cast to a ConversionService
|
||||
* @param converterRegistry the registry of converters to add to (must also be castable to ConversionService,
|
||||
* e.g. being a {@link ConfigurableConversionService})
|
||||
* @throws ClassCastException if the given ConverterRegistry could not be cast to a ConversionService
|
||||
*/
|
||||
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
|
||||
addScalarConverters(converterRegistry);
|
||||
addCollectionConverters(converterRegistry);
|
||||
addBinaryConverters(converterRegistry);
|
||||
addFallbackConverters(converterRegistry);
|
||||
|
||||
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
|
||||
if (zoneIdAvailable) {
|
||||
ZoneIdConverterRegistrar.registerZoneIdConverters(converterRegistry);
|
||||
}
|
||||
|
||||
converterRegistry.addConverter(new ObjectToObjectConverter());
|
||||
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
|
||||
converterRegistry.addConverter(new FallbackObjectToStringConverter());
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private static void addScalarConverters(ConverterRegistry converterRegistry) {
|
||||
ConversionService conversionService = (ConversionService) converterRegistry;
|
||||
converterRegistry.addConverter(new StringToBooleanConverter());
|
||||
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
|
||||
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
|
||||
|
||||
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
|
||||
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
|
||||
|
||||
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
|
||||
|
||||
converterRegistry.addConverter(new StringToCharacterConverter());
|
||||
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
|
||||
|
||||
converterRegistry.addConverter(new NumberToCharacterConverter());
|
||||
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
|
||||
|
||||
converterRegistry.addConverter(new StringToBooleanConverter());
|
||||
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
|
||||
|
||||
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
|
||||
converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter(conversionService));
|
||||
converterRegistry.addConverter(Enum.class, String.class,
|
||||
new EnumToStringConverter((ConversionService) converterRegistry));
|
||||
|
||||
converterRegistry.addConverter(new StringToLocaleConverter());
|
||||
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
|
||||
|
||||
converterRegistry.addConverter(new PropertiesToStringConverter());
|
||||
converterRegistry.addConverter(new StringToPropertiesConverter());
|
||||
converterRegistry.addConverter(new PropertiesToStringConverter());
|
||||
|
||||
converterRegistry.addConverter(new StringToUUIDConverter());
|
||||
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
|
||||
|
@ -90,6 +106,7 @@ public class DefaultConversionService extends GenericConversionService {
|
|||
|
||||
private static void addCollectionConverters(ConverterRegistry converterRegistry) {
|
||||
ConversionService conversionService = (ConversionService) converterRegistry;
|
||||
|
||||
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
|
||||
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
|
||||
|
||||
|
@ -110,16 +127,16 @@ public class DefaultConversionService extends GenericConversionService {
|
|||
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
|
||||
}
|
||||
|
||||
private static void addBinaryConverters(ConverterRegistry converterRegistry) {
|
||||
ConversionService conversionService = (ConversionService) converterRegistry;
|
||||
converterRegistry.addConverter(new ByteBufferConverter(conversionService));
|
||||
}
|
||||
|
||||
private static void addFallbackConverters(ConverterRegistry converterRegistry) {
|
||||
ConversionService conversionService = (ConversionService) converterRegistry;
|
||||
converterRegistry.addConverter(new ObjectToObjectConverter());
|
||||
converterRegistry.addConverter(new IdToEntityConverter(conversionService));
|
||||
converterRegistry.addConverter(new FallbackObjectToStringConverter());
|
||||
/**
|
||||
* Inner class to avoid a hard-coded dependency on Java 8's {@link java.time.ZoneId}.
|
||||
*/
|
||||
private static final class ZoneIdConverterRegistrar {
|
||||
|
||||
public static void registerZoneIdConverters(ConverterRegistry converterRegistry) {
|
||||
converterRegistry.addConverter(new TimeZoneToZoneIdConverter());
|
||||
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.core.convert.support;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
/**
|
||||
* Simple Converter from {@link java.util.TimeZone} to Java 8's {@link java.time.ZoneId}.
|
||||
*
|
||||
* <p>Note that Spring's default ConversionService setup understands the 'of' convention that
|
||||
* the JSR-310 {@code java.time} package consistently uses. That convention is implemented
|
||||
* reflectively in {@link ObjectToObjectConverter}, not in specific JSR-310 converters.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see ZoneIdToTimeZoneConverter
|
||||
*/
|
||||
class TimeZoneToZoneIdConverter implements Converter<TimeZone, ZoneId> {
|
||||
|
||||
@Override
|
||||
public ZoneId convert(TimeZone source) {
|
||||
return source.toZoneId();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.core.convert.support;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
/**
|
||||
* Simple Converter from Java 8's {@link java.time.ZoneId} to {@link java.util.TimeZone}.
|
||||
*
|
||||
* <p>Note that Spring's default ConversionService setup understands the 'of' convention that
|
||||
* the JSR-310 {@code java.time} package consistently uses. That convention is implemented
|
||||
* reflectively in {@link ObjectToObjectConverter}, not in specific JSR-310 converters.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see TimeZoneToZoneIdConverter
|
||||
*/
|
||||
class ZoneIdToTimeZoneConverter implements Converter<ZoneId, TimeZone> {
|
||||
|
||||
@Override
|
||||
public TimeZone convert(ZoneId source) {
|
||||
return TimeZone.getTimeZone(source);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
@ -28,6 +28,7 @@ import java.util.Locale;
|
|||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
|
@ -674,10 +675,11 @@ public abstract class StringUtils {
|
|||
/**
|
||||
* Parse the given {@code localeString} value into a {@link Locale}.
|
||||
* <p>This is the inverse operation of {@link Locale#toString Locale's toString}.
|
||||
* @param localeString the locale string, following {@code Locale's}
|
||||
* @param localeString the locale String, following {@code Locale's}
|
||||
* {@code toString()} format ("en", "en_UK", etc);
|
||||
* also accepts spaces as separators, as an alternative to underscores
|
||||
* @return a corresponding {@code Locale} instance
|
||||
* @throws IllegalArgumentException in case of an invalid locale specification
|
||||
*/
|
||||
public static Locale parseLocaleString(String localeString) {
|
||||
String[] parts = tokenizeToStringArray(localeString, "_ ", false, false);
|
||||
|
@ -719,6 +721,22 @@ public abstract class StringUtils {
|
|||
return locale.getLanguage() + (hasText(locale.getCountry()) ? "-" + locale.getCountry() : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given {@code timeZoneString} value into a {@link TimeZone}.
|
||||
* @param timeZoneString the time zone String, following {@link TimeZone#getTimeZone(String)}
|
||||
* but throwing {@link IllegalArgumentException} in case of an invalid time zone specification
|
||||
* @return a corresponding {@link TimeZone} instance
|
||||
* @throws IllegalArgumentException in case of an invalid time zone specification
|
||||
*/
|
||||
public static TimeZone parseTimeZoneString(String timeZoneString) {
|
||||
TimeZone timeZone = TimeZone.getTimeZone(timeZoneString);
|
||||
if ("GMT".equals(timeZone.getID()) && !timeZoneString.startsWith("GMT")) {
|
||||
// We don't want that GMT fallback...
|
||||
throw new IllegalArgumentException("Invalid time zone specification '" + timeZoneString + "'");
|
||||
}
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Convenience methods for working with String arrays
|
||||
|
|
|
@ -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.
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.remoting.httpinvoker;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.http.Header;
|
||||
|
@ -170,9 +171,12 @@ public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvoke
|
|||
*/
|
||||
protected HttpPost createHttpPost(HttpInvokerClientConfiguration config) throws IOException {
|
||||
HttpPost httpPost = new HttpPost(config.getServiceUrl());
|
||||
LocaleContext locale = LocaleContextHolder.getLocaleContext();
|
||||
if (locale != null) {
|
||||
httpPost.addHeader(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale()));
|
||||
LocaleContext localeContext = LocaleContextHolder.getLocaleContext();
|
||||
if (localeContext != null) {
|
||||
Locale locale = localeContext.getLocale();
|
||||
if (locale != null) {
|
||||
httpPost.addHeader(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale));
|
||||
}
|
||||
}
|
||||
if (isAcceptGzipEncoding()) {
|
||||
httpPost.addHeader(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.
|
||||
|
@ -22,6 +22,7 @@ import java.io.InputStream;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
|
@ -40,7 +41,6 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see CommonsHttpInvokerRequestExecutor
|
||||
* @see java.net.HttpURLConnection
|
||||
*/
|
||||
public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor {
|
||||
|
@ -133,9 +133,13 @@ public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequest
|
|||
connection.setRequestMethod(HTTP_METHOD_POST);
|
||||
connection.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType());
|
||||
connection.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer.toString(contentLength));
|
||||
LocaleContext locale = LocaleContextHolder.getLocaleContext();
|
||||
if (locale != null) {
|
||||
connection.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale()));
|
||||
|
||||
LocaleContext localeContext = LocaleContextHolder.getLocaleContext();
|
||||
if (localeContext != null) {
|
||||
Locale locale = localeContext.getLocale();
|
||||
if (locale != null) {
|
||||
connection.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale));
|
||||
}
|
||||
}
|
||||
if (isAcceptGzipEncoding()) {
|
||||
connection.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -36,6 +35,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
@ -1042,16 +1042,17 @@ public class DispatcherServlet extends FrameworkServlet {
|
|||
*/
|
||||
@Override
|
||||
protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
|
||||
return new LocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return localeResolver.resolveLocale(request);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return getLocale().toString();
|
||||
}
|
||||
};
|
||||
if (this.localeResolver instanceof LocaleContextResolver) {
|
||||
return ((LocaleContextResolver) this.localeResolver).resolveLocaleContext(request);
|
||||
}
|
||||
else {
|
||||
return new LocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return localeResolver.resolveLocale(request);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.web.servlet;
|
||||
|
||||
import java.util.Locale;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
|
||||
/**
|
||||
* Extension of {@link LocaleResolver}, adding support for a rich locale context
|
||||
* (potentially including locale and time zone information).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see org.springframework.context.i18n.LocaleContext
|
||||
* @see org.springframework.context.i18n.TimeZoneAwareLocaleContext
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getTimeZone
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
public interface LocaleContextResolver extends LocaleResolver {
|
||||
|
||||
/**
|
||||
* Resolve the current locale context via the given request.
|
||||
* <p>This is primarily intended for framework-level processing; consider using
|
||||
* {@link org.springframework.web.servlet.support.RequestContextUtils} or
|
||||
* {@link org.springframework.web.servlet.support.RequestContext} for
|
||||
* application-level access to the current locale and/or time zone.
|
||||
* <p>The returned context may be a
|
||||
* {@link org.springframework.context.i18n.TimeZoneAwareLocaleContext},
|
||||
* containing a locale with associated time zone information.
|
||||
* Simply apply an {@code instanceof} check and downcast accordingly.
|
||||
* <p>Custom resolver implementations may also return extra settings in
|
||||
* the returned context, which again can be accessed through downcasting.
|
||||
* @param request the request to resolve the locale context for
|
||||
* @return the current locale context (never {@code null}
|
||||
* @see #resolveLocale(HttpServletRequest)
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
LocaleContext resolveLocaleContext(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Set the current locale context to the given one,
|
||||
* potentially including a locale with associated time zone information.
|
||||
* @param request the request to be used for locale modification
|
||||
* @param response the response to be used for locale modification
|
||||
* @param localeContext the new locale context, or {@code null} to clear the locale
|
||||
* @throws UnsupportedOperationException if the LocaleResolver implementation
|
||||
* does not support dynamic changing of the locale or time zone
|
||||
* @see #setLocale(HttpServletRequest, HttpServletResponse, Locale)
|
||||
* @see org.springframework.context.i18n.SimpleLocaleContext
|
||||
* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext);
|
||||
|
||||
}
|
|
@ -34,8 +34,19 @@ import javax.servlet.http.HttpServletResponse;
|
|||
* to retrieve the current locale in controllers or views, independent
|
||||
* of the actual resolution strategy.
|
||||
*
|
||||
* <p>Note: As of Spring 4.0, there is an extended strategy interface
|
||||
* called {@link LocaleContextResolver}, allowing for resolution of
|
||||
* a {@link org.springframework.context.i18n.LocaleContext} object,
|
||||
* potentially including associated time zone information. Spring's
|
||||
* provided resolver implementations implement the extended
|
||||
* {@link LocaleContextResolver} interface wherever appropriate.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 27.02.2003
|
||||
* @see LocaleContextResolver
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
*/
|
||||
public interface LocaleResolver {
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.web.servlet.LocaleContextResolver;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link LocaleContextResolver} implementations.
|
||||
* Provides support for a default locale and a default time zone.
|
||||
*
|
||||
* <p>Also provides pre-implemented versions of {@link #resolveLocale} and {@link #setLocale},
|
||||
* delegating to {@link #resolveLocaleContext} and {@link #setLocaleContext}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public abstract class AbstractLocaleContextResolver extends AbstractLocaleResolver implements LocaleContextResolver {
|
||||
|
||||
private TimeZone defaultTimeZone;
|
||||
|
||||
|
||||
/**
|
||||
* Set a default TimeZone that this resolver will return if no other time zone found.
|
||||
*/
|
||||
public void setDefaultTimeZone(TimeZone defaultTimeZone) {
|
||||
this.defaultTimeZone = defaultTimeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default TimeZone that this resolver is supposed to fall back to, if any.
|
||||
*/
|
||||
public TimeZone getDefaultTimeZone() {
|
||||
return this.defaultTimeZone;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
return resolveLocaleContext(request).getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 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.
|
||||
|
@ -26,6 +26,7 @@ import org.springframework.web.servlet.LocaleResolver;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.9
|
||||
* @see #setDefaultLocale
|
||||
*/
|
||||
public abstract class AbstractLocaleResolver implements LocaleResolver {
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,12 +17,16 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.LocaleContextResolver;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.util.CookieGenerator;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
@ -33,29 +37,44 @@ import org.springframework.web.util.WebUtils;
|
|||
* or the request's accept-header locale.
|
||||
*
|
||||
* <p>This is particularly useful for stateless applications without user sessions.
|
||||
* The cookie may optionally contain an associated time zone value as well;
|
||||
* alternatively, you may specify a default time zone.
|
||||
*
|
||||
* <p>Custom controllers can thus override the user's locale by calling
|
||||
* {@link #setLocale(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.util.Locale)},
|
||||
* for example responding to a certain locale change request.
|
||||
* <p>Custom controllers can override the user's locale and time zone by calling
|
||||
* {@code #setLocale(Context)} on the resolver, e.g. responding to a locale change
|
||||
* request. As a more convenient alternative, consider using
|
||||
* {@link org.springframework.web.servlet.support.RequestContext#changeLocale}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Jean-Pierre Pawlak
|
||||
* @since 27.02.2003
|
||||
* @see #setDefaultLocale
|
||||
* @see #setLocale
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public class CookieLocaleResolver extends CookieGenerator implements LocaleResolver {
|
||||
public class CookieLocaleResolver extends CookieGenerator implements LocaleContextResolver {
|
||||
|
||||
/**
|
||||
* The name of the request attribute that holds the locale.
|
||||
* The name of the request attribute that holds the Locale.
|
||||
* <p>Only used for overriding a cookie value if the locale has been
|
||||
* changed in the course of the current request! Use
|
||||
* {@link org.springframework.web.servlet.support.RequestContext#getLocale}
|
||||
* changed in the course of the current request!
|
||||
* <p>Use {@code RequestContext(Utils).getLocale()}
|
||||
* to retrieve the current locale in controllers or views.
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
*/
|
||||
public static final String LOCALE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";
|
||||
|
||||
/**
|
||||
* The name of the request attribute that holds the TimeZone.
|
||||
* <p>Only used for overriding a cookie value if the locale has been
|
||||
* changed in the course of the current request!
|
||||
* <p>Use {@code RequestContext(Utils).getTimeZone()}
|
||||
* to retrieve the current time zone in controllers or views.
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getTimeZone
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
public static final String TIME_ZONE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".TIME_ZONE";
|
||||
|
||||
/**
|
||||
* The default cookie name used if none is explicitly set.
|
||||
*/
|
||||
|
@ -64,9 +83,11 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleResol
|
|||
|
||||
private Locale defaultLocale;
|
||||
|
||||
private TimeZone defaultTimeZone;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@link CookieLocaleResolver} class
|
||||
* Create a new instance of the {@link CookieLocaleResolver} class
|
||||
* using the {@link #DEFAULT_COOKIE_NAME default cookie name}.
|
||||
*/
|
||||
public CookieLocaleResolver() {
|
||||
|
@ -88,45 +109,100 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleResol
|
|||
return this.defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a fixed TimeZone that this resolver will return if no cookie found.
|
||||
*/
|
||||
public void setDefaultTimeZone(TimeZone defaultTimeZone) {
|
||||
this.defaultTimeZone = defaultTimeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fixed TimeZone that this resolver will return if no cookie found,
|
||||
* if any.
|
||||
*/
|
||||
protected TimeZone getDefaultTimeZone() {
|
||||
return this.defaultTimeZone;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
// Check request for pre-parsed or preset locale.
|
||||
Locale locale = (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
}
|
||||
parseLocaleCookieIfNecessary(request);
|
||||
return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
|
||||
}
|
||||
|
||||
// Retrieve and parse cookie value.
|
||||
Cookie cookie = WebUtils.getCookie(request, getCookieName());
|
||||
if (cookie != null) {
|
||||
locale = StringUtils.parseLocaleString(cookie.getValue());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale + "'");
|
||||
@Override
|
||||
public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
|
||||
parseLocaleCookieIfNecessary(request);
|
||||
return new TimeZoneAwareLocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
|
||||
}
|
||||
if (locale != null) {
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, locale);
|
||||
return locale;
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
return (TimeZone) request.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return determineDefaultLocale(request);
|
||||
private void parseLocaleCookieIfNecessary(HttpServletRequest request) {
|
||||
if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {
|
||||
// Retrieve and parse cookie value.
|
||||
Cookie cookie = WebUtils.getCookie(request, getCookieName());
|
||||
Locale locale = null;
|
||||
TimeZone timeZone = null;
|
||||
if (cookie != null) {
|
||||
String value = cookie.getValue();
|
||||
String localePart = value;
|
||||
String timeZonePart = null;
|
||||
int spaceIndex = localePart.indexOf(' ');
|
||||
if (spaceIndex != -1) {
|
||||
localePart = value.substring(0, spaceIndex);
|
||||
timeZonePart = value.substring(spaceIndex + 1);
|
||||
}
|
||||
locale = (!"-".equals(localePart) ? StringUtils.parseLocaleString(localePart) : null);
|
||||
if (timeZonePart != null) {
|
||||
timeZone = StringUtils.parseTimeZoneString(timeZonePart);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale +
|
||||
"'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : ""));
|
||||
}
|
||||
}
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
|
||||
(locale != null ? locale: determineDefaultLocale(request)));
|
||||
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
|
||||
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||
if (locale != null) {
|
||||
// Set request attribute and add cookie.
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, locale);
|
||||
addCookie(response, locale.toString());
|
||||
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
|
||||
Locale locale = null;
|
||||
TimeZone timeZone = null;
|
||||
if (localeContext != null) {
|
||||
locale = localeContext.getLocale();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
}
|
||||
addCookie(response, (locale != null ? locale : "-") + (timeZone != null ? ' ' + timeZone.getID() : ""));
|
||||
}
|
||||
else {
|
||||
// Set request attribute to fallback locale and remove cookie.
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, determineDefaultLocale(request));
|
||||
removeCookie(response);
|
||||
}
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
|
||||
(locale != null ? locale: determineDefaultLocale(request)));
|
||||
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
|
||||
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the default locale for the given request,
|
||||
* Called if no locale cookie has been found.
|
||||
|
@ -145,4 +221,17 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleResol
|
|||
return defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default time zone for the given request,
|
||||
* Called if no TimeZone cookie has been found.
|
||||
* <p>The default implementation returns the specified default time zone,
|
||||
* if any, or {@code null} otherwise.
|
||||
* @param request the request to resolve the time zone for
|
||||
* @return the default time zone (or {@code null} if none defined)
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
|
||||
return getDefaultTimeZone();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,30 +17,36 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.web.servlet.LocaleResolver} implementation
|
||||
* that always returns a fixed default locale. Default is the current
|
||||
* JVM's default locale.
|
||||
* that always returns a fixed default locale and optionally time zone.
|
||||
* Default is the current JVM's default locale.
|
||||
*
|
||||
* <p>Note: Does not support {@code setLocale}, as the fixed locale
|
||||
* cannot be changed.
|
||||
* <p>Note: Does not support {@code setLocale(Context)}, as the fixed
|
||||
* locale and time zone cannot be changed.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public class FixedLocaleResolver extends AbstractLocaleResolver {
|
||||
public class FixedLocaleResolver extends AbstractLocaleContextResolver {
|
||||
|
||||
/**
|
||||
* Create a default FixedLocaleResolver, exposing a configured default
|
||||
* locale (or the JVM's default locale as fallback).
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public FixedLocaleResolver() {
|
||||
setDefaultLocale(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,6 +57,16 @@ public class FixedLocaleResolver extends AbstractLocaleResolver {
|
|||
setDefaultLocale(locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FixedLocaleResolver that exposes the given locale and time zone.
|
||||
* @param locale the locale to expose
|
||||
* @param timeZone the time zone to expose
|
||||
*/
|
||||
public FixedLocaleResolver(Locale locale, TimeZone timeZone) {
|
||||
setDefaultLocale(locale);
|
||||
setDefaultTimeZone(timeZone);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
|
@ -62,9 +78,22 @@ public class FixedLocaleResolver extends AbstractLocaleResolver {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot change fixed locale - use a different locale resolution strategy");
|
||||
public LocaleContext resolveLocaleContext(HttpServletRequest request) {
|
||||
return new TimeZoneAwareLocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return getDefaultLocale();
|
||||
}
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
return getDefaultTimeZone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
|
||||
throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,10 +17,12 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
|
@ -30,27 +32,41 @@ import org.springframework.web.util.WebUtils;
|
|||
*
|
||||
* <p>This is most appropriate if the application needs user sessions anyway,
|
||||
* that is, when the HttpSession does not have to be created for the locale.
|
||||
* The session may optionally contain an associated time zone attribute as well;
|
||||
* alternatively, you may specify a default time zone.
|
||||
*
|
||||
* <p>Custom controllers can override the user's locale by calling
|
||||
* {@code setLocale}, e.g. responding to a locale change request.
|
||||
* <p>Custom controllers can override the user's locale and time zone by calling
|
||||
* {@code #setLocale(Context)} on the resolver, e.g. responding to a locale change
|
||||
* request. As a more convenient alternative, consider using
|
||||
* {@link org.springframework.web.servlet.support.RequestContext#changeLocale}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 27.02.2003
|
||||
* @see #setDefaultLocale
|
||||
* @see #setLocale
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public class SessionLocaleResolver extends AbstractLocaleResolver {
|
||||
public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
|
||||
/**
|
||||
* Name of the session attribute that holds the locale.
|
||||
* Name of the session attribute that holds the Locale.
|
||||
* Only used internally by this implementation.
|
||||
* Use {@code RequestContext(Utils).getLocale()}
|
||||
* <p>Use {@code RequestContext(Utils).getLocale()}
|
||||
* to retrieve the current locale in controllers or views.
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
*/
|
||||
public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE";
|
||||
|
||||
/**
|
||||
* Name of the session attribute that holds the TimeZone.
|
||||
* Only used internally by this implementation.
|
||||
* <p>Use {@code RequestContext(Utils).getTimeZone()}
|
||||
* to retrieve the current time zone in controllers or views.
|
||||
* @see org.springframework.web.servlet.support.RequestContext#getTimeZone
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
public static final String TIME_ZONE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".TIME_ZONE";
|
||||
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
|
@ -61,9 +77,46 @@ public class SessionLocaleResolver extends AbstractLocaleResolver {
|
|||
return locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
|
||||
return new TimeZoneAwareLocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);
|
||||
if (locale == null) {
|
||||
locale = determineDefaultLocale(request);
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME);
|
||||
if (timeZone == null) {
|
||||
timeZone = determineDefaultTimeZone(request);
|
||||
}
|
||||
return timeZone;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
|
||||
Locale locale = null;
|
||||
TimeZone timeZone = null;
|
||||
if (localeContext != null) {
|
||||
locale = localeContext.getLocale();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
}
|
||||
}
|
||||
WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);
|
||||
WebUtils.setSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME, timeZone);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the default locale for the given request,
|
||||
* Called if no locale session attribute has been found.
|
||||
* Called if no Locale session attribute has been found.
|
||||
* <p>The default implementation returns the specified default locale,
|
||||
* if any, else falls back to the request's accept-header locale.
|
||||
* @param request the request to resolve the locale for
|
||||
|
@ -79,9 +132,17 @@ public class SessionLocaleResolver extends AbstractLocaleResolver {
|
|||
return defaultLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||
WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);
|
||||
/**
|
||||
* Determine the default time zone for the given request,
|
||||
* Called if no TimeZone session attribute has been found.
|
||||
* <p>The default implementation returns the specified default time zone,
|
||||
* if any, or {@code null} otherwise.
|
||||
* @param request the request to resolve the time zone for
|
||||
* @return the default time zone (or {@code null} if none defined)
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
|
||||
return getDefaultTimeZone();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -21,8 +21,9 @@ import java.io.InputStream;
|
|||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Principal;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Locale;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -45,12 +46,15 @@ import org.springframework.web.servlet.support.RequestContextUtils;
|
|||
* <li>{@link HttpSession}
|
||||
* <li>{@link Principal}
|
||||
* <li>{@link Locale}
|
||||
* <li>{@link TimeZone} (as of Spring 4.0)
|
||||
* <li>{@link java.time.ZoneId} (as of Spring 4.0 and Java 8)</li>
|
||||
* <li>{@link InputStream}
|
||||
* <li>{@link Reader}
|
||||
* </ul>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
@ -64,6 +68,8 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
|||
HttpSession.class.isAssignableFrom(paramType) ||
|
||||
Principal.class.isAssignableFrom(paramType) ||
|
||||
Locale.class.equals(paramType) ||
|
||||
TimeZone.class.equals(paramType) ||
|
||||
"java.time.ZoneId".equals(paramType.getName()) ||
|
||||
InputStream.class.isAssignableFrom(paramType) ||
|
||||
Reader.class.isAssignableFrom(paramType);
|
||||
}
|
||||
|
@ -97,6 +103,13 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
|||
else if (Locale.class.equals(paramType)) {
|
||||
return RequestContextUtils.getLocale(request);
|
||||
}
|
||||
else if (TimeZone.class.equals(paramType)) {
|
||||
TimeZone timeZone = RequestContextUtils.getTimeZone(request);
|
||||
return (timeZone != null ? timeZone : TimeZone.getDefault());
|
||||
}
|
||||
else if ("java.time.ZoneId".equals(paramType.getName())) {
|
||||
return ZoneIdResolver.resolveZoneId(request);
|
||||
}
|
||||
else if (InputStream.class.isAssignableFrom(paramType)) {
|
||||
return request.getInputStream();
|
||||
}
|
||||
|
@ -110,4 +123,16 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard-coded dependency on Java 8's {@link java.time.ZoneId}.
|
||||
*/
|
||||
private static class ZoneIdResolver {
|
||||
|
||||
public static Object resolveZoneId(HttpServletRequest request) {
|
||||
TimeZone timeZone = RequestContextUtils.getTimeZone(request);
|
||||
return (timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.springframework.web.servlet.support;
|
|||
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -80,6 +80,10 @@ public abstract class JstlUtils {
|
|||
public static void exposeLocalizationContext(HttpServletRequest request, MessageSource messageSource) {
|
||||
Locale jstlLocale = RequestContextUtils.getLocale(request);
|
||||
Config.set(request, Config.FMT_LOCALE, jstlLocale);
|
||||
TimeZone timeZone = RequestContextUtils.getTimeZone(request);
|
||||
if (timeZone != null) {
|
||||
Config.set(request, Config.FMT_TIME_ZONE, timeZone);
|
||||
}
|
||||
if (messageSource != null) {
|
||||
LocalizationContext jstlContext = new SpringLocalizationContext(messageSource, request);
|
||||
Config.set(request, Config.FMT_LOCALIZATION_CONTEXT, jstlContext);
|
||||
|
@ -95,6 +99,10 @@ public abstract class JstlUtils {
|
|||
*/
|
||||
public static void exposeLocalizationContext(RequestContext requestContext) {
|
||||
Config.set(requestContext.getRequest(), Config.FMT_LOCALE, requestContext.getLocale());
|
||||
TimeZone timeZone = requestContext.getTimeZone();
|
||||
if (timeZone != null) {
|
||||
Config.set(requestContext.getRequest(), Config.FMT_TIME_ZONE, timeZone);
|
||||
}
|
||||
MessageSource messageSource = getJstlAwareMessageSource(
|
||||
requestContext.getServletContext(), requestContext.getMessageSource());
|
||||
LocalizationContext jstlContext = new SpringLocalizationContext(messageSource, requestContext.getRequest());
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -29,6 +30,9 @@ import javax.servlet.jsp.jstl.core.Config;
|
|||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceResolvable;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.ui.context.Theme;
|
||||
import org.springframework.ui.context.ThemeSource;
|
||||
import org.springframework.ui.context.support.ResourceBundleThemeSource;
|
||||
|
@ -40,15 +44,17 @@ import org.springframework.validation.BindingResult;
|
|||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.EscapedErrors;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.LocaleContextResolver;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Context holder for request-specific state, like current web application context, current locale, current theme, and
|
||||
* potential binding errors. Provides easy access to localized messages and Errors instances.
|
||||
* Context holder for request-specific state, like current web application context, current locale, current theme,
|
||||
* and potential binding errors. Provides easy access to localized messages and Errors instances.
|
||||
*
|
||||
* <p>Suitable for exposition to views, and usage within JSP's "useBean" tag, JSP scriptlets, JSTL EL, Velocity
|
||||
* templates, etc. Necessary for views that do not have access to the servlet request, like Velocity templates.
|
||||
|
@ -56,8 +62,8 @@ import org.springframework.web.util.WebUtils;
|
|||
* <p>Can be instantiated manually, or automatically exposed to views as model attribute via AbstractView's
|
||||
* "requestContextAttribute" property.
|
||||
*
|
||||
* <p>Will also work outside of DispatcherServlet requests, accessing the root WebApplicationContext and using an
|
||||
* appropriate fallback for the locale (the HttpServletRequest's primary locale).
|
||||
* <p>Will also work outside of DispatcherServlet requests, accessing the root WebApplicationContext and using
|
||||
* an appropriate fallback for the locale (the HttpServletRequest's primary locale).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rossen Stoyanchev
|
||||
|
@ -70,15 +76,16 @@ import org.springframework.web.util.WebUtils;
|
|||
public class RequestContext {
|
||||
|
||||
/**
|
||||
* Default theme name used if the RequestContext cannot find a ThemeResolver. Only applies to non-DispatcherServlet
|
||||
* requests. <p>Same as AbstractThemeResolver's default, but not linked in here to avoid package interdependencies.
|
||||
* Default theme name used if the RequestContext cannot find a ThemeResolver.
|
||||
* Only applies to non-DispatcherServlet requests.
|
||||
* <p>Same as AbstractThemeResolver's default, but not linked in here to avoid package interdependencies.
|
||||
* @see org.springframework.web.servlet.theme.AbstractThemeResolver#ORIGINAL_DEFAULT_THEME_NAME
|
||||
*/
|
||||
public static final String DEFAULT_THEME_NAME = "theme";
|
||||
|
||||
/**
|
||||
* Request attribute to hold the current web application context for RequestContext usage. By default, the
|
||||
* DispatcherServlet's context (or the root context as fallback) is exposed.
|
||||
* Request attribute to hold the current web application context for RequestContext usage.
|
||||
* By default, the DispatcherServlet's context (or the root context as fallback) is exposed.
|
||||
*/
|
||||
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = RequestContext.class.getName() + ".CONTEXT";
|
||||
|
||||
|
@ -102,6 +109,8 @@ public class RequestContext {
|
|||
|
||||
private Locale locale;
|
||||
|
||||
private TimeZone timeZone;
|
||||
|
||||
private Theme theme;
|
||||
|
||||
private Boolean defaultHtmlEscape;
|
||||
|
@ -114,10 +123,11 @@ public class RequestContext {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new RequestContext for the given request, using the request attributes for Errors retrieval. <p>This
|
||||
* only works with InternalResourceViews, as Errors instances are part of the model and not normally exposed as
|
||||
* request attributes. It will typically be used within JSPs or custom tags. <p><b>Will only work within a
|
||||
* DispatcherServlet request.</b> Pass in a ServletContext to be able to fallback to the root WebApplicationContext.
|
||||
* Create a new RequestContext for the given request, using the request attributes for Errors retrieval.
|
||||
* <p>This only works with InternalResourceViews, as Errors instances are part of the model and not
|
||||
* normally exposed as request attributes. It will typically be used within JSPs or custom tags.
|
||||
* <p><b>Will only work within a DispatcherServlet request.</b>
|
||||
* Pass in a ServletContext to be able to fallback to the root WebApplicationContext.
|
||||
* @param request current HTTP request
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.ServletContext)
|
||||
|
@ -127,13 +137,29 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new RequestContext for the given request, using the request attributes for Errors retrieval. <p>This
|
||||
* only works with InternalResourceViews, as Errors instances are part of the model and not normally exposed as
|
||||
* request attributes. It will typically be used within JSPs or custom tags. <p>If a ServletContext is specified,
|
||||
* the RequestContext will also work with the root WebApplicationContext (outside a DispatcherServlet).
|
||||
* Create a new RequestContext for the given request, using the request attributes for Errors retrieval.
|
||||
* <p>This only works with InternalResourceViews, as Errors instances are part of the model and not
|
||||
* normally exposed as request attributes. It will typically be used within JSPs or custom tags.
|
||||
* <p><b>Will only work within a DispatcherServlet request.</b>
|
||||
* Pass in a ServletContext to be able to fallback to the root WebApplicationContext.
|
||||
* @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 response current HTTP response
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RequestContext for the given request, using the request attributes for Errors retrieval.
|
||||
* <p>This only works with InternalResourceViews, as Errors instances are part of the model and not
|
||||
* normally exposed as request attributes. It will typically be used within JSPs or custom tags.
|
||||
* <p>If a ServletContext is specified, the RequestContext will also work with the root
|
||||
* WebApplicationContext (outside a DispatcherServlet).
|
||||
* @param request current HTTP request
|
||||
* @param servletContext the servlet context of the web application (can be {@code null};
|
||||
* necessary for fallback to root WebApplicationContext)
|
||||
* @see org.springframework.web.context.WebApplicationContext
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
*/
|
||||
|
@ -142,13 +168,13 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new RequestContext for the given request, using the given model attributes for Errors retrieval. <p>This
|
||||
* works with all View implementations. It will typically be used by View implementations. <p><b>Will only work
|
||||
* within a DispatcherServlet request.</b> Pass in a ServletContext to be able to fallback to the root
|
||||
* WebApplicationContext.
|
||||
* Create a new RequestContext for the given request, using the given model attributes for Errors retrieval.
|
||||
* <p>This works with all View implementations. It will typically be used by View implementations.
|
||||
* <p><b>Will only work within a DispatcherServlet request.</b>
|
||||
* Pass in a ServletContext to be able to fallback to the root WebApplicationContext.
|
||||
* @param request current HTTP request
|
||||
* @param model the model attributes for the current view (can be {@code null}, using the request attributes
|
||||
* for Errors retrieval)
|
||||
* @param model the model attributes for the current view (can be {@code null},
|
||||
* using the request attributes for Errors retrieval)
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, Map)
|
||||
*/
|
||||
|
@ -157,9 +183,10 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new RequestContext for the given request, using the given model attributes for Errors retrieval. <p>This
|
||||
* works with all View implementations. It will typically be used by View implementations. <p>If a ServletContext is
|
||||
* specified, the RequestContext will also work with a root WebApplicationContext (outside a DispatcherServlet).
|
||||
* Create a new RequestContext for the given request, using the given model attributes for Errors retrieval.
|
||||
* <p>This works with all View implementations. It will typically be used by View implementations.
|
||||
* <p>If a ServletContext is specified, the RequestContext will also work with a root
|
||||
* WebApplicationContext (outside a DispatcherServlet).
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @param servletContext the servlet context of the web application (can be {@code null}; necessary for
|
||||
|
@ -212,14 +239,25 @@ public class RequestContext {
|
|||
|
||||
// Determine locale to use for this RequestContext.
|
||||
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
|
||||
if (localeResolver != null) {
|
||||
if (localeResolver instanceof LocaleContextResolver) {
|
||||
LocaleContext localeContext = ((LocaleContextResolver) localeResolver).resolveLocaleContext(request);
|
||||
this.locale = localeContext.getLocale();
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
this.timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
}
|
||||
}
|
||||
else if (localeResolver != null) {
|
||||
// Try LocaleResolver (we're within a DispatcherServlet request).
|
||||
this.locale = localeResolver.resolveLocale(request);
|
||||
}
|
||||
else {
|
||||
// No LocaleResolver available -> try fallback.
|
||||
|
||||
// Try JSTL fallbacks if necessary.
|
||||
if (this.locale == null) {
|
||||
this.locale = getFallbackLocale();
|
||||
}
|
||||
if (this.timeZone == null) {
|
||||
this.timeZone = getFallbackTimeZone();
|
||||
}
|
||||
|
||||
// Determine default HTML escape setting from the "defaultHtmlEscape"
|
||||
// context-param in web.xml, if any.
|
||||
|
@ -235,9 +273,8 @@ 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()}.
|
||||
* <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()
|
||||
*/
|
||||
|
@ -251,6 +288,22 @@ public class RequestContext {
|
|||
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)
|
||||
*/
|
||||
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").
|
||||
|
@ -306,17 +359,65 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the current Locale (never {@code null}).
|
||||
* Return the current Locale (falling back to the request locale; never {@code null}).
|
||||
* <p>Typically coming from a DispatcherServlet's {@link LocaleResolver}.
|
||||
* Also includes a fallback check for JSTL's Locale attribute.
|
||||
* @see RequestContextUtils#getLocale
|
||||
*/
|
||||
public final Locale getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current TimeZone (or {@code null} if none derivable from the request).
|
||||
* <p>Typically coming from a DispatcherServlet's {@link LocaleContextResolver}.
|
||||
* Also includes a fallback check for JSTL's TimeZone attribute.
|
||||
* @see RequestContextUtils#getTimeZone
|
||||
*/
|
||||
public TimeZone getTimeZone() {
|
||||
return this.timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current locale to the specified one,
|
||||
* storing the new locale through the configured {@link LocaleResolver}.
|
||||
* @param locale the new locale
|
||||
* @see LocaleResolver#setLocale
|
||||
* @see #changeLocale(java.util.Locale, java.util.TimeZone)
|
||||
*/
|
||||
public void changeLocale(Locale locale) {
|
||||
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request);
|
||||
if (localeResolver == null) {
|
||||
throw new IllegalStateException("Cannot change locale if no LocaleResolver configured");
|
||||
}
|
||||
localeResolver.setLocale(this.request, this.response, locale);
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current locale to the specified locale and time zone context,
|
||||
* storing the new locale context through the configured {@link LocaleResolver}.
|
||||
* @param locale the new locale
|
||||
* @param timeZone the new time zone
|
||||
* @see LocaleContextResolver#setLocaleContext
|
||||
* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
public void changeLocale(Locale locale, TimeZone timeZone) {
|
||||
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request);
|
||||
if (!(localeResolver instanceof LocaleContextResolver)) {
|
||||
throw new IllegalStateException("Cannot change locale context if no LocaleContextResolver configured");
|
||||
}
|
||||
((LocaleContextResolver) localeResolver).setLocaleContext(this.request, this.response,
|
||||
new SimpleTimeZoneAwareLocaleContext(locale, timeZone));
|
||||
this.locale = locale;
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current theme (never {@code null}).
|
||||
* <p>Resolved lazily for more efficiency when theme support is not being used.
|
||||
*/
|
||||
public final Theme getTheme() {
|
||||
public Theme getTheme() {
|
||||
if (this.theme == null) {
|
||||
// Lazily determine theme to use for this RequestContext.
|
||||
this.theme = RequestContextUtils.getTheme(this.request);
|
||||
|
@ -329,8 +430,39 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* (De)activate default HTML escaping for messages and errors, for the scope of this RequestContext. The default is
|
||||
* the application-wide setting (the "defaultHtmlEscape" context-param in web.xml).
|
||||
* Change the current theme to the specified one,
|
||||
* storing the new theme name through the configured {@link ThemeResolver}.
|
||||
* @param theme the new theme
|
||||
* @see ThemeResolver#setThemeName
|
||||
*/
|
||||
public void changeTheme(Theme theme) {
|
||||
ThemeResolver themeResolver = RequestContextUtils.getThemeResolver(this.request);
|
||||
if (themeResolver == null) {
|
||||
throw new IllegalStateException("Cannot change theme if no ThemeResolver configured");
|
||||
}
|
||||
themeResolver.setThemeName(this.request, this.response, (theme != null ? theme.getName() : null));
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current theme to the specified theme by name,
|
||||
* storing the new theme name through the configured {@link ThemeResolver}.
|
||||
* @param themeName the name of the new theme
|
||||
* @see ThemeResolver#setThemeName
|
||||
*/
|
||||
public void changeTheme(String themeName) {
|
||||
ThemeResolver themeResolver = RequestContextUtils.getThemeResolver(this.request);
|
||||
if (themeResolver == null) {
|
||||
throw new IllegalStateException("Cannot change theme if no ThemeResolver configured");
|
||||
}
|
||||
themeResolver.setThemeName(this.request, this.response, themeName);
|
||||
// Ask for re-resolution on next getTheme call.
|
||||
this.theme = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* (De)activate default HTML escaping for messages and errors, for the scope of this RequestContext.
|
||||
* <p>The default is the application-wide setting (the "defaultHtmlEscape" context-param in web.xml).
|
||||
* @see org.springframework.web.util.WebUtils#isDefaultHtmlEscape
|
||||
*/
|
||||
public void setDefaultHtmlEscape(boolean defaultHtmlEscape) {
|
||||
|
@ -353,8 +485,8 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the UrlPathHelper to use for context path and request URI decoding. Can be used to pass a shared
|
||||
* UrlPathHelper instance in.
|
||||
* Set the UrlPathHelper to use for context path and request URI decoding.
|
||||
* Can be used to pass a shared UrlPathHelper instance in.
|
||||
* <p>A default UrlPathHelper is always available.
|
||||
*/
|
||||
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
|
||||
|
@ -363,8 +495,8 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the UrlPathHelper used for context path and request URI decoding. Can be used to configure the current
|
||||
* UrlPathHelper.
|
||||
* Return the UrlPathHelper used for context path and request URI decoding.
|
||||
* Can be used to configure the current UrlPathHelper.
|
||||
* <p>A default UrlPathHelper is always available.
|
||||
*/
|
||||
public UrlPathHelper getUrlPathHelper() {
|
||||
|
@ -381,8 +513,9 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the context path of the original request, that is, the path that indicates the current web application.
|
||||
* This is useful for building links to other resources within the application.
|
||||
* Return the context path of the original request, that is, the path that
|
||||
* indicates the current web application. This is useful for building links
|
||||
* to other resources within the application.
|
||||
* <p>Delegates to the UrlPathHelper for decoding.
|
||||
* @see javax.servlet.http.HttpServletRequest#getContextPath
|
||||
* @see #getUrlPathHelper
|
||||
|
@ -408,7 +541,6 @@ public class RequestContext {
|
|||
* Return a context-aware URl for the given relative URL with placeholders (named keys with braces {@code {}}).
|
||||
* For example, send in a relative URL {@code foo/{bar}?spam={spam}} and a parameter map
|
||||
* {@code {bar=baz,spam=nuts}} and the result will be {@code [contextpath]/foo/baz?spam=nuts}.
|
||||
*
|
||||
* @param relativeUrl the relative URL part
|
||||
* @param params a map of parameters to insert as placeholders in the url
|
||||
* @return a URL that points back to the server with an absolute path (also URL-encoded accordingly)
|
||||
|
@ -439,10 +571,9 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the request URI of the original request, that is, the invoked URL without parameters. This is particularly
|
||||
* useful as HTML form action target, possibly in combination with the original query string. <p><b>Note this
|
||||
* implementation will correctly resolve to the URI of any originating root request in the presence of a forwarded
|
||||
* request. However, this can only work when the Servlet 2.4 'forward' request attributes are present.
|
||||
* Return the request URI of the original request, that is, the invoked URL
|
||||
* without parameters. This is particularly useful as HTML form action target,
|
||||
* possibly in combination with the original query string.
|
||||
* <p>Delegates to the UrlPathHelper for decoding.
|
||||
* @see #getQueryString
|
||||
* @see org.springframework.web.util.UrlPathHelper#getOriginatingRequestUri
|
||||
|
@ -453,10 +584,9 @@ public class RequestContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the query string of the current request, that is, the part after the request path. This is particularly
|
||||
* useful for building an HTML form action target in combination with the original request URI. <p><b>Note this
|
||||
* implementation will correctly resolve to the query string of any originating root request in the presence of a
|
||||
* forwarded request. However, this can only work when the Servlet 2.4 'forward' request attributes are present.
|
||||
* Return the query string of the current request, that is, the part after
|
||||
* the request path. This is particularly useful for building an HTML form
|
||||
* action target in combination with the original request URI.
|
||||
* <p>Delegates to the UrlPathHelper for decoding.
|
||||
* @see #getRequestUri
|
||||
* @see org.springframework.web.util.UrlPathHelper#getOriginatingQueryString
|
||||
|
@ -768,6 +898,20 @@ public class RequestContext {
|
|||
}
|
||||
return (localeObject instanceof Locale ? (Locale) localeObject : null);
|
||||
}
|
||||
|
||||
public static TimeZone getJstlTimeZone(HttpServletRequest request, ServletContext servletContext) {
|
||||
Object timeZoneObject = Config.get(request, Config.FMT_TIME_ZONE);
|
||||
if (timeZoneObject == null) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
timeZoneObject = Config.get(session, Config.FMT_TIME_ZONE);
|
||||
}
|
||||
if (timeZoneObject == null && servletContext != null) {
|
||||
timeZoneObject = Config.get(servletContext, Config.FMT_TIME_ZONE);
|
||||
}
|
||||
}
|
||||
return (timeZoneObject instanceof TimeZone ? (TimeZone) timeZoneObject : null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -18,11 +18,13 @@ package org.springframework.web.servlet.support;
|
|||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.ui.context.Theme;
|
||||
import org.springframework.ui.context.ThemeSource;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
@ -30,6 +32,7 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
|
|||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
import org.springframework.web.servlet.LocaleContextResolver;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
|
||||
|
@ -98,23 +101,51 @@ public abstract class RequestContextUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current locale from the given request,
|
||||
* using the LocaleResolver bound to the request by the DispatcherServlet
|
||||
* Retrieve the current locale from the given request, using the
|
||||
* LocaleResolver bound to the request by the DispatcherServlet
|
||||
* (if available), falling back to the request's accept-header Locale.
|
||||
* <p>This method serves as a straightforward alternative to the standard
|
||||
* Servlet {@link javax.servlet.http.HttpServletRequest#getLocale()} method,
|
||||
* falling back to the latter if no more specific locale has been found.
|
||||
* <p>Consider using {@link org.springframework.context.i18n.LocaleContextHolder#getLocale()}
|
||||
* which will normally be populated with the same Locale.
|
||||
* @param request current HTTP request
|
||||
* @return the current locale, either from the LocaleResolver or from
|
||||
* the plain request
|
||||
* @return the current locale for the given request, either from the
|
||||
* LocaleResolver or from the plain request itself
|
||||
* @see #getLocaleResolver
|
||||
* @see javax.servlet.http.HttpServletRequest#getLocale()
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#getLocale()
|
||||
*/
|
||||
public static Locale getLocale(HttpServletRequest request) {
|
||||
LocaleResolver localeResolver = getLocaleResolver(request);
|
||||
if (localeResolver != null) {
|
||||
return localeResolver.resolveLocale(request);
|
||||
}
|
||||
else {
|
||||
return request.getLocale();
|
||||
return (localeResolver != null ? localeResolver.resolveLocale(request) : request.getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current time zone from the given request, using the
|
||||
* TimeZoneAwareLocaleResolver bound to the request by the DispatcherServlet
|
||||
* (if available), falling back to the system's default time zone.
|
||||
* <p>Note: This method returns {@code null} if no specific time zone can be
|
||||
* resolved for the given request. This is in contrast to {@link #getLocale}
|
||||
* where there is always the request's accept-header locale to fall back to.
|
||||
* <p>Consider using {@link org.springframework.context.i18n.LocaleContextHolder#getTimeZone()}
|
||||
* which will normally be populated with the same TimeZone: That method only
|
||||
* differs in terms of its fallback to the system time zone if the LocaleResolver
|
||||
* hasn't provided provided a specific time zone (instead of this method's {@code null}).
|
||||
* @param request current HTTP request
|
||||
* @return the current time zone for the given request, either from the
|
||||
* TimeZoneAwareLocaleResolver or {@code null} if none associated
|
||||
* @see #getLocaleResolver
|
||||
* @see org.springframework.context.i18n.LocaleContextHolder#getTimeZone()
|
||||
*/
|
||||
public static TimeZone getTimeZone(HttpServletRequest request) {
|
||||
LocaleResolver localeResolver = getLocaleResolver(request);
|
||||
if (localeResolver instanceof LocaleContextResolver) {
|
||||
LocaleContext localeContext = ((LocaleContextResolver) localeResolver).resolveLocaleContext(request);
|
||||
if (localeContext instanceof TimeZoneAwareLocaleContext) {
|
||||
return ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
@ -24,8 +24,10 @@ import java.sql.SQLException;
|
|||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.sql.DataSource;
|
||||
|
@ -580,14 +582,19 @@ public abstract class AbstractJasperReportsView extends AbstractUrlBasedView {
|
|||
*/
|
||||
protected void exposeLocalizationContext(Map<String, Object> model, HttpServletRequest request) {
|
||||
RequestContext rc = new RequestContext(request, getServletContext());
|
||||
Locale locale = rc.getLocale();
|
||||
if (!model.containsKey(JRParameter.REPORT_LOCALE)) {
|
||||
model.put(JRParameter.REPORT_LOCALE, rc.getLocale());
|
||||
model.put(JRParameter.REPORT_LOCALE, locale);
|
||||
}
|
||||
TimeZone timeZone = rc.getTimeZone();
|
||||
if (timeZone != null && !model.containsKey(JRParameter.REPORT_TIME_ZONE)) {
|
||||
model.put(JRParameter.REPORT_TIME_ZONE, timeZone);
|
||||
}
|
||||
JasperReport report = getReport();
|
||||
if ((report == null || report.getResourceBundle() == null) &&
|
||||
!model.containsKey(JRParameter.REPORT_RESOURCE_BUNDLE)) {
|
||||
model.put(JRParameter.REPORT_RESOURCE_BUNDLE,
|
||||
new MessageSourceResourceBundle(rc.getMessageSource(), rc.getLocale()));
|
||||
new MessageSourceResourceBundle(rc.getMessageSource(), locale));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.view.velocity;
|
|||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -408,12 +409,11 @@ public class VelocityView extends AbstractTemplateView {
|
|||
|
||||
// Expose locale-aware DateTool/NumberTool attributes.
|
||||
if (this.dateToolAttribute != null || this.numberToolAttribute != null) {
|
||||
Locale locale = RequestContextUtils.getLocale(request);
|
||||
if (this.dateToolAttribute != null) {
|
||||
velocityContext.put(this.dateToolAttribute, new LocaleAwareDateTool(locale));
|
||||
velocityContext.put(this.dateToolAttribute, new LocaleAwareDateTool(request));
|
||||
}
|
||||
if (this.numberToolAttribute != null) {
|
||||
velocityContext.put(this.numberToolAttribute, new LocaleAwareNumberTool(locale));
|
||||
velocityContext.put(this.numberToolAttribute, new LocaleAwareNumberTool(request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -528,41 +528,48 @@ public class VelocityView extends AbstractTemplateView {
|
|||
|
||||
|
||||
/**
|
||||
* Subclass of DateTool from Velocity Tools, using a passed-in Locale
|
||||
* (usually the RequestContext Locale) instead of the default Locale.N
|
||||
* Subclass of DateTool from Velocity Tools, using a Spring-resolved
|
||||
* Locale and TimeZone instead of the default Locale.
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
private static class LocaleAwareDateTool extends DateTool {
|
||||
|
||||
private final Locale locale;
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private LocaleAwareDateTool(Locale locale) {
|
||||
this.locale = locale;
|
||||
public LocaleAwareDateTool(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
return RequestContextUtils.getLocale(this.request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
TimeZone timeZone = RequestContextUtils.getTimeZone(this.request);
|
||||
return (timeZone != null ? timeZone : super.getTimeZone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of NumberTool from Velocity Tools, using a passed-in Locale
|
||||
* (usually the RequestContext Locale) instead of the default Locale.
|
||||
* Subclass of NumberTool from Velocity Tools, using a Spring-resolved
|
||||
* Locale instead of the default Locale.
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
*/
|
||||
private static class LocaleAwareNumberTool extends NumberTool {
|
||||
|
||||
private final Locale locale;
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private LocaleAwareNumberTool(Locale locale) {
|
||||
this.locale = locale;
|
||||
public LocaleAwareNumberTool(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
return RequestContextUtils.getLocale(this.request);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -60,6 +61,7 @@ import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
|||
import org.springframework.web.servlet.mvc.Controller;
|
||||
import org.springframework.web.servlet.mvc.ParameterizableViewController;
|
||||
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
import org.springframework.web.servlet.theme.SessionThemeResolver;
|
||||
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
|
||||
|
@ -402,21 +404,6 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
|
|||
if (!(request instanceof MultipartHttpServletRequest)) {
|
||||
throw new ServletException("Not in a MultipartHttpServletRequest");
|
||||
}
|
||||
if (!(RequestContextUtils.getLocaleResolver(request) instanceof SessionLocaleResolver)) {
|
||||
throw new ServletException("Incorrect LocaleResolver");
|
||||
}
|
||||
if (!Locale.CANADA.equals(RequestContextUtils.getLocale(request))) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (!Locale.CANADA.equals(LocaleContextHolder.getLocale())) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (!(RequestContextUtils.getThemeResolver(request) instanceof SessionThemeResolver)) {
|
||||
throw new ServletException("Incorrect ThemeResolver");
|
||||
}
|
||||
if (!"theme".equals(RequestContextUtils.getThemeResolver(request).resolveThemeName(request))) {
|
||||
throw new ServletException("Incorrect theme name");
|
||||
}
|
||||
if (request.getParameter("fail") != null) {
|
||||
throw new ModelAndViewDefiningException(new ModelAndView("failed1"));
|
||||
}
|
||||
|
@ -429,6 +416,45 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
|
|||
if (request.getParameter("exception") != null) {
|
||||
throw new RuntimeException("servlet");
|
||||
}
|
||||
if (!(RequestContextUtils.getLocaleResolver(request) instanceof SessionLocaleResolver)) {
|
||||
throw new ServletException("Incorrect LocaleResolver");
|
||||
}
|
||||
if (!Locale.CANADA.equals(RequestContextUtils.getLocale(request))) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (!Locale.CANADA.equals(LocaleContextHolder.getLocale())) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (RequestContextUtils.getTimeZone(request) != null) {
|
||||
throw new ServletException("Incorrect TimeZone");
|
||||
}
|
||||
if (!TimeZone.getDefault().equals(LocaleContextHolder.getTimeZone())) {
|
||||
throw new ServletException("Incorrect TimeZone");
|
||||
}
|
||||
if (!(RequestContextUtils.getThemeResolver(request) instanceof SessionThemeResolver)) {
|
||||
throw new ServletException("Incorrect ThemeResolver");
|
||||
}
|
||||
if (!"theme".equals(RequestContextUtils.getThemeResolver(request).resolveThemeName(request))) {
|
||||
throw new ServletException("Incorrect theme name");
|
||||
}
|
||||
RequestContext rc = new RequestContext(request);
|
||||
rc.changeLocale(Locale.US, TimeZone.getTimeZone("GMT+1"));
|
||||
rc.changeTheme("theme2");
|
||||
if (!Locale.US.equals(RequestContextUtils.getLocale(request))) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (!Locale.US.equals(LocaleContextHolder.getLocale())) {
|
||||
throw new ServletException("Incorrect Locale");
|
||||
}
|
||||
if (!TimeZone.getTimeZone("GMT+1").equals(RequestContextUtils.getTimeZone(request))) {
|
||||
throw new ServletException("Incorrect TimeZone");
|
||||
}
|
||||
if (!TimeZone.getTimeZone("GMT+1").equals(LocaleContextHolder.getTimeZone())) {
|
||||
throw new ServletException("Incorrect TimeZone");
|
||||
}
|
||||
if (!"theme2".equals(RequestContextUtils.getThemeResolver(request).resolveThemeName(request))) {
|
||||
throw new ServletException("Incorrect theme name");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,25 +17,32 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
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 static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Alef Arendsen
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public class CookieLocaleResolverTests extends TestCase {
|
||||
public class CookieLocaleResolverTests {
|
||||
|
||||
@Test
|
||||
public void testResolveLocale() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
Cookie cookie = new Cookie("LanguageKoekje", "nl");
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
request.setCookies(cookie);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
// yup, koekje is the Dutch name for Cookie ;-)
|
||||
|
@ -44,6 +51,37 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
assertEquals(loc.getLanguage(), "nl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleContext() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
Cookie cookie = new Cookie("LanguageKoekje", "nl");
|
||||
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());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertNull(((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleContextWithTimeZone() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
Cookie cookie = new Cookie("LanguageKoekje", "nl GMT+1");
|
||||
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());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndResolveLocale() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -59,13 +97,74 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
assertFalse(cookie.getSecure());
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
request.setCookies(cookie);
|
||||
|
||||
resolver = new CookieLocaleResolver();
|
||||
Locale loc = resolver.resolveLocale(request);
|
||||
assertEquals(loc.getLanguage(), "nl");
|
||||
assertEquals("nl", loc.getLanguage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndResolveLocaleContext() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("nl", "")));
|
||||
|
||||
Cookie cookie = response.getCookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME);
|
||||
request = new MockHttpServletRequest();
|
||||
request.setCookies(cookie);
|
||||
|
||||
resolver = new CookieLocaleResolver();
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals("nl", loc.getLocale().getLanguage());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertNull(((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndResolveLocaleContextWithTimeZone() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setLocaleContext(request, response,
|
||||
new SimpleTimeZoneAwareLocaleContext(new Locale("nl", ""), TimeZone.getTimeZone("GMT+1")));
|
||||
|
||||
Cookie cookie = response.getCookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME);
|
||||
request = new MockHttpServletRequest();
|
||||
request.setCookies(cookie);
|
||||
|
||||
resolver = new CookieLocaleResolver();
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals("nl", loc.getLocale().getLanguage());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndResolveLocaleContextWithTimeZoneOnly() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setLocaleContext(request, response,
|
||||
new SimpleTimeZoneAwareLocaleContext(null, TimeZone.getTimeZone("GMT+1")));
|
||||
|
||||
Cookie cookie = response.getCookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME);
|
||||
request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.GERMANY);
|
||||
request.setCookies(cookie);
|
||||
|
||||
resolver = new CookieLocaleResolver();
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals(Locale.GERMANY, loc.getLocale());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomCookie() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -87,24 +186,39 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
assertTrue(cookie.getSecure());
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
request.setCookies(cookie);
|
||||
|
||||
resolver = new CookieLocaleResolver();
|
||||
resolver.setCookieName("LanguageKoek");
|
||||
Locale loc = resolver.resolveLocale(request);
|
||||
assertEquals(loc.getLanguage(), "nl");
|
||||
assertEquals("nl", loc.getLanguage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleWithoutCookie() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
||||
Locale locale = resolver.resolveLocale(request);
|
||||
assertEquals(request.getLocale(), locale);
|
||||
Locale loc = resolver.resolveLocale(request);
|
||||
assertEquals(request.getLocale(), loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleContextWithoutCookie() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals(request.getLocale(), loc.getLocale());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertNull(((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleWithoutCookieAndDefaultLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
@ -112,27 +226,59 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setDefaultLocale(Locale.GERMAN);
|
||||
|
||||
Locale locale = resolver.resolveLocale(request);
|
||||
assertEquals(Locale.GERMAN, locale);
|
||||
Locale loc = resolver.resolveLocale(request);
|
||||
assertEquals(Locale.GERMAN, loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleContextWithoutCookieAndDefaultLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setDefaultLocale(Locale.GERMAN);
|
||||
resolver.setDefaultTimeZone(TimeZone.getTimeZone("GMT+1"));
|
||||
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals(Locale.GERMAN, loc.getLocale());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(TimeZone.getTimeZone("GMT+1"), ((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleWithCookieWithoutLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, "");
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, "");
|
||||
request.setCookies(cookie);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
||||
Locale locale = resolver.resolveLocale(request);
|
||||
assertEquals(request.getLocale(), locale);
|
||||
Locale loc = resolver.resolveLocale(request);
|
||||
assertEquals(request.getLocale(), loc);
|
||||
}
|
||||
|
||||
public void testSetLocaleToNullLocale() throws Exception {
|
||||
@Test
|
||||
public void testResolveLocaleContextWithCookieWithoutLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, Locale.UK.toString());
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, "");
|
||||
request.setCookies(cookie);
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
||||
LocaleContext loc = resolver.resolveLocaleContext(request);
|
||||
assertEquals(request.getLocale(), loc.getLocale());
|
||||
assertTrue(loc instanceof TimeZoneAwareLocaleContext);
|
||||
assertNull(((TimeZoneAwareLocaleContext) loc).getTimeZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLocaleToNull() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString());
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
@ -143,15 +289,38 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
Cookie[] cookies = response.getCookies();
|
||||
assertEquals(1, cookies.length);
|
||||
Cookie localeCookie = cookies[0];
|
||||
assertEquals(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, localeCookie.getName());
|
||||
assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_NAME, localeCookie.getName());
|
||||
assertEquals("", localeCookie.getValue());
|
||||
}
|
||||
|
||||
public void testSetLocaleToNullLocaleWithDefault() throws Exception {
|
||||
@Test
|
||||
public void testSetLocaleContextToNull() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, Locale.UK.toString());
|
||||
request.setCookies(new Cookie[]{cookie});
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString());
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setLocaleContext(request, response, null);
|
||||
Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME);
|
||||
assertEquals(Locale.TAIWAN, locale);
|
||||
TimeZone timeZone = (TimeZone) request.getAttribute(CookieLocaleResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME);
|
||||
assertNull(timeZone);
|
||||
|
||||
Cookie[] cookies = response.getCookies();
|
||||
assertEquals(1, cookies.length);
|
||||
Cookie localeCookie = cookies[0];
|
||||
assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_NAME, localeCookie.getName());
|
||||
assertEquals("", localeCookie.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLocaleToNullWithDefault() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString());
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
|
@ -163,8 +332,32 @@ public class CookieLocaleResolverTests extends TestCase {
|
|||
Cookie[] cookies = response.getCookies();
|
||||
assertEquals(1, cookies.length);
|
||||
Cookie localeCookie = cookies[0];
|
||||
assertEquals(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, localeCookie.getName());
|
||||
assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_NAME, localeCookie.getName());
|
||||
assertEquals("", localeCookie.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLocaleContextToNullWithDefault() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString());
|
||||
request.setCookies(cookie);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
CookieLocaleResolver resolver = new CookieLocaleResolver();
|
||||
resolver.setDefaultLocale(Locale.CANADA_FRENCH);
|
||||
resolver.setDefaultTimeZone(TimeZone.getTimeZone("GMT+1"));
|
||||
resolver.setLocaleContext(request, response, null);
|
||||
Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME);
|
||||
assertEquals(Locale.CANADA_FRENCH, locale);
|
||||
TimeZone timeZone = (TimeZone) request.getAttribute(CookieLocaleResolver.TIME_ZONE_REQUEST_ATTRIBUTE_NAME);
|
||||
assertEquals(TimeZone.getTimeZone("GMT+1"), timeZone);
|
||||
|
||||
Cookie[] cookies = response.getCookies();
|
||||
assertEquals(1, cookies.length);
|
||||
Cookie localeCookie = cookies[0];
|
||||
assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_NAME, localeCookie.getName());
|
||||
assertEquals("", localeCookie.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,26 +17,55 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
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.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.servlet.LocaleContextResolver;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 20.03.2003
|
||||
*/
|
||||
public class LocaleResolverTests extends TestCase {
|
||||
public class LocaleResolverTests {
|
||||
|
||||
private void internalTest(LocaleResolver localeResolver, boolean shouldSet) {
|
||||
@Test
|
||||
public void testAcceptHeaderLocaleResolver() {
|
||||
doTest(new AcceptHeaderLocaleResolver(), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixedLocaleResolver() {
|
||||
doTest(new FixedLocaleResolver(Locale.UK), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCookieLocaleResolver() {
|
||||
doTest(new CookieLocaleResolver(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionLocaleResolver() {
|
||||
doTest(new SessionLocaleResolver(), true);
|
||||
}
|
||||
|
||||
private void doTest(LocaleResolver localeResolver, boolean shouldSet) {
|
||||
// create mocks
|
||||
MockServletContext context = new MockServletContext();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(context);
|
||||
request.addPreferredLocale(Locale.UK);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
// check original locale
|
||||
Locale locale = localeResolver.resolveLocale(request);
|
||||
assertEquals(locale, Locale.UK);
|
||||
|
@ -50,21 +79,68 @@ public class LocaleResolverTests extends TestCase {
|
|||
assertEquals(locale, Locale.GERMANY);
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
if (shouldSet)
|
||||
if (shouldSet) {
|
||||
fail("should be able to set Locale");
|
||||
}
|
||||
}
|
||||
|
||||
// check LocaleContext
|
||||
if (localeResolver instanceof LocaleContextResolver) {
|
||||
LocaleContextResolver localeContextResolver = (LocaleContextResolver) localeResolver;
|
||||
LocaleContext localeContext = localeContextResolver.resolveLocaleContext(request);
|
||||
if (shouldSet) {
|
||||
assertEquals(localeContext.getLocale(), Locale.GERMANY);
|
||||
}
|
||||
else {
|
||||
assertEquals(localeContext.getLocale(), Locale.UK);
|
||||
}
|
||||
assertTrue(localeContext instanceof TimeZoneAwareLocaleContext);
|
||||
assertNull(((TimeZoneAwareLocaleContext) localeContext).getTimeZone());
|
||||
|
||||
if (localeContextResolver instanceof AbstractLocaleContextResolver) {
|
||||
((AbstractLocaleContextResolver) localeContextResolver).setDefaultTimeZone(TimeZone.getTimeZone("GMT+1"));
|
||||
assertEquals(((TimeZoneAwareLocaleContext) localeContext).getTimeZone(), TimeZone.getTimeZone("GMT+1"));
|
||||
}
|
||||
|
||||
try {
|
||||
localeContextResolver.setLocaleContext(request, response, new SimpleLocaleContext(Locale.US));
|
||||
if (!shouldSet) {
|
||||
fail("should not be able to set Locale");
|
||||
}
|
||||
localeContext = localeContextResolver.resolveLocaleContext(request);
|
||||
assertEquals(localeContext.getLocale(), Locale.US);
|
||||
if (localeContextResolver instanceof AbstractLocaleContextResolver) {
|
||||
assertEquals(((TimeZoneAwareLocaleContext) localeContext).getTimeZone(), TimeZone.getTimeZone("GMT+1"));
|
||||
}
|
||||
else {
|
||||
assertNull(((TimeZoneAwareLocaleContext) localeContext).getTimeZone());
|
||||
}
|
||||
|
||||
localeContextResolver.setLocaleContext(request, response,
|
||||
new SimpleTimeZoneAwareLocaleContext(Locale.GERMANY, TimeZone.getTimeZone("GMT+2")));
|
||||
localeContext = localeContextResolver.resolveLocaleContext(request);
|
||||
assertEquals(localeContext.getLocale(), Locale.GERMANY);
|
||||
assertTrue(localeContext instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(((TimeZoneAwareLocaleContext) localeContext).getTimeZone(), TimeZone.getTimeZone("GMT+2"));
|
||||
|
||||
localeContextResolver.setLocaleContext(request, response,
|
||||
new SimpleTimeZoneAwareLocaleContext(null, TimeZone.getTimeZone("GMT+3")));
|
||||
localeContext = localeContextResolver.resolveLocaleContext(request);
|
||||
assertEquals(localeContext.getLocale(), Locale.UK);
|
||||
assertTrue(localeContext instanceof TimeZoneAwareLocaleContext);
|
||||
assertEquals(((TimeZoneAwareLocaleContext) localeContext).getTimeZone(), TimeZone.getTimeZone("GMT+3"));
|
||||
|
||||
if (localeContextResolver instanceof AbstractLocaleContextResolver) {
|
||||
((AbstractLocaleContextResolver) localeContextResolver).setDefaultLocale(Locale.GERMANY);
|
||||
assertEquals(localeContext.getLocale(), Locale.GERMANY);
|
||||
}
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
if (shouldSet) {
|
||||
fail("should be able to set Locale");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testAcceptHeaderLocaleResolver() {
|
||||
internalTest(new AcceptHeaderLocaleResolver(), false);
|
||||
}
|
||||
|
||||
public void testCookieLocaleResolver() {
|
||||
internalTest(new CookieLocaleResolver(), true);
|
||||
}
|
||||
|
||||
public void testSessionLocaleResolver() {
|
||||
internalTest(new SessionLocaleResolver(), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -17,19 +17,21 @@
|
|||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class SessionLocaleResolverTests extends TestCase {
|
||||
public class SessionLocaleResolverTests {
|
||||
|
||||
@Test
|
||||
public void testResolveLocale() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.GERMAN);
|
||||
|
@ -38,6 +40,7 @@ public class SessionLocaleResolverTests extends TestCase {
|
|||
assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndResolveLocale() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -54,6 +57,7 @@ public class SessionLocaleResolverTests extends TestCase {
|
|||
assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleWithoutSession() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
@ -63,6 +67,7 @@ public class SessionLocaleResolverTests extends TestCase {
|
|||
assertEquals(request.getLocale(), resolver.resolveLocale(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveLocaleWithoutSessionAndDefaultLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
@ -73,6 +78,7 @@ public class SessionLocaleResolverTests extends TestCase {
|
|||
assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLocaleToNullLocale() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
|
|
@ -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.
|
||||
|
@ -20,7 +20,9 @@ import java.io.InputStream;
|
|||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Principal;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
@ -35,15 +37,15 @@ import org.springframework.web.context.request.ServletWebRequest;
|
|||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test fixture with {@link ServletRequestMethodArgumentResolver}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Nicholas Williams
|
||||
*/
|
||||
public class ServletRequestMethodArgumentResolverTests {
|
||||
|
||||
|
@ -60,7 +62,8 @@ public class ServletRequestMethodArgumentResolverTests {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
method = getClass().getMethod("supportedParams", ServletRequest.class, MultipartRequest.class,
|
||||
HttpSession.class, Principal.class, Locale.class, InputStream.class, Reader.class, WebRequest.class);
|
||||
HttpSession.class, Principal.class, Locale.class, InputStream.class, Reader.class,
|
||||
WebRequest.class, TimeZone.class, ZoneId.class);
|
||||
mavContainer = new ModelAndViewContainer();
|
||||
servletRequest = new MockHttpServletRequest();
|
||||
webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse());
|
||||
|
@ -121,6 +124,65 @@ public class ServletRequestMethodArgumentResolverTests {
|
|||
assertSame("Invalid result", locale, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void localeFromResolver() throws Exception {
|
||||
Locale locale = Locale.ENGLISH;
|
||||
servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE,
|
||||
new FixedLocaleResolver(locale));
|
||||
MethodParameter localeParameter = new MethodParameter(method, 4);
|
||||
|
||||
assertTrue("Locale not supported", resolver.supportsParameter(localeParameter));
|
||||
|
||||
Object result = resolver.resolveArgument(localeParameter, null, webRequest, null);
|
||||
assertSame("Invalid result", locale, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeZone() throws Exception {
|
||||
MethodParameter timeZoneParameter = new MethodParameter(method, 8);
|
||||
|
||||
assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter));
|
||||
|
||||
Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null);
|
||||
assertEquals("Invalid result", TimeZone.getDefault(), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeZoneFromResolver() throws Exception {
|
||||
TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
|
||||
servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE,
|
||||
new FixedLocaleResolver(Locale.US, timeZone));
|
||||
MethodParameter timeZoneParameter = new MethodParameter(method, 8);
|
||||
|
||||
assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter));
|
||||
|
||||
Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null);
|
||||
assertEquals("Invalid result", timeZone, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zoneId() throws Exception {
|
||||
MethodParameter zoneIdParameter = new MethodParameter(method, 9);
|
||||
|
||||
assertTrue("ZoneId not supported", resolver.supportsParameter(zoneIdParameter));
|
||||
|
||||
Object result = resolver.resolveArgument(zoneIdParameter, null, webRequest, null);
|
||||
assertEquals("Invalid result", ZoneId.systemDefault(), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zoneIdFromResolver() throws Exception {
|
||||
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
|
||||
servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE,
|
||||
new FixedLocaleResolver(Locale.US, timeZone));
|
||||
MethodParameter zoneIdParameter = new MethodParameter(method, 9);
|
||||
|
||||
assertTrue("ZoneId not supported", resolver.supportsParameter(zoneIdParameter));
|
||||
|
||||
Object result = resolver.resolveArgument(zoneIdParameter, null, webRequest, null);
|
||||
assertEquals("Invalid result", timeZone.toZoneId(), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStream() throws Exception {
|
||||
MethodParameter inputStreamParameter = new MethodParameter(method, 5);
|
||||
|
@ -151,6 +213,7 @@ public class ServletRequestMethodArgumentResolverTests {
|
|||
assertSame("Invalid result", webRequest, result);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void supportedParams(ServletRequest p0,
|
||||
MultipartRequest p1,
|
||||
HttpSession p2,
|
||||
|
@ -158,7 +221,9 @@ public class ServletRequestMethodArgumentResolverTests {
|
|||
Locale p4,
|
||||
InputStream p5,
|
||||
Reader p6,
|
||||
WebRequest p7) {
|
||||
WebRequest p7,
|
||||
TimeZone p8,
|
||||
ZoneId p9) {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue