From d553ddc5b3a657adebad04d9f3c7d466fbdd7b05 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 29 Mar 2018 23:50:17 +0200 Subject: [PATCH] Nullability refinements (based on IntelliJ IDEA 2018.1 introspection) Issue: SPR-15756 --- .../org/springframework/beans/BeanUtils.java | 14 +++--- .../factory/wiring/BeanConfigurerSupport.java | 11 +++-- .../annotation/ConfigurationClassParser.java | 6 +-- .../ApplicationListenerMethodAdapter.java | 2 +- .../org/springframework/util/ClassUtils.java | 19 ++++---- .../ListenableFutureCallbackRegistry.java | 12 +++-- .../expression/spel/CodeFlow.java | 4 +- .../expression/spel/ExpressionState.java | 19 ++++---- .../expression/spel/ast/ValueRef.java | 8 ++-- .../AbstractListenerContainerParser.java | 15 +++--- .../mock/jndi/SimpleNamingContext.java | 3 +- .../junit/jupiter/ParameterAutowireUtils.java | 48 +++++++------------ .../http/codec/xml/Jaxb2XmlDecoder.java | 4 +- .../http/server/DefaultPathContainer.java | 2 +- .../reactive/UndertowServerHttpResponse.java | 15 +----- .../reactive/result/view/AbstractView.java | 4 +- .../result/view/ViewResolverSupport.java | 5 +- 17 files changed, 84 insertions(+), 107 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java index 5819471ee8..f9712f4af2 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -367,23 +367,23 @@ public abstract class BeanUtils { public static Method resolveSignature(String signature, Class clazz) { Assert.hasText(signature, "'signature' must not be empty"); Assert.notNull(clazz, "Class must not be null"); - int firstParen = signature.indexOf('('); - int lastParen = signature.indexOf(')'); - if (firstParen > -1 && lastParen == -1) { + int startParen = signature.indexOf('('); + int endParen = signature.indexOf(')'); + if (startParen > -1 && endParen == -1) { throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected closing ')' for args list"); } - else if (lastParen > -1 && firstParen == -1) { + else if (startParen == -1 && endParen > -1) { throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected opening '(' for args list"); } - else if (firstParen == -1 && lastParen == -1) { + else if (startParen == -1) { return findMethodWithMinimalParameters(clazz, signature); } else { - String methodName = signature.substring(0, firstParen); + String methodName = signature.substring(0, startParen); String[] parameterTypeNames = - StringUtils.commaDelimitedListToStringArray(signature.substring(firstParen + 1, lastParen)); + StringUtils.commaDelimitedListToStringArray(signature.substring(startParen + 1, endParen)); Class[] parameterTypes = new Class[parameterTypeNames.length]; for (int i = 0; i < parameterTypeNames.length; i++) { String parameterTypeName = parameterTypeNames[i].trim(); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/wiring/BeanConfigurerSupport.java b/spring-beans/src/main/java/org/springframework/beans/factory/wiring/BeanConfigurerSupport.java index 601b06b34a..22944cf04c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/wiring/BeanConfigurerSupport.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/wiring/BeanConfigurerSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -144,15 +144,16 @@ public class BeanConfigurerSupport implements BeanFactoryAware, InitializingBean ConfigurableListableBeanFactory beanFactory = this.beanFactory; Assert.state(beanFactory != null, "No BeanFactory available"); try { - if (bwi.indicatesAutowiring() || (bwi.isDefaultBeanName() && bwi.getBeanName() != null && - !beanFactory.containsBean(bwi.getBeanName()))) { + String beanName = bwi.getBeanName(); + if (bwi.indicatesAutowiring() || (bwi.isDefaultBeanName() && beanName != null && + !beanFactory.containsBean(beanName))) { // Perform autowiring (also applying standard factory / post-processor callbacks). beanFactory.autowireBeanProperties(beanInstance, bwi.getAutowireMode(), bwi.getDependencyCheck()); - beanFactory.initializeBean(beanInstance, bwi.getBeanName()); + beanFactory.initializeBean(beanInstance, (beanName != null ? beanName : "")); } else { // Perform explicit wiring based on the specified bean definition. - beanFactory.configureBean(beanInstance, bwi.getBeanName()); + beanFactory.configureBean(beanInstance, (beanName != null ? beanName : "")); } } catch (BeanCreationException ex) { diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index 71790901d9..2d3bb969dc 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -588,7 +588,7 @@ class ConfigurationClassParser { } private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, - Collection importCandidates, boolean checkForCircularImports) throws IOException { + Collection importCandidates, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; @@ -1033,9 +1033,9 @@ class ConfigurationClassParser { public CircularImportProblem(ConfigurationClass attemptedImport, Deque importStack) { super(String.format("A circular @Import has been detected: " + "Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " + - "already present in the current import stack %s", importStack.peek().getSimpleName(), + "already present in the current import stack %s", importStack.element().getSimpleName(), attemptedImport.getSimpleName(), attemptedImport.getSimpleName(), importStack), - new Location(importStack.peek().getResource(), attemptedImport.getMetadata())); + new Location(importStack.element().getResource(), attemptedImport.getMetadata())); } } diff --git a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java index 2d38c021b6..f0cb18e4df 100644 --- a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java +++ b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java @@ -366,7 +366,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe payloadType != null && declaredEventType.isAssignableFrom(payloadType)) { return declaredEventType; } - if (declaredEventType.getRawClass().isInstance(event)) { + if (eventClass != null && eventClass.isInstance(event)) { return declaredEventType; } } diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index c0023dacad..33bf4bbf3c 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -209,14 +209,6 @@ public abstract class ClassUtils { } } - /** - * Determine if the supplied class is an inner class. - * @return {@code true} if the supplied class is an inner class - */ - public static boolean isInnerClass(Class clazz) { - return clazz != null && clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers()); - } - /** * Replacement for {@code Class.forName()} that also returns Class instances * for primitives (e.g. "int") and array class names (e.g. "String[]"). @@ -383,6 +375,17 @@ public abstract class ClassUtils { return clazz; } + /** + * Determine if the supplied class is an inner class, + * i.e. a non-static member of an enclosing class. + * @return {@code true} if the supplied class is an inner class + * @since 5.0.5 + * @see Class#isMemberClass() + */ + public static boolean isInnerClass(Class clazz) { + return (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())); + } + /** * Check whether the given class is cache-safe in the given context, * i.e. whether it is loaded by the given ClassLoader or a parent of it. diff --git a/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java b/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java index 6f7aba4772..3c581db9e8 100644 --- a/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java +++ b/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -136,8 +136,9 @@ public class ListenableFutureCallbackRegistry { synchronized (this.mutex) { this.state = State.SUCCESS; this.result = result; - while (!this.successCallbacks.isEmpty()) { - notifySuccess(this.successCallbacks.poll()); + SuccessCallback callback; + while ((callback = this.successCallbacks.poll()) != null) { + notifySuccess(callback); } } } @@ -151,8 +152,9 @@ public class ListenableFutureCallbackRegistry { synchronized (this.mutex) { this.state = State.FAILURE; this.result = ex; - while (!this.failureCallbacks.isEmpty()) { - notifyFailure(this.failureCallbacks.poll()); + FailureCallback callback; + while ((callback = this.failureCallbacks.poll()) != null) { + notifyFailure(callback); } } } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java b/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java index 66b232c88d..934f15a05a 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java @@ -58,7 +58,7 @@ public class CodeFlow implements Opcodes { * sub-expressions like the expressions for the argument values in a method invocation * expression. */ - private final Deque> compilationScopes; + private final Deque> compilationScopes; /** * As SpEL ast nodes are called to generate code for the main evaluation method @@ -128,7 +128,7 @@ public class CodeFlow implements Opcodes { */ public void pushDescriptor(@Nullable String descriptor) { if (descriptor != null) { - this.compilationScopes.peek().add(descriptor); + this.compilationScopes.element().add(descriptor); } } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java b/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java index 3f244d4142..42f2e3d336 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java @@ -106,7 +106,7 @@ public class ExpressionState { if (CollectionUtils.isEmpty(this.contextObjects)) { return this.rootObject; } - return this.contextObjects.peek(); + return this.contextObjects.element(); } public void pushActiveContextObject(TypedValue obj) { @@ -136,7 +136,7 @@ public class ExpressionState { if (CollectionUtils.isEmpty(this.scopeRootObjects)) { return this.rootObject; } - return this.scopeRootObjects.peek(); + return this.scopeRootObjects.element(); } public void setVariable(String name, @Nullable Object value) { @@ -157,8 +157,8 @@ public class ExpressionState { } public Object convertValue(Object value, TypeDescriptor targetTypeDescriptor) throws EvaluationException { - Object result = this.relatedContext.getTypeConverter().convertValue(value, - TypeDescriptor.forObject(value), targetTypeDescriptor); + Object result = this.relatedContext.getTypeConverter().convertValue( + value, TypeDescriptor.forObject(value), targetTypeDescriptor); if (result == null) { throw new IllegalStateException("Null conversion result for value [" + value + "]"); } @@ -172,7 +172,8 @@ public class ExpressionState { @Nullable public Object convertValue(TypedValue value, TypeDescriptor targetTypeDescriptor) throws EvaluationException { Object val = value.getValue(); - return this.relatedContext.getTypeConverter().convertValue(val, TypeDescriptor.forObject(val), targetTypeDescriptor); + return this.relatedContext.getTypeConverter().convertValue( + val, TypeDescriptor.forObject(val), targetTypeDescriptor); } /* @@ -199,7 +200,7 @@ public class ExpressionState { } public void setLocalVariable(String name, Object value) { - initVariableScopes().peek().setVariable(name, value); + initVariableScopes().element().setVariable(name, value); } @Nullable @@ -212,16 +213,16 @@ public class ExpressionState { return null; } - private LinkedList initVariableScopes() { + private Deque initVariableScopes() { if (this.variableScopes == null) { this.variableScopes = new LinkedList<>(); - // top level empty variable scope + // top-level empty variable scope this.variableScopes.add(new VariableScope()); } return this.variableScopes; } - private ArrayDeque initScopeRootObjects() { + private Deque initScopeRootObjects() { if (this.scopeRootObjects == null) { this.scopeRootObjects = new ArrayDeque<>(); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ValueRef.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ValueRef.java index 85f47c4dfb..702f0e5c6a 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ValueRef.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ValueRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -58,7 +58,7 @@ public interface ValueRef { /** * A ValueRef for the null value. */ - static class NullValueRef implements ValueRef { + class NullValueRef implements ValueRef { static final NullValueRef INSTANCE = new NullValueRef(); @@ -85,13 +85,13 @@ public interface ValueRef { /** * A ValueRef holder for a single value, which cannot be set. */ - static class TypedValueHolderValueRef implements ValueRef { + class TypedValueHolderValueRef implements ValueRef { private final TypedValue typedValue; private final SpelNodeImpl node; // used only for error reporting - public TypedValueHolderValueRef(TypedValue typedValue,SpelNodeImpl node) { + public TypedValueHolderValueRef(TypedValue typedValue, SpelNodeImpl node) { this.typedValue = typedValue; this.node = node; } diff --git a/spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java b/spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java index db1388326a..7fc7767412 100644 --- a/spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java +++ b/spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -268,16 +268,13 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser { boolean replyPubSubDomain = false; String replyDestinationType = containerEle.getAttribute(RESPONSE_DESTINATION_TYPE_ATTRIBUTE); - if (DESTINATION_TYPE_TOPIC.equals(replyDestinationType)) { + if (!StringUtils.hasText(replyDestinationType)) { + replyPubSubDomain = pubSubDomain; // the default: same value as pubSubDomain + } + else if (DESTINATION_TYPE_TOPIC.equals(replyDestinationType)) { replyPubSubDomain = true; } - else if (DESTINATION_TYPE_QUEUE.equals(replyDestinationType)) { - replyPubSubDomain = false; - } - else if (!StringUtils.hasText(replyDestinationType)) { - replyPubSubDomain = pubSubDomain; // the default: same value as pubSubDomain - } - else if (StringUtils.hasText(replyDestinationType)) { + else if (!DESTINATION_TYPE_QUEUE.equals(replyDestinationType)) { parserContext.getReaderContext().error("Invalid listener container 'response-destination-type': only " + "\"queue\", \"topic\" supported.", containerEle); } diff --git a/spring-test/src/main/java/org/springframework/mock/jndi/SimpleNamingContext.java b/spring-test/src/main/java/org/springframework/mock/jndi/SimpleNamingContext.java index 841de69fa9..b2108b471f 100644 --- a/spring-test/src/main/java/org/springframework/mock/jndi/SimpleNamingContext.java +++ b/spring-test/src/main/java/org/springframework/mock/jndi/SimpleNamingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -209,6 +209,7 @@ public class SimpleNamingContext implements Context { } @Override + @Nullable public Object addToEnvironment(String propName, Object propVal) { return this.environment.put(propName, propVal); } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/ParameterAutowireUtils.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/ParameterAutowireUtils.java index 2c81b450b0..b6c9c101c1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/ParameterAutowireUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/ParameterAutowireUtils.java @@ -21,7 +21,6 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Parameter; -import java.util.Optional; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; @@ -41,23 +40,21 @@ import org.springframework.util.ClassUtils; * * @author Sam Brannen * @since 5.0 - * @see #isAutowirable(Parameter) - * @see #resolveDependency(Parameter, Class, ApplicationContext) + * @see #isAutowirable + * @see #resolveDependency */ abstract class ParameterAutowireUtils { private static final AnnotatedElement EMPTY_ANNOTATED_ELEMENT = new AnnotatedElement() { - @Override + @Nullable public T getAnnotation(Class annotationClass) { return null; } - @Override public Annotation[] getAnnotations() { return new Annotation[0]; } - @Override public Annotation[] getDeclaredAnnotations() { return new Annotation[0]; @@ -65,11 +62,6 @@ abstract class ParameterAutowireUtils { }; - - private ParameterAutowireUtils() { - /* no-op */ - } - /** * Determine if the supplied {@link Parameter} can potentially be * autowired from an {@link ApplicationContext}. @@ -79,16 +71,16 @@ abstract class ParameterAutowireUtils { * {@link Qualifier @Qualifier}, or {@link Value @Value}. * @param parameter the parameter whose dependency should be autowired * @param parameterIndex the index of the parameter - * @see #resolveDependency(Parameter, Class, ApplicationContext) + * @see #resolveDependency */ static boolean isAutowirable(Parameter parameter, int parameterIndex) { if (ApplicationContext.class.isAssignableFrom(parameter.getType())) { return true; } AnnotatedElement annotatedParameter = getEffectiveAnnotatedParameter(parameter, parameterIndex); - return AnnotatedElementUtils.hasAnnotation(annotatedParameter, Autowired.class) - || AnnotatedElementUtils.hasAnnotation(annotatedParameter, Qualifier.class) - || AnnotatedElementUtils.hasAnnotation(annotatedParameter, Value.class); + return (AnnotatedElementUtils.hasAnnotation(annotatedParameter, Autowired.class) || + AnnotatedElementUtils.hasAnnotation(annotatedParameter, Qualifier.class) || + AnnotatedElementUtils.hasAnnotation(annotatedParameter, Value.class)); } /** @@ -113,62 +105,54 @@ abstract class ParameterAutowireUtils { * dependency * @return the resolved object, or {@code null} if none found * @throws BeansException if dependency resolution failed - * @see #isAutowirable(Parameter) + * @see #isAutowirable * @see Autowired#required * @see SynthesizingMethodParameter#forParameter(Parameter) * @see AutowireCapableBeanFactory#resolveDependency(DependencyDescriptor, String) */ @Nullable - static Object resolveDependency(Parameter parameter, int parameterIndex, Class containingClass, ApplicationContext applicationContext) { + static Object resolveDependency( + Parameter parameter, int parameterIndex, Class containingClass, ApplicationContext applicationContext) { + AnnotatedElement annotatedParameter = getEffectiveAnnotatedParameter(parameter, parameterIndex); - boolean required = findMergedAnnotation(annotatedParameter, Autowired.class).map(Autowired::required).orElse(true); + Autowired autowired = AnnotatedElementUtils.findMergedAnnotation(annotatedParameter, Autowired.class); + boolean required = (autowired == null || autowired.required()); + MethodParameter methodParameter = SynthesizingMethodParameter.forParameter(parameter); DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required); descriptor.setContainingClass(containingClass); return applicationContext.getAutowireCapableBeanFactory().resolveDependency(descriptor, null); } - private static Optional findMergedAnnotation(AnnotatedElement element, Class annotationType) { - return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType)); - } - /** * Due to a bug in {@code javac} on JDK versions prior to JDK 9, looking up * annotations directly on a {@link Parameter} will fail for inner class * constructors. - * *

Bug in javac in JDK < 9

*

The parameter annotations array in the compiled byte code excludes an entry * for the implicit enclosing instance parameter for an inner class * constructor. - * *

Workaround

*

This method provides a workaround for this off-by-one error by allowing the * caller to access annotations on the preceding {@link Parameter} object (i.e., * {@code index - 1}). If the supplied {@code index} is zero, this method returns * an empty {@code AnnotatedElement}. - * *

WARNING

*

The {@code AnnotatedElement} returned by this method should never be cast and * treated as a {@code Parameter} since the metadata (e.g., {@link Parameter#getName()}, * {@link Parameter#getType()}, etc.) will not match those for the declared parameter * at the given index in an inner class constructor. - * * @return the supplied {@code parameter} or the effective {@code Parameter} * if the aforementioned bug is in effect */ private static AnnotatedElement getEffectiveAnnotatedParameter(Parameter parameter, int index) { Executable executable = parameter.getDeclaringExecutable(); - - if (executable instanceof Constructor && - ClassUtils.isInnerClass(executable.getDeclaringClass()) && + if (executable instanceof Constructor && ClassUtils.isInnerClass(executable.getDeclaringClass()) && executable.getParameterAnnotations().length == executable.getParameterCount() - 1) { - // Bug in javac in JDK <9: annotation array excludes enclosing instance parameter // for inner classes, so access it with the actual parameter index lowered by 1 - return (index == 0) ? EMPTY_ANNOTATED_ELEMENT : executable.getParameters()[index - 1]; + return (index == 0 ? EMPTY_ANNOTATED_ELEMENT : executable.getParameters()[index - 1]); } - return parameter; } diff --git a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java index 90ed50eaf0..a51802eb40 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -222,12 +222,14 @@ public class Jaxb2XmlDecoder extends AbstractDecoder { this.elementDepth++; } if (this.elementDepth > this.barrier) { + Assert.state(this.events != null, "No XMLEvent List"); this.events.add(event); } if (event.isEndElement()) { this.elementDepth--; if (this.elementDepth == this.barrier) { this.barrier = Integer.MAX_VALUE; + Assert.state(this.events != null, "No XMLEvent List"); return Mono.just(this.events); } } diff --git a/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java b/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java index 5a715d1fb1..e97418f818 100644 --- a/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java +++ b/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java @@ -180,9 +180,9 @@ class DefaultPathContainer implements PathContainer { return EMPTY_PATH; } - Assert.isTrue(fromIndex < toIndex, () -> "fromIndex: " + fromIndex + " should be < toIndex " + toIndex); Assert.isTrue(fromIndex >= 0 && fromIndex < elements.size(), () -> "Invalid fromIndex: " + fromIndex); Assert.isTrue(toIndex >= 0 && toIndex <= elements.size(), () -> "Invalid toIndex: " + toIndex); + Assert.isTrue(fromIndex < toIndex, () -> "fromIndex: " + fromIndex + " should be < toIndex " + toIndex); List subList = elements.subList(fromIndex, toIndex); String path = subList.stream().map(Element::value).collect(Collectors.joining("")); diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java index 7d93e21374..52abd5e5d0 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java @@ -109,9 +109,7 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl public Mono writeWith(File file, long position, long count) { return doCommit(() -> Mono.defer(() -> { - FileChannel source = null; - try { - source = FileChannel.open(file.toPath(), StandardOpenOption.READ); + try (FileChannel source = FileChannel.open(file.toPath(), StandardOpenOption.READ)) { StreamSinkChannel destination = this.exchange.getResponseChannel(); Channels.transferBlocking(destination, source, position, count); return Mono.empty(); @@ -119,17 +117,6 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl catch (IOException ex) { return Mono.error(ex); } - finally { - if (source != null) { - try { - source.close(); - } - catch (IOException ex) { - // ignore - } - } - } - })); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/AbstractView.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/AbstractView.java index 4cda6ab082..5841b899a9 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/AbstractView.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/AbstractView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -83,7 +83,7 @@ public abstract class AbstractView implements View, ApplicationContextAware { * Set the supported media types for this view. * Default is "text/html;charset=UTF-8". */ - public void setSupportedMediaTypes(@Nullable List supportedMediaTypes) { + public void setSupportedMediaTypes(List supportedMediaTypes) { Assert.notEmpty(supportedMediaTypes, "MediaType List must not be empty"); this.mediaTypes.clear(); this.mediaTypes.addAll(supportedMediaTypes); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolverSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolverSupport.java index 637303983d..bd621ae75f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolverSupport.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolverSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -23,7 +23,6 @@ import java.util.List; import org.springframework.core.Ordered; import org.springframework.http.MediaType; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -54,7 +53,7 @@ public abstract class ViewResolverSupport implements Ordered { * Set the supported media types for this view. * Default is "text/html;charset=UTF-8". */ - public void setSupportedMediaTypes(@Nullable List supportedMediaTypes) { + public void setSupportedMediaTypes(List supportedMediaTypes) { Assert.notEmpty(supportedMediaTypes, "MediaType List must not be empty"); this.mediaTypes.clear(); this.mediaTypes.addAll(supportedMediaTypes);