Polishing

This commit is contained in:
Juergen Hoeller 2017-01-31 12:00:13 +01:00
parent 9243a14794
commit f84907a1fc
8 changed files with 88 additions and 80 deletions

View File

@ -45,6 +45,7 @@ public interface MultiValueMap<K, V> extends Map<K, List<V>> {
* Add all the values of the given list to the current list of values for the given key. * Add all the values of the given list to the current list of values for the given key.
* @param key they key * @param key they key
* @param values the values to be added * @param values the values to be added
* @since 5.0
*/ */
void addAll(K key, List<V> values); void addAll(K key, List<V> values);

View File

@ -23,23 +23,17 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertNull;
/** /**
* @author Arjen Poutsma * @author Arjen Poutsma
*/ */
public class LinkedMultiValueMapTests { public class LinkedMultiValueMapTests {
private LinkedMultiValueMap<String, String> map; private final LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
@Before
public void setUp() {
map = new LinkedMultiValueMap<>();
}
@Test @Test
public void add() { public void add() {

View File

@ -76,7 +76,7 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Hand written SpEL parser. Instances are reusable but are not thread-safe. * Hand-written SpEL parser. Instances are reusable but are not thread-safe.
* *
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
@ -162,7 +162,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} }
nextToken(); // elvis has left the building nextToken(); // elvis has left the building
SpelNodeImpl valueIfNull = eatExpression(); SpelNodeImpl valueIfNull = eatExpression();
if (valueIfNull==null) { if (valueIfNull == null) {
valueIfNull = new NullLiteral(toPos(t.startPos + 1, t.endPos + 1)); valueIfNull = new NullLiteral(toPos(t.startPos + 1, t.endPos + 1));
} }
return new Elvis(toPos(t), expr, valueIfNull); return new Elvis(toPos(t), expr, valueIfNull);
@ -364,7 +364,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
expr = maybeEatNonDottedNode(); expr = maybeEatNonDottedNode();
} }
if (expr==null) { if (expr == null) {
return false; return false;
} }
else { else {
@ -393,11 +393,10 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// )) // ))
// ; // ;
private SpelNodeImpl eatDottedNode() { private SpelNodeImpl eatDottedNode() {
Token t = nextToken();// it was a '.' or a '?.' Token t = nextToken(); // it was a '.' or a '?.'
boolean nullSafeNavigation = t.kind == TokenKind.SAFE_NAVI; boolean nullSafeNavigation = (t.kind == TokenKind.SAFE_NAVI);
if (maybeEatMethodOrProperty(nullSafeNavigation) || maybeEatFunctionOrVar() if (maybeEatMethodOrProperty(nullSafeNavigation) || maybeEatFunctionOrVar() ||
|| maybeEatProjection(nullSafeNavigation) maybeEatProjection(nullSafeNavigation) || maybeEatSelection(nullSafeNavigation)) {
|| maybeEatSelection(nullSafeNavigation)) {
return pop(); return pop();
} }
if (peekToken() == null) { if (peekToken() == null) {
@ -405,8 +404,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
raiseInternalException(t.startPos, SpelMessage.OOD); raiseInternalException(t.startPos, SpelMessage.OOD);
} }
else { else {
raiseInternalException(t.startPos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, raiseInternalException(t.startPos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, toString(peekToken()));
toString(peekToken()));
} }
return null; return null;
} }
@ -425,13 +423,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
Token functionOrVariableName = eatToken(TokenKind.IDENTIFIER); Token functionOrVariableName = eatToken(TokenKind.IDENTIFIER);
SpelNodeImpl[] args = maybeEatMethodArgs(); SpelNodeImpl[] args = maybeEatMethodArgs();
if (args == null) { if (args == null) {
push(new VariableReference(functionOrVariableName.data, toPos(t.startPos, push(new VariableReference(functionOrVariableName.data,
functionOrVariableName.endPos))); toPos(t.startPos, functionOrVariableName.endPos)));
return true; return true;
} }
push(new FunctionReference(functionOrVariableName.data, toPos(t.startPos, push(new FunctionReference(functionOrVariableName.data,
functionOrVariableName.endPos), args)); toPos(t.startPos, functionOrVariableName.endPos), args));
return true; return true;
} }
@ -448,7 +446,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) { private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) {
if (!peekToken(TokenKind.LPAREN)) { if (!peekToken(TokenKind.LPAREN)) {
throw new InternalParseException(new SpelParseException(this.expressionString,positionOf(peekToken()),SpelMessage.MISSING_CONSTRUCTOR_ARGS)); throw new InternalParseException(new SpelParseException(this.expressionString,
positionOf(peekToken()), SpelMessage.MISSING_CONSTRUCTOR_ARGS));
} }
consumeArguments(accumulatedArguments); consumeArguments(accumulatedArguments);
eatToken(TokenKind.RPAREN); eatToken(TokenKind.RPAREN);
@ -461,7 +460,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
int pos = peekToken().startPos; int pos = peekToken().startPos;
Token next; Token next;
do { do {
nextToken(); // consume ( (first time through) or comma (subsequent times) nextToken(); // consume (first time through) or comma (subsequent times)
Token t = peekToken(); Token t = peekToken();
if (t == null) { if (t == null) {
raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS);
@ -544,13 +543,15 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
SpelMessage.INVALID_BEAN_REFERENCE); SpelMessage.INVALID_BEAN_REFERENCE);
} }
BeanReference beanReference = null; BeanReference beanReference;
if (beanRefToken.getKind() == TokenKind.FACTORY_BEAN_REF) { if (beanRefToken.getKind() == TokenKind.FACTORY_BEAN_REF) {
String beanNameString = new StringBuilder().append(TokenKind.FACTORY_BEAN_REF.tokenChars).append(beanName).toString(); String beanNameString = new StringBuilder().
beanReference = new BeanReference(toPos(beanRefToken.startPos,beanNameToken.endPos),beanNameString); append(TokenKind.FACTORY_BEAN_REF.tokenChars).append(beanName).toString();
beanReference = new BeanReference(
toPos(beanRefToken.startPos, beanNameToken.endPos), beanNameString);
} }
else { else {
beanReference = new BeanReference(toPos(beanNameToken) ,beanName); beanReference = new BeanReference(toPos(beanNameToken), beanName);
} }
this.constructedNodes.push(beanReference); this.constructedNodes.push(beanReference);
return true; return true;
@ -561,14 +562,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatTypeReference() { private boolean maybeEatTypeReference() {
if (peekToken(TokenKind.IDENTIFIER)) { if (peekToken(TokenKind.IDENTIFIER)) {
Token typeName = peekToken(); Token typeName = peekToken();
if (!typeName.stringValue().equals("T")) { if (!"T".equals(typeName.stringValue())) {
return false; return false;
} }
// It looks like a type reference but is T being used as a map key? // It looks like a type reference but is T being used as a map key?
Token t = nextToken(); Token t = nextToken();
if (peekToken(TokenKind.RSQUARE)) { if (peekToken(TokenKind.RSQUARE)) {
// looks like 'T]' (T is map key) // looks like 'T]' (T is map key)
push(new PropertyOrFieldReference(false,t.data,toPos(t))); push(new PropertyOrFieldReference(false, t.data, toPos(t)));
return true; return true;
} }
eatToken(TokenKind.LPAREN); eatToken(TokenKind.LPAREN);
@ -581,7 +582,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
dims++; dims++;
} }
eatToken(TokenKind.RPAREN); eatToken(TokenKind.RPAREN);
this.constructedNodes.push(new TypeReference(toPos(typeName),node,dims)); this.constructedNodes.push(new TypeReference(toPos(typeName), node, dims));
return true; return true;
} }
return false; return false;
@ -590,7 +591,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatNullReference() { private boolean maybeEatNullReference() {
if (peekToken(TokenKind.IDENTIFIER)) { if (peekToken(TokenKind.IDENTIFIER)) {
Token nullToken = peekToken(); Token nullToken = peekToken();
if (!nullToken.stringValue().equalsIgnoreCase("null")) { if (!"null".equalsIgnoreCase(nullToken.stringValue())) {
return false; return false;
} }
nextToken(); nextToken();
@ -623,12 +624,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
Token closingCurly = peekToken(); Token closingCurly = peekToken();
if (peekToken(TokenKind.RCURLY, true)) { if (peekToken(TokenKind.RCURLY, true)) {
// empty list '{}' // empty list '{}'
expr = new InlineList(toPos(t.startPos,closingCurly.endPos)); expr = new InlineList(toPos(t.startPos, closingCurly.endPos));
} }
else if (peekToken(TokenKind.COLON,true)) { else if (peekToken(TokenKind.COLON, true)) {
closingCurly = eatToken(TokenKind.RCURLY); closingCurly = eatToken(TokenKind.RCURLY);
// empty map '{:}' // empty map '{:}'
expr = new InlineMap(toPos(t.startPos,closingCurly.endPos)); expr = new InlineMap(toPos(t.startPos, closingCurly.endPos));
} }
else { else {
SpelNodeImpl firstExpression = eatExpression(); SpelNodeImpl firstExpression = eatExpression();
@ -636,35 +637,37 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// '}' - end of list // '}' - end of list
// ',' - more expressions in this list // ',' - more expressions in this list
// ':' - this is a map! // ':' - this is a map!
if (peekToken(TokenKind.RCURLY)) { // list with one item in it
if (peekToken(TokenKind.RCURLY)) { // list with one item in it
List<SpelNodeImpl> listElements = new ArrayList<>(); List<SpelNodeImpl> listElements = new ArrayList<>();
listElements.add(firstExpression); listElements.add(firstExpression);
closingCurly = eatToken(TokenKind.RCURLY); closingCurly = eatToken(TokenKind.RCURLY);
expr = new InlineList(toPos(t.startPos,closingCurly.endPos),listElements.toArray(new SpelNodeImpl[listElements.size()])); expr = new InlineList(toPos(t.startPos, closingCurly.endPos),
listElements.toArray(new SpelNodeImpl[listElements.size()]));
} }
else if (peekToken(TokenKind.COMMA, true)) { // multi item list else if (peekToken(TokenKind.COMMA, true)) { // multi-item list
List<SpelNodeImpl> listElements = new ArrayList<>(); List<SpelNodeImpl> listElements = new ArrayList<>();
listElements.add(firstExpression); listElements.add(firstExpression);
do { do {
listElements.add(eatExpression()); listElements.add(eatExpression());
} }
while (peekToken(TokenKind.COMMA,true)); while (peekToken(TokenKind.COMMA, true));
closingCurly = eatToken(TokenKind.RCURLY); closingCurly = eatToken(TokenKind.RCURLY);
expr = new InlineList(toPos(t.startPos,closingCurly.endPos),listElements.toArray(new SpelNodeImpl[listElements.size()])); expr = new InlineList(toPos(t.startPos, closingCurly.endPos),
listElements.toArray(new SpelNodeImpl[listElements.size()]));
} }
else if (peekToken(TokenKind.COLON, true)) { // map! else if (peekToken(TokenKind.COLON, true)) { // map!
List<SpelNodeImpl> mapElements = new ArrayList<>(); List<SpelNodeImpl> mapElements = new ArrayList<>();
mapElements.add(firstExpression); mapElements.add(firstExpression);
mapElements.add(eatExpression()); mapElements.add(eatExpression());
while (peekToken(TokenKind.COMMA,true)) { while (peekToken(TokenKind.COMMA, true)) {
mapElements.add(eatExpression()); mapElements.add(eatExpression());
eatToken(TokenKind.COLON); eatToken(TokenKind.COLON);
mapElements.add(eatExpression()); mapElements.add(eatExpression());
} }
closingCurly = eatToken(TokenKind.RCURLY); closingCurly = eatToken(TokenKind.RCURLY);
expr = new InlineMap(toPos(t.startPos,closingCurly.endPos),mapElements.toArray(new SpelNodeImpl[mapElements.size()])); expr = new InlineMap(toPos(t.startPos, closingCurly.endPos),
mapElements.toArray(new SpelNodeImpl[mapElements.size()]));
} }
else { else {
raiseInternalException(t.startPos, SpelMessage.OOD); raiseInternalException(t.startPos, SpelMessage.OOD);
@ -718,7 +721,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
while (isValidQualifiedId(node)) { while (isValidQualifiedId(node)) {
nextToken(); nextToken();
if (node.kind != TokenKind.DOT) { if (node.kind != TokenKind.DOT) {
qualifiedIdPieces.add(new Identifier(node.stringValue(),toPos(node))); qualifiedIdPieces.add(new Identifier(node.stringValue(), toPos(node)));
} }
node = peekToken(); node = peekToken();
} }
@ -729,8 +732,10 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
raiseInternalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, raiseInternalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN,
"qualified ID", node.getKind().toString().toLowerCase()); "qualified ID", node.getKind().toString().toLowerCase());
} }
int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition()); int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(),
return new QualifiedIdentifier(pos, qualifiedIdPieces.toArray(new SpelNodeImpl[qualifiedIdPieces.size()])); qualifiedIdPieces.getLast().getEndPosition());
return new QualifiedIdentifier(pos,
qualifiedIdPieces.toArray(new SpelNodeImpl[qualifiedIdPieces.size()]));
} }
private boolean isValidQualifiedId(Token node) { private boolean isValidQualifiedId(Token node) {
@ -744,19 +749,22 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return (StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches()); return (StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches());
} }
// This is complicated due to the support for dollars in identifiers. Dollars are normally separate tokens but // This is complicated due to the support for dollars in identifiers.
// there we want to combine a series of identifiers and dollars into a single identifier // Dollars are normally separate tokens but there we want to combine
// a series of identifiers and dollars into a single identifier.
private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) { private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) {
if (peekToken(TokenKind.IDENTIFIER)) { if (peekToken(TokenKind.IDENTIFIER)) {
Token methodOrPropertyName = nextToken(); Token methodOrPropertyName = nextToken();
SpelNodeImpl[] args = maybeEatMethodArgs(); SpelNodeImpl[] args = maybeEatMethodArgs();
if (args==null) { if (args == null) {
// property // property
push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.data,toPos(methodOrPropertyName))); push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.data,
toPos(methodOrPropertyName)));
return true; return true;
} }
// methodreference // method reference
push(new MethodReference(nullSafeNavigation, methodOrPropertyName.data, toPos(methodOrPropertyName), args)); push(new MethodReference(nullSafeNavigation, methodOrPropertyName.data,
toPos(methodOrPropertyName), args));
// TODO what is the end position for a method reference? the name or the last arg? // TODO what is the end position for a method reference? the name or the last arg?
return true; return true;
} }
@ -771,7 +779,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// It looks like a constructor reference but is NEW being used as a map key? // It looks like a constructor reference but is NEW being used as a map key?
if (peekToken(TokenKind.RSQUARE)) { if (peekToken(TokenKind.RSQUARE)) {
// looks like 'NEW]' (so NEW used as map key) // looks like 'NEW]' (so NEW used as map key)
push(new PropertyOrFieldReference(false,newToken.data,toPos(newToken))); push(new PropertyOrFieldReference(false, newToken.data, toPos(newToken)));
return true; return true;
} }
SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId(); SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId();
@ -780,7 +788,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (peekToken(TokenKind.LSQUARE)) { if (peekToken(TokenKind.LSQUARE)) {
// array initializer // array initializer
List<SpelNodeImpl> dimensions = new ArrayList<>(); List<SpelNodeImpl> dimensions = new ArrayList<>();
while (peekToken(TokenKind.LSQUARE,true)) { while (peekToken(TokenKind.LSQUARE, true)) {
if (!peekToken(TokenKind.RSQUARE)) { if (!peekToken(TokenKind.RSQUARE)) {
dimensions.add(eatExpression()); dimensions.add(eatExpression());
} }
@ -792,7 +800,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (maybeEatInlineListOrMap()) { if (maybeEatInlineListOrMap()) {
nodes.add(pop()); nodes.add(pop());
} }
push(new ConstructorReference(toPos(newToken), dimensions.toArray(new SpelNodeImpl[dimensions.size()]), push(new ConstructorReference(toPos(newToken),
dimensions.toArray(new SpelNodeImpl[dimensions.size()]),
nodes.toArray(new SpelNodeImpl[nodes.size()]))); nodes.toArray(new SpelNodeImpl[nodes.size()])));
} }
else { else {
@ -915,7 +924,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} }
private boolean peekToken(TokenKind desiredTokenKind) { private boolean peekToken(TokenKind desiredTokenKind) {
return peekToken(desiredTokenKind,false); return peekToken(desiredTokenKind, false);
} }
private boolean peekToken(TokenKind desiredTokenKind, boolean consumeIfMatched) { private boolean peekToken(TokenKind desiredTokenKind, boolean consumeIfMatched) {
@ -931,9 +940,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} }
if (desiredTokenKind == TokenKind.IDENTIFIER) { if (desiredTokenKind == TokenKind.IDENTIFIER) {
// might be one of the textual forms of the operators (e.g. NE for != ) - in which case we can treat it as an identifier // Might be one of the textual forms of the operators (e.g. NE for != ) -
// The list is represented here: Tokenizer.alternativeOperatorNames and those ones are in order in the TokenKind enum // in which case we can treat it as an identifier. The list is represented here:
if (t.kind.ordinal() >= TokenKind.DIV.ordinal() && t.kind.ordinal() <= TokenKind.NOT.ordinal() && t.data != null) { // Tokenizer.alternativeOperatorNames and those ones are in order in the TokenKind enum.
if (t.kind.ordinal() >= TokenKind.DIV.ordinal() && t.kind.ordinal() <= TokenKind.NOT.ordinal() &&
t.data != null) {
// if t.data were null, we'd know it wasn't the textual form, it was the symbol form // if t.data were null, we'd know it wasn't the textual form, it was the symbol form
return true; return true;
} }
@ -1008,7 +1019,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} }
private void checkLeftOperand(Token token, SpelNodeImpl operandExpression) { private void checkLeftOperand(Token token, SpelNodeImpl operandExpression) {
if (operandExpression==null) { if (operandExpression == null) {
raiseInternalException(token.startPos, SpelMessage.LEFT_OPERAND_PROBLEM); raiseInternalException(token.startPos, SpelMessage.LEFT_OPERAND_PROBLEM);
} }
} }
@ -1019,10 +1030,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} }
} }
/**
* Compress the start and end of a token into a single int.
*/
private int toPos(Token t) { private int toPos(Token t) {
// Compress the start and end of a token into a single int
return (t.startPos<<16) + t.endPos; return (t.startPos<<16) + t.endPos;
} }

