diff --git a/build.gradle b/build.gradle
index ee9347475a..4dc15ceb58 100644
--- a/build.gradle
+++ b/build.gradle
@@ -334,7 +334,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
- toolVersion = "8.36"
+ toolVersion = "8.36.1"
configDirectory.set(rootProject.file("src/checkstyle"))
}
diff --git a/spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java b/spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java
index b5e37e3698..c9d21201a6 100644
--- a/spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java
+++ b/spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.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.
@@ -159,8 +159,6 @@ public class MimeMessageHelper {
private static final String HEADER_PRIORITY = "X-Priority";
- private static final String HEADER_CONTENT_ID = "Content-ID";
-
private final MimeMessage mimeMessage;
@@ -175,6 +173,8 @@ public class MimeMessageHelper {
private FileTypeMap fileTypeMap;
+ private boolean encodeFilenames = true;
+
private boolean validateAddresses = false;
@@ -464,7 +464,7 @@ public class MimeMessageHelper {
* Set the Java Activation Framework {@code FileTypeMap} to use
* for determining the content type of inline content and attachments
* that get added to the message.
- *
Default is the {@code FileTypeMap} that the underlying
+ *
The default is the {@code FileTypeMap} that the underlying
* MimeMessage carries, if any, or the Activation Framework's default
* {@code FileTypeMap} instance else.
* @see #addInline
@@ -480,18 +480,40 @@ public class MimeMessageHelper {
/**
* Return the {@code FileTypeMap} used by this MimeMessageHelper.
+ * @see #setFileTypeMap
*/
public FileTypeMap getFileTypeMap() {
return this.fileTypeMap;
}
+ /**
+ * Set whether to encode attachment filenames passed to this helper's
+ * {@code #addAttachment} methods.
+ *
The default is {@code true} for compatibility with older email clients;
+ * turn this to {@code false} for standard MIME behavior. On a related note,
+ * check out JavaMail's {@code mail.mime.encodefilename} system property.
+ * @since 5.2.9
+ * @see #addAttachment(String, DataSource)
+ * @see MimeBodyPart#setFileName(String)
+ */
+ public void setEncodeFilenames(boolean encodeFilenames) {
+ this.encodeFilenames = encodeFilenames;
+ }
+
+ /**
+ * Return whether to encode attachment filenames passed to this helper's
+ * {@code #addAttachment} methods.
+ * @since 5.2.9
+ * @see #setEncodeFilenames
+ */
+ public boolean isEncodeFilenames() {
+ return this.encodeFilenames;
+ }
+
/**
* Set whether to validate all addresses which get passed to this helper.
- * Default is "false".
- *
Note that this is by default just available for JavaMail >= 1.3.
- * You can override the default {@code validateAddress method} for
- * validation on older JavaMail versions (or for custom validation).
+ *
The default is {@code false}.
* @see #validateAddress
*/
public void setValidateAddresses(boolean validateAddresses) {
@@ -500,6 +522,7 @@ public class MimeMessageHelper {
/**
* Return whether this helper will validate all addresses passed to it.
+ * @see #setValidateAddresses
*/
public boolean isValidateAddresses() {
return this.validateAddresses;
@@ -508,10 +531,8 @@ public class MimeMessageHelper {
/**
* Validate the given mail address.
* Called by all of MimeMessageHelper's address setters and adders.
- *
Default implementation invokes {@code InternetAddress.validate()},
+ *
The default implementation invokes {@link InternetAddress#validate()},
* provided that address validation is activated for the helper instance.
- *
Note that this method will just work on JavaMail >= 1.3. You can override
- * it for validation on older JavaMail versions or for custom validation.
* @param address the address to validate
* @throws AddressException if validation failed
* @see #isValidateAddresses()
@@ -525,7 +546,8 @@ public class MimeMessageHelper {
/**
* Validate all given mail addresses.
- * Default implementation simply delegates to validateAddress for each address.
+ *
The default implementation simply delegates to {@link #validateAddress}
+ * for each address.
* @param addresses the addresses to validate
* @throws AddressException if validation failed
* @see #validateAddress(InternetAddress)
@@ -885,9 +907,7 @@ public class MimeMessageHelper {
Assert.notNull(dataSource, "DataSource must not be null");
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setDisposition(MimeBodyPart.INLINE);
- // We're using setHeader here to remain compatible with JavaMail 1.2,
- // rather than JavaMail 1.3's setContentID.
- mimeBodyPart.setHeader(HEADER_CONTENT_ID, "<" + contentId + ">");
+ mimeBodyPart.setContentID("<" + contentId + ">");
mimeBodyPart.setDataHandler(new DataHandler(dataSource));
getMimeMultipart().addBodyPart(mimeBodyPart);
}
@@ -997,7 +1017,8 @@ public class MimeMessageHelper {
try {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
- mimeBodyPart.setFileName(MimeUtility.encodeText(attachmentFilename));
+ mimeBodyPart.setFileName(isEncodeFilenames() ?
+ MimeUtility.encodeText(attachmentFilename) : attachmentFilename);
mimeBodyPart.setDataHandler(new DataHandler(dataSource));
getRootMimeMultipart().addBodyPart(mimeBodyPart);
}
diff --git a/spring-core/src/main/java/org/springframework/core/codec/StringDecoder.java b/spring-core/src/main/java/org/springframework/core/codec/StringDecoder.java
index 1069110f80..143d1c6ff1 100644
--- a/spring-core/src/main/java/org/springframework/core/codec/StringDecoder.java
+++ b/spring-core/src/main/java/org/springframework/core/codec/StringDecoder.java
@@ -103,6 +103,7 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
return this.defaultCharset;
}
+
@Override
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
return (elementType.resolve() == String.class && super.canDecode(elementType, mimeType));
@@ -167,7 +168,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
/**
* Finds the first match and longest delimiter, {@link EndFrameBuffer} just after it.
- *
* @param dataBuffer the buffer to find delimiters in
* @param matcher used to find the first delimiters
* @return a flux of buffers, containing {@link EndFrameBuffer} after each delimiter that was
@@ -221,7 +221,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
}
DataBuffer result = dataBuffers.get(0).factory().join(dataBuffers);
-
if (stripDelimiter && matchingDelimiter != null) {
result.writePosition(result.writePosition() - matchingDelimiter.length);
}
@@ -229,8 +228,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
}
-
-
/**
* Create a {@code StringDecoder} for {@code "text/plain"}.
* @param stripDelimiter this flag is ignored
@@ -293,8 +290,7 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
private static final DataBuffer BUFFER = DefaultDataBufferFactory.sharedInstance.wrap(new byte[0]);
- private byte[] delimiter;
-
+ private final byte[] delimiter;
public EndFrameBuffer(byte[] delimiter) {
super(BUFFER);
@@ -304,7 +300,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
public byte[] delimiter() {
return this.delimiter;
}
-
}
@@ -313,7 +308,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder {
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final LimitedDataBufferList list;
-
LimitChecker(int maxInMemorySize) {
this.list = new LimitedDataBufferList(maxInMemorySize);
}
diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java
index f4f4393218..a476de69cc 100644
--- a/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java
+++ b/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.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.
@@ -30,9 +30,9 @@ import org.springframework.core.convert.converter.Converter;
*/
final class StringToBooleanConverter implements Converter {
- private static final Set trueValues = new HashSet<>(4);
+ private static final Set trueValues = new HashSet<>(8);
- private static final Set falseValues = new HashSet<>(4);
+ private static final Set falseValues = new HashSet<>(8);
static {
trueValues.add("true");
@@ -46,6 +46,7 @@ final class StringToBooleanConverter implements Converter {
falseValues.add("0");
}
+
@Override
public Boolean convert(String source) {
String value = source.trim();
diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/StringToUUIDConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/StringToUUIDConverter.java
index 6a3d858569..cb63290f4e 100644
--- a/spring-core/src/main/java/org/springframework/core/convert/support/StringToUUIDConverter.java
+++ b/spring-core/src/main/java/org/springframework/core/convert/support/StringToUUIDConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 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.
@@ -19,6 +19,7 @@ package org.springframework.core.convert.support;
import java.util.UUID;
import org.springframework.core.convert.converter.Converter;
+import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -31,6 +32,7 @@ import org.springframework.util.StringUtils;
final class StringToUUIDConverter implements Converter {
@Override
+ @Nullable
public UUID convert(String source) {
return (StringUtils.hasText(source) ? UUID.fromString(source.trim()) : null);
}
diff --git a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
index 004067d4d0..6db7d90f6a 100644
--- a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
+++ b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
@@ -562,7 +562,7 @@ public final class ContentDisposition {
private static class BuilderImpl implements Builder {
- private String type;
+ private final String type;
@Nullable
private String name;
diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java
index f5b9493951..01e403e17f 100644
--- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java
+++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java
@@ -861,7 +861,7 @@ public class HttpHeaders implements MultiValueMap, Serializable
public void setContentDispositionFormData(String name, @Nullable String filename) {
Assert.notNull(name, "Name must not be null");
ContentDisposition.Builder disposition = ContentDisposition.builder("form-data").name(name);
- if (filename != null) {
+ if (StringUtils.hasText(filename)) {
disposition.filename(filename);
}
setContentDisposition(disposition.build());
@@ -888,7 +888,7 @@ public class HttpHeaders implements MultiValueMap, Serializable
*/
public ContentDisposition getContentDisposition() {
String contentDisposition = getFirst(CONTENT_DISPOSITION);
- if (contentDisposition != null) {
+ if (StringUtils.hasText(contentDisposition)) {
return ContentDisposition.parse(contentDisposition);
}
return ContentDisposition.empty();
diff --git a/src/docs/asciidoc/core/core-aop-api.adoc b/src/docs/asciidoc/core/core-aop-api.adoc
index da9e0dca2b..cbfbab9e0b 100644
--- a/src/docs/asciidoc/core/core-aop-api.adoc
+++ b/src/docs/asciidoc/core/core-aop-api.adoc
@@ -103,13 +103,13 @@ The `MethodMatcher` interface is normally more important. The complete interface
The `matches(Method, Class)` method is used to test whether this pointcut ever
matches a given method on a target class. This evaluation can be performed when an AOP
proxy is created to avoid the need for a test on every method invocation. If the
-two-argument `matches` method returns `true` for a given method, and the `isRuntime()` method
-for the MethodMatcher returns `true`, the three-argument matches method is invoked on
-every method invocation. This lets a pointcut look at the arguments passed to the
-method invocation immediately before the target advice starts.
+two-argument `matches` method returns `true` for a given method, and the `isRuntime()`
+method for the MethodMatcher returns `true`, the three-argument matches method is
+invoked on every method invocation. This lets a pointcut look at the arguments passed
+to the method invocation immediately before the target advice starts.
-Most `MethodMatcher` implementations are static, meaning that their `isRuntime()` method returns `false`.
-In this case, the three-argument `matches` method is never invoked.
+Most `MethodMatcher` implementations are static, meaning that their `isRuntime()` method
+returns `false`. In this case, the three-argument `matches` method is never invoked.
TIP: If possible, try to make pointcuts static, allowing the AOP framework to cache the
results of pointcut evaluation when an AOP proxy is created.
@@ -145,20 +145,20 @@ See the <> for a discussion of supported AspectJ pointcut
[[aop-api-pointcuts-impls]]
=== Convenience Pointcut Implementations
-Spring provides several convenient pointcut implementations. You can use some of them directly.
-Others are intended to be subclassed in application-specific pointcuts.
+Spring provides several convenient pointcut implementations. You can use some of them
+directly; others are intended to be subclassed in application-specific pointcuts.
[[aop-api-pointcuts-static]]
==== Static Pointcuts
-Static pointcuts are based on the method and the target class and cannot take into account the
-method's arguments. Static pointcuts suffice -- and are best -- for most usages.
-Spring can evaluate a static pointcut only once, when a method is first
-invoked. After that, there is no need to evaluate the pointcut again with each method
-invocation.
+Static pointcuts are based on the method and the target class and cannot take into account
+the method's arguments. Static pointcuts suffice -- and are best -- for most usages.
+Spring can evaluate a static pointcut only once, when a method is first invoked.
+After that, there is no need to evaluate the pointcut again with each method invocation.
-The rest of this section describes some of the static pointcut implementations that are included with Spring.
+The rest of this section describes some of the static pointcut implementations that are
+included with Spring.
[[aop-api-pointcuts-regex]]
===== Regular Expression Pointcuts
@@ -168,9 +168,9 @@ frameworks besides Spring make this possible.
`org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular
expression pointcut that uses the regular expression support in the JDK.
-With the `JdkRegexpMethodPointcut` class, you can provide a list of pattern strings. If
-any of these is a match, the pointcut evaluates to `true`. (So, the result is
-effectively the union of these patterns.)
+With the `JdkRegexpMethodPointcut` class, you can provide a list of pattern strings.
+If any of these is a match, the pointcut evaluates to `true`. (As a consequence,
+the resulting pointcut is effectively the union of the specified patterns.)
The following example shows how to use `JdkRegexpMethodPointcut`:
diff --git a/src/docs/asciidoc/core/core-beans.adoc b/src/docs/asciidoc/core/core-beans.adoc
index 775d24dddd..df0f1f33f2 100644
--- a/src/docs/asciidoc/core/core-beans.adoc
+++ b/src/docs/asciidoc/core/core-beans.adoc
@@ -4424,7 +4424,8 @@ which these `BeanFactoryPostProcessor` instances run by setting the `order` prop
However, you can only set this property if the `BeanFactoryPostProcessor` implements the
`Ordered` interface. If you write your own `BeanFactoryPostProcessor`, you should
consider implementing the `Ordered` interface, too. See the javadoc of the
-{api-spring-framework}/beans/factory/config/BeanFactoryPostProcessor.html[`BeanFactoryPostProcessor`] and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces for more details.
+{api-spring-framework}/beans/factory/config/BeanFactoryPostProcessor.html[`BeanFactoryPostProcessor`]
+and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces for more details.
[NOTE]
====