From bacf6ca37b062a298fd1aca1ceeab4649dad890b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 7 Oct 2020 15:03:26 +0200 Subject: [PATCH] Polishing --- .../DefaultManagedTaskScheduler.java | 5 +- .../org/springframework/util/MimeType.java | 7 +-- .../converter/AbstractMessageConverter.java | 40 +++++++------ .../simp/stomp/DefaultStompSession.java | 4 +- .../support/NativeMessageHeaderAccessor.java | 58 +++++++++++++++---- .../MappingJackson2MessageConverterTests.java | 22 +++---- .../http/converter/HttpMessageConverter.java | 6 +- .../web/util/UriComponentsBuilder.java | 2 +- 8 files changed, 92 insertions(+), 52 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskScheduler.java index 3c1897207f9..92b4053eb4d 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskScheduler.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskScheduler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2020 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. @@ -35,10 +35,11 @@ import org.springframework.jndi.JndiTemplate; * * @author Juergen Hoeller * @since 4.0 + * @see javax.enterprise.concurrent.ManagedScheduledExecutorService */ public class DefaultManagedTaskScheduler extends ConcurrentTaskScheduler implements InitializingBean { - private JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate(); + private final JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate(); private String jndiName = "java:comp/DefaultManagedScheduledExecutorService"; diff --git a/spring-core/src/main/java/org/springframework/util/MimeType.java b/spring-core/src/main/java/org/springframework/util/MimeType.java index eee47407aab..569f56be0fd 100644 --- a/spring-core/src/main/java/org/springframework/util/MimeType.java +++ b/spring-core/src/main/java/org/springframework/util/MimeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -193,7 +193,7 @@ public class MimeType implements Comparable, Serializable { * @see HTTP 1.1, section 2.2 */ private void checkToken(String token) { - for (int i = 0; i < token.length(); i++ ) { + for (int i = 0; i < token.length(); i++) { char ch = token.charAt(i); if (!TOKEN.get(ch)) { throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + token + "\""); @@ -206,8 +206,7 @@ public class MimeType implements Comparable, Serializable { Assert.hasLength(value, "'value' must not be empty"); checkToken(attribute); if (PARAM_CHARSET.equals(attribute)) { - value = unquote(value); - Charset.forName(value); + Charset.forName(unquote(value)); } else if (!isQuotedString(value)) { checkToken(value); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java index bbfb0aa2357..ff5c8c4e905 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -149,20 +149,6 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter } - /** - * Returns the default content type for the payload. Called when - * {@link #toMessage(Object, MessageHeaders)} is invoked without message headers or - * without a content type header. - *

By default, this returns the first element of the {@link #getSupportedMimeTypes() - * supportedMimeTypes}, if any. Can be overridden in sub-classes. - * @param payload the payload being converted to message - * @return the content type, or {@code null} if not known - */ - protected MimeType getDefaultContentType(Object payload) { - List mimeTypes = getSupportedMimeTypes(); - return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null); - } - @Override public final Object fromMessage(Message message, Class targetClass) { return fromMessage(message, targetClass, null); @@ -176,10 +162,6 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter return convertFromInternal(message, targetClass, conversionHint); } - protected boolean canConvertFrom(Message message, Class targetClass) { - return (supports(targetClass) && supportsMimeType(message.getHeaders())); - } - @Override public final Message toMessage(Object payload, MessageHeaders headers) { return toMessage(payload, headers, null); @@ -213,6 +195,11 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter return builder.build(); } + + protected boolean canConvertFrom(Message message, Class targetClass) { + return (supports(targetClass) && supportsMimeType(message.getHeaders())); + } + protected boolean canConvertTo(Object payload, MessageHeaders headers) { Class clazz = (payload != null ? payload.getClass() : null); return (supports(clazz) && supportsMimeType(headers)); @@ -238,6 +225,21 @@ public abstract class AbstractMessageConverter implements SmartMessageConverter return (this.contentTypeResolver != null ? this.contentTypeResolver.resolve(headers) : null); } + /** + * Return the default content type for the payload. Called when + * {@link #toMessage(Object, MessageHeaders)} is invoked without + * message headers or without a content type header. + *

By default, this returns the first element of the + * {@link #getSupportedMimeTypes() supportedMimeTypes}, if any. + * Can be overridden in subclasses. + * @param payload the payload being converted to a message + * @return the content type, or {@code null} if not known + */ + protected MimeType getDefaultContentType(Object payload) { + List mimeTypes = getSupportedMimeTypes(); + return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null); + } + /** * Whether the given class is supported by this converter. diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java index 2a6bedbdb30..af0b2ca26f7 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -654,8 +654,10 @@ public class DefaultStompSession implements ConnectionHandlingStompSession { if (conn != null) { conn.send(HEARTBEAT).addCallback( new ListenableFutureCallback() { + @Override public void onSuccess(Void result) { } + @Override public void onFailure(Throwable ex) { handleFailure(ex); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/NativeMessageHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/support/NativeMessageHeaderAccessor.java index 72f64dfa3de..a2690b663ad 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/NativeMessageHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/NativeMessageHeaderAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. @@ -52,14 +52,14 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { /** - * A protected constructor to create new headers. + * Protected constructor to create a new instance. */ protected NativeMessageHeaderAccessor() { this((Map>) null); } /** - * A protected constructor to create new headers. + * Protected constructor to create an instance with the given native headers. * @param nativeHeaders native headers to create the message with (may be {@code null}) */ protected NativeMessageHeaderAccessor(Map> nativeHeaders) { @@ -69,7 +69,7 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { } /** - * A protected constructor accepting the headers of an existing message to copy. + * Protected constructor that copies headers from another message. */ protected NativeMessageHeaderAccessor(Message message) { super(message); @@ -84,13 +84,17 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { } } + + /** + * Subclasses can use this method to access the "native" headers sub-map. + */ @SuppressWarnings("unchecked") private Map> getNativeHeaders() { return (Map>) getHeader(NATIVE_HEADERS); } /** - * Return a copy of the native header values or an empty map. + * Return a copy of the native headers sub-map, or an empty map. */ public Map> toNativeHeaderMap() { Map> map = getNativeHeaders(); @@ -112,6 +116,7 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { /** * Whether the native header map contains the give header name. + * @param headerName the name of the header */ public boolean containsNativeHeader(String headerName) { Map> map = getNativeHeaders(); @@ -119,7 +124,9 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { } /** - * @return all values for the specified native header or {@code null}. + * Return all values for the specified native header, if present. + * @param headerName the name of the header + * @return the associated values, or {@code null} if none */ public List getNativeHeader(String headerName) { Map> map = getNativeHeaders(); @@ -127,13 +134,15 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { } /** - * @return the first value for the specified native header of {@code null}. + * Return the first value for the specified native header, if present. + * @param headerName the name of the header + * @return the associated value, or {@code null} if none */ public String getFirstNativeHeader(String headerName) { Map> map = getNativeHeaders(); if (map != null) { List values = map.get(headerName); - if (values != null) { + if (!CollectionUtils.isEmpty(values)) { return values.get(0); } } @@ -142,6 +151,8 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { /** * Set the specified native header value replacing existing values. + *

In order for this to work, the accessor must be {@link #isMutable() + * mutable}. See {@link MessageHeaderAccessor} for details. */ public void setNativeHeader(String name, String value) { Assert.state(isMutable(), "Already immutable"); @@ -167,6 +178,10 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { /** * Add the specified native header value to existing values. + *

In order for this to work, the accessor must be {@link #isMutable() + * mutable}. See {@link MessageHeaderAccessor} for details. + * @param name the name of the header + * @param value the header value to set */ public void addNativeHeader(String name, String value) { Assert.state(isMutable(), "Already immutable"); @@ -187,6 +202,10 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { setModified(true); } + /** + * Add the specified native headers to existing values. + * @param headers the headers to set + */ public void addNativeHeaders(MultiValueMap headers) { if (headers == null) { return; @@ -198,21 +217,36 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor { } } - public List removeNativeHeader(String name) { + /** + * Remove the specified native header value replacing existing values. + *

In order for this to work, the accessor must be {@link #isMutable() + * mutable}. See {@link MessageHeaderAccessor} for details. + * @param headerName the name of the header + * @return the associated values, or {@code null} if the header was not present + */ + public List removeNativeHeader(String headerName) { Assert.state(isMutable(), "Already immutable"); Map> nativeHeaders = getNativeHeaders(); - if (nativeHeaders == null) { + if (CollectionUtils.isEmpty(nativeHeaders)) { return null; } - return nativeHeaders.remove(name); + return nativeHeaders.remove(headerName); } + + /** + * Return the first value for the specified native header, + * or {@code null} if none. + * @param headerName the name of the header + * @param headers the headers map to introspect + * @return the associated value, or {@code null} if none + */ @SuppressWarnings("unchecked") public static String getFirstNativeHeader(String headerName, Map headers) { Map> map = (Map>) headers.get(NATIVE_HEADERS); if (map != null) { List values = map.get(headerName); - if (values != null) { + if (!CollectionUtils.isEmpty(values)) { return values.get(0); } } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java b/spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java index dd9052478d0..c0c3d1b6db3 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/converter/MappingJackson2MessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package org.springframework.messaging.converter; -import java.io.IOException; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -74,7 +73,7 @@ public class MappingJackson2MessageConverterTests { } @Test - public void fromMessage() throws Exception { + public void fromMessage() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); String payload = "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; Message message = MessageBuilder.withPayload(payload.getBytes(UTF_8)).build(); @@ -89,7 +88,7 @@ public class MappingJackson2MessageConverterTests { } @Test - public void fromMessageUntyped() throws Exception { + public void fromMessageUntyped() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); String payload = "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"]," + "\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; @@ -106,7 +105,7 @@ public class MappingJackson2MessageConverterTests { } @Test(expected = MessageConversionException.class) - public void fromMessageInvalidJson() throws Exception { + public void fromMessageInvalidJson() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); String payload = "FooBar"; Message message = MessageBuilder.withPayload(payload.getBytes(UTF_8)).build(); @@ -114,7 +113,7 @@ public class MappingJackson2MessageConverterTests { } @Test - public void fromMessageValidJsonWithUnknownProperty() throws IOException { + public void fromMessageValidJsonWithUnknownProperty() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); String payload = "{\"string\":\"string\",\"unknownProperty\":\"value\"}"; Message message = MessageBuilder.withPayload(payload.getBytes(UTF_8)).build(); @@ -151,7 +150,7 @@ public class MappingJackson2MessageConverterTests { } @Test - public void toMessage() throws Exception { + public void toMessage() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); MyBean payload = new MyBean(); payload.setString("Foo"); @@ -239,11 +238,14 @@ public class MappingJackson2MessageConverterTests { return bean; } - public void jsonViewPayload(@JsonView(MyJacksonView2.class) JacksonViewBean payload) {} + public void jsonViewPayload(@JsonView(MyJacksonView2.class) JacksonViewBean payload) { + } - void handleList(List payload) {} + void handleList(List payload) { + } - void handleMessage(Message message) {} + void handleMessage(Message message) { + } public static class MyBean { diff --git a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverter.java index 12ce8f2b5f3..9fb987b101f 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; /** - * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses. + * Strategy interface for converting from and to HTTP requests and responses. * * @author Arjen Poutsma * @author Juergen Hoeller @@ -52,7 +52,7 @@ public interface HttpMessageConverter { /** * Return the list of {@link MediaType} objects supported by this converter. - * @return the list of supported media types + * @return the list of supported media types, potentially an immutable copy */ List getSupportedMediaTypes(); diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index a757e00055b..6dc2afd8077 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -213,7 +213,7 @@ public class UriComponentsBuilder implements Cloneable { } builder.scheme(scheme); if (opaque) { - String ssp = uri.substring(scheme.length()).substring(1); + String ssp = uri.substring(scheme.length() + 1); if (StringUtils.hasLength(fragment)) { ssp = ssp.substring(0, ssp.length() - (fragment.length() + 1)); }