Polishing

This commit is contained in:
Juergen Hoeller 2020-08-07 13:02:43 +02:00
parent 94eee6a32a
commit 8dd285f877
13 changed files with 68 additions and 61 deletions

View File

@ -96,8 +96,7 @@ import org.springframework.util.StringUtils;
* operating on pre-resolved bean definition metadata objects. * operating on pre-resolved bean definition metadata objects.
* *
* <p>Note that readers for specific bean definition formats are typically * <p>Note that readers for specific bean definition formats are typically
* implemented separately rather than as bean factory subclasses: * implemented separately rather than as bean factory subclasses: see for example
* see for example {@link PropertiesBeanDefinitionReader} and
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}. * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
* *
* <p>For an alternative implementation of the * <p>For an alternative implementation of the
@ -184,7 +183,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private volatile String[] frozenBeanDefinitionNames; private volatile String[] frozenBeanDefinitionNames;
/** Whether bean definition metadata may be cached for all beans. */ /** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen = false; private volatile boolean configurationFrozen;
/** /**
@ -355,12 +354,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
@Override @Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) throws BeansException { public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
Assert.notNull(requiredType, "Required type must not be null"); Assert.notNull(requiredType, "Required type must not be null");
return getBeanProvider(ResolvableType.forRawClass(requiredType)); return getBeanProvider(ResolvableType.forRawClass(requiredType));
} }
@SuppressWarnings("unchecked")
@Override @Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) { public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
return new BeanObjectProvider<T>() { return new BeanObjectProvider<T>() {
@ -390,12 +388,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public T getIfUnique() throws BeansException { public T getIfUnique() throws BeansException {
return resolveBean(requiredType, null, true); return resolveBean(requiredType, null, true);
} }
@SuppressWarnings("unchecked")
@Override @Override
public Stream<T> stream() { public Stream<T> stream() {
return Arrays.stream(getBeanNamesForTypedStream(requiredType)) return Arrays.stream(getBeanNamesForTypedStream(requiredType))
.map(name -> (T) getBean(name)) .map(name -> (T) getBean(name))
.filter(bean -> !(bean instanceof NullBean)); .filter(bean -> !(bean instanceof NullBean));
} }
@SuppressWarnings("unchecked")
@Override @Override
public Stream<T> orderedStream() { public Stream<T> orderedStream() {
String[] beanNames = getBeanNamesForTypedStream(requiredType); String[] beanNames = getBeanNamesForTypedStream(requiredType);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,8 +55,7 @@ public abstract class AbstractValueAdaptingCache implements Cache {
@Override @Override
@Nullable @Nullable
public ValueWrapper get(Object key) { public ValueWrapper get(Object key) {
Object value = lookup(key); return toValueWrapper(lookup(key));
return toValueWrapper(value);
} }
@Override @Override
@ -123,5 +122,4 @@ public abstract class AbstractValueAdaptingCache implements Cache {
return (storeValue != null ? new SimpleValueWrapper(fromStoreValue(storeValue)) : null); return (storeValue != null ? new SimpleValueWrapper(fromStoreValue(storeValue)) : null);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -52,7 +52,7 @@ public class FileUrlResource extends UrlResource implements WritableResource {
/** /**
* Create a new {@code FileUrlResource} based on the given URL object. * Create a new {@code FileUrlResource} based on the given URL object.
* <p>Note that this does not enforce "file" as URL protocol. If a protocol * <p>Note that this does not enforce "file" as URL protocol. If a protocol
* is known to be resolvable to a file, * is known to be resolvable to a file, it is acceptable for this purpose.
* @param url a URL * @param url a URL
* @see ResourceUtils#isFileURL(URL) * @see ResourceUtils#isFileURL(URL)
* @see #getFile() * @see #getFile()

View File

@ -428,7 +428,7 @@ public abstract class MimeTypeUtils {
private final Function<K, V> generator; private final Function<K, V> generator;
private volatile int size = 0; private volatile int size;
public ConcurrentLruCache(int maxSize, Function<K, V> generator) { public ConcurrentLruCache(int maxSize, Function<K, V> generator) {
Assert.isTrue(maxSize > 0, "LRU max size should be positive"); Assert.isTrue(maxSize > 0, "LRU max size should be positive");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -60,7 +60,7 @@ public class RSocketRequesterMethodArgumentResolver implements HandlerMethodArgu
return Mono.just(requester); return Mono.just(requester);
} }
else if (RSocket.class.isAssignableFrom(type)) { else if (RSocket.class.isAssignableFrom(type)) {
return Mono.just(requester.rsocket()); return Mono.justOrEmpty(requester.rsocket());
} }
else { else {
return Mono.error(new IllegalArgumentException("Unexpected parameter type: " + parameter)); return Mono.error(new IllegalArgumentException("Unexpected parameter type: " + parameter));

View File

@ -146,7 +146,8 @@ public class PersistenceExceptionTranslationInterceptor
else { else {
PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator; PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator;
if (translator == null) { if (translator == null) {
Assert.state(this.beanFactory != null, "Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory"); Assert.state(this.beanFactory != null,
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
translator = detectPersistenceExceptionTranslators(this.beanFactory); translator = detectPersistenceExceptionTranslators(this.beanFactory);
this.persistenceExceptionTranslator = translator; this.persistenceExceptionTranslator = translator;
} }
@ -157,16 +158,15 @@ public class PersistenceExceptionTranslationInterceptor
/** /**
* Detect all PersistenceExceptionTranslators in the given BeanFactory. * Detect all PersistenceExceptionTranslators in the given BeanFactory.
* @param beanFactory the ListableBeanFactory to obtaining all * @param bf the ListableBeanFactory to obtain PersistenceExceptionTranslators from
* PersistenceExceptionTranslators from
* @return a chained PersistenceExceptionTranslator, combining all * @return a chained PersistenceExceptionTranslator, combining all
* PersistenceExceptionTranslators found in the factory * PersistenceExceptionTranslators found in the given bean factory
* @see ChainedPersistenceExceptionTranslator * @see ChainedPersistenceExceptionTranslator
*/ */
protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory beanFactory) { protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory bf) {
// Find all translators, being careful not to activate FactoryBeans. // Find all translators, being careful not to activate FactoryBeans.
Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors( Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors(
beanFactory, PersistenceExceptionTranslator.class, false, false); bf, PersistenceExceptionTranslator.class, false, false);
ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator(); ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator();
for (PersistenceExceptionTranslator pet : pets.values()) { for (PersistenceExceptionTranslator pet : pets.values()) {
cpet.addDelegate(pet); cpet.addDelegate(pet);

View File

@ -49,7 +49,6 @@ import org.springframework.util.StringUtils;
* @see <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1"> * @see <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
* HTTP 1.1: Semantics and Content, section 3.1.1.1</a> * HTTP 1.1: Semantics and Content, section 3.1.1.1</a>
*/ */
@SuppressWarnings("deprecation")
public class MediaType extends MimeType implements Serializable { public class MediaType extends MimeType implements Serializable {
private static final long serialVersionUID = 2069937152339670231L; private static final long serialVersionUID = 2069937152339670231L;
@ -647,7 +646,7 @@ public class MediaType extends MimeType implements Serializable {
*/ */
public static List<MediaType> asMediaTypes(List<MimeType> mimeTypes) { public static List<MediaType> asMediaTypes(List<MimeType> mimeTypes) {
List<MediaType> mediaTypes = new ArrayList<>(mimeTypes.size()); List<MediaType> mediaTypes = new ArrayList<>(mimeTypes.size());
for(MimeType mimeType : mimeTypes) { for (MimeType mimeType : mimeTypes) {
mediaTypes.add(MediaType.asMediaType(mimeType)); mediaTypes.add(MediaType.asMediaType(mimeType));
} }
return mediaTypes; return mediaTypes;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -64,7 +64,7 @@ public class WebExchangeDataBinder extends WebDataBinder {
/** /**
* Bind query params, form data, and or multipart form data to the binder target. * Bind query params, form data, and or multipart form data to the binder target.
* @param exchange the current exchange. * @param exchange the current exchange
* @return a {@code Mono<Void>} when binding is complete * @return a {@code Mono<Void>} when binding is complete
*/ */
public Mono<Void> bind(ServerWebExchange exchange) { public Mono<Void> bind(ServerWebExchange exchange) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -109,12 +109,12 @@ public class WebRequestDataBinder extends WebDataBinder {
*/ */
public void bind(WebRequest request) { public void bind(WebRequest request) {
MutablePropertyValues mpvs = new MutablePropertyValues(request.getParameterMap()); MutablePropertyValues mpvs = new MutablePropertyValues(request.getParameterMap());
if (isMultipartRequest(request) && request instanceof NativeWebRequest) { if (request instanceof NativeWebRequest) {
MultipartRequest multipartRequest = ((NativeWebRequest) request).getNativeRequest(MultipartRequest.class); MultipartRequest multipartRequest = ((NativeWebRequest) request).getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) { if (multipartRequest != null) {
bindMultipart(multipartRequest.getMultiFileMap(), mpvs); bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
} }
else { else if (isMultipartRequest(request)) {
HttpServletRequest servletRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class); HttpServletRequest servletRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class);
if (servletRequest != null) { if (servletRequest != null) {
bindParts(servletRequest, mpvs); bindParts(servletRequest, mpvs);
@ -130,7 +130,7 @@ public class WebRequestDataBinder extends WebDataBinder {
*/ */
private boolean isMultipartRequest(WebRequest request) { private boolean isMultipartRequest(WebRequest request) {
String contentType = request.getHeader("Content-Type"); String contentType = request.getHeader("Content-Type");
return StringUtils.startsWithIgnoreCase(contentType, "multipart"); return StringUtils.startsWithIgnoreCase(contentType, "multipart/");
} }
private void bindParts(HttpServletRequest request, MutablePropertyValues mpvs) { private void bindParts(HttpServletRequest request, MutablePropertyValues mpvs) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -85,7 +85,6 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueSyncAr
} }
@Override @Override
@SuppressWarnings("unchecked")
protected Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) { protected Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
String attributeName = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; String attributeName = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
return exchange.getAttributeOrDefault(attributeName, Collections.emptyMap()).get(name); return exchange.getAttributeOrDefault(attributeName, Collections.emptyMap()).get(name);
@ -97,7 +96,6 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueSyncAr
} }
@Override @Override
@SuppressWarnings("unchecked")
protected void handleResolvedValue( protected void handleResolvedValue(
@Nullable Object arg, String name, MethodParameter parameter, Model model, ServerWebExchange exchange) { @Nullable Object arg, String name, MethodParameter parameter, Model model, ServerWebExchange exchange) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -88,14 +88,23 @@ public class HandlerExecutionChain {
return this.handler; return this.handler;
} }
/**
* Add the given interceptor to the end of this chain.
*/
public void addInterceptor(HandlerInterceptor interceptor) { public void addInterceptor(HandlerInterceptor interceptor) {
initInterceptorList().add(interceptor); initInterceptorList().add(interceptor);
} }
/**
* Add the given interceptor at the specified index of this chain.
*/
public void addInterceptor(int index, HandlerInterceptor interceptor) { public void addInterceptor(int index, HandlerInterceptor interceptor) {
initInterceptorList().add(index, interceptor); initInterceptorList().add(index, interceptor);
} }
/**
* Add the given interceptors to the end of this chain.
*/
public void addInterceptors(HandlerInterceptor... interceptors) { public void addInterceptors(HandlerInterceptor... interceptors) {
if (!ObjectUtils.isEmpty(interceptors)) { if (!ObjectUtils.isEmpty(interceptors)) {
CollectionUtils.mergeArrayIntoCollection(interceptors, initInterceptorList()); CollectionUtils.mergeArrayIntoCollection(interceptors, initInterceptorList());
@ -192,13 +201,16 @@ public class HandlerExecutionChain {
HandlerInterceptor[] interceptors = getInterceptors(); HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) { if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) { for (int i = interceptors.length - 1; i >= 0; i--) {
if (interceptors[i] instanceof AsyncHandlerInterceptor) { HandlerInterceptor interceptor = interceptors[i];
if (interceptor instanceof AsyncHandlerInterceptor) {
try { try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i]; AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptor;
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler); asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
} }
catch (Throwable ex) { catch (Throwable ex) {
logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex); if (logger.isErrorEnabled()) {
logger.error("Interceptor [" + interceptor + "] failed in afterConcurrentHandlingStarted", ex);
}
} }
} }
} }

View File

@ -301,22 +301,22 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
} }
/** /**
* Detect beans of type {@link MappedInterceptor} and add them to the list of mapped interceptors. * Detect beans of type {@link MappedInterceptor} and add them to the list
* <p>This is called in addition to any {@link MappedInterceptor MappedInterceptors} that may have been provided * of mapped interceptors.
* via {@link #setInterceptors}, by default adding all beans of type {@link MappedInterceptor} * <p>This is called in addition to any {@link MappedInterceptor}s that may
* from the current context and its ancestors. Subclasses can override and refine this policy. * have been provided via {@link #setInterceptors}, by default adding all
* @param mappedInterceptors an empty list to add {@link MappedInterceptor} instances to * beans of type {@link MappedInterceptor} from the current context and its
* ancestors. Subclasses can override and refine this policy.
* @param mappedInterceptors an empty list to add to
*/ */
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) { protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll( mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
BeanFactoryUtils.beansOfTypeIncludingAncestors( obtainApplicationContext(), MappedInterceptor.class, true, false).values());
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
} }
/** /**
* Initialize the specified interceptors, checking for {@link MappedInterceptor MappedInterceptors} and * Initialize the specified interceptors adapting
* adapting {@link HandlerInterceptor}s and {@link WebRequestInterceptor HandlerInterceptor}s and * {@link WebRequestInterceptor}s to {@link HandlerInterceptor}.
* {@link WebRequestInterceptor}s if necessary.
* @see #setInterceptors * @see #setInterceptors
* @see #adaptInterceptor * @see #adaptInterceptor
*/ */
@ -333,13 +333,13 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
} }
/** /**
* Adapt the given interceptor object to the {@link HandlerInterceptor} interface. * Adapt the given interceptor object to {@link HandlerInterceptor}.
* <p>By default, the supported interceptor types are {@link HandlerInterceptor} * <p>By default, the supported interceptor types are
* and {@link WebRequestInterceptor}. Each given {@link WebRequestInterceptor} * {@link HandlerInterceptor} and {@link WebRequestInterceptor}. Each given
* will be wrapped in a {@link WebRequestHandlerInterceptorAdapter}. * {@link WebRequestInterceptor} is wrapped with
* Can be overridden in subclasses. * {@link WebRequestHandlerInterceptorAdapter}.
* @param interceptor the specified interceptor object * @param interceptor the interceptor
* @return the interceptor wrapped as HandlerInterceptor * @return the interceptor downcast or adapted to HandlerInterceptor
* @see org.springframework.web.servlet.HandlerInterceptor * @see org.springframework.web.servlet.HandlerInterceptor
* @see org.springframework.web.context.request.WebRequestInterceptor * @see org.springframework.web.context.request.WebRequestInterceptor
* @see WebRequestHandlerInterceptorAdapter * @see WebRequestHandlerInterceptorAdapter
@ -358,7 +358,8 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
/** /**
* Return the adapted interceptors as {@link HandlerInterceptor} array. * Return the adapted interceptors as {@link HandlerInterceptor} array.
* @return the array of {@link HandlerInterceptor HandlerInterceptors}, or {@code null} if none * @return the array of {@link HandlerInterceptor HandlerInterceptor}s,
* or {@code null} if none
*/ */
@Nullable @Nullable
protected final HandlerInterceptor[] getAdaptedInterceptors() { protected final HandlerInterceptor[] getAdaptedInterceptors() {
@ -367,8 +368,8 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
} }
/** /**
* Return all configured {@link MappedInterceptor MappedInterceptors} as an array. * Return all configured {@link MappedInterceptor}s as an array.
* @return the array of {@link MappedInterceptor MappedInterceptors}, or {@code null} if none * @return the array of {@link MappedInterceptor}s, or {@code null} if none
*/ */
@Nullable @Nullable
protected final MappedInterceptor[] getMappedInterceptors() { protected final MappedInterceptor[] getMappedInterceptors() {
@ -447,7 +448,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
* Build a {@link HandlerExecutionChain} for the given handler, including * Build a {@link HandlerExecutionChain} for the given handler, including
* applicable interceptors. * applicable interceptors.
* <p>The default implementation builds a standard {@link HandlerExecutionChain} * <p>The default implementation builds a standard {@link HandlerExecutionChain}
* with the given handler, the handler mapping's common interceptors, and any * with the given handler, the common interceptors of the handler mapping, and any
* {@link MappedInterceptor MappedInterceptors} matching to the current request URL. Interceptors * {@link MappedInterceptor MappedInterceptors} matching to the current request URL. Interceptors
* are added in the order they were registered. Subclasses may override this * are added in the order they were registered. Subclasses may override this
* in order to extend/rearrange the list of interceptors. * in order to extend/rearrange the list of interceptors.
@ -529,12 +530,12 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
if (CorsUtils.isPreFlightRequest(request)) { if (CorsUtils.isPreFlightRequest(request)) {
HandlerInterceptor[] interceptors = chain.getInterceptors(); HandlerInterceptor[] interceptors = chain.getInterceptors();
chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors); return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
} }
else { else {
chain.addInterceptor(0, new CorsInterceptor(config)); chain.addInterceptor(0, new CorsInterceptor(config));
return chain;
} }
return chain;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -335,7 +335,6 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
* @see #setDefaultLocale * @see #setDefaultLocale
* @see javax.servlet.http.HttpServletRequest#getLocale() * @see javax.servlet.http.HttpServletRequest#getLocale()
*/ */
@Nullable
protected Locale determineDefaultLocale(HttpServletRequest request) { protected Locale determineDefaultLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale(); Locale defaultLocale = getDefaultLocale();
if (defaultLocale == null) { if (defaultLocale == null) {