diff --git a/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java b/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java index cd9eed9634..0e5b1a91ae 100644 --- a/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java +++ b/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java @@ -168,7 +168,7 @@ public class AntPathMatcher implements PathMatcher { @Override - public boolean isPattern(String path) { + public boolean isPattern(@Nullable String path) { if (path == null) { return false; } @@ -207,10 +207,10 @@ public class AntPathMatcher implements PathMatcher { * as far as the given base path goes is sufficient) * @return {@code true} if the supplied {@code path} matched, {@code false} if it didn't */ - protected boolean doMatch(String pattern, String path, boolean fullMatch, + protected boolean doMatch(String pattern, @Nullable String path, boolean fullMatch, @Nullable Map uriTemplateVariables) { - if ((path == null) || (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator))) { + if (path == null || path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { return false; } @@ -220,7 +220,6 @@ public class AntPathMatcher implements PathMatcher { } String[] pathDirs = tokenizePath(path); - int pattIdxStart = 0; int pattIdxEnd = pattDirs.length - 1; int pathIdxStart = 0; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/DestinationVariable.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/DestinationVariable.java index c0b4dc19ff..99a117de03 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/DestinationVariable.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/DestinationVariable.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2019 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,13 +26,12 @@ import java.lang.annotation.Target; * Annotation that indicates a method parameter should be bound to a template variable * in a destination template string. Supported on message handling methods such as * {@link MessageMapping @MessageMapping}. - *

- * A {@code @DestinationVariable} template variable is always required. + * + *

A {@code @DestinationVariable} template variable is always required. * * @author Brian Clozel * @author Rossen Stoyanchev * @since 4.0 - * * @see org.springframework.messaging.handler.annotation.MessageMapping * @see org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler */ diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/MessageMapping.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/MessageMapping.java index d9a0c4cb29..27c4076c8d 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/MessageMapping.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/MessageMapping.java @@ -23,7 +23,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.messaging.Message; -import org.springframework.messaging.simp.annotation.SendToUser; /** * Annotation for mapping a {@link Message} onto a message-handling method by @@ -65,11 +64,11 @@ import org.springframework.messaging.simp.annotation.SendToUser; * authenticated user. * * - *

How the return value is handled depends on the processing scenario. - * For STOMP over WebSocket, it is turned into a message and sent to a default - * response destination or to a custom destination specified with an - * {@link SendTo @SendTo} or {@link SendToUser @SendToUser} annotation. - * For RSocket, the response is used to reply to the stream request. + *

How the return value is handled depends on the processing scenario. For + * STOMP over WebSocket, it is turned into a message and sent to a default response + * destination or to a custom destination specified with an {@link SendTo @SendTo} + * or {@link org.springframework.messaging.simp.annotation.SendToUser @SendToUser} + * annotation. For RSocket, the response is used to reply to the stream request. * *

Specializations of this annotation including * {@link org.springframework.messaging.simp.annotation.SubscribeMapping @SubscribeMapping} or diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/DefaultClientResponderFactory.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/DefaultClientResponderFactory.java index ba80b0f418..db412dfc2e 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/DefaultClientResponderFactory.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/DefaultClientResponderFactory.java @@ -35,6 +35,7 @@ import org.springframework.util.RouteMatcher; */ class DefaultClientResponderFactory implements ClientResponderFactory, ClientResponderFactory.Config { + @Nullable private List handlers; @Nullable @@ -52,9 +53,10 @@ class DefaultClientResponderFactory implements ClientResponderFactory, ClientRes @Nullable private ArgumentResolverConfigurer argumentResolverConfigurer; + @Override public ClientResponderFactory handlers(Object... handlers) { - Assert.notEmpty(handlers, "handlers should not be empty"); + Assert.notEmpty(handlers, "Handlers array must not be empty"); this.handlers = Arrays.asList(handlers); return this; } @@ -89,9 +91,10 @@ class DefaultClientResponderFactory implements ClientResponderFactory, ClientRes return this; } + @Override public void accept(RSocketFactory.ClientRSocketFactory clientRSocketFactory) { - Assert.notEmpty(this.handlers, "handlers should not be empty"); + Assert.state(this.handlers != null, "No handlers set"); RSocketMessageHandler messageHandler = new RSocketMessageHandler(); messageHandler.setHandlers(this.handlers); if (this.strategies != null) { diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 95b03df8d2..6b3aa23b9d 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -232,9 +232,9 @@ public class MockHttpServletResponse implements HttpServletResponse { * @see #getContentAsString() */ public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException { - return isCharset() ? + return (isCharset() && this.characterEncoding != null ? this.content.toString(this.characterEncoding) : - this.content.toString(fallbackCharset.name()); + this.content.toString(fallbackCharset.name())); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java index 5094cbc4a1..6424f89212 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java @@ -438,7 +438,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter parts, MediaType contentType, HttpOutputMessage outputMessage) + private void writeMultipart( + MultiValueMap parts, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException { // If the supplied content type is null, fall back to multipart/form-data. diff --git a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java index 6f7349c9b3..90b59765d9 100644 --- a/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java +++ b/spring-web/src/main/java/org/springframework/web/method/ControllerAdviceBean.java @@ -110,13 +110,13 @@ public class ControllerAdviceBean implements Ordered { public ControllerAdviceBean(String beanName, BeanFactory beanFactory, @Nullable ControllerAdvice controllerAdvice) { Assert.hasText(beanName, "Bean name must contain text"); Assert.notNull(beanFactory, "BeanFactory must not be null"); - Assert.isTrue(beanFactory.containsBean(beanName), () -> "BeanFactory [" + beanFactory - + "] does not contain specified controller advice bean '" + beanName + "'"); + Assert.isTrue(beanFactory.containsBean(beanName), () -> "BeanFactory [" + beanFactory + + "] does not contain specified controller advice bean '" + beanName + "'"); this.beanOrName = beanName; this.beanType = getBeanType(beanName, beanFactory); - this.beanTypePredicate = (controllerAdvice != null ? createBeanTypePredicate(controllerAdvice) - : createBeanTypePredicate(this.beanType)); + this.beanTypePredicate = (controllerAdvice != null ? createBeanTypePredicate(controllerAdvice) : + createBeanTypePredicate(this.beanType)); this.beanFactory = beanFactory; } @@ -140,8 +140,11 @@ public class ControllerAdviceBean implements Ordered { if (resolvedBean instanceof Ordered) { this.order = ((Ordered) resolvedBean).getOrder(); } + else if (this.beanType != null) { + this.order = OrderUtils.getOrder(this.beanType, Ordered.LOWEST_PRECEDENCE); + } else { - this.order = OrderUtils.getOrder(getBeanType(), Ordered.LOWEST_PRECEDENCE); + this.order = Ordered.LOWEST_PRECEDENCE; } } return this.order; @@ -236,18 +239,19 @@ public class ControllerAdviceBean implements Ordered { return adviceBeans; } + @Nullable private static Class getBeanType(String beanName, BeanFactory beanFactory) { Class beanType = beanFactory.getType(beanName); return (beanType != null ? ClassUtils.getUserClass(beanType) : null); } - private static HandlerTypePredicate createBeanTypePredicate(Class beanType) { + private static HandlerTypePredicate createBeanTypePredicate(@Nullable Class beanType) { ControllerAdvice controllerAdvice = (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, ControllerAdvice.class) : null); return createBeanTypePredicate(controllerAdvice); } - private static HandlerTypePredicate createBeanTypePredicate(ControllerAdvice controllerAdvice) { + private static HandlerTypePredicate createBeanTypePredicate(@Nullable ControllerAdvice controllerAdvice) { if (controllerAdvice != null) { return HandlerTypePredicate.builder() .basePackage(controllerAdvice.basePackages()) diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java index 40791c6a26..08fba223e3 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java @@ -231,11 +231,10 @@ public class MockHttpServletResponse implements HttpServletResponse { * @since 5.2 * @see #getContentAsString() */ - public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException { - return isCharset() ? + return (isCharset() && this.characterEncoding != null ? this.content.toString(this.characterEncoding) : - this.content.toString(fallbackCharset.name()); + this.content.toString(fallbackCharset.name())); } @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java index 9fb6f45617..23907d0f1d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java @@ -124,6 +124,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView { /** * See {@link ScriptTemplateConfigurer#setEngineSupplier(Supplier)} documentation. + * @since 5.2 */ public void setEngineSupplier(Supplier engineSupplier) { this.engineSupplier = engineSupplier; @@ -276,8 +277,9 @@ public class ScriptTemplateView extends AbstractUrlBasedView { } private ScriptEngine createEngineFromSupplier() { + Assert.state(this.engineSupplier != null, "No engine supplier available"); ScriptEngine engine = this.engineSupplier.get(); - if (this.renderFunction != null && engine != null) { + if (this.renderFunction != null) { Assert.isInstanceOf(Invocable.class, engine, "ScriptEngine must implement Invocable when 'renderFunction' is specified"); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java index 5a2ff4c44f..2a2fec4e57 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java @@ -144,6 +144,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView { /** * See {@link ScriptTemplateConfigurer#setEngineSupplier(Supplier)} documentation. + * @since 5.2 */ public void setEngineSupplier(Supplier engineSupplier) { this.engineSupplier = engineSupplier; @@ -286,9 +287,8 @@ public class ScriptTemplateView extends AbstractUrlBasedView { engines = new HashMap<>(4); enginesHolder.set(engines); } - String name = (this.engineName != null ? this.engineName : this.engineSupplier.getClass().getSimpleName()); - Object engineKey = (!ObjectUtils.isEmpty(this.scripts) ? - new EngineKey(name, this.scripts) : name); + String name = (this.engineName != null ? this.engineName : ""); + Object engineKey = (!ObjectUtils.isEmpty(this.scripts) ? new EngineKey(name, this.scripts) : name); ScriptEngine engine = engines.get(engineKey); if (engine == null) { if (this.engineName != null) { @@ -308,18 +308,22 @@ public class ScriptTemplateView extends AbstractUrlBasedView { } } - protected ScriptEngine createEngineFromName(@Nullable String engineName) { - if (this.scriptEngineManager == null) { - this.scriptEngineManager = new ScriptEngineManager(obtainApplicationContext().getClassLoader()); + protected ScriptEngine createEngineFromName(String engineName) { + ScriptEngineManager scriptEngineManager = this.scriptEngineManager; + if (scriptEngineManager == null) { + scriptEngineManager = new ScriptEngineManager(obtainApplicationContext().getClassLoader()); + this.scriptEngineManager = scriptEngineManager; } - ScriptEngine engine = StandardScriptUtils.retrieveEngineByName(this.scriptEngineManager, engineName); + + ScriptEngine engine = StandardScriptUtils.retrieveEngineByName(scriptEngineManager, engineName); loadScripts(engine); return engine; } private ScriptEngine createEngineFromSupplier() { + Assert.state(this.engineSupplier != null, "No engine supplier available"); ScriptEngine engine = this.engineSupplier.get(); - if (this.renderFunction != null && engine != null) { + if (this.renderFunction != null) { Assert.isInstanceOf(Invocable.class, engine, "ScriptEngine must implement Invocable when 'renderFunction' is specified"); }