View File

@ -1333,8 +1333,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
*/ */
@Override @Override
public void add(String headerName, String headerValue) { public void add(String headerName, String headerValue) {
List<String> headerValues = List<String> headerValues = this.headers.computeIfAbsent(headerName, k -> new LinkedList<>());
this.headers.computeIfAbsent(headerName, k -> new LinkedList<>());
headerValues.add(headerValue); headerValues.add(headerValue);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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.
@ -23,10 +23,12 @@ import java.util.List;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
/** /**
* Wrapper for a {@link ClientHttpRequestFactory} that has support for {@link ClientHttpRequestInterceptor}s. * {@link ClientHttpRequestFactory} wrapper with support for {@link ClientHttpRequestInterceptor}s.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 3.1 * @since 3.1
* @see ClientHttpRequestFactory
* @see ClientHttpRequestInterceptor
*/ */
public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper { public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {
@ -45,6 +47,7 @@ public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequ
this.interceptors = (interceptors != null ? interceptors : Collections.emptyList()); this.interceptors = (interceptors != null ? interceptors : Collections.emptyList());
} }
@Override @Override
protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) { protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod); return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);

View File

@ -41,6 +41,7 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor; import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.context.support.ServletContextResourceLoader; import org.springframework.web.context.support.ServletContextResourceLoader;
import org.springframework.web.context.support.StandardServletEnvironment; import org.springframework.web.context.support.StandardServletEnvironment;
@ -78,8 +79,7 @@ import org.springframework.web.context.support.StandardServletEnvironment;
* @see #doPost * @see #doPost
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public abstract class HttpServletBean extends HttpServlet public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
implements EnvironmentCapable, EnvironmentAware {
/** Logger available to subclasses */ /** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
@ -128,7 +128,9 @@ public abstract class HttpServletBean extends HttpServlet
bw.setPropertyValues(pvs, true); bw.setPropertyValues(pvs, true);
} }
catch (BeansException ex) { catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); if (logger.isErrorEnabled()) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
}
throw ex; throw ex;
} }
@ -231,12 +233,12 @@ public abstract class HttpServletBean extends HttpServlet
public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
throws ServletException { throws ServletException {
Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ? Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty() ?
new HashSet<>(requiredProperties) : null; new HashSet<>(requiredProperties) : null);
Enumeration<String> en = config.getInitParameterNames(); Enumeration<String> paramNames = config.getInitParameterNames();
while (en.hasMoreElements()) { while (paramNames.hasMoreElements()) {
String property = en.nextElement(); String property = paramNames.nextElement();
Object value = config.getInitParameter(property); Object value = config.getInitParameter(property);
addPropertyValue(new PropertyValue(property, value)); addPropertyValue(new PropertyValue(property, value));
if (missingProps != null) { if (missingProps != null) {
@ -245,7 +247,7 @@ public abstract class HttpServletBean extends HttpServlet
} }
// Fail if we are still missing properties. // Fail if we are still missing properties.
if (missingProps != null && missingProps.size() > 0) { if (!CollectionUtils.isEmpty(missingProps)) {
throw new ServletException( throw new ServletException(
"Initialization from ServletConfig for servlet '" + config.getServletName() + "Initialization from ServletConfig for servlet '" + config.getServletName() +
"' failed; the following required properties were missing: " + "' failed; the following required properties were missing: " +

View File

@ -63,9 +63,9 @@ public class ResponseBodyEmitterReturnValueHandler implements AsyncHandlerMethod
public ResponseBodyEmitterReturnValueHandler(List<HttpMessageConverter<?>> messageConverters) { public ResponseBodyEmitterReturnValueHandler(List<HttpMessageConverter<?>> messageConverters) {
Assert.notEmpty(messageConverters, "'messageConverters' must not be empty"); Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty");
this.messageConverters = messageConverters; this.messageConverters = messageConverters;
this.adapterMap = new HashMap<>(3); this.adapterMap = new HashMap<>(4);
this.adapterMap.put(ResponseBodyEmitter.class, new SimpleResponseBodyEmitterAdapter()); this.adapterMap.put(ResponseBodyEmitter.class, new SimpleResponseBodyEmitterAdapter());
} }

View File

@ -71,12 +71,12 @@ public abstract class AbstractStandardUpgradeStrategy implements RequestUpgradeS
} }
protected final HttpServletRequest getHttpServletRequest(ServerHttpRequest request) { protected final HttpServletRequest getHttpServletRequest(ServerHttpRequest request) {
Assert.isTrue(request instanceof ServletServerHttpRequest, "ServletServerHttpRequest required"); Assert.isInstanceOf(ServletServerHttpRequest.class, request, "ServletServerHttpRequest required");
return ((ServletServerHttpRequest) request).getServletRequest(); return ((ServletServerHttpRequest) request).getServletRequest();
} }
protected final HttpServletResponse getHttpServletResponse(ServerHttpResponse response) { protected final HttpServletResponse getHttpServletResponse(ServerHttpResponse response) {
Assert.isTrue(response instanceof ServletServerHttpResponse, "ServletServerHttpResponse required"); Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required");
return ((ServletServerHttpResponse) response).getServletResponse(); return ((ServletServerHttpResponse) response).getServletResponse();
} }