Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Builds 508cc346e0 Release v5.3.22 2022-07-14 08:39:33 +00:00
135 changed files with 681 additions and 1182 deletions
@@ -1,9 +1,6 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
permissions:
contents: read
jobs:
validation:
name: "Validation"
+1 -1
View File
@@ -1,3 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=8.0.345-librca
java=8.0.333-librca
+15 -14
View File
@@ -28,10 +28,10 @@ configure(allprojects) { project ->
dependencyManagement {
imports {
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.7"
mavenBom "io.netty:netty-bom:4.1.82.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.23"
mavenBom "io.netty:netty-bom:4.1.79.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.21"
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR13"
mavenBom "io.rsocket:rsocket-bom:1.1.3"
mavenBom "io.rsocket:rsocket-bom:1.1.2"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.48.v20220622"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.32"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
@@ -67,8 +67,8 @@ configure(allprojects) { project ->
dependency "io.reactivex:rxjava:1.3.8"
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
dependency "io.reactivex.rxjava2:rxjava:2.2.21"
dependency "io.reactivex.rxjava3:rxjava:3.1.5"
dependency "io.smallrye.reactive:mutiny:1.7.0"
dependency "io.reactivex.rxjava3:rxjava:3.1.4"
dependency "io.smallrye.reactive:mutiny:1.4.0"
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
dependency "com.caucho:hessian:4.0.63"
@@ -124,22 +124,22 @@ configure(allprojects) { project ->
dependency "org.ehcache:jcache:1.0.1"
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core:5.4.33.Final"
dependency "org.hibernate:hibernate-validator:6.2.5.Final"
dependency "org.hibernate:hibernate-validator:6.2.3.Final"
dependency "org.webjars:webjars-locator-core:0.48"
dependency "org.webjars:underscorejs:1.8.3"
dependencySet(group: 'org.apache.tomcat', version: '9.0.65') {
dependencySet(group: 'org.apache.tomcat', version: '9.0.64') {
entry 'tomcat-util'
entry('tomcat-websocket') {
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
}
}
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.65') {
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.64') {
entry 'tomcat-embed-core'
entry 'tomcat-embed-websocket'
}
dependencySet(group: 'io.undertow', version: '2.2.19.Final') {
dependencySet(group: 'io.undertow', version: '2.2.18.Final') {
entry 'undertow-core'
entry('undertow-servlet') {
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
@@ -206,10 +206,10 @@ configure(allprojects) { project ->
}
dependency "io.mockk:mockk:1.12.1"
dependency("net.sourceforge.htmlunit:htmlunit:2.64.0") {
dependency("net.sourceforge.htmlunit:htmlunit:2.63.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:htmlunit-driver:2.64.0") {
dependency("org.seleniumhq.selenium:htmlunit-driver:2.63.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
@@ -217,7 +217,7 @@ configure(allprojects) { project ->
exclude group: "io.netty", name: "netty"
}
dependency "org.skyscreamer:jsonassert:1.5.0"
dependency "com.jayway.jsonpath:json-path:2.7.0"
dependency "com.jayway.jsonpath:json-path:2.6.0"
dependency "org.bouncycastle:bcpkix-jdk18on:1.71"
dependencySet(group: 'org.apache.tiles', version: '3.0.8') {
@@ -340,7 +340,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
toolVersion = "10.3.3"
toolVersion = "10.3.1"
configDirectory.set(rootProject.file("src/checkstyle"))
}
@@ -380,7 +380,8 @@ configure([rootProject] + javaProjects) { project ->
"https://fasterxml.github.io/jackson-core/javadoc/2.10/",
"https://fasterxml.github.io/jackson-databind/javadoc/2.10/",
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.10/",
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
// TODO Uncomment once httpclient5 API docs are again online.
// "https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
// Disabling linking to JUnit 5.8.2, since the `package-list` file no longer exists due to
+1 -1
View File
@@ -1,4 +1,4 @@
FROM ubuntu:focal-20220826
FROM ubuntu:focal-20220531
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
+4 -4
View File
@@ -3,16 +3,16 @@ set -e
case "$1" in
java8)
echo "https://github.com/bell-sw/Liberica/releases/download/8u345+1/bellsoft-jdk8u345+1-linux-amd64.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/8u333+2/bellsoft-jdk8u333+2-linux-amd64.tar.gz"
;;
java11)
echo "https://github.com/bell-sw/Liberica/releases/download/11.0.16+8/bellsoft-jdk11.0.16+8-linux-amd64.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/11.0.15.1+2/bellsoft-jdk11.0.15.1+2-linux-amd64.tar.gz"
;;
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.4+8/bellsoft-jdk17.0.4+8-linux-amd64.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.3.1+2/bellsoft-jdk17.0.3.1+2-linux-amd64.tar.gz"
;;
java18)
echo "https://github.com/bell-sw/Liberica/releases/download/18.0.2+10/bellsoft-jdk18.0.2+10-linux-amd64.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/18.0.1.1+2/bellsoft-jdk18.0.1.1+2-linux-amd64.tar.gz"
;;
*)
echo $"Unknown java version"
+1 -1
View File
@@ -1,4 +1,4 @@
version=5.3.23
version=5.3.22
org.gradle.jvmargs=-Xmx2048m
org.gradle.caching=true
org.gradle.parallel=true
+1 -1
View File
@@ -153,7 +153,7 @@ asciidoctorPdf {
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokkaHtmlMultiModule']) {
group = "Distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs/."
"for deployment at https://docs.spring.io/spring-framework/docs."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
+1 -1
View File
@@ -31,6 +31,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
## FAQ
Q. What about IntelliJ IDEA's own [Gradle support](https://www.jetbrains.com/help/idea/gradle.html)?
Q. What about IntelliJ IDEA's own [Gradle support](https://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
A. Keep an eye on https://youtrack.jetbrains.com/issue/IDEA-53476
@@ -147,7 +147,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
/**
* Set whether the proxy should be frozen, preventing advice
* from being added to it once it is created.
* <p>Overridden from the superclass to prevent the proxy configuration
* <p>Overridden from the super class to prevent the proxy configuration
* from being frozen before the proxy is created.
*/
@Override
@@ -35,7 +35,7 @@ public abstract aspect AbstractDependencyInjectionAspect {
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Select least specific supertype that is marked for DI
* Select least specific super type that is marked for DI
* (so that injection occurs only once with pre-construction injection).
*/
public abstract pointcut leastSpecificSuperTypeConstruction();
@@ -2167,25 +2167,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Nullable
public Object getOrderSource(Object obj) {
String beanName = this.instancesToBeanNames.get(obj);
if (beanName == null) {
if (beanName == null || !containsBeanDefinition(beanName)) {
return null;
}
try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) getMergedBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray();
RootBeanDefinition beanDefinition = getMergedLocalBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
catch (NoSuchBeanDefinitionException ex) {
return null;
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray();
}
}
@@ -1982,21 +1982,6 @@ class DefaultListableBeanFactoryTests {
assertThat(bean.getSpouse()).isEqualTo(lbf.getBean("spouse"));
}
@Test
void beanProviderWithParentBeanFactoryReuseOrder() {
DefaultListableBeanFactory parentBf = new DefaultListableBeanFactory();
parentBf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
parentBf.registerBeanDefinition("regular", new RootBeanDefinition(TestBean.class));
parentBf.registerBeanDefinition("test", new RootBeanDefinition(HighPriorityTestBean.class));
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
lbf.setParentBeanFactory(parentBf);
lbf.registerBeanDefinition("low", new RootBeanDefinition(LowPriorityTestBean.class));
List<Class<?>> orderedTypes = lbf.getBeanProvider(TestBean.class).orderedStream()
.map(Object::getClass).collect(Collectors.toList());
assertThat(orderedTypes).containsExactly(
HighPriorityTestBean.class, LowPriorityTestBean.class, TestBean.class);
}
@Test
void autowireExistingBeanByName() {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
@@ -81,7 +81,7 @@ class TypeHelper {
}
/**
* Return the superclass of the specified {@link Element} or null if this
* Return the super class of the specified {@link Element} or null if this
* {@code element} represents {@link Object}.
*/
public Element getSuperClass(Element element) {
@@ -100,7 +100,7 @@ class TypeHelper {
public List<Element> getDirectInterfaces(Element element) {
List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType());
List<Element> directInterfaces = new ArrayList<>();
if (superTypes.size() > 1) { // index 0 is the superclass
if (superTypes.size() > 1) { // index 0 is the super class
for (int i = 1; i < superTypes.size(); i++) {
Element e = this.types.asElement(superTypes.get(i));
if (e != null) {
@@ -50,7 +50,7 @@ video/x-msvideo avi
################################################################################
#
# Additional file types adapted from
# https://web.archive.org/web/20220119153325/http%3A//sites.utoronto.ca/webdocs/HTMLdocs/Book/Book-3ed/appb/mimetype.html
# http://sites.utoronto.ca/webdocs/HTMLdocs/Book/Book-3ed/appb/mimetype.html
# kindly re-licensed to Apache Software License 2.0 by Ian Graham.
#
################################################################################
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -24,7 +24,7 @@ import org.springframework.lang.Nullable;
* Interface that defines common cache operations.
*
* <b>Note:</b> Due to the generic use of caching, it is recommended that
* implementations allow storage of {@code null} values (for example to
* implementations allow storage of <tt>null</tt> values (for example to
* cache methods that return {@code null}).
*
* @author Costin Leau
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -111,8 +111,7 @@ public @interface CacheEvict {
/**
* Spring Expression Language (SpEL) expression used for making the cache
* eviction operation conditional. Evict that cache if the condition evaluates
* to {@code true}.
* eviction operation conditional.
* <p>Default is {@code ""}, meaning the cache eviction is always performed.
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -118,8 +118,7 @@ public @interface CachePut {
/**
* Spring Expression Language (SpEL) expression used for making the cache
* put operation conditional. Update the cache if the condition evaluates to
* {@code true}.
* put operation conditional.
* <p>This expression is evaluated after the method has been called due to the
* nature of the put operation and can therefore refer to the {@code result}.
* <p>Default is {@code ""}, meaning the method result is always cached.
@@ -143,7 +142,6 @@ public @interface CachePut {
/**
* Spring Expression Language (SpEL) expression used to veto the cache put operation.
* Veto updating the cache if the condition evaluates to {@code true}.
* <p>Default is {@code ""}, meaning that caching is never vetoed.
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -123,8 +123,7 @@ public @interface Cacheable {
/**
* Spring Expression Language (SpEL) expression used for making the method
* caching conditional. Cache the result if the condition evaluates to
* {@code true}.
* caching conditional.
* <p>Default is {@code ""}, meaning the method result is always cached.
* <p>The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
@@ -143,7 +142,6 @@ public @interface Cacheable {
/**
* Spring Expression Language (SpEL) expression used to veto method caching.
* Veto caching the result if the condition evaluates to {@code true}.
* <p>Unlike {@link #condition}, this expression is evaluated after the method
* has been called and can therefore refer to the {@code result}.
* <p>Default is {@code ""}, meaning that caching is never vetoed.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -54,6 +54,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase;
import org.springframework.context.annotation.DeferredImportSelector.Group;
import org.springframework.core.NestedIOException;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
@@ -679,7 +680,6 @@ class ConfigurationClassParser {
/**
* Factory method to obtain a {@link SourceClass} from a class name.
*/
@SuppressWarnings("deprecation")
SourceClass asSourceClass(@Nullable String className, Predicate<String> filter) throws IOException {
if (className == null || filter.test(className)) {
return this.objectSourceClass;
@@ -690,7 +690,7 @@ class ConfigurationClassParser {
return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new org.springframework.core.NestedIOException("Failed to load class [" + className + "]", ex);
throw new NestedIOException("Failed to load class [" + className + "]", ex);
}
}
return new SourceClass(this.metadataReaderFactory.getMetadataReader(className));
@@ -1073,7 +1073,6 @@ class ConfigurationClassParser {
return result;
}
@SuppressWarnings("deprecation")
private SourceClass getRelated(String className) throws IOException {
if (this.source instanceof Class) {
try {
@@ -1083,7 +1082,7 @@ class ConfigurationClassParser {
catch (ClassNotFoundException ex) {
// Ignore -> fall back to ASM next, except for core java types.
if (className.startsWith("java")) {
throw new org.springframework.core.NestedIOException("Failed to load class [" + className + "]", ex);
throw new NestedIOException("Failed to load class [" + className + "]", ex);
}
return new SourceClass(metadataReaderFactory.getMetadataReader(className));
}
@@ -1,6 +1,6 @@
/**
* Package providing integration of
* <a href="https://beanshell.github.io/">BeanShell</a>
* <a href="http://www.beanshell.org">BeanShell</a>
* (and <a href="https://code.google.com/p/beanshell2/">BeanShell2</a>)
* into Spring's scripting infrastructure.
*/
@@ -1,6 +1,6 @@
/**
* Package providing integration of
* <a href="https://www.groovy-lang.org/">Groovy</a>
* <a href="http://www.groovy-lang.org/">Groovy</a>
* into Spring's scripting infrastructure.
*/
@NonNullApi
@@ -1,81 +0,0 @@
/*
* Copyright 2002-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.springframework.core.annotation.Order;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for gh-29105.
*
* @author Stephane Nicoll
*/
public class Gh29105Tests {
@Test
void beanProviderWithParentContextReuseOrder() {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
parent.register(DefaultConfiguration.class);
parent.register(CustomConfiguration.class);
parent.refresh();
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.setParent(parent);
child.register(DefaultConfiguration.class);
child.refresh();
List<Class<?>> orderedTypes = child.getBeanProvider(MyService.class)
.orderedStream().map(Object::getClass).collect(Collectors.toList());
assertThat(orderedTypes).containsExactly(CustomService.class, DefaultService.class);
}
interface MyService {}
static class CustomService implements MyService {}
static class DefaultService implements MyService {}
@Configuration
static class CustomConfiguration {
@Bean
@Order(-1)
CustomService customService() {
return new CustomService();
}
}
@Configuration
static class DefaultConfiguration {
@Bean
@Order(0)
DefaultService defaultService() {
return new DefaultService();
}
}
}
@@ -117,7 +117,7 @@ class ApplicationContextExpressionTests {
ac.registerBeanDefinition("tb1", bd1);
GenericBeanDefinition bd2 = new GenericBeanDefinition();
bd2.setBeanClassName("#{tb1.class}");
bd2.setBeanClassName("#{tb1.class.name}");
bd2.setScope("myScope");
bd2.getPropertyValues().add("name", "{ XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ }");
bd2.getPropertyValues().add("age", "#{mySpecialAttr}");
@@ -46,7 +46,11 @@ import static org.assertj.core.api.Assertions.assertThat;
* {@code jmxremote_optional.jar} into your classpath, for example in the {@code lib/ext}
* folder of your JVM.
*
* <p>See also: <a href="https://jira.spring.io/browse/SPR-8093">SPR-8093</a>
* <p>See also:
* <ul>
* <li><a href="https://jira.spring.io/browse/SPR-8093">SPR-8093</a></li>
* <li><a href="https://issuetracker.springsource.com/browse/EBR-349">EBR-349</a></li>
* </ul>
*
* @author Rob Harrop
* @author Juergen Hoeller
-1
View File
@@ -58,7 +58,6 @@ dependencies {
testImplementation("org.xmlunit:xmlunit-matchers")
testImplementation("io.projectreactor:reactor-test")
testImplementation("io.projectreactor.tools:blockhound")
testImplementation("com.squareup.okhttp3:mockwebserver")
testFixturesImplementation("com.google.code.findbugs:jsr305")
testFixturesImplementation("org.junit.platform:junit-platform-launcher")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api")
@@ -708,8 +708,8 @@ public final class Type {
*
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code
* i >> 2}, and returnSize to {@code i & 0x03}).
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@@ -721,8 +721,8 @@ public final class Type {
* @param methodDescriptor a method descriptor.
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code
* i >> 2}, and returnSize to {@code i & 0x03}).
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
*/
public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
int argumentsSize = 1;
@@ -226,7 +226,7 @@ public final class BridgeMethodResolver {
/**
* Compare the signatures of the bridge method and the method which it bridges. If
* the parameter and return types are the same, it is a 'visibility' bridge method
* introduced in Java 6 to fix https://bugs.openjdk.org/browse/JDK-6342411.
* introduced in Java 6 to fix https://bugs.java.com/view_bug.do?bug_id=6342411.
* See also https://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html
* @return whether signatures match as described
*/
@@ -191,8 +191,7 @@ public final class CollectionFactory {
else if (LinkedList.class == collectionType) {
return new LinkedList<>();
}
else if (TreeSet.class == collectionType || NavigableSet.class == collectionType
|| SortedSet.class == collectionType) {
else if (SortedSet.class == collectionType || NavigableSet.class == collectionType) {
return new TreeSet<>();
}
else if (EnumSet.class.isAssignableFrom(collectionType)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -29,6 +29,7 @@ import org.springframework.lang.Nullable;
* @since 2.0
* @see NestedRuntimeException
* @see NestedCheckedException
* @see NestedIOException
* @see org.springframework.web.util.NestedServletException
*/
public abstract class NestedExceptionUtils {
@@ -37,9 +37,7 @@ import org.springframework.lang.Nullable;
* @see #printStackTrace
* @see org.springframework.core.NestedCheckedException
* @see org.springframework.core.NestedRuntimeException
* @deprecated as of 5.3.23, in favor of using {@link IOException} directly
*/
@Deprecated
@SuppressWarnings("serial")
public class NestedIOException extends IOException {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2015 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.
@@ -173,7 +173,7 @@ import java.lang.annotation.Target;
* @author Sam Brannen
* @since 4.2
* @see MergedAnnotations
* @see AnnotationUtils#isSynthesizedAnnotation(Annotation)
* @see SynthesizedAnnotation
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2015 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,7 +25,7 @@ import org.springframework.core.NestedRuntimeException;
* @author Sam Brannen
* @since 4.2
* @see AnnotationUtils
* @see AnnotationUtils#isSynthesizedAnnotation(java.lang.annotation.Annotation)
* @see SynthesizedAnnotation
*/
@SuppressWarnings("serial")
public class AnnotationConfigurationException extends NestedRuntimeException {
@@ -160,7 +160,7 @@ final class AnnotationTypeMappings {
* @param index the index to return
* @return the {@link AnnotationTypeMapping}
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
AnnotationTypeMapping get(int index) {
return this.mappings.get(index);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -1188,7 +1188,7 @@ public abstract class AnnotationUtils {
public static <A extends Annotation> A synthesizeAnnotation(
A annotation, @Nullable AnnotatedElement annotatedElement) {
if (isSynthesizedAnnotation(annotation) || AnnotationFilter.PLAIN.matches(annotation)) {
if (annotation instanceof SynthesizedAnnotation || AnnotationFilter.PLAIN.matches(annotation)) {
return annotation;
}
return MergedAnnotation.from(annotatedElement, annotation).synthesize();
@@ -1282,18 +1282,6 @@ public abstract class AnnotationUtils {
return synthesized;
}
/**
* Determine if the supplied {@link Annotation} has been <em>synthesized</em>
* by Spring (i.e. wrapped in a dynamic proxy) with additional functionality
* such as attribute alias handling.
* @param annotation the annotation to check
* @return {@code true} if the supplied annotation is a synthesized annotation
* @since 5.3.23
*/
public static boolean isSynthesizedAnnotation(@Nullable Annotation annotation) {
return (annotation instanceof SynthesizedAnnotation);
}
/**
* Clear the internal annotation metadata cache.
* @since 4.3.15
@@ -168,7 +168,7 @@ final class AttributeMethods {
* @param index the index of the attribute to return
* @return the attribute method
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
Method get(int index) {
return this.attributeMethods[index];
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -27,7 +27,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;
/**
* Abstract base class for {@link Encoder} implementations.
* Abstract base class for {@link Decoder} implementations.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -238,7 +238,7 @@ public class TypeDescriptor implements Serializable {
* <p>As of Spring Framework 4.2, this method supports arbitrary levels
* of meta-annotations.
* @param annotationType the annotation type
* @return {@code true} if the annotation is present
* @return <tt>true</tt> if the annotation is present
*/
public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
if (this.annotatedElement.isEmpty()) {
@@ -273,8 +273,8 @@ public class TypeDescriptor implements Serializable {
* On the other hand, {@code valueOf(Number.class).isAssignableTo(valueOf(Integer.class))}
* returns {@code false} because, while all Integers are Numbers, not all Numbers are Integers.
* <p>For arrays, collections, and maps, element and key/value types are checked if declared.
* For example, a {@code List<String>} field value is assignable to a {@code Collection<CharSequence>}
* field, but {@code List<Number>} is not assignable to {@code List<Integer>}.
* For example, a List&lt;String&gt; field value is assignable to a Collection&lt;CharSequence&gt;
* field, but List&lt;Number&gt; is not assignable to List&lt;Integer&gt;.
* @return {@code true} if this type is assignable to the type represented by the provided
* type descriptor
* @see #getObjectType()
@@ -576,7 +576,7 @@ public class TypeDescriptor implements Serializable {
/**
* Create a new type descriptor from a {@link java.util.Map} type.
* <p>Useful for converting to typed Maps.
* <p>For example, a {@code Map<String, String>} could be converted to a {@code Map<Id, EmailAddress>}
* <p>For example, a Map&lt;String, String&gt; could be converted to a Map&lt;Id, EmailAddress&gt;
* by converting to a targetType built with this method:
* The method call to construct such a TypeDescriptor would look something like:
* <pre class="code">
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -104,7 +104,7 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
/**
* Adapts a {@link ConversionService} and {@code targetType} to a {@link Converter}.
* Adapts a {@link ConversionService} and <tt>targetType</tt> to a {@link Converter}.
*/
private static class ConversionServiceConverter<S, T> implements Converter<S, T> {
@@ -57,7 +57,6 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
HttpURLConnection httpCon =
(con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
if (httpCon != null) {
httpCon.setRequestMethod("HEAD");
int code = httpCon.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
return true;
@@ -109,7 +108,6 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
int code = httpCon.getResponseCode();
if (code != HttpURLConnection.HTTP_OK) {
httpCon.disconnect();
@@ -247,10 +245,6 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
// Try a URL connection content-length header
URLConnection con = url.openConnection();
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
}
return con.getContentLengthLong();
}
}
@@ -276,10 +270,6 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
// Try a URL connection last-modified header
URLConnection con = url.openConnection();
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
}
long lastModified = con.getLastModified();
if (fileCheck && lastModified == 0 && con.getContentLengthLong() <= 0) {
throw new FileNotFoundException(getDescription() +
@@ -289,7 +279,8 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
}
/**
* Customize the given {@link URLConnection} before fetching the resource.
* Customize the given {@link URLConnection}, obtained in the course of an
* {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
* <p>Calls {@link ResourceUtils#useCachesIfNecessary(URLConnection)} and
* delegates to {@link #customizeConnection(HttpURLConnection)} if possible.
* Can be overridden in subclasses.
@@ -304,12 +295,14 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
}
/**
* Customize the given {@link HttpURLConnection} before fetching the resource.
* <p>Can be overridden in subclasses for configuring request headers and timeouts.
* Customize the given {@link HttpURLConnection}, obtained in the course of an
* {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
* <p>Sets request method "HEAD" by default. Can be overridden in subclasses.
* @param con the HttpURLConnection to customize
* @throws IOException if thrown from HttpURLConnection methods
*/
protected void customizeConnection(HttpURLConnection con) throws IOException {
con.setRequestMethod("HEAD");
}
@@ -29,6 +29,7 @@ import java.nio.channels.ReadableByteChannel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.NestedIOException;
import org.springframework.lang.Nullable;
import org.springframework.util.ResourceUtils;
@@ -118,14 +119,13 @@ public abstract class AbstractResource implements Resource {
* by {@link #getURL()}.
*/
@Override
@SuppressWarnings("deprecation")
public URI getURI() throws IOException {
URL url = getURL();
try {
return ResourceUtils.toURI(url);
}
catch (URISyntaxException ex) {
throw new org.springframework.core.NestedIOException("Invalid URI [" + url + "]", ex);
throw new NestedIOException("Invalid URI [" + url + "]", ex);
}
}
@@ -28,6 +28,7 @@ import java.net.URLConnection;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
/**
@@ -182,7 +183,7 @@ public class UrlResource extends AbstractFileResolvingResource {
@Override
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
customizeConnection(con);
ResourceUtils.useCachesIfNecessary(con);
try {
return con.getInputStream();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import org.springframework.core.NestedIOException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -71,24 +72,22 @@ public class VfsResource extends AbstractResource {
}
@Override
@SuppressWarnings("deprecation")
public URL getURL() throws IOException {
try {
return VfsUtils.getURL(this.resource);
}
catch (Exception ex) {
throw new org.springframework.core.NestedIOException("Failed to obtain URL for file " + this.resource, ex);
throw new NestedIOException("Failed to obtain URL for file " + this.resource, ex);
}
}
@Override
@SuppressWarnings("deprecation")
public URI getURI() throws IOException {
try {
return VfsUtils.getURI(this.resource);
}
catch (Exception ex) {
throw new org.springframework.core.NestedIOException("Failed to obtain URI for " + this.resource, ex);
throw new NestedIOException("Failed to obtain URI for " + this.resource, ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -38,9 +38,9 @@ import org.springframework.util.Assert;
* the following invariant holds for the read and write positions, and the capacity:
*
* <blockquote>
* {@code 0} {@code <=}
* <i>readPosition</i> {@code <=}
* <i>writePosition</i> {@code <=}
* <tt>0</tt> <tt>&lt;=</tt>
* <i>readPosition</i> <tt>&lt;=</tt>
* <i>writePosition</i> <tt>&lt;=</tt>
* <i>capacity</i>
* </blockquote>
*
@@ -366,8 +366,7 @@ public abstract class DataBufferUtils {
sink.onDispose(() -> closeChannel(channel));
write(source, channel).subscribe(DataBufferUtils::release,
sink::error,
sink::success,
Context.of(sink.contextView()));
sink::success);
}
catch (IOException ex) {
sink.error(ex);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -21,6 +21,7 @@ import java.io.InputStream;
import java.io.ObjectInputStream;
import org.springframework.core.ConfigurableObjectInputStream;
import org.springframework.core.NestedIOException;
import org.springframework.lang.Nullable;
/**
@@ -64,14 +65,14 @@ public class DefaultDeserializer implements Deserializer<Object> {
* @see ObjectInputStream#readObject()
*/
@Override
@SuppressWarnings("deprecation")
@SuppressWarnings("resource")
public Object deserialize(InputStream inputStream) throws IOException {
ObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);
try {
return objectInputStream.readObject();
}
catch (ClassNotFoundException ex) {
throw new org.springframework.core.NestedIOException("Failed to deserialize object type", ex);
throw new NestedIOException("Failed to deserialize object type", ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InputStream;
import org.springframework.asm.ClassReader;
import org.springframework.core.NestedIOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
@@ -50,14 +51,13 @@ final class SimpleMetadataReader implements MetadataReader {
this.annotationMetadata = visitor.getMetadata();
}
@SuppressWarnings("deprecation")
private static ClassReader getClassReader(Resource resource) throws IOException {
try (InputStream is = resource.getInputStream()) {
try {
return new ClassReader(is);
}
catch (IllegalArgumentException ex) {
throw new org.springframework.core.NestedIOException("ASM ClassReader failed to parse class file - " +
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
}
}
@@ -86,7 +86,7 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read superclass [" + metadata.getSuperClassName() +
logger.debug("Could not read super class [" + metadata.getSuperClassName() +
"] of type-filtered class [" + metadata.getClassName() + "]");
}
}
@@ -638,7 +638,7 @@ public class AntPathMatcher implements PathMatcher {
/**
* Tests whether a string matches against a pattern via a {@link Pattern}.
* <p>The pattern may contain special characters: '*' means zero or more characters; '?' means one and
* only one character; '{' and '}' indicate a URI template pattern. For example {@code /users/{user}}.
* only one character; '{' and '}' indicate a URI template pattern. For example <tt>/users/{user}</tt>.
*/
protected static class AntPathStringMatcher {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -150,7 +150,7 @@ public class FastByteArrayOutputStream extends OutputStream {
/**
* Convert the buffer's contents into a string decoding bytes using the
* platform's default character set. The length of the new {@code String}
* platform's default character set. The length of the new <tt>String</tt>
* is a function of the character set, and hence may not be equal to the
* size of the buffer.
* <p>This method always replaces malformed-input and unmappable-character
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -114,7 +114,6 @@ public class SettableListenableFuture<T> implements ListenableFuture<T> {
* {@link java.util.concurrent.CancellationException} if the future has been cancelled.
* @return the value associated with this future
*/
@Nullable
@Override
public T get() throws InterruptedException, ExecutionException {
return this.settableTask.get();
@@ -130,7 +129,6 @@ public class SettableListenableFuture<T> implements ListenableFuture<T> {
* @param unit the unit of the timeout argument
* @return the value associated with this future
*/
@Nullable
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.settableTask.get(timeout, unit);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -33,7 +33,7 @@ class AnnotationBackCompatibilityTests {
@Test
void multiplRoutesToMetaAnnotation() {
Class<?> source = WithMetaMetaTestAnnotation1AndMetaTestAnnotation2.class;
Class<WithMetaMetaTestAnnotation1AndMetaTestAnnotation2> source = WithMetaMetaTestAnnotation1AndMetaTestAnnotation2.class;
// Merged annotation chooses lowest depth
MergedAnnotation<TestAnnotation> mergedAnnotation = MergedAnnotations.from(source).get(TestAnnotation.class);
assertThat(mergedAnnotation.getString("value")).isEqualTo("testAndMetaTest");
@@ -45,7 +45,7 @@ class AnnotationBackCompatibilityTests {
@Test
void defaultValue() {
DefaultValueAnnotation synthesized = MergedAnnotations.from(WithDefaultValue.class).get(DefaultValueAnnotation.class).synthesize();
assertThat(AnnotationUtils.isSynthesizedAnnotation(synthesized)).as("synthesized annotation").isTrue();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
Object defaultValue = AnnotationUtils.getDefaultValue(synthesized, "enumValue");
assertThat(defaultValue).isEqualTo(TestEnum.ONE);
}
@@ -60,12 +60,14 @@ class AnnotationBackCompatibilityTests {
@Retention(RetentionPolicy.RUNTIME)
@TestAnnotation("metaTest")
@interface MetaTestAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
@TestAnnotation("testAndMetaTest")
@MetaTestAnnotation
@interface TestAndMetaTestAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
@@ -76,6 +78,7 @@ class AnnotationBackCompatibilityTests {
@MetaMetaTestAnnotation
@TestAndMetaTestAnnotation
static class WithMetaMetaTestAnnotation1AndMetaTestAnnotation2 {
}
@Retention(RetentionPolicy.RUNTIME)
@@ -91,6 +94,7 @@ class AnnotationBackCompatibilityTests {
@DefaultValueAnnotation
static class WithDefaultValue {
}
enum TestEnum {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -45,7 +45,7 @@ class MergedAnnotationCollectorsTests {
MergedAnnotationCollectors.toAnnotationSet());
assertThat(set).isInstanceOf(LinkedHashSet.class).flatExtracting(
TestAnnotation::value).containsExactly("a", "b", "c");
assertThat(set).allMatch(AnnotationUtils::isSynthesizedAnnotation);
assertThat(set).allMatch(SynthesizedAnnotation.class::isInstance);
}
@Test
@@ -55,7 +55,7 @@ class MergedAnnotationCollectorsTests {
assertThat(Arrays.stream(array).map(
annotation -> ((TestAnnotation) annotation).value())).containsExactly("a",
"b", "c");
assertThat(array).allMatch(AnnotationUtils::isSynthesizedAnnotation);
assertThat(array).allMatch(SynthesizedAnnotation.class::isInstance);
}
@Test
@@ -64,7 +64,7 @@ class MergedAnnotationCollectorsTests {
MergedAnnotationCollectors.toAnnotationArray(TestAnnotation[]::new));
assertThat(Arrays.stream(array).map(TestAnnotation::value)).containsExactly("a",
"b", "c");
assertThat(array).allMatch(AnnotationUtils::isSynthesizedAnnotation);
assertThat(array).allMatch(SynthesizedAnnotation.class::isInstance);
}
@Test
@@ -1395,10 +1395,9 @@ class MergedAnnotationsTests {
RequestMapping synthesizedWebMapping = MergedAnnotation.from(webMapping).synthesize();
RequestMapping synthesizedAgainWebMapping = MergedAnnotation.from(synthesizedWebMapping).synthesize();
assertSynthesized(synthesizedWebMapping);
assertSynthesized(synthesizedAgainWebMapping);
assertThat(synthesizedWebMapping).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedAgainWebMapping).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedWebMapping).isEqualTo(synthesizedAgainWebMapping);
assertThat(synthesizedWebMapping).isSameAs(synthesizedAgainWebMapping);
assertThat(synthesizedWebMapping.name()).isEqualTo("foo");
assertThat(synthesizedWebMapping.path()).containsExactly("/test");
assertThat(synthesizedWebMapping.value()).containsExactly("/test");
@@ -1413,7 +1412,7 @@ class MergedAnnotationsTests {
Id synthesizedId = MergedAnnotation.from(id).synthesize();
assertThat(id).isEqualTo(synthesizedId);
// It doesn't make sense to synthesize @Id since it declares zero attributes.
assertNotSynthesized(synthesizedId);
assertThat(synthesizedId).isNotInstanceOf(SynthesizedAnnotation.class);
assertThat(id).isSameAs(synthesizedId);
GeneratedValue generatedValue = method.getAnnotation(GeneratedValue.class);
@@ -1421,7 +1420,7 @@ class MergedAnnotationsTests {
GeneratedValue synthesizedGeneratedValue = MergedAnnotation.from(generatedValue).synthesize();
assertThat(generatedValue).isEqualTo(synthesizedGeneratedValue);
// It doesn't make sense to synthesize @GeneratedValue since it declares zero attributes with aliases.
assertNotSynthesized(synthesizedGeneratedValue);
assertThat(synthesizedGeneratedValue).isNotInstanceOf(SynthesizedAnnotation.class);
assertThat(generatedValue).isSameAs(synthesizedGeneratedValue);
}
@@ -1431,19 +1430,19 @@ class MergedAnnotationsTests {
MergedAnnotations mergedAnnotations = MergedAnnotations.from(directlyAnnotatedField);
RootAnnotation rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
assertThat(rootAnnotation.flag()).isFalse();
assertNotSynthesized(rootAnnotation);
assertThat(rootAnnotation).isNotInstanceOf(SynthesizedAnnotation.class);
Field metaAnnotatedField = ReflectionUtils.findField(DomainType.class, "metaAnnotated");
mergedAnnotations = MergedAnnotations.from(metaAnnotatedField);
rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
assertThat(rootAnnotation.flag()).isTrue();
assertSynthesized(rootAnnotation);
assertThat(rootAnnotation).isInstanceOf(SynthesizedAnnotation.class);
Field metaMetaAnnotatedField = ReflectionUtils.findField(DomainType.class, "metaMetaAnnotated");
mergedAnnotations = MergedAnnotations.from(metaMetaAnnotatedField);
rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
assertThat(rootAnnotation.flag()).isTrue();
assertSynthesized(rootAnnotation);
assertThat(rootAnnotation).isInstanceOf(SynthesizedAnnotation.class);
}
@Test // gh-28704
@@ -1451,10 +1450,10 @@ class MergedAnnotationsTests {
MergedAnnotations mergedAnnotations = MergedAnnotations.from(SecurityConfig.class);
EnableWebSecurity enableWebSecurity = mergedAnnotations.get(EnableWebSecurity.class).synthesize();
assertNotSynthesized(enableWebSecurity);
assertThat(enableWebSecurity).isNotInstanceOf(SynthesizedAnnotation.class);
EnableGlobalAuthentication enableGlobalAuthentication = mergedAnnotations.get(EnableGlobalAuthentication.class).synthesize();
assertNotSynthesized(enableGlobalAuthentication);
assertThat(enableGlobalAuthentication).isNotInstanceOf(SynthesizedAnnotation.class);
}
/**
@@ -1473,8 +1472,8 @@ class MergedAnnotationsTests {
RequestMapping synthesizedWebMapping1 = mergedAnnotation1.synthesize();
RequestMapping synthesizedWebMapping2 = MergedAnnotation.from(webMapping).synthesize();
assertSynthesized(synthesizedWebMapping1);
assertSynthesized(synthesizedWebMapping2);
assertThat(synthesizedWebMapping1).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedWebMapping2).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedWebMapping1).isEqualTo(synthesizedWebMapping2);
// Synthesizing an annotation from a different MergedAnnotation results in a different synthesized annotation instance.
@@ -1596,11 +1595,14 @@ class MergedAnnotationsTests {
testSynthesisWithImplicitAliases(GroovyImplicitAliasesSimpleTestConfigurationClass.class, "groovyScript");
}
private void testSynthesisWithImplicitAliases(Class<?> clazz, String expected) throws Exception {
ImplicitAliasesTestConfiguration config = clazz.getAnnotation(ImplicitAliasesTestConfiguration.class);
private void testSynthesisWithImplicitAliases(Class<?> clazz, String expected)
throws Exception {
ImplicitAliasesTestConfiguration config = clazz.getAnnotation(
ImplicitAliasesTestConfiguration.class);
assertThat(config).isNotNull();
ImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from(config).synthesize();
assertSynthesized(synthesized);
ImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from(
config).synthesize();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.value()).isEqualTo(expected);
assertThat(synthesized.location1()).isEqualTo(expected);
assertThat(synthesized.xmlFile()).isEqualTo(expected);
@@ -1628,7 +1630,7 @@ class MergedAnnotationsTests {
assertThat(config).isNotNull();
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration synthesized =
MergedAnnotation.from(config).synthesize();
assertSynthesized(synthesized);
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.value()).isEqualTo(expected);
assertThat(synthesized.location()).isEqualTo(expected);
assertThat(synthesized.xmlFile()).isEqualTo(expected);
@@ -1640,7 +1642,7 @@ class MergedAnnotationsTests {
ImplicitAliasesForAliasPairTestConfigurationClass.class.getAnnotation(
ImplicitAliasesForAliasPairTestConfiguration.class);
ImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from(config).synthesize();
assertSynthesized(synthesized);
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.xmlFile()).isEqualTo("test.xml");
assertThat(synthesized.groovyScript()).isEqualTo("test.xml");
}
@@ -1651,7 +1653,7 @@ class MergedAnnotationsTests {
TransitiveImplicitAliasesTestConfigurationClass.class.getAnnotation(
TransitiveImplicitAliasesTestConfiguration.class);
TransitiveImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from(config).synthesize();
assertSynthesized(synthesized);
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.xml()).isEqualTo("test.xml");
assertThat(synthesized.groovy()).isEqualTo("test.xml");
}
@@ -1663,7 +1665,7 @@ class MergedAnnotationsTests {
TransitiveImplicitAliasesForAliasPairTestConfiguration.class);
TransitiveImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from(
config).synthesize();
assertSynthesized(synthesized);
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.xml()).isEqualTo("test.xml");
assertThat(synthesized.groovy()).isEqualTo("test.xml");
}
@@ -1722,7 +1724,7 @@ class MergedAnnotationsTests {
Map<String, Object> map = Collections.singletonMap("value", "webController");
MergedAnnotation<Component> annotation = MergedAnnotation.of(Component.class, map);
Component synthesizedComponent = annotation.synthesize();
assertSynthesized(synthesizedComponent);
assertThat(synthesizedComponent).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedComponent.value()).isEqualTo("webController");
}
@@ -1743,7 +1745,7 @@ class MergedAnnotationsTests {
MergedAnnotation<ComponentScanSingleFilter> annotation = MergedAnnotation.of(
ComponentScanSingleFilter.class, map);
ComponentScanSingleFilter synthesizedComponentScan = annotation.synthesize();
assertSynthesized(synthesizedComponentScan);
assertThat(synthesizedComponentScan).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedComponentScan.value().pattern()).isEqualTo("newFoo");
}
@@ -1767,7 +1769,7 @@ class MergedAnnotationsTests {
MergedAnnotation<ComponentScan> annotation = MergedAnnotation.of(
ComponentScan.class, map);
ComponentScan synthesizedComponentScan = annotation.synthesize();
assertSynthesized(synthesizedComponentScan);
assertThat(synthesizedComponentScan).isInstanceOf(SynthesizedAnnotation.class);
assertThat(Arrays.stream(synthesizedComponentScan.excludeFilters()).map(
Filter::pattern)).containsExactly("newFoo", "newBar");
}
@@ -1886,7 +1888,7 @@ class MergedAnnotationsTests {
assertThat(component).isNotNull();
Map<String, Object> attributes = MergedAnnotation.from(component).asMap();
Component synthesized = MergedAnnotation.of(Component.class, attributes).synthesize();
assertSynthesized(synthesized);
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized).isEqualTo(component);
}
@@ -2045,7 +2047,7 @@ class MergedAnnotationsTests {
assertThat(annotation).isNotNull();
MergedAnnotation<Annotation> mergedAnnotation = MergedAnnotation.from(annotation);
Annotation synthesizedAnnotation = mergedAnnotation.synthesize();
assertSynthesized(synthesizedAnnotation);
assertThat(synthesizedAnnotation).isInstanceOf(SynthesizedAnnotation.class);
assertThat(mergedAnnotation.getString("name")).isEqualTo("test");
assertThat(mergedAnnotation.getString("path")).isEqualTo("/test");
assertThat(mergedAnnotation.getString("value")).isEqualTo("/test");
@@ -2056,10 +2058,10 @@ class MergedAnnotationsTests {
Hierarchy hierarchy = HierarchyClass.class.getAnnotation(Hierarchy.class);
assertThat(hierarchy).isNotNull();
Hierarchy synthesizedHierarchy = MergedAnnotation.from(hierarchy).synthesize();
assertSynthesized(synthesizedHierarchy);
assertThat(synthesizedHierarchy).isInstanceOf(SynthesizedAnnotation.class);
TestConfiguration[] configs = synthesizedHierarchy.value();
assertThat(configs).isNotNull();
assertThat(configs).allMatch(AnnotationUtils::isSynthesizedAnnotation);
assertThat(configs).allMatch(SynthesizedAnnotation.class::isInstance);
assertThat(configs).extracting(TestConfiguration::value).containsExactly("A", "B");
assertThat(configs).extracting(TestConfiguration::location).containsExactly("A", "B");
@@ -2080,7 +2082,7 @@ class MergedAnnotationsTests {
assertThat(charsContainer).isNotNull();
CharsContainer synthesizedCharsContainer = MergedAnnotation.from(
charsContainer).synthesize();
assertSynthesized(synthesizedCharsContainer);
assertThat(synthesizedCharsContainer).isInstanceOf(SynthesizedAnnotation.class);
char[] chars = synthesizedCharsContainer.chars();
assertThat(chars).containsExactly('x', 'y', 'z');
// Alter array returned from synthesized annotation
@@ -3680,12 +3682,4 @@ class MergedAnnotationsTests {
}
// @formatter:on
static void assertSynthesized(Annotation annotation) {
assertThat(AnnotationUtils.isSynthesizedAnnotation(annotation)).as("synthesized annotation").isTrue();
}
static void assertNotSynthesized(Annotation annotation) {
assertThat(AnnotationUtils.isSynthesizedAnnotation(annotation)).as("synthesized annotation").isFalse();
}
}
@@ -23,32 +23,20 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.stream.Stream;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Unit tests for various {@link Resource} implementations.
@@ -56,25 +44,137 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
* @author Brian Clozel
* @since 09.09.2004
*/
class ResourceTests {
@Test
void byteArrayResource() throws IOException {
Resource resource = new ByteArrayResource("testString".getBytes());
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isFalse();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new ByteArrayResource("testString".getBytes())).isEqualTo(resource);
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void resourceIsValid(Resource resource) throws Exception {
@Test
void byteArrayResourceWithDescription() throws IOException {
Resource resource = new ByteArrayResource("testString".getBytes(), "my description");
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isFalse();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(resource.getDescription().contains("my description")).isTrue();
assertThat(new ByteArrayResource("testString".getBytes())).isEqualTo(resource);
}
@Test
void inputStreamResource() throws IOException {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is);
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isTrue();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new InputStreamResource(is)).isEqualTo(resource);
}
@Test
void inputStreamResourceWithDescription() throws IOException {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is, "my description");
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isTrue();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(resource.getDescription().contains("my description")).isTrue();
assertThat(new InputStreamResource(is)).isEqualTo(resource);
}
@Test
void classPathResource() throws IOException {
Resource resource = new ClassPathResource("org/springframework/core/io/Resource.class");
doTestResource(resource);
Resource resource2 = new ClassPathResource("org/springframework/core/../core/io/./Resource.class");
assertThat(resource2).isEqualTo(resource);
Resource resource3 = new ClassPathResource("org/springframework/core/").createRelative("../core/io/./Resource.class");
assertThat(resource3).isEqualTo(resource);
// Check whether equal/hashCode works in a HashSet.
HashSet<Resource> resources = new HashSet<>();
resources.add(resource);
resources.add(resource2);
assertThat(resources.size()).isEqualTo(1);
}
@Test
void classPathResourceWithClassLoader() throws IOException {
Resource resource =
new ClassPathResource("org/springframework/core/io/Resource.class", getClass().getClassLoader());
doTestResource(resource);
assertThat(new ClassPathResource("org/springframework/core/../core/io/./Resource.class", getClass().getClassLoader())).isEqualTo(resource);
}
@Test
void classPathResourceWithClass() throws IOException {
Resource resource = new ClassPathResource("Resource.class", getClass());
doTestResource(resource);
assertThat(new ClassPathResource("Resource.class", getClass())).isEqualTo(resource);
}
@Test
void fileSystemResource() throws IOException {
String file = getClass().getResource("Resource.class").getFile();
Resource resource = new FileSystemResource(file);
doTestResource(resource);
assertThat(resource).isEqualTo(new FileSystemResource(file));
}
@Test
void fileSystemResourceWithFile() throws IOException {
File file = new File(getClass().getResource("Resource.class").getFile());
Resource resource = new FileSystemResource(file);
doTestResource(resource);
assertThat(resource).isEqualTo(new FileSystemResource(file));
}
@Test
void fileSystemResourceWithFilePath() throws Exception {
Path filePath = Paths.get(getClass().getResource("Resource.class").toURI());
Resource resource = new FileSystemResource(filePath);
doTestResource(resource);
assertThat(resource).isEqualTo(new FileSystemResource(filePath));
}
@Test
void fileSystemResourceWithPlainPath() {
Resource resource = new FileSystemResource("core/io/Resource.class");
assertThat(new FileSystemResource("core/../core/io/./Resource.class")).isEqualTo(resource);
}
@Test
void urlResource() throws IOException {
Resource resource = new UrlResource(getClass().getResource("Resource.class"));
doTestResource(resource);
assertThat(resource).isEqualTo(new UrlResource(getClass().getResource("Resource.class")));
Resource resource2 = new UrlResource("file:core/io/Resource.class");
assertThat(new UrlResource("file:core/../core/io/./Resource.class")).isEqualTo(resource2);
assertThat(new UrlResource("file:/dir/test.txt?argh").getFilename()).isEqualTo("test.txt");
assertThat(new UrlResource("file:\\dir\\test.txt?argh").getFilename()).isEqualTo("test.txt");
assertThat(new UrlResource("file:\\dir/test.txt?argh").getFilename()).isEqualTo("test.txt");
}
private void doTestResource(Resource resource) throws IOException {
assertThat(resource.getFilename()).isEqualTo("Resource.class");
assertThat(resource.getURL().getFile().endsWith("Resource.class")).isTrue();
assertThat(resource.exists()).isTrue();
assertThat(resource.isReadable()).isTrue();
assertThat(resource.contentLength() > 0).isTrue();
assertThat(resource.lastModified() > 0).isTrue();
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void resourceCreateRelative(Resource resource) throws Exception {
Resource relative1 = resource.createRelative("ClassPathResource.class");
assertThat(relative1.getFilename()).isEqualTo("ClassPathResource.class");
assertThat(relative1.getURL().getFile().endsWith("ClassPathResource.class")).isTrue();
@@ -82,11 +182,7 @@ class ResourceTests {
assertThat(relative1.isReadable()).isTrue();
assertThat(relative1.contentLength() > 0).isTrue();
assertThat(relative1.lastModified() > 0).isTrue();
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void resourceCreateRelativeWithFolder(Resource resource) throws Exception {
Resource relative2 = resource.createRelative("support/ResourcePatternResolver.class");
assertThat(relative2.getFilename()).isEqualTo("ResourcePatternResolver.class");
assertThat(relative2.getURL().getFile().endsWith("ResourcePatternResolver.class")).isTrue();
@@ -94,11 +190,7 @@ class ResourceTests {
assertThat(relative2.isReadable()).isTrue();
assertThat(relative2.contentLength() > 0).isTrue();
assertThat(relative2.lastModified() > 0).isTrue();
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void resourceCreateRelativeWithDotPath(Resource resource) throws Exception {
Resource relative3 = resource.createRelative("../SpringVersion.class");
assertThat(relative3.getFilename()).isEqualTo("SpringVersion.class");
assertThat(relative3.getURL().getFile().endsWith("SpringVersion.class")).isTrue();
@@ -106,11 +198,7 @@ class ResourceTests {
assertThat(relative3.isReadable()).isTrue();
assertThat(relative3.contentLength() > 0).isTrue();
assertThat(relative3.lastModified() > 0).isTrue();
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void resourceCreateRelativeUnknown(Resource resource) throws Exception {
Resource relative4 = resource.createRelative("X.class");
assertThat(relative4.exists()).isFalse();
assertThat(relative4.isReadable()).isFalse();
@@ -120,323 +208,126 @@ class ResourceTests {
relative4::lastModified);
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void loadingMissingResourceFails(Resource resource) {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("X").getInputStream());
@Test
void classPathResourceWithRelativePath() throws IOException {
Resource resource = new ClassPathResource("dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new ClassPathResource("dir/subdir"));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void readingMissingResourceFails(Resource resource) {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("X").readableChannel());
@Test
void fileSystemResourceWithRelativePath() throws IOException {
Resource resource = new FileSystemResource("dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new FileSystemResource("dir/subdir"));
}
private static Stream<Arguments> resource() throws URISyntaxException {
URL resourceClass = ResourceTests.class.getResource("Resource.class");
Path resourceClassFilePath = Paths.get(resourceClass.toURI());
return Stream.of(
Arguments.of(Named.of("ClassPathResource", new ClassPathResource("org/springframework/core/io/Resource.class"))),
Arguments.of(Named.of("ClassPathResource with ClassLoader", new ClassPathResource("org/springframework/core/io/Resource.class", ResourceTests.class.getClassLoader()))),
Arguments.of(Named.of("ClassPathResource with Class", new ClassPathResource("Resource.class", ResourceTests.class))),
Arguments.of(Named.of("FileSystemResource", new FileSystemResource(resourceClass.getFile()))),
Arguments.of(Named.of("FileSystemResource with File", new FileSystemResource(new File(resourceClass.getFile())))),
Arguments.of(Named.of("FileSystemResource with File path", new FileSystemResource(resourceClassFilePath))),
Arguments.of(Named.of("UrlResource", new UrlResource(resourceClass)))
);
@Test
void urlResourceWithRelativePath() throws IOException {
Resource resource = new UrlResource("file:dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new UrlResource("file:dir/subdir"));
}
@Test
void nonFileResourceExists() throws Exception {
URL url = new URL("https://spring.io/");
@Nested
class ByteArrayResourceTests {
@Test
void hasContent() throws Exception {
Resource resource = new ByteArrayResource("testString".getBytes());
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isFalse();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new ByteArrayResource("testString".getBytes())).isEqualTo(resource);
}
@Test
void isNotOpen() {
Resource resource = new ByteArrayResource("testString".getBytes());
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isFalse();
}
@Test
void hasDescription() {
Resource resource = new ByteArrayResource("testString".getBytes(), "my description");
assertThat(resource.getDescription().contains("my description")).isTrue();
}
// Abort if spring.io is not reachable.
assumeTrue(urlIsReachable(url));
Resource resource = new UrlResource(url);
assertThat(resource.exists()).isTrue();
}
@Nested
class InputStreamResourceTests {
@Test
void hasContent() throws Exception {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is);
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new InputStreamResource(is)).isEqualTo(resource);
private boolean urlIsReachable(URL url) {
try {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
connection.setReadTimeout(5_000);
return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
}
@Test
void isOpen() {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is);
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isTrue();
}
@Test
void hasDescription() {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is, "my description");
assertThat(resource.getDescription().contains("my description")).isTrue();
catch (Exception ex) {
return false;
}
}
@Test
void abstractResourceExceptions() throws Exception {
final String name = "test-resource";
@Nested
class ClassPathResourceTests {
@Test
void equalsAndHashCode() {
Resource resource = new ClassPathResource("org/springframework/core/io/Resource.class");
Resource resource2 = new ClassPathResource("org/springframework/core/../core/io/./Resource.class");
Resource resource3 = new ClassPathResource("org/springframework/core/").createRelative("../core/io/./Resource.class");
assertThat(resource2).isEqualTo(resource);
assertThat(resource3).isEqualTo(resource);
// Check whether equal/hashCode works in a HashSet.
HashSet<Resource> resources = new HashSet<>();
resources.add(resource);
resources.add(resource2);
assertThat(resources.size()).isEqualTo(1);
}
@Test
void resourcesWithDifferentPathsAreEqual() {
Resource resource = new ClassPathResource("org/springframework/core/io/Resource.class", getClass().getClassLoader());
ClassPathResource sameResource = new ClassPathResource("org/springframework/core/../core/io/./Resource.class", getClass().getClassLoader());
assertThat(sameResource).isEqualTo(resource);
}
@Test
void relativeResourcesAreEqual() throws Exception {
Resource resource = new ClassPathResource("dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new ClassPathResource("dir/subdir"));
}
}
@Nested
class FileSystemResourceTests {
@Test
void sameResourceIsEqual() {
String file = getClass().getResource("Resource.class").getFile();
Resource resource = new FileSystemResource(file);
assertThat(resource).isEqualTo(new FileSystemResource(file));
}
@Test
void sameResourceFromFileIsEqual() {
File file = new File(getClass().getResource("Resource.class").getFile());
Resource resource = new FileSystemResource(file);
assertThat(resource).isEqualTo(new FileSystemResource(file));
}
@Test
void sameResourceFromFilePathIsEqual() throws Exception {
Path filePath = Paths.get(getClass().getResource("Resource.class").toURI());
Resource resource = new FileSystemResource(filePath);
assertThat(resource).isEqualTo(new FileSystemResource(filePath));
}
@Test
void sameResourceFromDotPathIsEqual() {
Resource resource = new FileSystemResource("core/io/Resource.class");
assertThat(new FileSystemResource("core/../core/io/./Resource.class")).isEqualTo(resource);
}
@Test
void relativeResourcesAreEqual() throws Exception {
Resource resource = new FileSystemResource("dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new FileSystemResource("dir/subdir"));
}
@Test
void readableChannelProvidesContent() throws Exception {
Resource resource = new FileSystemResource(getClass().getResource("Resource.class").getFile());
try (ReadableByteChannel channel = resource.readableChannel()) {
ByteBuffer buffer = ByteBuffer.allocate((int) resource.contentLength());
channel.read(buffer);
buffer.rewind();
assertThat(buffer.limit() > 0).isTrue();
}
}
}
@Nested
class UrlResourceTests {
private MockWebServer server = new MockWebServer();
@Test
void sameResourceWithRelativePathIsEqual() throws Exception {
Resource resource = new UrlResource("file:core/io/Resource.class");
assertThat(new UrlResource("file:core/../core/io/./Resource.class")).isEqualTo(resource);
}
@Test
void filenameIsExtractedFromFilePath() throws Exception {
assertThat(new UrlResource("file:/dir/test.txt?argh").getFilename()).isEqualTo("test.txt");
assertThat(new UrlResource("file:\\dir\\test.txt?argh").getFilename()).isEqualTo("test.txt");
assertThat(new UrlResource("file:\\dir/test.txt?argh").getFilename()).isEqualTo("test.txt");
}
@Test
void relativeResourcesAreEqual() throws Exception {
Resource resource = new UrlResource("file:dir/");
Resource relative = resource.createRelative("subdir");
assertThat(relative).isEqualTo(new UrlResource("file:dir/subdir"));
}
@Test
void missingRemoteResourceDoesNotExist() throws Exception {
String baseUrl = startServer();
UrlResource resource = new UrlResource(baseUrl + "/missing");
assertThat(resource.exists()).isFalse();
}
@Test
void remoteResourceExists() throws Exception {
String baseUrl = startServer();
UrlResource resource = new UrlResource(baseUrl + "/resource");
assertThat(resource.exists()).isTrue();
assertThat(resource.contentLength()).isEqualTo(6);
}
@Test
void canCustomizeHttpUrlConnectionForExists() throws Exception {
String baseUrl = startServer();
CustomResource resource = new CustomResource(baseUrl + "/resource");
assertThat(resource.exists()).isTrue();
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("HEAD");
assertThat(request.getHeader("Framework-Name")).isEqualTo("Spring");
}
@Test
void canCustomizeHttpUrlConnectionForRead() throws Exception {
String baseUrl = startServer();
CustomResource resource = new CustomResource(baseUrl + "/resource");
assertThat(resource.getInputStream()).hasContent("Spring");
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getHeader("Framework-Name")).isEqualTo("Spring");
}
@AfterEach
void shutdown() throws Exception {
this.server.shutdown();
}
private String startServer() throws Exception {
this.server.setDispatcher(new ResourceDispatcher());
this.server.start();
return "http://localhost:" + this.server.getPort();
}
class CustomResource extends UrlResource {
public CustomResource(String path) throws MalformedURLException {
super(path);
}
Resource resource = new AbstractResource() {
@Override
protected void customizeConnection(HttpURLConnection con) throws IOException {
con.setRequestProperty("Framework-Name", "Spring");
public String getDescription() {
return name;
}
}
class ResourceDispatcher extends Dispatcher {
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
if (request.getPath().equals("/resource")) {
switch (request.getMethod()) {
case "HEAD":
return new MockResponse()
.addHeader("Content-Length", "6");
case "GET":
return new MockResponse()
.addHeader("Content-Length", "6")
.addHeader("Content-Type", "text/plain")
.setBody("Spring");
}
}
return new MockResponse().setResponseCode(404);
public InputStream getInputStream() throws IOException {
throw new FileNotFoundException();
}
};
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(
resource::getURL)
.withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(
resource::getFile)
.withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("/testing"))
.withMessageContaining(name);
assertThat(resource.getFilename()).isNull();
}
@Test
void contentLength() throws IOException {
AbstractResource resource = new AbstractResource() {
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(new byte[] { 'a', 'b', 'c' });
}
@Override
public String getDescription() {
return "";
}
};
assertThat(resource.contentLength()).isEqualTo(3L);
}
@Test
void readableChannel() throws IOException {
Resource resource = new FileSystemResource(getClass().getResource("Resource.class").getFile());
try (ReadableByteChannel channel = resource.readableChannel()) {
ByteBuffer buffer = ByteBuffer.allocate((int) resource.contentLength());
channel.read(buffer);
buffer.rewind();
assertThat(buffer.limit() > 0).isTrue();
}
}
@Nested
class AbstractResourceTests {
@Test
void inputStreamNotFoundOnFileSystemResource() throws IOException {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
new FileSystemResource(getClass().getResource("Resource.class").getFile()).createRelative("X").getInputStream());
}
@Test
void missingResourceIsNotReadable() {
final String name = "test-resource";
@Test
void readableChannelNotFoundOnFileSystemResource() throws IOException {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
new FileSystemResource(getClass().getResource("Resource.class").getFile()).createRelative("X").readableChannel());
}
Resource resource = new AbstractResource() {
@Override
public String getDescription() {
return name;
}
@Override
public InputStream getInputStream() throws IOException {
throw new FileNotFoundException();
}
};
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(resource::getURL)
.withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(resource::getFile)
.withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("/testing")).withMessageContaining(name);
assertThat(resource.getFilename()).isNull();
}
@Test
void hasContentLength() throws Exception {
AbstractResource resource = new AbstractResource() {
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(new byte[] {'a', 'b', 'c'});
}
@Override
public String getDescription() {
return "";
}
};
assertThat(resource.contentLength()).isEqualTo(3L);
}
@Test
void inputStreamNotFoundOnClassPathResource() throws IOException {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
new ClassPathResource("Resource.class", getClass()).createRelative("X").getInputStream());
}
@Test
void readableChannelNotFoundOnClassPathResource() throws IOException {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
new ClassPathResource("Resource.class", getClass()).createRelative("X").readableChannel());
}
}
@@ -990,27 +990,6 @@ class DataBufferUtilsTests extends AbstractDataBufferAllocatingTests {
}
}
@ParameterizedDataBufferAllocatingTest
void propagateContextPath(DataBufferFactory bufferFactory) throws IOException {
Path path = Paths.get(this.resource.getURI());
Path out = Files.createTempFile("data-buffer-utils-tests", ".tmp");
Flux<Void> result = DataBufferUtils.read(path, bufferFactory, 1024, StandardOpenOption.READ)
.transformDeferredContextual((f, ctx) -> {
assertThat(ctx.getOrDefault("key", "EMPTY")).isEqualTo("TEST");
return f;
})
.transform(f -> DataBufferUtils.write(f, out))
.transformDeferredContextual((f, ctx) -> {
assertThat(ctx.getOrDefault("key", "EMPTY")).isEqualTo("TEST");
return f;
})
.contextWrite(Context.of("key", "TEST"));
StepVerifier.create(result)
.verifyComplete();
}
private static class ZeroDemandSubscriber extends BaseSubscriber<DataBuffer> {
@Override
+2 -2
View File
@@ -31,10 +31,10 @@ Syntax
- Need to agree on a standard date format for 'default' processing of dates. Currently it is:
formatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.UK);
// this is something of this format: "Wed, 4 Jul 2001 12:08:56 GMT"
// https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
// https://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html
- See LiteralTests for Date (4,5,6) - should date take an expression rather than be hardcoded in the grammar
to take 2 strings only?
- when doing arithmetic, eg. 8.4 / 4 and the user asks for an Integer return type - do we silently coerce or
say we cannot as it won't fit into an int? (see OperatorTests.testMathOperatorDivide04)
- Is $index within projection/selection useful or just cute?
- All reals are represented as Doubles (so 1.25f is held internally as a double, can be converted to float when required though) - is that ok?
- All reals are represented as Doubles (so 1.25f is held internally as a double, can be converted to float when required though) - is that ok?
@@ -19,7 +19,7 @@ package org.springframework.expression;
import org.springframework.lang.Nullable;
/**
* Superclass for exceptions that can occur whilst processing expressions.
* Super class for exceptions that can occur whilst processing expressions.
*
* @author Andy Clement
* @author Phillip Webb
@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
///CLOVER:OFF
/**
* Spring Security scenarios from https://docs.spring.io/spring-security/reference/servlet/authorization/expression-based.html
* Spring Security scenarios from https://wiki.springsource.com/display/SECURITY/Spring+Security+Expression-based+Authorization
*
* @author Andy Clement
*/
@@ -29,7 +29,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Convenient superclass for JDBC-based data access objects.
* Convenient super class for JDBC-based data access objects.
*
* <p>Requires a {@link javax.sql.DataSource} to be set, providing a
* {@link org.springframework.jdbc.core.JdbcTemplate} based on it to
@@ -25,7 +25,7 @@ package org.springframework.jdbc.datasource.embedded;
*/
public enum EmbeddedDatabaseType {
/** The <a href="https://hsqldb.org">Hypersonic</a> Embedded Java SQL Database. */
/** The <a href="http://hsqldb.org">Hypersonic</a> Embedded Java SQL Database. */
HSQL,
/** The <a href="https://h2database.com">H2</a> Embedded Java SQL Database Engine. */
@@ -27,7 +27,7 @@ import org.springframework.jms.core.JmsTemplate;
import org.springframework.lang.Nullable;
/**
* Convenient superclass for application classes that need JMS access.
* Convenient super class for application classes that need JMS access.
*
* <p>Requires a ConnectionFactory or a JmsTemplate instance to be set.
* It will create its own JmsTemplate if a ConnectionFactory is passed in.
@@ -29,7 +29,7 @@ import org.springframework.util.Assert;
/**
* Implementation of {@link MessageConverter} that can read and write JSON
* using the <a href="https://javaee.github.io/jsonb-spec/">JSON Binding API</a>.
* using the <a href="http://json-b.net/">JSON Binding API</a>.
*
* @author Juergen Hoeller
* @since 5.3
@@ -262,7 +262,7 @@ public abstract class AbstractBrokerMessageHandler
* may still independently alternate between being on and off depending on the
* concrete subclass implementation.
* <p>Application components may implement
* {@code org.springframework.context.ApplicationListener<BrokerAvailabilityEvent>}
* {@code org.springframework.context.ApplicationListener&lt;BrokerAvailabilityEvent&gt;}
* to receive notifications when broker becomes available and unavailable.
*/
public boolean isBrokerAvailable() {
@@ -461,9 +461,6 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
if (registerDefaults) {
converters.add(new StringMessageConverter());
converters.add(new ByteArrayMessageConverter());
if (kotlinSerializationJsonPresent) {
converters.add(new KotlinSerializationJsonMessageConverter());
}
if (jackson2Present) {
converters.add(createJacksonConverter());
}
@@ -473,6 +470,9 @@ public abstract class AbstractMessageBrokerConfiguration implements ApplicationC
else if (jsonbPresent) {
converters.add(new JsonbMessageConverter());
}
else if (kotlinSerializationJsonPresent) {
converters.add(new KotlinSerializationJsonMessageConverter());
}
}
return new CompositeMessageConverter(converters);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -18,6 +18,7 @@ package org.springframework.messaging.simp.stomp;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -26,7 +27,6 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import org.apache.commons.logging.Log;
@@ -441,7 +441,7 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
String receiptId = headers.getReceiptId();
ReceiptHandler handler = this.receiptHandlers.get(receiptId);
if (handler != null) {
handler.handleReceiptReceived(headers);
handler.handleReceiptReceived();
}
else if (logger.isDebugEnabled()) {
logger.debug("No matching receipt: " + accessor.getDetailedLogMessage(message.getPayload()));
@@ -546,7 +546,7 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
@Nullable
private final String receiptId;
private final List<Consumer<StompHeaders>> receiptCallbacks = new ArrayList<>(2);
private final List<Runnable> receiptCallbacks = new ArrayList<>(2);
private final List<Runnable> receiptLostCallbacks = new ArrayList<>(2);
@@ -556,9 +556,6 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
@Nullable
private Boolean result;
@Nullable
private StompHeaders receiptHeaders;
public ReceiptHandler(@Nullable String receiptId) {
this.receiptId = receiptId;
if (receiptId != null) {
@@ -581,80 +578,64 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
@Override
public void addReceiptTask(Runnable task) {
addReceiptTask(headers -> task.run());
}
@Override
public void addReceiptTask(Consumer<StompHeaders> task) {
Assert.notNull(this.receiptId, "Set autoReceiptEnabled to track receipts or add a 'receiptId' header");
synchronized (this) {
if (this.result != null) {
if (this.result) {
task.accept(this.receiptHeaders);
}
}
else {
this.receiptCallbacks.add(task);
}
}
addTask(task, true);
}
@Override
public void addReceiptLostTask(Runnable task) {
addTask(task, false);
}
private void addTask(Runnable task, boolean successTask) {
Assert.notNull(this.receiptId,
"To track receipts, set autoReceiptEnabled=true or add 'receiptId' header");
synchronized (this) {
if (this.result != null) {
if (!this.result) {
task.run();
}
if (this.result != null && this.result == successTask) {
invoke(Collections.singletonList(task));
}
else {
this.receiptLostCallbacks.add(task);
if (successTask) {
this.receiptCallbacks.add(task);
}
else {
this.receiptLostCallbacks.add(task);
}
}
}
}
public void handleReceiptReceived(StompHeaders receiptHeaders) {
handleInternal(true, receiptHeaders);
private void invoke(List<Runnable> callbacks) {
for (Runnable runnable : callbacks) {
try {
runnable.run();
}
catch (Throwable ex) {
// ignore
}
}
}
public void handleReceiptReceived() {
handleInternal(true);
}
public void handleReceiptNotReceived() {
handleInternal(false, null);
handleInternal(false);
}
private void handleInternal(boolean result, @Nullable StompHeaders receiptHeaders) {
private void handleInternal(boolean result) {
synchronized (this) {
if (this.result != null) {
return;
}
this.result = result;
this.receiptHeaders = receiptHeaders;
if (result) {
this.receiptCallbacks.forEach(consumer -> {
try {
consumer.accept(this.receiptHeaders);
}
catch (Throwable ex) {
// ignore
}
});
}
else {
this.receiptLostCallbacks.forEach(task -> {
try {
task.run();
}
catch (Throwable ex) {
// ignore
}
});
}
invoke(result ? this.receiptCallbacks : this.receiptLostCallbacks);
DefaultStompSession.this.receiptHandlers.remove(this.receiptId);
if (this.future != null) {
this.future.cancel(true);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -16,8 +16,6 @@
package org.springframework.messaging.simp.stomp;
import java.util.function.Consumer;
import org.springframework.lang.Nullable;
/**
@@ -141,27 +139,16 @@ public interface StompSession {
/**
* Task to invoke when a receipt is received.
* @param task the task to invoke
* @throws java.lang.IllegalArgumentException if the receiptId is {@code null}
*/
void addReceiptTask(Runnable task);
/**
* Variant of {@link #addReceiptTask(Runnable)} with a {@link Consumer}
* of the headers from the {@code RECEIPT} frame.
* @param task the consumer to invoke
* @throws java.lang.IllegalArgumentException if the receiptId is {@code null}
* @since 5.3.23
*/
void addReceiptTask(Consumer<StompHeaders> task);
void addReceiptTask(Runnable runnable);
/**
* Task to invoke when a receipt is not received in the configured time.
* @param task the task to invoke
* @throws java.lang.IllegalArgumentException if the receiptId is {@code null}
* @see org.springframework.messaging.simp.stomp.StompClientSupport#setReceiptTimeLimit(long)
*/
void addReceiptLostTask(Runnable task);
void addReceiptLostTask(Runnable runnable);
}
@@ -39,7 +39,6 @@ import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.ContentTypeResolver;
import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.KotlinSerializationJsonMessageConverter;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
@@ -283,13 +282,12 @@ public class MessageBrokerConfigurationTests {
CompositeMessageConverter compositeConverter = config.brokerMessageConverter();
List<MessageConverter> converters = compositeConverter.getConverters();
assertThat(converters).hasSize(4);
assertThat(converters).hasSize(3);
assertThat(converters.get(0)).isInstanceOf(StringMessageConverter.class);
assertThat(converters.get(1)).isInstanceOf(ByteArrayMessageConverter.class);
assertThat(converters.get(2)).isInstanceOf(KotlinSerializationJsonMessageConverter.class);
assertThat(converters.get(3)).isInstanceOf(MappingJackson2MessageConverter.class);
assertThat(converters.get(2)).isInstanceOf(MappingJackson2MessageConverter.class);
ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(3)).getContentTypeResolver();
ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver();
assertThat(((DefaultContentTypeResolver) resolver).getDefaultMimeType()).isEqualTo(MimeTypeUtils.APPLICATION_JSON);
}
@@ -342,12 +340,11 @@ public class MessageBrokerConfigurationTests {
};
CompositeMessageConverter compositeConverter = config.brokerMessageConverter();
assertThat(compositeConverter.getConverters()).hasSize(5);
assertThat(compositeConverter.getConverters()).hasSize(4);
Iterator<MessageConverter> iterator = compositeConverter.getConverters().iterator();
assertThat(iterator.next()).isEqualTo(testConverter);
assertThat(iterator.next()).isInstanceOf(StringMessageConverter.class);
assertThat(iterator.next()).isInstanceOf(ByteArrayMessageConverter.class);
assertThat(iterator.next()).isInstanceOf(KotlinSerializationJsonMessageConverter.class);
assertThat(iterator.next()).isInstanceOf(MappingJackson2MessageConverter.class);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -576,30 +576,22 @@ public class DefaultStompSessionTests {
this.session.setTaskScheduler(mock(TaskScheduler.class));
AtomicReference<Boolean> received = new AtomicReference<>();
AtomicReference<StompHeaders> receivedHeaders = new AtomicReference<>();
StompHeaders headers = new StompHeaders();
headers.setDestination("/topic/foo");
headers.setReceipt("my-receipt");
Subscription subscription = this.session.subscribe(headers, mock(StompFrameHandler.class));
subscription.addReceiptTask(receiptHeaders -> {
received.set(true);
receivedHeaders.set(receiptHeaders);
});
subscription.addReceiptTask(() -> received.set(true));
assertThat((Object) received.get()).isNull();
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.RECEIPT);
accessor.setReceiptId("my-receipt");
accessor.setNativeHeader("foo", "bar");
accessor.setLeaveMutable(true);
this.session.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders()));
assertThat(received.get()).isNotNull();
assertThat(received.get()).isTrue();
assertThat(receivedHeaders.get()).isNotNull();
assertThat(receivedHeaders.get().get("foo").size()).isEqualTo(1);
assertThat(receivedHeaders.get().get("foo").get(0)).isEqualTo("bar");
}
@Test
@@ -608,7 +600,6 @@ public class DefaultStompSessionTests {
this.session.setTaskScheduler(mock(TaskScheduler.class));
AtomicReference<Boolean> received = new AtomicReference<>();
AtomicReference<StompHeaders> receivedHeaders = new AtomicReference<>();
StompHeaders headers = new StompHeaders();
headers.setDestination("/topic/foo");
@@ -617,20 +608,13 @@ public class DefaultStompSessionTests {
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.RECEIPT);
accessor.setReceiptId("my-receipt");
accessor.setNativeHeader("foo", "bar");
accessor.setLeaveMutable(true);
this.session.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders()));
subscription.addReceiptTask(receiptHeaders -> {
received.set(true);
receivedHeaders.set(receiptHeaders);
});
subscription.addReceiptTask(() -> received.set(true));
assertThat(received.get()).isNotNull();
assertThat(received.get()).isTrue();
assertThat(receivedHeaders.get()).isNotNull();
assertThat(receivedHeaders.get().get("foo").size()).isEqualTo(1);
assertThat(receivedHeaders.get().get("foo").get(0)).isEqualTo("bar");
}
@Test
@@ -26,7 +26,7 @@ import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.util.Assert;
/**
* Convenient superclass for Hibernate-based data access objects.
* Convenient super class for Hibernate-based data access objects.
*
* <p>Requires a {@link SessionFactory} to be set, providing a
* {@link org.springframework.orm.hibernate5.HibernateTemplate} based on it to
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -73,6 +73,40 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
this.contextCache = contextCache;
}
/**
* Get the {@link ContextCache} used by this context loader delegate.
*/
protected ContextCache getContextCache() {
return this.contextCache;
}
/**
* Load the {@code ApplicationContext} for the supplied merged context configuration.
* <p>Supports both the {@link SmartContextLoader} and {@link ContextLoader} SPIs.
* @throws Exception if an error occurs while loading the application context
*/
protected ApplicationContext loadContextInternal(MergedContextConfiguration mergedContextConfiguration)
throws Exception {
ContextLoader contextLoader = mergedContextConfiguration.getContextLoader();
Assert.notNull(contextLoader, "Cannot load an ApplicationContext with a NULL 'contextLoader'. " +
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
ApplicationContext applicationContext;
if (contextLoader instanceof SmartContextLoader) {
SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader;
applicationContext = smartContextLoader.loadContext(mergedContextConfiguration);
}
else {
String[] locations = mergedContextConfiguration.getLocations();
Assert.notNull(locations, "Cannot load an ApplicationContext with a NULL 'locations' array. " +
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
applicationContext = contextLoader.loadContext(locations);
}
return applicationContext;
}
@Override
public boolean isContextLoaded(MergedContextConfiguration mergedContextConfiguration) {
@@ -118,34 +152,4 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
}
}
/**
* Get the {@link ContextCache} used by this context loader delegate.
*/
protected ContextCache getContextCache() {
return this.contextCache;
}
/**
* Load the {@code ApplicationContext} for the supplied merged context configuration.
* <p>Supports both the {@link SmartContextLoader} and {@link ContextLoader} SPIs.
* @throws Exception if an error occurs while loading the application context
*/
protected ApplicationContext loadContextInternal(MergedContextConfiguration mergedContextConfiguration)
throws Exception {
ContextLoader contextLoader = mergedContextConfiguration.getContextLoader();
Assert.notNull(contextLoader, "Cannot load an ApplicationContext with a NULL 'contextLoader'. " +
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
if (contextLoader instanceof SmartContextLoader) {
return ((SmartContextLoader) contextLoader).loadContext(mergedContextConfiguration);
}
else {
String[] locations = mergedContextConfiguration.getLocations();
Assert.notNull(locations, "Cannot load an ApplicationContext with a NULL 'locations' array. " +
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
return contextLoader.loadContext(locations);
}
}
}
@@ -200,10 +200,9 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* Factory method for creating the {@link GenericApplicationContext} used by
* this {@code ContextLoader}.
* <p>The default implementation creates a {@code GenericApplicationContext}
* using the default constructor. This method may be overridden &mdash; for
* example, to use a custom context subclass or to create a
* {@code GenericApplicationContext} with a custom
* {@link DefaultListableBeanFactory} implementation.
* using the default constructor. This method may get overridden e.g. to use
* a custom context subclass or to create a {@code GenericApplicationContext}
* with a custom {@link DefaultListableBeanFactory} implementation.
* @return a newly instantiated {@code GenericApplicationContext}
* @since 5.2.9
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -114,7 +114,7 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
validateMergedContextConfiguration(webMergedConfig);
GenericWebApplicationContext context = createContext();
GenericWebApplicationContext context = new GenericWebApplicationContext();
ApplicationContext parent = mergedConfig.getParentApplicationContext();
if (parent != null) {
@@ -145,21 +145,6 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
// no-op
}
/**
* Factory method for creating the {@link GenericWebApplicationContext} used
* by this {@code ContextLoader}.
* <p>The default implementation creates a {@code GenericWebApplicationContext}
* using the default constructor. This method may be overridden &mdash; for
* example, to use a custom context subclass or to create a
* {@code GenericWebApplicationContext} with a custom
* {@link DefaultListableBeanFactory} implementation.
* @return a newly instantiated {@code GenericWebApplicationContext}
* @since 5.3.23
*/
protected GenericWebApplicationContext createContext() {
return new GenericWebApplicationContext();
}
/**
* Configures web resources for the supplied web application context (WAC).
* <h4>Implementation Details</h4>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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,25 +19,26 @@ package org.springframework.test.context.web.socket;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.ClassUtils;
/**
* {@link ContextCustomizerFactory} which creates a {@link MockServerContainerContextCustomizer}
* if WebSocket support is present in the classpath and the test class or one of
* its enclosing classes is annotated or meta-annotated with
* {@link WebAppConfiguration @WebAppConfiguration}.
* if WebSocket support is present in the classpath and the test class is annotated
* with {@code @WebAppConfiguration}.
*
* @author Sam Brannen
* @since 4.3.1
*/
class MockServerContainerContextCustomizerFactory implements ContextCustomizerFactory {
private static final String WEB_APP_CONFIGURATION_ANNOTATION_CLASS_NAME =
"org.springframework.test.context.web.WebAppConfiguration";
private static final String MOCK_SERVER_CONTAINER_CONTEXT_CUSTOMIZER_CLASS_NAME =
"org.springframework.test.context.web.socket.MockServerContainerContextCustomizer";
@@ -67,7 +68,8 @@ class MockServerContainerContextCustomizerFactory implements ContextCustomizerFa
}
private static boolean isAnnotatedWithWebAppConfiguration(Class<?> testClass) {
return TestContextAnnotationUtils.hasAnnotation(testClass, WebAppConfiguration.class);
return (AnnotatedElementUtils.findMergedAnnotationAttributes(testClass,
WEB_APP_CONFIGURATION_ANNOTATION_CLASS_NAME, false, false) != null);
}
}
@@ -255,7 +255,7 @@ public class ContentRequestMatchers {
* two are "similar" - i.e. they contain the same elements and attributes
* regardless of order.
* <p>Use of this matcher assumes the
* <a href="https://www.xmlunit.org/">XMLUnit</a> library is available.
* <a href="http://xmlunit.sourceforge.net/">XMLUnit</a> library is available.
* @param expectedXmlContent the expected XML content
*/
public RequestMatcher xml(String expectedXmlContent) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -56,11 +56,9 @@ import org.springframework.web.servlet.DispatcherServlet;
* MockMvc mockMvc = webAppContextSetup(wac).build();
*
* mockMvc.perform(get("/form"))
* .andExpectAll(
* status().isOk(),
* content().contentType("text/html"),
* forwardedUrl("/WEB-INF/layouts/main.jsp")
* );
* .andExpect(status().isOk())
* .andExpect(content().mimeType("text/html"))
* .andExpect(forwardedUrl("/WEB-INF/layouts/main.jsp"));
* </pre>
*
* @author Rossen Stoyanchev
@@ -40,7 +40,7 @@ import org.springframework.util.Assert;
/**
* {@code MockMvcWebConnection} enables {@link MockMvc} to transform a
* {@link WebRequest} into a {@link WebResponse}.
* <p>This is the core integration with <a href="https://htmlunit.sourceforge.io/">HtmlUnit</a>.
* <p>This is the core integration with <a href="http://htmlunit.sourceforge.net/">HtmlUnit</a>.
* <p>Example usage can be seen below.
*
* <pre class="code">
@@ -160,7 +160,7 @@ public class ContentResultMatchers {
* are "similar" - i.e. they contain the same elements and attributes
* regardless of order.
* <p>Use of this matcher requires the <a
* href="https://www.xmlunit.org/">XMLUnit</a> library.
* href="http://xmlunit.sourceforge.net/">XMLUnit</a> library.
* @param xmlContent the expected XML content
* @see MockMvcResultMatchers#xpath(String, Object...)
* @see MockMvcResultMatchers#xpath(String, Map, Object...)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -18,7 +18,6 @@ package org.springframework.test.context.web.socket;
import javax.websocket.server.ServerContainer;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -47,20 +46,6 @@ class WebSocketServletServerContainerFactoryBeanTests {
assertThat(serverContainer.getDefaultMaxTextMessageBufferSize()).isEqualTo(42);
}
/*
* @Nested test class to verify that the MockServerContainerContextCustomizerFactory
* properly supports finding @WebAppConfiguration on an enclosing class.
*/
@Nested
class NestedTests {
@Test // gh-29037
void servletServerContainerFactoryBeanSupport(@Autowired ServerContainer serverContainer) {
assertThat(serverContainer.getDefaultMaxTextMessageBufferSize()).isEqualTo(42);
}
}
@Configuration
@EnableWebSocket
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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,7 +25,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Convenient superclass for CCI-based data access objects.
* Convenient super class for CCI-based data access objects.
*
* <p>Requires a {@link javax.resource.cci.ConnectionFactory} to be set,
* providing a {@link org.springframework.jca.cci.core.CciTemplate} based
@@ -29,7 +29,7 @@ import org.springframework.util.StringUtils;
* {@link TransactionAttributeEditor} in this package.
*
* <p>Strings are in property syntax, with the form:<br>
* {@code FQCN.methodName=<transaction attribute string>}
* {@code FQCN.methodName=&lt;transaction attribute string&gt;}
*
* <p>For example:<br>
* {@code com.mycompany.mycode.MyClass.myMethod=PROPAGATION_MANDATORY,ISOLATION_DEFAULT}
@@ -28,7 +28,6 @@ import java.util.function.Consumer;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.util.UriTemplateHandler;
/**
* Extension of {@link HttpEntity} that also exposes the HTTP method and the
@@ -159,23 +158,11 @@ public class RequestEntity<T> extends HttpEntity<T> {
}
/**
* Return the {@link URI} for the target HTTP endpoint.
* <p><strong>Note:</strong> This method raises
* {@link UnsupportedOperationException} if the {@code RequestEntity} was
* created with a URI template and variables rather than with a {@link URI}
* instance. This is because a URI cannot be created without further input
* on how to expand template and encode the URI. In such cases, the
* {@code URI} is prepared by the
* {@link org.springframework.web.client.RestTemplate} with the help of the
* {@link UriTemplateHandler} it is configured with.
* Return the URL of the request.
*/
public URI getUrl() {
if (this.url == null) {
throw new UnsupportedOperationException(
"The RequestEntity was created with a URI template and variables, " +
"and there is not enough information on how to correctly expand and " +
"encode the URI template. This will be done by the RestTemplate instead " +
"with help from the UriTemplateHandler it is configured with.");
throw new UnsupportedOperationException();
}
return this.url;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -238,13 +238,13 @@ public final class ResponseCookie extends HttpCookie {
}
@Override
public ResponseCookieBuilder domain(@Nullable String domain) {
public ResponseCookieBuilder domain(String domain) {
this.domain = initDomain(domain);
return this;
}
@Nullable
private String initDomain(@Nullable String domain) {
private String initDomain(String domain) {
if (lenient && StringUtils.hasLength(domain)) {
String str = domain.trim();
if (str.startsWith("\"") && str.endsWith("\"")) {
@@ -257,7 +257,7 @@ public final class ResponseCookie extends HttpCookie {
}
@Override
public ResponseCookieBuilder path(@Nullable String path) {
public ResponseCookieBuilder path(String path) {
this.path = path;
return this;
}
@@ -312,12 +312,12 @@ public final class ResponseCookie extends HttpCookie {
/**
* Set the cookie "Path" attribute.
*/
ResponseCookieBuilder path(@Nullable String path);
ResponseCookieBuilder path(String path);
/**
* Set the cookie "Domain" attribute.
*/
ResponseCookieBuilder domain(@Nullable String domain);
ResponseCookieBuilder domain(String domain);
/**
* Add the "Secure" attribute to the cookie.
@@ -746,15 +746,8 @@ final class PartGenerator extends BaseSubscriber<MultipartParser.Token> {
@Override
public void partComplete(boolean finalPart) {
State state = PartGenerator.this.state.get();
// writeComplete might have changed our state to IdleFileState
if (state != this) {
state.partComplete(finalPart);
}
else {
this.completed = true;
this.finalPart = finalPart;
}
this.completed = true;
this.finalPart = finalPart;
}
public void writeBuffer(DataBuffer dataBuffer) {
@@ -778,16 +771,14 @@ final class PartGenerator extends BaseSubscriber<MultipartParser.Token> {
private void writeComplete() {
IdleFileState newState = new IdleFileState(this);
if (this.disposed) {
if (this.completed) {
newState.partComplete(this.finalPart);
}
else if (this.disposed) {
newState.dispose();
}
else if (changeState(this, newState)) {
if (this.completed) {
newState.partComplete(this.finalPart);
}
else {
requestToken();
}
requestToken();
}
else {
MultipartUtils.closeChannel(this.channel);
@@ -553,7 +553,7 @@ public class Jackson2ObjectMapperBuilder {
/**
* Variant of {@link #modules(Module...)} with a {@link Consumer} for full
* control over the underlying list of modules.
* @since 5.3.22
* @since 6.0
* @see #modules(Module...)
* @see #modules(List)
* @see com.fasterxml.jackson.databind.Module
@@ -589,7 +589,7 @@ public class Jackson2ObjectMapperBuilder {
/**
* Variant of {@link #modulesToInstall(Module...)} with a {@link Consumer}
* for full control over the underlying list of modules.
* @since 5.3.22
* @since 6.0
* @see #modulesToInstall(Module...)
* @see #modulesToInstall(Class...)
* @see com.fasterxml.jackson.databind.Module
@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
/**
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
* that can read and write JSON using the
* <a href="https://javaee.github.io/jsonb-spec/">JSON Binding API</a>.
* <a href="http://json-b.net/">JSON Binding API</a>.
*
* <p>This converter can be used to bind to typed beans or untyped {@code HashMap}s.
* By default, it supports {@code application/json} and {@code application/*+json} with
@@ -87,9 +87,6 @@ public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConv
}
}
if (kotlinSerializationJsonPresent) {
addPartConverter(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2Present) {
addPartConverter(new MappingJackson2HttpMessageConverter());
}
@@ -99,6 +96,9 @@ public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConv
else if (jsonbPresent) {
addPartConverter(new JsonbHttpMessageConverter());
}
else if (kotlinSerializationJsonPresent) {
addPartConverter(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2XmlPresent && !shouldIgnoreXml) {
addPartConverter(new MappingJackson2XmlHttpMessageConverter());
@@ -56,6 +56,8 @@ import org.springframework.util.StringUtils;
*/
public class ServletServerHttpRequest implements ServerHttpRequest {
protected static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded";
protected static final Charset FORM_CHARSET = StandardCharsets.UTF_8;
@@ -229,7 +231,7 @@ public class ServletServerHttpRequest implements ServerHttpRequest {
private static boolean isFormPost(HttpServletRequest request) {
String contentType = request.getContentType();
return (contentType != null && contentType.contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE) &&
return (contentType != null && contentType.contains(FORM_CONTENT_TYPE) &&
HttpMethod.POST.matches(request.getMethod()));
}
@@ -174,9 +174,6 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
}
if (kotlinSerializationJsonPresent) {
this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}
@@ -186,6 +183,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
else if (jsonbPresent) {
this.messageConverters.add(new JsonbHttpMessageConverter());
}
else if (kotlinSerializationJsonPresent) {
this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2SmilePresent) {
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
@@ -24,7 +24,7 @@ import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
/**
* Convenient superclass for application classes that need REST access.
* Convenient super class for application classes that need REST access.
*
* <p>Requires a {@link ClientHttpRequestFactory} or a {@link RestTemplate} instance to be set.
*
@@ -28,7 +28,7 @@ import org.springframework.lang.Nullable;
* this class which {@link RequestAttributes} scope to read attributes from.
*
* <p>Subclasses may wish to override the {@link #get} and {@link #remove}
* methods to add synchronization around the call back into this superclass.
* methods to add synchronization around the call back into this super class.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -95,8 +95,6 @@ public class StandardServletEnvironment extends StandardEnvironment implements C
* {@link StubPropertySource stubs} at this stage, and will be
* {@linkplain #initPropertySources(ServletContext, ServletConfig) fully initialized}
* once the actual {@link ServletContext} object becomes available.
* <p>Addition of {@value #JNDI_PROPERTY_SOURCE_NAME} can be disabled with
* {@link JndiLocatorDelegate#IGNORE_JNDI_PROPERTY_NAME}.
* @see StandardEnvironment#customizePropertySources
* @see org.springframework.core.env.AbstractEnvironment#customizePropertySources
* @see ServletConfigPropertySource
@@ -16,8 +16,6 @@
package org.springframework.web.filter;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@@ -46,11 +44,9 @@ final class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper {
@Override
public void sendRedirect(String location) throws IOException {
resetBuffer();
public void sendRedirect(String location) {
setStatus(this.redirectStatus.value());
setHeader(HttpHeaders.LOCATION, location);
flushBuffer();
}
@@ -128,7 +128,7 @@ public final class HandlerTypePredicate implements Predicate<Class<?>> {
/**
* Match handlers that are assignable to a given type.
* @param types one or more handler supertypes
* @param types one or more handler super types
*/
public static HandlerTypePredicate forAssignableType(Class<?>... types) {
return new Builder().assignableType(types).build();
@@ -187,7 +187,7 @@ public final class HandlerTypePredicate implements Predicate<Class<?>> {
/**
* Match handlers that are assignable to a given type.
* @param types one or more handler supertypes
* @param types one or more handler super types
*/
public Builder assignableType(Class<?>... types) {
this.assignableTypes.addAll(Arrays.asList(types));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -33,7 +33,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
@@ -56,6 +55,9 @@ import org.springframework.lang.Nullable;
*/
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded";
private final ByteArrayOutputStream cachedContent;
@Nullable
@@ -150,7 +152,7 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private boolean isFormPost() {
String contentType = getContentType();
return (contentType != null && contentType.contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE) &&
return (contentType != null && contentType.contains(FORM_CONTENT_TYPE) &&
HttpMethod.POST.matches(getMethod()));
}
@@ -21,7 +21,7 @@ package org.springframework.web.util;
* Escapes based on the JavaScript 1.5 recommendation.
*
* <p>Reference:
* <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#string_literals">
* <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Values,_variables,_and_literals#String_literals">
* JavaScript Guide</a> on Mozilla Developer Network.
*
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -628,17 +628,17 @@ public abstract class WebUtils {
* following algorithm:
* <ol>
* <li>Try to get the parameter value using just the given <i>logical</i> name.
* This handles parameters of the form {@code logicalName = value}. For normal
* This handles parameters of the form <tt>logicalName = value</tt>. For normal
* parameters, e.g. submitted using a hidden HTML form field, this will return
* the requested value.</li>
* <li>Try to obtain the parameter value from the parameter name, where the
* parameter name in the request is of the form {@code logicalName_value = xyz}
* parameter name in the request is of the form <tt>logicalName_value = xyz</tt>
* with "_" being the configured delimiter. This deals with parameter values
* submitted using an HTML form submit button.</li>
* <li>If the value obtained in the previous step has a ".x" or ".y" suffix,
* remove that. This handles cases where the value was submitted using an
* HTML form image button. In this case the parameter in the request would
* actually be of the form {@code logicalName_value.x = 123}.</li>
* actually be of the form <tt>logicalName_value.x = 123</tt>. </li>
* </ol>
* @param parameters the available parameter map
* @param name the <i>logical</i> name of the request parameter
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@@ -192,8 +192,8 @@ class InternalPathPatternParser {
* Just hit a ':' and want to jump over the regex specification for this
* variable. pos will be pointing at the ':', we want to skip until the }.
* <p>
* Nested {...} pairs don't have to be escaped: <code>/abc/{var:x{1,2}}/def</code>
* <p>An escaped } will not be treated as the end of the regex: <code>/abc/{var:x\\{y:}/def</code>
* Nested {...} pairs don't have to be escaped: <tt>/abc/{var:x{1,2}}/def</tt>
* <p>An escaped } will not be treated as the end of the regex: <tt>/abc/{var:x\\{y:}/def</tt>
* <p>A separator that should not indicate the end of the regex can be escaped:
*/
private void skipCaptureRegex() {
@@ -26,11 +26,9 @@ import org.springframework.web.util.pattern.PathPattern.MatchingContext;
/**
* A regex path element. Used to represent any complicated element of the path.
*
* <p>For example in '<code>/foo/&#42;_&#42;/&#42;_{foobar}</code>' both {@code *_*}
* and <code>*_{foobar}</code> are {@link RegexPathElement regex path elements}.
*
* <p>Derived from the general {@link org.springframework.util.AntPathMatcher} approach.
* For example in '<tt>/foo/&ast;_&ast;/&ast;_{foobar}</tt>' both <tt>*_*</tt> and <tt>*_{foobar}</tt>
* are {@link RegexPathElement} path elements. Derived from the general
* {@link org.springframework.util.AntPathMatcher} approach.
*
* @author Andy Clement
* @since 5.0
@@ -51,8 +51,6 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.DefaultUriBuilderFactory;
@@ -105,16 +103,6 @@ class RestTemplateTests {
template.setErrorHandler(errorHandler);
}
@Test // gh-29008
void defaultMessageConvertersWithKotlinSerialization() {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> httpMessageConverters = restTemplate.getMessageConverters();
assertThat(httpMessageConverters).extracting("class").containsOnlyOnce(
KotlinSerializationJsonHttpMessageConverter.class,
MappingJackson2HttpMessageConverter.class
);
}
@Test
void constructorPreconditions() {
assertThatIllegalArgumentException()

Some files were not shown because too many files have changed in this diff Show More