Skip to content

Commit edd6876

Browse files
author
yuyang
committed
Merge branch 'master' of https://github.com/spring-projects/spring-framework into read_yuyang
* 'master' of https://github.com/spring-projects/spring-framework: Update copyright date Hoist concatenation of two constant Strings out of loops Avoid setting special Content-* response headers for Tomcat Consistent use of AnnotationUtils.rethrowAnnotationConfigurationException() Fix Checkstyle violation Introduce @disabled regression test for spring-projectsgh-24375 Polishing contribution Expose proxyPing Reactor Netty WebSocket Updates to Validation section in reference HttpWebHandlerAdapter#formatRequest is protected Fix issue with new line handling in StompDecoder Simplify getCache() implementation in CaffeineCacheManager Publish a build scan only if authenticated Update Artifactory plugin to 4.12.0
2 parents 6b4597c + b344049 commit edd6876

File tree

18 files changed

+306
-110
lines changed

18 files changed

+306
-110
lines changed

build.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
id 'io.spring.nohttp' version '0.0.4.RELEASE'
77
id 'de.undercouch.download' version '4.0.0'
88
id 'com.gradle.build-scan' version '3.1.1'
9-
id "com.jfrog.artifactory" version '4.11.0' apply false
9+
id "com.jfrog.artifactory" version '4.12.0' apply false
1010
id "io.freefair.aspectj" version "4.1.1" apply false
1111
id "com.github.ben-manes.versions" version "0.24.0"
1212
}
@@ -17,7 +17,8 @@ buildScan {
1717
obfuscation {
1818
ipAddresses { addresses -> addresses.collect { address -> '0.0.0.0'} }
1919
}
20-
publishAlwaysIf(System.getenv('GRADLE_ENTERPRISE_URL') != null)
20+
publishAlways()
21+
publishIfAuthenticated()
2122
server = 'https://ge.spring.io'
2223
}
2324

