diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java index ee7d751b7f2..4773958990c 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java @@ -48,6 +48,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -543,6 +544,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport * @see #setInterceptorNames */ private Advisor[] resolveInterceptorNames() { + Assert.state(this.beanFactory != null, "BeanFactory required for resolving interceptor names"); ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) this.beanFactory : null); List advisors = new ArrayList<>(); diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java index 3225a458f4b..9ead0e79ed4 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -205,7 +205,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements * @throws TypeMismatchException if type conversion failed */ @Nullable - public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException { + public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException { CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults(); PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName); if (pd == null) { diff --git a/spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java b/spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java index 32361e94d3e..1344e194e34 100644 --- a/spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java +++ b/spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java @@ -541,6 +541,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { return this.registeredType; } + @Nullable private PropertyEditor getPropertyEditor(@Nullable Class requiredType) { // Special case: If no required type specified, which usually only happens for // Collection elements, or required type is not assignable to registered type, diff --git a/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java b/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java index 519840e019e..1f1536fc1b9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java +++ b/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java @@ -97,7 +97,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri * @param original the PropertyValue to link to (never {@code null}) * @param newValue the new value to apply */ - public PropertyValue(PropertyValue original, Object newValue) { + public PropertyValue(PropertyValue original, @Nullable Object newValue) { Assert.notNull(original, "Original must not be null"); this.name = original.getName(); this.value = newValue; @@ -172,7 +172,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri * Set the converted value of the constructor argument, * after processed type conversion. */ - public synchronized void setConvertedValue(Object value) { + public synchronized void setConvertedValue(@Nullable Object value) { this.converted = true; this.convertedValue = value; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java index 39598b184b7..04d32dae780 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java @@ -459,21 +459,18 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp boolean hasClosureArgument = (args[args.length - 1] instanceof Closure); if (args[0] instanceof Class) { Class beanClass = (Class) args[0]; - if (args.length >= 1) { - if (hasClosureArgument) { - if (args.length - 1 != 1) { - this.currentBeanDefinition = new GroovyBeanDefinitionWrapper( - beanName, beanClass, resolveConstructorArguments(args, 1, args.length - 1)); - } - else { - this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, beanClass); - } - } - else { + if (hasClosureArgument) { + if (args.length - 1 != 1) { this.currentBeanDefinition = new GroovyBeanDefinitionWrapper( - beanName, beanClass, resolveConstructorArguments(args, 1, args.length)); + beanName, beanClass, resolveConstructorArguments(args, 1, args.length - 1)); } - + else { + this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, beanClass); + } + } + else { + this.currentBeanDefinition = new GroovyBeanDefinitionWrapper( + beanName, beanClass, resolveConstructorArguments(args, 1, args.length)); } } else if (args[0] instanceof RuntimeBeanReference) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 25c25335272..3d9ac6a8c2e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1556,7 +1556,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param pvs the new property values */ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { - if (pvs == null || pvs.isEmpty()) { + if (pvs.isEmpty()) { return; } @@ -1649,7 +1649,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * Convert the given value for the specified target property. */ @Nullable - private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) { + private Object convertForProperty( + @Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) { + if (converter instanceof BeanWrapperImpl) { return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index c18745722a6..c022d854454 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -145,7 +145,6 @@ abstract class AutowireUtils { * @param requiredType the type to assign the result to * @return the resolved value */ - @Nullable public static Object resolveAutowiringValue(Object autowiringValue, Class requiredType) { if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) { ObjectFactory factory = (ObjectFactory) autowiringValue; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/ParserContext.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/ParserContext.java index a27ebd487b5..eaf5a9c5e2b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/ParserContext.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/ParserContext.java @@ -93,6 +93,7 @@ public final class ParserContext { return this.readerContext.extractSource(sourceCandidate); } + @Nullable public CompositeComponentDefinition getContainingComponent() { return (!this.containingComponents.isEmpty() ? (CompositeComponentDefinition) this.containingComponents.lastElement() : null); diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java index 1622741711c..e5f8535c84c 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheFactoryBean.java @@ -205,7 +205,9 @@ public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBea String cacheName = getName(); if (cacheName == null) { cacheName = this.beanName; - setName(cacheName); + if (cacheName != null) { + setName(cacheName); + } } // If no CacheManager given, fetch the default. diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index 640f869b8ca..39adf0647ee 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -597,7 +597,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean else if (embeddedValueResolver != null) { resourceName = embeddedValueResolver.resolveStringValue(resourceName); } - if (resourceType != null && Object.class != resourceType) { + if (Object.class != resourceType) { checkResourceType(resourceType); } else { @@ -642,7 +642,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean resourceName = Introspector.decapitalize(resourceName.substring(3)); } } - if (resourceType != null && Object.class != resourceType) { + if (Object.class != resourceType) { checkResourceType(resourceType); } else { @@ -726,7 +726,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean } } Class resourceType = resource.beanInterface(); - if (resourceType != null && Object.class != resourceType) { + if (Object.class != resourceType) { checkResourceType(resourceType); } else { diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index 683e62c0716..c10e3d98c1a 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -364,7 +364,6 @@ class ConfigurationClassEnhancer { return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName); } - @Nullable private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName) { diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java index 97f77b1cc6b..bb89e3da3c6 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java @@ -35,6 +35,7 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; /** @@ -205,6 +206,7 @@ abstract class ConfigurationClassUtils { * or {@link Ordered#LOWEST_PRECEDENCE} if none declared * @since 5.0 */ + @Nullable public static Integer getOrder(AnnotationMetadata metadata) { Map orderAttributes = metadata.getAnnotationAttributes(Order.class.getName()); return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null); diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 66a35ab9830..a3b25d889ea 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -766,6 +766,7 @@ public class ResolvableType implements Serializable { return (this.resolved != null ? this.resolved : fallback); } + @Nullable private Class resolveClass() { if (this.type == EmptyType.INSTANCE) { return null; @@ -1474,6 +1475,7 @@ public class ResolvableType implements Serializable { } @Override + @Nullable public Type getOwnerType() { return null; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index e4e81c3a198..e0fe472c6f9 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -153,7 +153,6 @@ public class AnnotatedElementUtils { * @see #getMetaAnnotationTypes(AnnotatedElement, String) * @see #hasMetaAnnotationTypes */ - @Nullable public static Set getMetaAnnotationTypes(AnnotatedElement element, Class annotationType) { Assert.notNull(element, "AnnotatedElement must not be null"); Assert.notNull(annotationType, "'annotationType' must not be null"); @@ -1114,7 +1113,7 @@ public class AnnotatedElementUtils { processor.alwaysProcesses()) { T result = processor.process(element, annotation, metaDepth); if (result != null) { - if (processor.aggregates() && metaDepth == 0) { + if (aggregatedResults != null && metaDepth == 0) { aggregatedResults.add(result); } else { @@ -1126,7 +1125,7 @@ public class AnnotatedElementUtils { else if (currentAnnotationType == containerType) { for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) { T result = processor.process(element, contained, metaDepth); - if (result != null) { + if (aggregatedResults != null && result != null) { // No need to post-process since repeatable annotations within a // container cannot be composed annotations. aggregatedResults.add(result); @@ -1144,7 +1143,7 @@ public class AnnotatedElementUtils { containerType, processor, visited, metaDepth + 1); if (result != null) { processor.postProcess(currentAnnotationType, annotation, result); - if (processor.aggregates() && metaDepth == 0) { + if (aggregatedResults != null && metaDepth == 0) { aggregatedResults.add(result); } else { @@ -1154,7 +1153,7 @@ public class AnnotatedElementUtils { } } - if (processor.aggregates()) { + if (aggregatedResults != null) { // Prepend to support top-down ordering within class hierarchies processor.getAggregatedResults().addAll(0, aggregatedResults); } @@ -1237,9 +1236,10 @@ public class AnnotatedElementUtils { return null; } - private static T searchOnInterfaces(Method method, Class annotationType, - String annotationName, Class containerType, Processor processor, - Set visited, int metaDepth, Class[] ifcs) { + @Nullable + private static T searchOnInterfaces(Method method, @Nullable Class annotationType, + @Nullable String annotationName, @Nullable Class containerType, + Processor processor, Set visited, int metaDepth, Class[] ifcs) { for (Class iface : ifcs) { if (AnnotationUtils.isInterfaceWithAnnotatedMethods(iface)) { @@ -1495,7 +1495,6 @@ public class AnnotatedElementUtils { static class AlwaysTrueBooleanAnnotationProcessor extends SimpleAnnotationProcessor { @Override - @Nullable public final Boolean process(@Nullable AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { return Boolean.TRUE; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 063d77678f7..b7ed7e8ec20 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -292,7 +292,6 @@ public abstract class AnnotationUtils { * @see java.lang.annotation.Repeatable * @see java.lang.reflect.AnnotatedElement#getAnnotationsByType */ - @Nullable public static Set getRepeatableAnnotations(AnnotatedElement annotatedElement, Class annotationType) { @@ -1524,7 +1523,6 @@ public abstract class AnnotationUtils { * @see #synthesizeAnnotation(Map, Class, AnnotatedElement) * @see #synthesizeAnnotation(Annotation, AnnotatedElement) */ - @Nullable public static A synthesizeAnnotation(Class annotationType) { return synthesizeAnnotation(Collections. emptyMap(), annotationType, null); } diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java index 59989ae4035..8084669943c 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java @@ -129,6 +129,7 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { return (getValidatedMember(targetClass, sourceClass) != null); } + @Nullable private static Member getValidatedMember(Class targetClass, Class sourceClass) { Member member = conversionMemberCache.get(targetClass); if (isApplicable(member, sourceClass)) { @@ -166,6 +167,7 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { } } + @Nullable private static Method determineToMethod(Class targetClass, Class sourceClass) { if (String.class == targetClass || String.class == sourceClass) { // Do not accept a toString() method or any to methods on String itself @@ -177,6 +179,7 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { ClassUtils.isAssignable(targetClass, method.getReturnType()) ? method : null); } + @Nullable private static Method determineFactoryMethod(Class targetClass, Class sourceClass) { if (String.class == targetClass) { // Do not accept the String.valueOf(Object) method diff --git a/spring-core/src/main/java/org/springframework/lang/NonNull.java b/spring-core/src/main/java/org/springframework/lang/NonNull.java index 879db7b3a7f..6c78e010975 100644 --- a/spring-core/src/main/java/org/springframework/lang/NonNull.java +++ b/spring-core/src/main/java/org/springframework/lang/NonNull.java @@ -30,9 +30,8 @@ import javax.annotation.meta.TypeQualifierNickname; * Leverages JSR 305 meta-annotations to indicate nullability in Java to common tools with * JSR 305 support and used by Kotlin to infer nullability of Spring API. * - *