spring-beans/src/main/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReader.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -422,10 +422,13 @@ protected void registerBeanDefinition(String beanName, Map<?, ?> map, String pre
422422
ConstructorArgumentValues cas = new ConstructorArgumentValues();
423423
MutablePropertyValues pvs = new MutablePropertyValues();
424424

425+
String prefixWithSep = prefix + SEPARATOR;
426+
int beginIndex = prefix.length() + SEPARATOR.length();
427+
425428
for (Map.Entry<?, ?> entry : map.entrySet()) {
426429
String key = StringUtils.trimWhitespace((String) entry.getKey());
427-
if (key.startsWith(prefix + SEPARATOR)) {
428-
String property = key.substring(prefix.length() + SEPARATOR.length());
430+
if (key.startsWith(prefixWithSep)) {
431+
String property = key.substring(beginIndex);
429432
if (CLASS_KEY.equals(property)) {
430433
className = StringUtils.trimWhitespace((String) entry.getValue());
431434
}

spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCacheManager.java

+4-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@
5050
* @author Ben Manes
5151
* @author Juergen Hoeller
5252
* @author Stephane Nicoll
53+
* @author Sam Brannen
5354
* @since 4.3
5455
* @see CaffeineCache
5556
*/
@@ -178,17 +179,8 @@ public Collection<String> getCacheNames() {
178179
@Override
179180
@Nullable
180181
public Cache getCache(String name) {
181-
Cache cache = this.cacheMap.get(name);
182-
if (cache == null && this.dynamic) {
183-
synchronized (this.cacheMap) {
184-
cache = this.cacheMap.get(name);
185-
if (cache == null) {
186-
cache = createCaffeineCache(name);
187-
this.cacheMap.put(name, cache);
188-
}
189-
}
190-
}
191-
return cache;
182+
return this.cacheMap.computeIfAbsent(name, cacheName ->
183+
this.dynamic ? createCaffeineCache(cacheName) : null);
192184
}
193185

194186
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2002-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package example.gh24375;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
import org.springframework.core.annotation.AliasFor;
25+
26+
@Target(ElementType.TYPE)
27+
@Retention(RetentionPolicy.RUNTIME)
28+
public @interface A {
29+
30+
@AliasFor("value")
31+
B other() default @B;
32+
33+
@AliasFor("other")
34+
B value() default @B;
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2002-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package example.gh24375;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
@Target(ElementType.ANNOTATION_TYPE)
25+
@Retention(RetentionPolicy.RUNTIME)
26+
public @interface B {
27+
28+
String name() default "";
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2002-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package example.gh24375;
18+
19+
import org.springframework.stereotype.Component;
20+
21+
@Component
22+
@A(other = @B)
23+
public class MyComponent {
24+
}

spring-context/src/test/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProviderTests.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.Set;
2222
import java.util.regex.Pattern;
2323

24+
import example.gh24375.MyComponent;
2425
import example.profilescan.DevComponent;
2526
import example.profilescan.ProfileAnnotatedComponent;
2627
import example.profilescan.ProfileMetaAnnotatedComponent;
@@ -38,6 +39,7 @@
3839
import example.scannable.StubFooDao;
3940
import example.scannable.sub.BarComponent;
4041
import org.aspectj.lang.annotation.Aspect;
42+
import org.junit.jupiter.api.Disabled;
4143
import org.junit.jupiter.api.Test;
4244

4345
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
@@ -500,6 +502,16 @@ public void testIntegrationWithAnnotationConfigApplicationContext_metaProfile()
500502
}
501503
}
502504

505+
@Test
506+
@Disabled("Disabled until gh-24375 is resolved")
507+
public void gh24375() {
508+
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
509+
Set<BeanDefinition> components = provider.findCandidateComponents(MyComponent.class.getPackage().getName());
510+
assertThat(components).hasSize(1);
511+
assertThat(components.iterator().next().getBeanClassName()).isEqualTo(MyComponent.class.getName());
512+
}
513+
514+
503515
private boolean containsBeanClass(Set<BeanDefinition> candidates, Class<?> beanClass) {
504516
for (BeanDefinition candidate : candidates) {
505517
if (beanClass.getName().equals(candidate.getBeanClassName())) {

spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,9 +116,7 @@ private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable Annotat
116116
queue.addLast(new AnnotationTypeMapping(source, annotationType, ann));
117117
}
118118
catch (Exception ex) {
119-
if (ex instanceof AnnotationConfigurationException) {
120-
throw (AnnotationConfigurationException) ex;
121-
}
119+
AnnotationUtils.rethrowAnnotationConfigurationException(ex);
122120
if (failureLogger.isEnabled()) {
123121
failureLogger.log("Failed to introspect meta-annotation " + annotationType.getName(),
124122
(source != null ? source.getAnnotationType() : null), ex);

spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -1076,7 +1076,7 @@ public static Object getValue(@Nullable Annotation annotation, @Nullable String
10761076
* <p>Otherwise, this method does nothing.
10771077
* @param ex the throwable to inspect
10781078
*/
1079-
private static void rethrowAnnotationConfigurationException(Throwable ex) {
1079+
static void rethrowAnnotationConfigurationException(Throwable ex) {
10801080
if (ex instanceof AnnotationConfigurationException) {
10811081
throw (AnnotationConfigurationException) ex;
10821082
}

spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -672,9 +672,7 @@ private static <A extends Annotation> TypeMappedAnnotation<A> createIfPossible(
672672
valueExtractor, aggregateIndex);
673673
}
674674
catch (Exception ex) {
675-
if (ex instanceof AnnotationConfigurationException) {
676-
throw (AnnotationConfigurationException) ex;
677-
}
675+
AnnotationUtils.rethrowAnnotationConfigurationException(ex);
678676
if (logger.isEnabled()) {
679677
String type = mapping.getAnnotationType().getName();
680678
String item = (mapping.getDistance() == 0 ? "annotation " + type :

spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -166,9 +166,10 @@ public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotatio
166166
if (attributes == null) {
167167
return null;
168168
}
169+
String annotatedElement = "class '" + getClassName() + "'";
169170
for (AnnotationAttributes raw : attributes) {
170171
for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues(
171-
"class '" + getClassName() + "'", this.classLoader, raw, classValuesAsString).entrySet()) {
172+
annotatedElement, this.classLoader, raw, classValuesAsString).entrySet()) {
172173
allAttributes.add(entry.getKey(), entry.getValue());
173174
}
174175
}

spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -114,6 +114,10 @@ public List<Message<byte[]>> decode(ByteBuffer byteBuffer,
114114
Message<byte[]> message = decodeMessage(byteBuffer, partialMessageHeaders);
115115
if (message != null) {
116116
messages.add(message);
117+
skipEol(byteBuffer);
118+
if (!byteBuffer.hasRemaining()) {
119+
break;
120+
}
117121
}
118122
else {
119123
break;
@@ -128,7 +132,7 @@ public List<Message<byte[]>> decode(ByteBuffer byteBuffer,
128132
@Nullable
129133
private Message<byte[]> decodeMessage(ByteBuffer byteBuffer, @Nullable MultiValueMap<String, String> headers) {
130134
Message<byte[]> decodedMessage = null;
131-
skipLeadingEol(byteBuffer);
135+
skipEol(byteBuffer);
132136

133137
// Explicit mark/reset access via Buffer base type for compatibility
134138
// with covariant return type on JDK 9's ByteBuffer...
@@ -196,9 +200,10 @@ private void initHeaders(StompHeaderAccessor headerAccessor) {
196200

197201
/**
198202
* Skip one ore more EOL characters at the start of the given ByteBuffer.
199-
* Those are STOMP heartbeat frames.
203+
* STOMP, section 2.1 says: "The NULL octet can be optionally followed by
204+
* multiple EOLs."
200205
*/
201-
protected void skipLeadingEol(ByteBuffer byteBuffer) {
206+
protected void skipEol(ByteBuffer byteBuffer) {
202207
while (true) {
203208
if (!tryConsumeEndOfLine(byteBuffer)) {
204209
break;

spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompDecoderTests.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.messaging.simp.stomp;
1818

19-
import java.io.UnsupportedEncodingException;
2019
import java.nio.ByteBuffer;
2120
import java.util.List;
2221

@@ -78,7 +77,7 @@ public void decodeFrameWithNoBody() {
7877
}
7978

8079
@Test
81-
public void decodeFrame() throws UnsupportedEncodingException {
80+
public void decodeFrame() {
8281
Message<byte[]> frame = decode("SEND\ndestination:test\n\nThe body of the message\0");
8382
StompHeaderAccessor headers = StompHeaderAccessor.wrap(frame);
8483

@@ -166,6 +165,17 @@ public void decodeFrameBodyNotAllowed() {
166165
decode("CONNECT\naccept-version:1.2\n\nThe body of the message\0"));
167166
}
168167

168+
@Test // gh-23713
169+
public void decodeFramesWithExtraNewLines() {
170+
String frame1 = "SEND\ndestination:test\n\nbody\0\n\n\n";
171+
ByteBuffer buffer = ByteBuffer.wrap((frame1).getBytes());
172+
173+
final List<Message<byte[]>> messages = decoder.decode(buffer);
174+
175+
assertThat(messages.size()).isEqualTo(1);
176+
assertThat(StompHeaderAccessor.wrap(messages.get(0)).getCommand()).isEqualTo(StompCommand.SEND);
177+
}
178+
169179
@Test
170180
public void decodeMultipleFramesFromSameBuffer() {
171181
String frame1 = "SEND\ndestination:test\n\nThe body of the message\0";
@@ -179,9 +189,7 @@ public void decodeMultipleFramesFromSameBuffer() {
179189
assertThat(StompHeaderAccessor.wrap(messages.get(1)).getCommand()).isEqualTo(StompCommand.DISCONNECT);
180190
}
181191

182-
// SPR-13111
183-
184-
@Test
192+
@Test // SPR-13111
185193
public void decodeFrameWithHeaderWithEmptyValue() {
186194
String accept = "accept-version:1.1\n";
187195
String valuelessKey = "key:\n";

spring-web/src/main/java/org/springframework/http/server/reactive/TomcatHttpHandlerAdapter.java

+2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ protected void applyHeaders() {
216216
if (response.getContentType() == null && contentType != null) {
217217
response.setContentType(contentType.toString());
218218
}
219+
getHeaders().remove(HttpHeaders.CONTENT_TYPE);
219220
Charset charset = (contentType != null ? contentType.getCharset() : null);
220221
if (response.getCharacterEncoding() == null && charset != null) {
221222
response.setCharacterEncoding(charset.name());
@@ -224,6 +225,7 @@ protected void applyHeaders() {
224225
if (contentLength != -1) {
225226
response.setContentLengthLong(contentLength);
226227
}
228+
getHeaders().remove(HttpHeaders.CONTENT_LENGTH);
227229
}
228230

229231
@Override

0 commit comments

Comments
 (0)