Should be used at parameter, return value, and field level. - * Methods overrides should repeat parent {@code @NonNull} annotations unless they behave - * differently. + *

Should be used at parameter, return value, and field level. Method overrides should + * repeat parent {@code @NonNull} annotations unless they behave differently. * *

Use {@code @NonNullApi} (scope = parameters + return values) and/or {@code @NonNullFields} * (scope = fields) to set the default behavior to non-nullable in order to avoid annotating diff --git a/spring-core/src/main/java/org/springframework/lang/NonNullApi.java b/spring-core/src/main/java/org/springframework/lang/NonNullApi.java index c216e8b8f60..92e4f177986 100644 --- a/spring-core/src/main/java/org/springframework/lang/NonNullApi.java +++ b/spring-core/src/main/java/org/springframework/lang/NonNullApi.java @@ -27,8 +27,9 @@ import javax.annotation.meta.TypeQualifierDefault; /** * A common Spring annotation to declare that parameters and return values * are to be considered as non-nullable by default for a given package. - * Leverages JSR 305 meta-annotations to indicate nullability in Java to common tools with - * JSR 305 support and used by Kotlin to infer nullability of Spring API. + * + *

Leverages JSR-305 meta-annotations to indicate nullability in Java to common + * tools with JSR-305 support and used by Kotlin to infer nullability of Spring API. * *

Should be used at package level in association with {@link Nullable} * annotations at parameter and return value level. diff --git a/spring-core/src/main/java/org/springframework/lang/NonNullFields.java b/spring-core/src/main/java/org/springframework/lang/NonNullFields.java index fb1b3f3940d..3c9d39ddc28 100644 --- a/spring-core/src/main/java/org/springframework/lang/NonNullFields.java +++ b/spring-core/src/main/java/org/springframework/lang/NonNullFields.java @@ -21,15 +21,15 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - import javax.annotation.Nonnull; import javax.annotation.meta.TypeQualifierDefault; /** * A common Spring annotation to declare that fields are to be considered as - * non-nullable by default for a given package. Leverages JSR 305 meta-annotations to - * indicate nullability in Java to common tools with JSR 305 support and used by Kotlin - * to infer nullability of Spring API. + * non-nullable by default for a given package. + * + *

Leverages JSR-305 meta-annotations to indicate nullability in Java to common + * tools with JSR-305 support and used by Kotlin to infer nullability of Spring API. * *

Should be used at package level in association with {@link Nullable} * annotations at field level. diff --git a/spring-core/src/main/java/org/springframework/lang/Nullable.java b/spring-core/src/main/java/org/springframework/lang/Nullable.java index 3d176e760b0..3bfbe0e11da 100644 --- a/spring-core/src/main/java/org/springframework/lang/Nullable.java +++ b/spring-core/src/main/java/org/springframework/lang/Nullable.java @@ -30,9 +30,8 @@ import javax.annotation.meta.When; * some circumstance. Leverages JSR 305 meta-annotations to indicate nullability in Java * to common tools with JSR 305 support and used by Kotlin to infer nullability of Spring API. * - *

Should be used at parameter, return value, and field level. - * Methods overrides should repeat parent {@code @Nullable} annotations unless they behave - * differently. + *

Should be used at parameter, return value, and field level. Methods override should + * repeat parent {@code @Nullable} annotations unless they behave differently. * *

Can be used in association with {@code NonNullApi} or {@code @NonNullFields} to * override the default non-nullable semantic to nullable. diff --git a/spring-core/src/main/java/org/springframework/util/Base64Utils.java b/spring-core/src/main/java/org/springframework/util/Base64Utils.java index 64c7be8131c..9806852017d 100644 --- a/spring-core/src/main/java/org/springframework/util/Base64Utils.java +++ b/spring-core/src/main/java/org/springframework/util/Base64Utils.java @@ -20,8 +20,6 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Base64; -import org.springframework.lang.Nullable; - /** * A simple utility class for Base64 encoding and decoding. * @@ -90,9 +88,8 @@ public abstract class Base64Utils { * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime * @since 4.2.4 */ - @Nullable - public static byte[] decodeUrlSafe(@Nullable byte[] src) { - if (src == null || src.length == 0) { + public static byte[] decodeUrlSafe(byte[] src) { + if (src.length == 0) { return src; } return Base64.getUrlDecoder().decode(src); @@ -130,7 +127,6 @@ public abstract class Base64Utils { * @throws IllegalStateException if Base64 encoding between byte arrays is not * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime */ - @Nullable public static String encodeToUrlSafeString(byte[] src) { return new String(encodeUrlSafe(src), DEFAULT_CHARSET); } @@ -143,7 +139,6 @@ public abstract class Base64Utils { * @throws IllegalStateException if Base64 encoding between byte arrays is not * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime */ - @Nullable public static byte[] decodeFromUrlSafeString(String src) { return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET)); } diff --git a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java index 03f9f241fc0..2804b840586 100644 --- a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java +++ b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java @@ -306,7 +306,6 @@ public class ConcurrentReferenceHashMap extends AbstractMap implemen public boolean remove(Object key, final Object value) { Boolean result = doTask(key, new Task(TaskOption.RESTRUCTURE_AFTER, TaskOption.SKIP_IF_EMPTY) { @Override - @Nullable protected Boolean execute(@Nullable Reference reference, @Nullable Entry entry) { if (entry != null && ObjectUtils.nullSafeEquals(entry.getValue(), value)) { if (reference != null) { @@ -324,7 +323,6 @@ public class ConcurrentReferenceHashMap extends AbstractMap implemen public boolean replace(K key, final V oldValue, final V newValue) { Boolean result = doTask(key, new Task(TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY) { @Override - @Nullable protected Boolean execute(@Nullable Reference reference, @Nullable Entry entry) { if (entry != null && ObjectUtils.nullSafeEquals(entry.getValue(), oldValue)) { entry.setValue(newValue); diff --git a/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java b/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java index 50ed50c317c..429423c691b 100644 --- a/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java +++ b/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java @@ -396,12 +396,6 @@ public class FastByteArrayOutputStream extends OutputStream { else if (len == 0) { return 0; } - else if (len < 0) { - throw new IllegalArgumentException("len must be 0 or greater: " + len); - } - else if (off < 0) { - throw new IllegalArgumentException("off must be 0 or greater: " + off); - } else { if (this.currentBuffer == null) { // This stream doesn't have any data in it... diff --git a/spring-core/src/main/java/org/springframework/util/concurrent/FutureAdapter.java b/spring-core/src/main/java/org/springframework/util/concurrent/FutureAdapter.java index 6084418d5d8..d6ff2804b9e 100644 --- a/spring-core/src/main/java/org/springframework/util/concurrent/FutureAdapter.java +++ b/spring-core/src/main/java/org/springframework/util/concurrent/FutureAdapter.java @@ -51,7 +51,7 @@ public abstract class FutureAdapter implements Future { * @param adaptee the future to delegate to */ protected FutureAdapter(Future adaptee) { - Assert.notNull(adaptee, "'delegate' must not be null"); + Assert.notNull(adaptee, "Delegate must not be null"); this.adaptee = adaptee; } @@ -98,6 +98,7 @@ public abstract class FutureAdapter implements Future { case SUCCESS: return (T) this.result; case FAILURE: + Assert.state(this.result instanceof ExecutionException, "Failure without exception"); throw (ExecutionException) this.result; case NEW: try { diff --git a/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java b/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java index ee661e572fd..d7d53a054db 100644 --- a/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java +++ b/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java @@ -165,6 +165,7 @@ public class XmlValidationModeDetector { * Consume the next comment token, update the "inComment" flag * and return the remaining content. */ + @Nullable private String consume(String line) { int index = (this.inComment ? endComment(line) : startComment(line)); return (index == -1 ? null : line.substring(index)); diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java index a664e3ab723..c7b75f382be 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java @@ -32,7 +32,7 @@ import org.springframework.lang.Nullable; */ public class CompoundExpression extends SpelNodeImpl { - public CompoundExpression(int pos,SpelNodeImpl... expressionComponents) { + public CompoundExpression(int pos, SpelNodeImpl... expressionComponents) { super(pos, expressionComponents); if (expressionComponents.length < 2) { throw new IllegalStateException("Do not build compound expressions with less than two entries: " + diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java index 4e0f2c0797b..3e2c9b20d58 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java @@ -61,7 +61,6 @@ public class Selection extends SpelNodeImpl { public Selection(boolean nullSafe, int variant, int pos, SpelNodeImpl expression) { super(pos, expression); - Assert.notNull(expression, "Expression must not be null"); this.nullSafe = nullSafe; this.variant = variant; } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java index 745bab0006a..f635908a6fe 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java @@ -72,8 +72,9 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes { Assert.isTrue(pos != 0, "Pos must not be 0"); if (!ObjectUtils.isEmpty(operands)) { this.children = operands; - for (SpelNodeImpl childNode : operands) { - childNode.parent = this; + for (SpelNodeImpl operand : operands) { + Assert.notNull(operand, "Operand must not be null"); + operand.parent = this; } } } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java b/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java index 9c62e82d62b..4b8fb023be7 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java @@ -329,13 +329,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { if (t.kind == TokenKind.NOT) { return new OperatorNot(toPos(t), expr); } - if (t.kind == TokenKind.PLUS) { return new OpPlus(toPos(t), expr); } Assert.isTrue(t.kind == TokenKind.MINUS, "Minus token expected"); return new OpMinus(toPos(t), expr); - } if (peekToken(TokenKind.INC, TokenKind.DEC)) { Token t = takeToken(); @@ -345,48 +343,40 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { } return new OpDec(toPos(t), false, expr); } - return eatPrimaryExpression(); } // primaryExpression : startNode (node)? -> ^(EXPRESSION startNode (node)?); + @Nullable private SpelNodeImpl eatPrimaryExpression() { - List nodes = new ArrayList<>(); SpelNodeImpl start = eatStartNode(); // always a start node - nodes.add(start); - while (maybeEatNode()) { - nodes.add(pop()); + List nodes = null; + SpelNodeImpl node = eatNode(); + while (node != null) { + if (nodes == null) { + nodes = new ArrayList<>(4); + nodes.add(start); + } + nodes.add(node); + node = eatNode(); } - if (nodes.size() == 1) { - return nodes.get(0); + if (start == null || nodes == null) { + return start; } - return new CompoundExpression(toPos((start != null ? start.getStartPosition() : 0), + return new CompoundExpression(toPos(start.getStartPosition(), nodes.get(nodes.size() - 1).getEndPosition()), nodes.toArray(new SpelNodeImpl[nodes.size()])); } // node : ((DOT dottedNode) | (SAFE_NAVI dottedNode) | nonDottedNode)+; - private boolean maybeEatNode() { - SpelNodeImpl expr = null; - if (peekToken(TokenKind.DOT, TokenKind.SAFE_NAVI)) { - expr = eatDottedNode(); - } - else { - expr = maybeEatNonDottedNode(); - } - - if (expr == null) { - return false; - } - else { - push(expr); - return true; - } + @Nullable + private SpelNodeImpl eatNode() { + return (peekToken(TokenKind.DOT, TokenKind.SAFE_NAVI) ? eatDottedNode() : eatNonDottedNode()); } // nonDottedNode: indexer; @Nullable - private SpelNodeImpl maybeEatNonDottedNode() { + private SpelNodeImpl eatNonDottedNode() { if (peekToken(TokenKind.LSQUARE)) { if (maybeEatIndexer()) { return pop(); @@ -404,7 +394,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { // | lastSelection // )) // ; - @Nullable private SpelNodeImpl eatDottedNode() { Token t = takeToken(); // it was a '.' or a '?.' boolean nullSafeNavigation = (t.kind == TokenKind.SAFE_NAVI); @@ -414,12 +403,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { } if (peekToken() == null) { // unexpectedly ran out of data - raiseInternalException(t.startPos, SpelMessage.OOD); + throw internalException(t.startPos, SpelMessage.OOD); } else { - raiseInternalException(t.startPos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, toString(peekToken())); + throw internalException(t.startPos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, toString(peekToken())); } - return null; } // functionOrVar @@ -479,7 +467,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { nextToken(); // consume (first time through) or comma (subsequent times) t = peekToken(); if (t == null) { - raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); + throw internalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } if (t.kind != TokenKind.RPAREN) { accumulatedArguments.add(eatExpression()); @@ -489,7 +477,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { while (next != null && next.kind == TokenKind.COMMA); if (next == null) { - raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); + throw internalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } } @@ -556,10 +544,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { beanName = beanName.substring(1, beanName.length() - 1); } else { - raiseInternalException(beanRefToken.startPos, - SpelMessage.INVALID_BEAN_REFERENCE); + throw internalException(beanRefToken.startPos, SpelMessage.INVALID_BEAN_REFERENCE); } - BeanReference beanReference; if (beanRefToken.getKind() == TokenKind.FACTORY_BEAN_REF) { String beanNameString = String.valueOf(TokenKind.FACTORY_BEAN_REF.tokenChars) + beanName; @@ -692,7 +678,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { mapElements.toArray(new SpelNodeImpl[mapElements.size()])); } else { - raiseInternalException(t.startPos, SpelMessage.OOD); + throw internalException(t.startPos, SpelMessage.OOD); } } this.constructedNodes.push(expr); @@ -721,7 +707,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { nextToken(); SpelNodeImpl expr = eatExpression(); if (expr == null) { - raiseInternalException(toPos(t), SpelMessage.MISSING_SELECTION_EXPRESSION); + throw internalException(toPos(t), SpelMessage.MISSING_SELECTION_EXPRESSION); } eatToken(TokenKind.RSQUARE); if (t.kind == TokenKind.SELECT_FIRST) { @@ -752,9 +738,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { } if (qualifiedIdPieces.isEmpty()) { if (node == null) { - raiseInternalException( this.expressionString.length(), SpelMessage.OOD); + throw internalException( this.expressionString.length(), SpelMessage.OOD); } - raiseInternalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, + throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(), @@ -942,10 +928,10 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { Token t = nextToken(); if (t == null) { int pos = this.expressionString.length(); - raiseInternalException(pos, SpelMessage.OOD); + throw internalException(pos, SpelMessage.OOD); } if (t.kind != expectedKind) { - raiseInternalException(t.startPos, SpelMessage.NOT_EXPECTED_TOKEN, + throw internalException(t.startPos, SpelMessage.NOT_EXPECTED_TOKEN, expectedKind.toString().toLowerCase(), t.getKind().toString().toLowerCase()); } return t; @@ -1035,10 +1021,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { return this.tokenStream.get(this.tokenStreamPointer); } - private void raiseInternalException(int pos, SpelMessage message, Object... inserts) { - throw new InternalParseException(new SpelParseException(this.expressionString, pos, message, inserts)); - } - public String toString(@Nullable Token t) { if (t == null) { return ""; @@ -1056,23 +1038,27 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { private void checkLeftOperand(Token token, @Nullable SpelNodeImpl operandExpression) { if (operandExpression == null) { - raiseInternalException(token.startPos, SpelMessage.LEFT_OPERAND_PROBLEM); + throw internalException(token.startPos, SpelMessage.LEFT_OPERAND_PROBLEM); } } private void checkRightOperand(Token token, @Nullable SpelNodeImpl operandExpression) { if (operandExpression == null) { - raiseInternalException(token.startPos, SpelMessage.RIGHT_OPERAND_PROBLEM); + throw internalException(token.startPos, SpelMessage.RIGHT_OPERAND_PROBLEM); } } + private InternalParseException internalException(int pos, SpelMessage message, Object... inserts) { + return new InternalParseException(new SpelParseException(this.expressionString, pos, message, inserts)); + } + 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; } private int toPos(int start, int end) { - return (start<<16) + end; + return (start << 16) + end; } } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java index ed9789b0c7a..99d5d59c600 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java @@ -381,7 +381,6 @@ public class SpelParserTests { checkNumber("22", 22, Integer.class); checkNumber("+22", 22, Integer.class); checkNumber("-22", -22, Integer.class); - checkNumber("2L", 2L, Long.class); checkNumber("22l", 22L, Long.class); @@ -392,13 +391,10 @@ public class SpelParserTests { checkNumberError("0x", SpelMessage.NOT_AN_INTEGER); checkNumberError("0xL", SpelMessage.NOT_A_LONG); - checkNumberError(".324", SpelMessage.UNEXPECTED_DATA_AFTER_DOT); - checkNumberError("3.4L", SpelMessage.REAL_CANNOT_BE_LONG); checkNumber("3.5f", 3.5f, Float.class); - checkNumber("1.2e3", 1.2e3d, Double.class); checkNumber("1.2e+3", 1.2e3d, Double.class); checkNumber("1.2e-3", 1.2e-3d, Double.class); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/UncategorizedSQLException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/UncategorizedSQLException.java index 0d7593e434f..8b25da41342 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/UncategorizedSQLException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/UncategorizedSQLException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 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.jdbc; import java.sql.SQLException; import org.springframework.dao.UncategorizedDataAccessException; +import org.springframework.lang.Nullable; /** * Exception thrown when we can't classify a SQLException into @@ -31,6 +32,7 @@ import org.springframework.dao.UncategorizedDataAccessException; public class UncategorizedSQLException extends UncategorizedDataAccessException { /** SQL that led to the problem */ + @Nullable private final String sql; @@ -40,9 +42,10 @@ public class UncategorizedSQLException extends UncategorizedDataAccessException * @param sql the offending SQL statement * @param ex the root cause */ - public UncategorizedSQLException(String task, String sql, SQLException ex) { - super(task + "; uncategorized SQLException for SQL [" + sql + "]; SQL state [" + - ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + ex.getMessage(), ex); + public UncategorizedSQLException(String task, @Nullable String sql, SQLException ex) { + super(task + "; uncategorized SQLException" + (sql != null ? " for SQL [" + sql + "]" : "") + + "; SQL state [" + ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + + ex.getMessage(), ex); this.sql = sql; } @@ -55,8 +58,9 @@ public class UncategorizedSQLException extends UncategorizedDataAccessException } /** - * Return the SQL that led to the problem. + * Return the SQL that led to the problem (if known). */ + @Nullable public String getSql() { return this.sql; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java index 9b498666aeb..133a148121c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -41,6 +41,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.support.DataAccessUtils; import org.springframework.jdbc.SQLWarningException; +import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.datasource.ConnectionProxy; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.support.JdbcAccessor; @@ -329,9 +330,10 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. + String sql = getSql(action); DataSourceUtils.releaseConnection(con, getDataSource()); con = null; - throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex); + throw translateException("ConnectionCallback", sql, ex); } finally { DataSourceUtils.releaseConnection(con, getDataSource()); @@ -378,11 +380,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. + String sql = getSql(action); JdbcUtils.closeStatement(stmt); stmt = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; - throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); + throw translateException("StatementCallback", sql, ex); } finally { JdbcUtils.closeStatement(stmt); @@ -446,12 +449,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { @Override public List query(String sql, RowMapper rowMapper) throws DataAccessException { - return nonNull(query(sql, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(sql, new RowMapperResultSetExtractor<>(rowMapper))); } @Override public Map queryForMap(String sql) throws DataAccessException { - return nonNull(queryForObject(sql, getColumnMapRowMapper())); + return result(queryForObject(sql, getColumnMapRowMapper())); } @Override @@ -479,7 +482,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { @Override public SqlRowSet queryForRowSet(String sql) throws DataAccessException { - return nonNull(query(sql, new SqlRowSetResultSetExtractor())); + return result(query(sql, new SqlRowSetResultSetExtractor())); } @Override @@ -612,7 +615,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { ps = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; - throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); + throw translateException("PreparedStatementCallback", sql, ex); } finally { if (psc instanceof ParameterDisposer) { @@ -728,27 +731,27 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { @Override public List query(PreparedStatementCreator psc, RowMapper rowMapper) throws DataAccessException { - return nonNull(query(psc, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(psc, new RowMapperResultSetExtractor<>(rowMapper))); } @Override public List query(String sql, @Nullable PreparedStatementSetter pss, RowMapper rowMapper) throws DataAccessException { - return nonNull(query(sql, pss, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(sql, pss, new RowMapperResultSetExtractor<>(rowMapper))); } @Override public List query(String sql, Object[] args, int[] argTypes, RowMapper rowMapper) throws DataAccessException { - return nonNull(query(sql, args, argTypes, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(sql, args, argTypes, new RowMapperResultSetExtractor<>(rowMapper))); } @Override public List query(String sql, @Nullable Object[] args, RowMapper rowMapper) throws DataAccessException { - return nonNull(query(sql, args, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(sql, args, new RowMapperResultSetExtractor<>(rowMapper))); } @Override public List query(String sql, RowMapper rowMapper, @Nullable Object... args) throws DataAccessException { - return nonNull(query(sql, args, new RowMapperResultSetExtractor<>(rowMapper))); + return result(query(sql, args, new RowMapperResultSetExtractor<>(rowMapper))); } @Override @@ -794,12 +797,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { @Override public Map queryForMap(String sql, Object[] args, int[] argTypes) throws DataAccessException { - return nonNull(queryForObject(sql, args, argTypes, getColumnMapRowMapper())); + return result(queryForObject(sql, args, argTypes, getColumnMapRowMapper())); } @Override public Map queryForMap(String sql, @Nullable Object... args) throws DataAccessException { - return nonNull(queryForObject(sql, args, getColumnMapRowMapper())); + return result(queryForObject(sql, args, getColumnMapRowMapper())); } @Override @@ -829,12 +832,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { @Override public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes) throws DataAccessException { - return nonNull(query(sql, args, argTypes, new SqlRowSetResultSetExtractor())); + return result(query(sql, args, argTypes, new SqlRowSetResultSetExtractor())); } @Override public SqlRowSet queryForRowSet(String sql, @Nullable Object... args) throws DataAccessException { - return nonNull(query(sql, args, new SqlRowSetResultSetExtractor())); + return result(query(sql, args, new SqlRowSetResultSetExtractor())); } protected int update(final PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss) @@ -882,7 +885,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { try { RowMapperResultSetExtractor> rse = new RowMapperResultSetExtractor<>(getColumnMapRowMapper(), 1); - generatedKeys.addAll(nonNull(rse.extractData(keys))); + generatedKeys.addAll(result(rse.extractData(keys))); } finally { JdbcUtils.closeResultSet(keys); @@ -1057,7 +1060,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { cs = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; - throw getExceptionTranslator().translate("CallableStatementCallback", sql, ex); + throw translateException("CallableStatementCallback", sql, ex); } finally { if (csc instanceof ParameterDisposer) { @@ -1384,6 +1387,20 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } + /** + * Translate the given {@link SQLException} into a generic {@link DataAccessException}. + * @param task readable text describing the task being attempted + * @param sql SQL query or update that caused the problem (may be {@code null}) + * @param ex the offending {@code SQLException} + * @return a DataAccessException wrapping the {@code SQLException} (never {@code null}) + * @since 5.0 + * @see #getExceptionTranslator() + */ + protected DataAccessException translateException(String task, @Nullable String sql, SQLException ex) { + DataAccessException dae = getExceptionTranslator().translate(task, sql, ex); + return (dae != null ? dae : new UncategorizedSQLException(task, sql, ex)); + } + /** * Determine SQL from potential provider object. @@ -1401,7 +1418,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } - private static T nonNull(@Nullable T result) { + private static T result(@Nullable T result) { Assert.state(result != null, "No result"); return result; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java index 44e8f002545..8a3b50e83c7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java @@ -26,7 +26,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.jdbc.support.MetaDataAccessException; -import org.springframework.util.Assert; /** * Factory used to create a {@link CallMetaDataProvider} implementation @@ -130,7 +129,6 @@ public class CallMetaDataProviderFactory { } return provider; }); - Assert.state(result != null, "No CallMetaDataProvider"); return result; } catch (MetaDataAccessException ex) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java index 88ceaf42fb3..539cf223f1d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java @@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.jdbc.support.MetaDataAccessException; -import org.springframework.util.Assert; /** * Factory used to create a {@link TableMetaDataProvider} implementation @@ -77,7 +76,6 @@ public class TableMetaDataProviderFactory { } return provider; }); - Assert.state(result != null, "No TableMetaDataProvider"); return result; } catch (MetaDataAccessException ex) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcDaoSupport.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcDaoSupport.java index 9f873415054..027c6753124 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcDaoSupport.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcDaoSupport.java @@ -76,6 +76,7 @@ public abstract class JdbcDaoSupport extends DaoSupport { /** * Return the JDBC DataSource used by this DAO. */ + @Nullable public final DataSource getDataSource() { return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java index cc198cf0d1e..4b6b11792d4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.UncategorizedSQLException; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -64,26 +65,26 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep * {@link #getFallbackTranslator() fallback translator} if necessary. */ @Override - @Nullable - public DataAccessException translate(@Nullable String task, @Nullable String sql, SQLException ex) { + @NonNull + public DataAccessException translate(String task, @Nullable String sql, SQLException ex) { Assert.notNull(ex, "Cannot translate a null SQLException"); - if (task == null) { - task = ""; - } - if (sql == null) { - sql = ""; - } - DataAccessException dex = doTranslate(task, sql, ex); - if (dex != null) { + DataAccessException dae = doTranslate(task, sql, ex); + if (dae != null) { // Specific exception match found. - return dex; + return dae; } + // Looking for a fallback... SQLExceptionTranslator fallback = getFallbackTranslator(); if (fallback != null) { - return fallback.translate(task, sql, ex); + dae = fallback.translate(task, sql, ex); + if (dae != null) { + // Fallback exception match found. + return dae; + } } + // We couldn't identify it more precisely. return new UncategorizedSQLException(task, sql, ex); } @@ -94,13 +95,13 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep * is allowed to return {@code null} to indicate that no exception match has * been found and that fallback translation should kick in. * @param task readable text describing the task being attempted - * @param sql SQL query or update that caused the problem + * @param sql SQL query or update that caused the problem (if known) * @param ex the offending {@code SQLException} * @return the DataAccessException, wrapping the {@code SQLException}; * or {@code null} if no exception match found */ @Nullable - protected abstract DataAccessException doTranslate(String task, String sql, SQLException ex); + protected abstract DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex); /** @@ -112,8 +113,8 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep * @param ex the offending {@code SQLException} * @return the message {@code String} to use */ - protected String buildMessage(String task, String sql, SQLException ex) { - return task + "; SQL [" + sql + "]; " + ex.getMessage(); + protected String buildMessage(String task, @Nullable String sql, SQLException ex) { + return task + "; " + (sql != null ? "SQL [" + sql : "]; " + "") + ex.getMessage(); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java index a07b328cb89..76754cd367a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java @@ -97,11 +97,12 @@ public class DatabaseStartupValidator implements InitializingBean { */ @Override public void afterPropertiesSet() { - if (this.dataSource == null) { - throw new IllegalArgumentException("dataSource is required"); + DataSource dataSource = this.dataSource; + if (dataSource == null) { + throw new IllegalArgumentException("Property 'dataSource' is required"); } if (this.validationQuery == null) { - throw new IllegalArgumentException("validationQuery is required"); + throw new IllegalArgumentException("Property 'validationQuery' is required"); } try { @@ -114,10 +115,10 @@ public class DatabaseStartupValidator implements InitializingBean { Connection con = null; Statement stmt = null; try { - con = this.dataSource.getConnection(); + con = dataSource.getConnection(); if (con == null) { throw new CannotGetJdbcConnectionException("Failed to execute validation query: " + - "DataSource returned null from getConnection(): " + this.dataSource); + "DataSource returned null from getConnection(): " + dataSource); } stmt = con.createStatement(); stmt.execute(this.validationQuery); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java index 297643286b3..1e55c05f0da 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java @@ -132,6 +132,7 @@ public abstract class JdbcUtils { * @throws SQLException if thrown by the JDBC API * @see #getResultSetValue(ResultSet, int) */ + @Nullable public static Object getResultSetValue(ResultSet rs, int index, @Nullable Class requiredType) throws SQLException { if (requiredType == null) { return getResultSetValue(rs, index); @@ -310,7 +311,6 @@ public abstract class JdbcUtils { * the DatabaseMetaDataCallback's {@code processMetaData} method * @throws MetaDataAccessException if meta data access failed */ - @Nullable public static Object extractDatabaseMetaData(DataSource dataSource, DatabaseMetaDataCallback action) throws MetaDataAccessException { @@ -350,7 +350,6 @@ public abstract class JdbcUtils { * @see java.sql.DatabaseMetaData */ @SuppressWarnings("unchecked") - @Nullable public static T extractDatabaseMetaData(DataSource dataSource, final String metaDataMethodName) throws MetaDataAccessException { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java index 114fc5e7acb..5cc996c1d1b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java @@ -169,7 +169,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep @Override @Nullable - protected DataAccessException doTranslate(String task, String sql, SQLException ex) { + protected DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex) { SQLException sqlEx = ex; if (sqlEx instanceof BatchUpdateException && sqlEx.getNextException() != null) { SQLException nestedSqlEx = sqlEx.getNextException(); @@ -232,11 +232,11 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep // Next, look for grouped error codes. if (Arrays.binarySearch(this.sqlErrorCodes.getBadSqlGrammarCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); - return new BadSqlGrammarException(task, sql, sqlEx); + return new BadSqlGrammarException(task, (sql != null ? sql : ""), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getInvalidResultSetAccessCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); - return new InvalidResultSetAccessException(task, sql, sqlEx); + return new InvalidResultSetAccessException(task, (sql != null ? sql : ""), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); @@ -397,12 +397,12 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep } } - private void logTranslation(String task, String sql, SQLException sqlEx, boolean custom) { + private void logTranslation(String task, @Nullable String sql, SQLException sqlEx, boolean custom) { if (logger.isDebugEnabled()) { String intro = custom ? "Custom translation of" : "Translating"; logger.debug(intro + " SQLException with SQL state '" + sqlEx.getSQLState() + - "', error code '" + sqlEx.getErrorCode() + "', message [" + sqlEx.getMessage() + - "]; SQL was [" + sql + "] for task [" + task + "]"); + "', error code '" + sqlEx.getErrorCode() + "', message [" + sqlEx.getMessage() + "]" + + (sql != null ? "; SQL was [" + sql + "]": "") + " for task [" + task + "]"); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java index 0c340e82397..f175a28720f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java @@ -32,6 +32,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.PatternMatchUtils; +import org.springframework.util.StringUtils; /** * Factory for creating {@link SQLErrorCodes} based on the @@ -211,7 +212,7 @@ public class SQLErrorCodesFactory { // We could not find it - got to look it up. try { String name = JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); - if (name != null) { + if (StringUtils.hasLength(name)) { return registerDatabase(dataSource, name); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java index 5d4274d3b39..7654066d732 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java @@ -64,7 +64,7 @@ public class SQLExceptionSubclassTranslator extends AbstractFallbackSQLException @Override @Nullable - protected DataAccessException doTranslate(String task, String sql, SQLException ex) { + protected DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex) { if (ex instanceof SQLTransientException) { if (ex instanceof SQLTransientConnectionException) { return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); @@ -90,7 +90,7 @@ public class SQLExceptionSubclassTranslator extends AbstractFallbackSQLException return new PermissionDeniedDataAccessException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLSyntaxErrorException) { - return new BadSqlGrammarException(task, sql, ex); + return new BadSqlGrammarException(task, (sql != null ? sql : ""), ex); } else if (ex instanceof SQLFeatureNotSupportedException) { return new InvalidDataAccessApiUsageException(buildMessage(task, sql, ex), ex); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java index 48560ba376b..ef1cd82f982 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionTranslator.java @@ -46,12 +46,15 @@ public interface SQLExceptionTranslator { * check (and subsequent cast) is considered reliable when expecting JDBC-based * access to have happened. * @param task readable text describing the task being attempted - * @param sql SQL query or update that caused the problem (may be {@code null}) + * @param sql SQL query or update that caused the problem (if known) * @param ex the offending {@code SQLException} - * @return the DataAccessException, wrapping the {@code SQLException} + * @return the DataAccessException wrapping the {@code SQLException}, + * or {@code null} if no translation could be applied + * (in a custom translator; the default translators always throw an + * {@link org.springframework.jdbc.UncategorizedSQLException} in such a case) * @see org.springframework.dao.DataAccessException#getRootCause() */ @Nullable - DataAccessException translate(@Nullable String task, @Nullable String sql, SQLException ex); + DataAccessException translate(String task, @Nullable String sql, SQLException ex); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java index eb3939a2dd1..3178f0c21a7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java @@ -89,7 +89,7 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException @Override @Nullable - protected DataAccessException doTranslate(String task, String sql, SQLException ex) { + protected DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex) { // First, the getSQLState check... String sqlState = getSqlState(ex); if (sqlState != null && sqlState.length() >= 2) { @@ -98,7 +98,7 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException logger.debug("Extracted SQL state class '" + classCode + "' from value '" + sqlState + "'"); } if (BAD_SQL_GRAMMAR_CODES.contains(classCode)) { - return new BadSqlGrammarException(task, sql, ex); + return new BadSqlGrammarException(task, (sql != null ? sql : ""), ex); } else if (DATA_INTEGRITY_VIOLATION_CODES.contains(classCode)) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java index 9668204f595..7df5f2da7c0 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java @@ -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"); * you may not use this file except in compliance with the License. @@ -688,14 +688,10 @@ public class StoredProcedureTests { setDataSource(ds); setSql(SQL); getJdbcTemplate().setExceptionTranslator(new SQLExceptionTranslator() { - @Override - @Nullable - public DataAccessException translate(String task, @Nullable String sql, - SQLException sqlex) { - return new CustomDataException(sql, sqlex); + public DataAccessException translate(String task, @Nullable String sql, SQLException ex) { + return new CustomDataException(sql, ex); } - }); compile(); } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/support/CustomSqlExceptionTranslator.java b/spring-jdbc/src/test/java/org/springframework/jdbc/support/CustomSqlExceptionTranslator.java index 3bdf60a1ae5..012eb5bcc52 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/support/CustomSqlExceptionTranslator.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/support/CustomSqlExceptionTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 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 org.springframework.lang.Nullable; * @author Thomas Risberg */ public class CustomSqlExceptionTranslator implements SQLExceptionTranslator { + @Override public DataAccessException translate(String task, @Nullable String sql, SQLException ex) { if (ex.getErrorCode() == 2) { @@ -35,4 +36,5 @@ public class CustomSqlExceptionTranslator implements SQLExceptionTranslator { } return null; } + } diff --git a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java index 896874fb83a..5c60a650bfc 100644 --- a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java +++ b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java @@ -345,7 +345,9 @@ public class JmsListenerAnnotationBeanPostProcessor private MessageHandlerMethodFactory createDefaultJmsHandlerMethodFactory() { DefaultMessageHandlerMethodFactory defaultFactory = new DefaultMessageHandlerMethodFactory(); - defaultFactory.setBeanFactory(beanFactory); + if (beanFactory != null) { + defaultFactory.setBeanFactory(beanFactory); + } defaultFactory.afterPropertiesSet(); return defaultFactory; } diff --git a/spring-jms/src/main/java/org/springframework/jms/core/support/JmsGatewaySupport.java b/spring-jms/src/main/java/org/springframework/jms/core/support/JmsGatewaySupport.java index 30814dc8848..5114072abce 100644 --- a/spring-jms/src/main/java/org/springframework/jms/core/support/JmsGatewaySupport.java +++ b/spring-jms/src/main/java/org/springframework/jms/core/support/JmsGatewaySupport.java @@ -76,6 +76,7 @@ public abstract class JmsGatewaySupport implements InitializingBean { /** * Return the JMS ConnectionFactory used by the gateway. */ + @Nullable public final ConnectionFactory getConnectionFactory() { return (this.jmsTemplate != null ? this.jmsTemplate.getConnectionFactory() : null); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/DestinationVariableMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/DestinationVariableMethodArgumentResolver.java index 1291cab2c50..c476aaac229 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/DestinationVariableMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/DestinationVariableMethodArgumentResolver.java @@ -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"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.ValueConstants; +import org.springframework.util.Assert; /** * Resolves method parameters annotated with @@ -52,6 +53,7 @@ public class DestinationVariableMethodArgumentResolver extends AbstractNamedValu @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { DestinationVariable annotation = parameter.getParameterAnnotation(DestinationVariable.class); + Assert.state(annotation != null, "No DestinationVariable annotation"); return new DestinationVariableNamedValueInfo(annotation); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolver.java index 26a6b842f82..8bf0b02b2f8 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolver.java @@ -30,6 +30,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.support.NativeMessageHeaderAccessor; +import org.springframework.util.Assert; /** * Resolves method parameters annotated with {@link Header @Header}. @@ -55,6 +56,7 @@ public class HeaderMethodArgumentResolver extends AbstractNamedValueMethodArgume @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { Header annotation = parameter.getParameterAnnotation(Header.class); + Assert.state(annotation != null, "No Header annotation"); return new HeaderNamedValueInfo(annotation); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java index 9d118934939..5b19e6de7ff 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java @@ -522,6 +522,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { return (credentials != null ? credentials.passcode : null); } + @Nullable public static Integer getContentLength(Map> nativeHeaders) { List values = nativeHeaders.get(STOMP_CONTENT_LENGTH_HEADER); return (!CollectionUtils.isEmpty(values) ? Integer.valueOf(values.get(0)) : null); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java index ce369aa6eaf..065a16982a7 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java @@ -161,6 +161,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver { return null; } + @Nullable private ParseResult parseSubscriptionMessage(Message message, String sourceDestination) { MessageHeaders headers = message.getHeaders(); String sessionId = SimpMessageHeaderAccessor.getSessionId(headers); diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java index 2cd6caf9883..ebeb108d4dc 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java @@ -17,7 +17,6 @@ package org.springframework.orm.jpa; import java.util.Map; - import javax.persistence.EntityExistsException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @@ -481,12 +480,14 @@ public abstract class EntityManagerFactoryUtils { em.flush(); } catch (RuntimeException ex) { + DataAccessException dae; if (this.jpaDialect != null) { - throw this.jpaDialect.translateExceptionIfPossible(ex); + dae = this.jpaDialect.translateExceptionIfPossible(ex); } else { - throw convertJpaAccessExceptionIfPossible(ex); + dae = convertJpaAccessExceptionIfPossible(ex); } + throw (dae != null ? dae : ex); } } diff --git a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java index 61fb4a84aba..93e1b1224a3 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java @@ -490,7 +490,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi if (context == null) { try { if (StringUtils.hasLength(this.contextPath)) { - context = createJaxbContextFromContextPath(); + context = createJaxbContextFromContextPath(this.contextPath); } else if (!ObjectUtils.isEmpty(this.classesToBeBound)) { context = createJaxbContextFromClasses(this.classesToBeBound); @@ -511,26 +511,26 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi } } - private JAXBContext createJaxbContextFromContextPath() throws JAXBException { + private JAXBContext createJaxbContextFromContextPath(String contextPath) throws JAXBException { if (logger.isInfoEnabled()) { logger.info("Creating JAXBContext with context path [" + this.contextPath + "]"); } if (this.jaxbContextProperties != null) { if (this.beanClassLoader != null) { - return JAXBContext.newInstance(this.contextPath, this.beanClassLoader, this.jaxbContextProperties); + return JAXBContext.newInstance(contextPath, this.beanClassLoader, this.jaxbContextProperties); } else { // analogous to the JAXBContext.newInstance(String) implementation - return JAXBContext.newInstance(this.contextPath, Thread.currentThread().getContextClassLoader(), + return JAXBContext.newInstance(contextPath, Thread.currentThread().getContextClassLoader(), this.jaxbContextProperties); } } else { if (this.beanClassLoader != null) { - return JAXBContext.newInstance(this.contextPath, this.beanClassLoader); + return JAXBContext.newInstance(contextPath, this.beanClassLoader); } else { - return JAXBContext.newInstance(this.contextPath); + return JAXBContext.newInstance(contextPath); } } } diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockExpressionEvaluator.java b/spring-test/src/main/java/org/springframework/mock/web/MockExpressionEvaluator.java index 00334454f4e..a09d9a757f2 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockExpressionEvaluator.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockExpressionEvaluator.java @@ -68,7 +68,6 @@ public class MockExpressionEvaluator extends javax.servlet.jsp.el.ExpressionEval public Object evaluate(String expression, Class expectedType, javax.servlet.jsp.el.VariableResolver variableResolver, javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException { - Assert.isNull(variableResolver, "Custom VariableResolver not supported"); return doEvaluate(expression, expectedType, functionMapper); } @@ -76,7 +75,6 @@ public class MockExpressionEvaluator extends javax.servlet.jsp.el.ExpressionEval protected Object doEvaluate(String expression, Class expectedType, javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException { - Assert.isNull(functionMapper, "Custom FunctionMapper not supported"); try { return ExpressionEvaluatorManager.evaluate("JSP EL expression", expression, expectedType, this.pageContext); } diff --git a/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java index bcd2afe2df4..1e54f550da2 100644 --- a/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java @@ -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"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.lang.Nullable; import org.springframework.test.context.TestContext; import org.springframework.test.context.jdbc.Sql.ExecutionPhase; import org.springframework.test.context.jdbc.SqlConfig.ErrorMode; @@ -231,6 +232,7 @@ public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListen } } + @Nullable private DataSource getDataSourceFromTransactionManager(PlatformTransactionManager transactionManager) { try { Method getDataSourceMethod = transactionManager.getClass().getMethod("getDataSource"); diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/AbstractExpressionEvaluatingCondition.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/AbstractExpressionEvaluatingCondition.java index cc8276d2a35..f177f7739f8 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/AbstractExpressionEvaluatingCondition.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/AbstractExpressionEvaluatingCondition.java @@ -23,7 +23,6 @@ import java.util.function.Function; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; @@ -69,7 +68,6 @@ abstract class AbstractExpressionEvaluatingCondition implements ExecutionConditi /** * Evaluate the expression configured via the supplied annotation type on * the {@link AnnotatedElement} for the supplied {@link ExtensionContext}. - * * @param annotationType the type of annotation to process * @param expressionExtractor a function that extracts the expression from * the annotation @@ -88,6 +86,7 @@ abstract class AbstractExpressionEvaluatingCondition implements ExecutionConditi Function expressionExtractor, Function reasonExtractor, Function loadContextExtractor, boolean enabledOnTrue, ExtensionContext context) { + Assert.state(context.getElement().isPresent(), "No AnnotatedElement"); AnnotatedElement element = context.getElement().get(); Optional annotation = findMergedAnnotation(element, annotationType); @@ -100,13 +99,11 @@ abstract class AbstractExpressionEvaluatingCondition implements ExecutionConditi return ConditionEvaluationResult.enabled(reason); } - // @formatter:off String expression = annotation.map(expressionExtractor).map(String::trim).filter(StringUtils::hasLength) .orElseThrow(() -> new IllegalStateException(String.format( "The expression in @%s on [%s] must not be blank", annotationType.getSimpleName(), element))); - // @formatter:on - boolean loadContext = annotation.map(loadContextExtractor).get(); + boolean loadContext = loadContextExtractor.apply(annotation.get()); boolean evaluatedToTrue = evaluateExpression(expression, loadContext, annotationType, context); if (evaluatedToTrue) { @@ -127,20 +124,21 @@ abstract class AbstractExpressionEvaluatingCondition implements ExecutionConditi if (logger.isDebugEnabled()) { logger.debug(reason); } - return (enabledOnTrue ? ConditionEvaluationResult.disabled(reason) - : ConditionEvaluationResult.enabled(reason)); + return (enabledOnTrue ? ConditionEvaluationResult.disabled(reason) : + ConditionEvaluationResult.enabled(reason)); } } private boolean evaluateExpression(String expression, boolean loadContext, - Class annotationType, ExtensionContext extensionContext) { + Class annotationType, ExtensionContext context) { - AnnotatedElement element = extensionContext.getElement().get(); + Assert.state(context.getElement().isPresent(), "No AnnotatedElement"); + AnnotatedElement element = context.getElement().get(); GenericApplicationContext gac = null; ApplicationContext applicationContext; if (loadContext) { - applicationContext = SpringExtension.getApplicationContext(extensionContext); + applicationContext = SpringExtension.getApplicationContext(context); } else { gac = new GenericApplicationContext(); @@ -191,8 +189,9 @@ abstract class AbstractExpressionEvaluatingCondition implements ExecutionConditi } } - private static Optional findMergedAnnotation(AnnotatedElement element, - Class annotationType) { + private static Optional findMergedAnnotation( + AnnotatedElement element, Class annotationType) { + return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType)); } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java index 883af7902cc..e6820235493 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java @@ -20,9 +20,9 @@ import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExtensionContext; /** - * {@code DisabledIfCondition} is an {@link ExecutionCondition} that supports the - * {@link DisabledIf @DisabledIf} annotation when using the Spring TestContext - * Framework in conjunction with JUnit 5's Jupiter programming model. + * {@code DisabledIfCondition} is an {@link org.junit.jupiter.api.extension.ExecutionCondition} + * that supports the {@link DisabledIf @DisabledIf} annotation when using the Spring + * TestContext Framework in conjunction with JUnit 5's Jupiter programming model. * *

Any attempt to use the {@code DisabledIfCondition} without the presence of * {@link DisabledIf @DisabledIf} will result in an enabled @@ -43,8 +43,8 @@ public class DisabledIfCondition extends AbstractExpressionEvaluatingCondition { */ @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - return evaluateAnnotation(DisabledIf.class, DisabledIf::expression, DisabledIf::reason, DisabledIf::loadContext, - false, context); + return evaluateAnnotation(DisabledIf.class, DisabledIf::expression, DisabledIf::reason, + DisabledIf::loadContext, false, context); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java index edbc6887149..7b28f172fdd 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java @@ -20,9 +20,9 @@ import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExtensionContext; /** - * {@code EnabledIfCondition} is an {@link ExecutionCondition} that supports the - * {@link EnabledIf @EnabledIf} annotation when using the Spring TestContext - * Framework in conjunction with JUnit 5's Jupiter programming model. + * {@code EnabledIfCondition} is an {@link org.junit.jupiter.api.extension.ExecutionCondition} + * that supports the {@link EnabledIf @EnabledIf} annotation when using the Spring + * TestContext Framework in conjunction with JUnit 5's Jupiter programming model. * *

Any attempt to use the {@code EnabledIfCondition} without the presence of * {@link EnabledIf @EnabledIf} will result in an enabled @@ -43,8 +43,8 @@ public class EnabledIfCondition extends AbstractExpressionEvaluatingCondition { */ @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - return evaluateAnnotation(EnabledIf.class, EnabledIf::expression, EnabledIf::reason, EnabledIf::loadContext, - true, context); + return evaluateAnnotation(EnabledIf.class, EnabledIf::expression, EnabledIf::reason, + EnabledIf::loadContext, true, context); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTestNGSpringContextTests.java b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTestNGSpringContextTests.java index 8f5cdda1b1a..596ca27d86b 100644 --- a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTestNGSpringContextTests.java +++ b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTestNGSpringContextTests.java @@ -115,7 +115,6 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App /** * Set the {@link ApplicationContext} to be used by this test instance, * provided via {@link ApplicationContextAware} semantics. - * * @param applicationContext the ApplicationContext that this test runs in */ @Override @@ -123,13 +122,11 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App this.applicationContext = applicationContext; } + /** * Delegates to the configured {@link TestContextManager} to call - * {@linkplain TestContextManager#beforeTestClass() 'before test class'} - * callbacks. - * - * @throws Exception if a registered TestExecutionListener throws an - * exception + * {@linkplain TestContextManager#beforeTestClass() 'before test class'} callbacks. + * @throws Exception if a registered TestExecutionListener throws an exception */ @BeforeClass(alwaysRun = true) protected void springTestContextBeforeTestClass() throws Exception { @@ -141,9 +138,7 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App * {@linkplain TestContextManager#prepareTestInstance(Object) prepare} this test * instance prior to execution of any individual tests, for example for * injecting dependencies, etc. - * - * @throws Exception if a registered TestExecutionListener throws an - * exception + * @throws Exception if a registered TestExecutionListener throws an exception */ @BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextBeforeTestClass") protected void springTestContextPrepareTestInstance() throws Exception { @@ -154,7 +149,6 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App * Delegates to the configured {@link TestContextManager} to * {@linkplain TestContextManager#beforeTestMethod(Object,Method) pre-process} * the test method before the actual test is executed. - * * @param testMethod the test method which is about to be executed * @throws Exception allows all exceptions to propagate */ @@ -167,7 +161,6 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App * Delegates to the {@linkplain IHookCallBack#runTestMethod(ITestResult) test * method} in the supplied {@code callback} to execute the actual test * and then tracks the exception thrown during test execution, if any. - * * @see org.testng.IHookable#run(IHookCallBack, ITestResult) */ @Override @@ -224,15 +217,14 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App /** * Delegates to the configured {@link TestContextManager} to call * {@linkplain TestContextManager#afterTestClass() 'after test class'} callbacks. - * - * @throws Exception if a registered TestExecutionListener throws an - * exception + * @throws Exception if a registered TestExecutionListener throws an exception */ @AfterClass(alwaysRun = true) protected void springTestContextAfterTestClass() throws Exception { this.testContextManager.afterTestClass(); } + private Throwable getTestResultException(ITestResult testResult) { Throwable testResultException = testResult.getThrowable(); if (testResultException instanceof InvocationTargetException) { @@ -241,12 +233,10 @@ public abstract class AbstractTestNGSpringContextTests implements IHookable, App return testResultException; } - @Nullable private RuntimeException throwAsUncheckedException(Throwable t) { throwAs(t); - // Appeasing the compiler: the following line will never be executed. - return null; + throw new IllegalStateException(t); } @SuppressWarnings("unchecked") diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java index 8711001106a..ccf80918ba3 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java @@ -95,7 +95,7 @@ public final class MockMvc { * A default request builder merged into every performed request. * @see org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder#defaultRequest(RequestBuilder) */ - void setDefaultRequest(RequestBuilder requestBuilder) { + void setDefaultRequest(@Nullable RequestBuilder requestBuilder) { this.defaultRequestBuilder = requestBuilder; } @@ -104,7 +104,7 @@ public final class MockMvc { * @see org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder#alwaysExpect(ResultMatcher) */ void setGlobalResultMatchers(List resultMatchers) { - Assert.notNull(resultMatchers, "resultMatchers is required"); + Assert.notNull(resultMatchers, "ResultMatcher List is required"); this.defaultResultMatchers = resultMatchers; } @@ -113,7 +113,7 @@ public final class MockMvc { * @see org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder#alwaysDo(ResultHandler) */ void setGlobalResultHandlers(List resultHandlers) { - Assert.notNull(resultHandlers, "resultHandlers is required"); + Assert.notNull(resultHandlers, "ResultHandler List is required"); this.defaultResultHandlers = resultHandlers; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java index 01773787bc9..070abe66091 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java @@ -41,7 +41,7 @@ import org.springframework.web.context.WebApplicationContext; public abstract class MockMvcBuilderSupport { protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig, - WebApplicationContext webAppContext, RequestBuilder defaultRequestBuilder, + WebApplicationContext webAppContext, @Nullable RequestBuilder defaultRequestBuilder, List globalResultMatchers, List globalResultHandlers, @Nullable List dispatcherServletCustomizers) { diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java index 1b6726d160a..07e17055bd8 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java @@ -448,7 +448,6 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override - @Nullable public String getName() { return joinpointIdentification; } diff --git a/spring-web/spring-web.gradle b/spring-web/spring-web.gradle index 3a244f21422..35e78057179 100644 --- a/spring-web/spring-web.gradle +++ b/spring-web/spring-web.gradle @@ -26,7 +26,7 @@ dependencies { optional("javax.faces:javax.faces-api:2.2") optional("javax.validation:validation-api:1.1.0.Final") optional("org.codehaus.groovy:groovy-all:${groovyVersion}") - optional("com.caucho:hessian:4.0.38") + optional("com.caucho:hessian:4.0.51") optional("commons-fileupload:commons-fileupload:1.3.3") optional("org.synchronoss.cloud:nio-multipart-parser:1.1.0") optional("io.projectreactor.ipc:reactor-netty") diff --git a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java index 389b98eb25e..e160d739308 100644 --- a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java @@ -30,6 +30,7 @@ import okhttp3.RequestBody; import org.springframework.beans.factory.DisposableBean; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -145,6 +146,7 @@ public class OkHttp3ClientHttpRequestFactory return builder.build(); } + @Nullable private static okhttp3.MediaType getContentType(HttpHeaders headers) { String rawContentType = headers.getFirst(HttpHeaders.CONTENT_TYPE); return (StringUtils.hasText(rawContentType) ? okhttp3.MediaType.parse(rawContentType) : null); diff --git a/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java index 8535fb9b63e..67988a271c2 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java @@ -79,6 +79,7 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl return result; } + @Nullable private Decoder getSseDecoder() { if (this.sseDecoder != null) { return this.sseDecoder; diff --git a/spring-web/src/main/java/org/springframework/http/codec/DefaultServerCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/DefaultServerCodecConfigurer.java index 18a62958885..5313c4b5d81 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/DefaultServerCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/DefaultServerCodecConfigurer.java @@ -91,6 +91,7 @@ class DefaultServerCodecConfigurer extends AbstractCodecConfigurer implements Se return result; } + @Nullable private Encoder getSseEncoder() { if (this.sseEncoder != null) { return this.sseEncoder; diff --git a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java index 0b487c1b174..9366f2c956c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java @@ -67,6 +67,7 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter { this.defaultMediaType = initDefaultMediaType(this.mediaTypes); } + @Nullable private static MediaType initDefaultMediaType(List mediaTypes) { return mediaTypes.stream().filter(MediaType::isConcrete).findFirst().orElse(null); } diff --git a/spring-web/src/main/java/org/springframework/web/context/request/RequestContextHolder.java b/spring-web/src/main/java/org/springframework/web/context/request/RequestContextHolder.java index be50f557800..0134e6f7ff0 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/RequestContextHolder.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/RequestContextHolder.java @@ -145,6 +145,7 @@ public abstract class RequestContextHolder { */ private static class FacesRequestAttributesFactory { + @Nullable public static RequestAttributes getFacesRequestAttributes() { FacesContext facesContext = FacesContext.getCurrentInstance(); return (facesContext != null ? new FacesRequestAttributes(facesContext) : null); diff --git a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java index 37f10e5cb65..f9ed7fb086a 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java @@ -146,6 +146,10 @@ public abstract class CommonsFileUploadSupport { this.fileUpload.setHeaderEncoding(defaultEncoding); } + /** + * Determine the default encoding to use for parsing requests. + * @see #setDefaultEncoding + */ protected String getDefaultEncoding() { String encoding = getFileUpload().getHeaderEncoding(); if (encoding == null) { @@ -167,6 +171,10 @@ public abstract class CommonsFileUploadSupport { this.uploadTempDirSpecified = true; } + /** + * Return the temporary directory where uploaded files get stored. + * @see #setUploadTempDir + */ protected boolean isUploadTempDirSpecified() { return this.uploadTempDirSpecified; } @@ -247,19 +255,14 @@ public abstract class CommonsFileUploadSupport { if (fileItem.isFormField()) { String value; String partEncoding = determineEncoding(fileItem.getContentType(), encoding); - if (partEncoding != null) { - try { - value = fileItem.getString(partEncoding); - } - catch (UnsupportedEncodingException ex) { - if (logger.isWarnEnabled()) { - logger.warn("Could not decode multipart item '" + fileItem.getFieldName() + - "' with encoding '" + partEncoding + "': using platform default"); - } - value = fileItem.getString(); - } + try { + value = fileItem.getString(partEncoding); } - else { + catch (UnsupportedEncodingException ex) { + if (logger.isWarnEnabled()) { + logger.warn("Could not decode multipart item '" + fileItem.getFieldName() + + "' with encoding '" + partEncoding + "': using platform default"); + } value = fileItem.getString(); } String[] curParam = multipartParameters.get(fileItem.getFieldName()); @@ -324,7 +327,6 @@ public abstract class CommonsFileUploadSupport { } } - @Nullable private String determineEncoding(String contentTypeHeader, String defaultEncoding) { if (!StringUtils.hasText(contentTypeHeader)) { return defaultEncoding; diff --git a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java index f251d918290..bd1beaf2602 100644 --- a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java +++ b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -135,6 +136,7 @@ final class HierarchicalUriComponents extends UriComponents { } @Override + @NonNull public String getPath() { return this.path.getPath(); } diff --git a/spring-web/src/main/java/org/springframework/web/util/WebUtils.java b/spring-web/src/main/java/org/springframework/web/util/WebUtils.java index 02ddfc3a3ca..d51c005575a 100644 --- a/spring-web/src/main/java/org/springframework/web/util/WebUtils.java +++ b/spring-web/src/main/java/org/springframework/web/util/WebUtils.java @@ -299,7 +299,6 @@ public abstract class WebUtils { * @return the value of the session attribute, or {@code null} if not found * @throws IllegalStateException if the session attribute could not be found */ - @Nullable public static Object getRequiredSessionAttribute(HttpServletRequest request, String name) throws IllegalStateException { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java index f888282ea2a..f74a832cc7a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java @@ -334,15 +334,12 @@ class DefaultWebClient implements WebClient { } private HttpHeaders initHeaders() { - if (CollectionUtils.isEmpty(defaultHeaders) && CollectionUtils.isEmpty(this.headers)) { - return new HttpHeaders(); + if (CollectionUtils.isEmpty(this.headers)) { + return (defaultHeaders != null ? defaultHeaders : new HttpHeaders()); } else if (CollectionUtils.isEmpty(defaultHeaders)) { return this.headers; } - else if (CollectionUtils.isEmpty(this.headers)) { - return defaultHeaders; - } else { HttpHeaders result = new HttpHeaders(); result.putAll(this.headers); @@ -356,15 +353,12 @@ class DefaultWebClient implements WebClient { } private MultiValueMap initCookies() { - if (CollectionUtils.isEmpty(defaultCookies) && CollectionUtils.isEmpty(this.cookies)) { - return new LinkedMultiValueMap<>(0); + if (CollectionUtils.isEmpty(this.cookies)) { + return (defaultCookies != null ? defaultCookies : new LinkedMultiValueMap<>(0)); } else if (CollectionUtils.isEmpty(defaultCookies)) { return this.cookies; } - else if (CollectionUtils.isEmpty(this.cookies)) { - return defaultCookies; - } else { MultiValueMap result = new LinkedMultiValueMap<>(); result.putAll(this.cookies); @@ -379,9 +373,11 @@ class DefaultWebClient implements WebClient { } } + private static class DefaultResponseSpec implements ResponseSpec { - private static final StatusHandler DEFAULT_STATUS_HANDLER = new StatusHandler(HttpStatus::isError, DefaultResponseSpec::createResponseException); + private static final StatusHandler DEFAULT_STATUS_HANDLER = + new StatusHandler(HttpStatus::isError, DefaultResponseSpec::createResponseException); private final Mono responseMono; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java index 8d0f4df2e46..77eada63078 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/CompositeRequestCondition.java @@ -50,7 +50,7 @@ public class CompositeRequestCondition extends AbstractRequestCondition... requestConditions) { + public CompositeRequestCondition(RequestCondition... requestConditions) { this.requestConditions = wrap(requestConditions); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/RequestConditionHolder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/RequestConditionHolder.java index 9d2e882af90..ed9b016f9d9 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/RequestConditionHolder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/RequestConditionHolder.java @@ -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"); * you may not use this file except in compliance with the License. @@ -38,12 +38,13 @@ import org.springframework.web.server.ServerWebExchange; */ public final class RequestConditionHolder extends AbstractRequestCondition { + @Nullable private final RequestCondition condition; /** * Create a new holder to wrap the given request condition. - * @param requestCondition the condition to hold, may be {@code null} + * @param requestCondition the condition to hold (may be {@code null}) */ @SuppressWarnings("unchecked") public RequestConditionHolder(@Nullable RequestCondition requestCondition) { @@ -86,23 +87,12 @@ public final class RequestConditionHolder extends AbstractRequestCondition combined = (RequestCondition) this.condition.combine(other.condition); return new RequestConditionHolder(combined); } } - /** - * Ensure the held request conditions are of the same type. - */ - private void assertEqualConditionTypes(RequestConditionHolder other) { - Class clazz = this.condition.getClass(); - Class otherClazz = other.condition.getClass(); - if (!clazz.equals(otherClazz)) { - throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz); - } - } - /** * Get the matching condition for the held request condition wrap it in a * new RequestConditionHolder instance. Or otherwise if this is an empty @@ -134,9 +124,20 @@ public final class RequestConditionHolder extends AbstractRequestCondition cond1, RequestCondition cond2) { + Class clazz = cond1.getClass(); + Class otherClazz = cond2.getClass(); + if (!clazz.equals(otherClazz)) { + throw new ClassCastException("Incompatible request conditions: " + clazz + " vs " + otherClazz); + } + } + } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java index 6777ee7ce72..8f02444d16c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java @@ -124,6 +124,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi * @see #getCustomTypeCondition(Class) * @see #getCustomMethodCondition(Method) */ + @Nullable private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); RequestCondition condition = (element instanceof Class ? diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index 3dd375ac827..7949c16ad56 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -467,6 +467,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { } } + @Nullable private String getAsyncTimeout(Element element) { Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support"); return (asyncElement != null) ? asyncElement.getAttribute("default-timeout") : null; @@ -555,6 +556,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { return result; } + @Nullable private ManagedList getReturnValueHandlers(Element element, ParserContext parserContext) { Element handlers = DomUtils.getChildElementByTagName(element, "return-value-handlers"); return (handlers != null ? extractBeanSubElements(handlers, parserContext) : null); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java index 58446e8e414..255c8b42823 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java @@ -154,6 +154,7 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser { } } + @Nullable private String registerResourceHandler(ParserContext parserContext, Element element, @Nullable Object source) { String locationAttr = element.getAttribute("location"); if (!StringUtils.hasText(locationAttr)) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java index 8390c11677d..4e2ab4bbf0e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java @@ -123,19 +123,19 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser { compositeResolverBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); names = new String[] {"content-negotiation"}; - List contentnNegotiationElements = DomUtils.getChildElementsByTagName(element, names); - if (contentnNegotiationElements.isEmpty()) { + List contentNegotiationElements = DomUtils.getChildElementsByTagName(element, names); + if (contentNegotiationElements.isEmpty()) { compositeResolverBeanDef.getPropertyValues().add("viewResolvers", resolvers); } - else if (contentnNegotiationElements.size() == 1) { - BeanDefinition beanDef = createContentNegotiatingViewResolver(contentnNegotiationElements.get(0), context); + else if (contentNegotiationElements.size() == 1) { + BeanDefinition beanDef = createContentNegotiatingViewResolver(contentNegotiationElements.get(0), context); beanDef.getPropertyValues().add("viewResolvers", resolvers); ManagedList list = new ManagedList<>(1); list.add(beanDef); compositeResolverBeanDef.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); compositeResolverBeanDef.getPropertyValues().add("viewResolvers", list); } - else if (contentnNegotiationElements.size() > 1) { + else { throw new IllegalArgumentException("Only one element is allowed."); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java index 5ec810f6ea2..8fa1c402439 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java @@ -232,6 +232,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition message) { for (SubProtocolHandler handler : this.protocolHandlerLookup.values()) { String sessionId = handler.resolveSessionId(message); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/SpringConfigurator.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/SpringConfigurator.java index 304459917fd..d407a00b1b5 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/SpringConfigurator.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/SpringConfigurator.java @@ -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"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -97,6 +98,7 @@ public class SpringConfigurator extends Configurator { return wac.getAutowireCapableBeanFactory().createBean(endpointClass); } + @Nullable private String getBeanNameByType(WebApplicationContext wac, Class endpointClass) { String wacId = wac.getId();