mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 508cc346e0 |
@@ -1,9 +1,6 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
|
||||
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
+10
-15
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-15
@@ -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);
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-3
@@ -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:
|
||||
|
||||
+2
-4
@@ -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:
|
||||
|
||||
+2
-4
@@ -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.
|
||||
|
||||
+4
-5
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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 << 2) | returnSize} (argumentsSize is therefore equal to {@code
|
||||
* i >> 2}, and returnSize to {@code i & 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 << 2) | returnSize} (argumentsSize is therefore equal to {@code
|
||||
* i >> 2}, and returnSize to {@code i & 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)
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 < 0 || index >= 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 < 0 || index >= 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<String> field value is assignable to a Collection<CharSequence>
|
||||
* field, but List<Number> is not assignable to List<Integer>.
|
||||
* @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<String, String> could be converted to a Map<Id, EmailAddress>
|
||||
* by converting to a targetType built with this method:
|
||||
* The method call to construct such a TypeDescriptor would look something like:
|
||||
* <pre class="code">
|
||||
|
||||
+2
-2
@@ -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> {
|
||||
|
||||
|
||||
+6
-13
@@ -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><=</tt>
|
||||
* <i>readPosition</i> <tt><=</tt>
|
||||
* <i>writePosition</i> <tt><=</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);
|
||||
|
||||
+4
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
-3
@@ -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);
|
||||
|
||||
+7
-3
@@ -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 {
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+30
-36
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-21
@@ -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
|
||||
|
||||
@@ -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?
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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. */
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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<BrokerAvailabilityEvent>}
|
||||
* to receive notifications when broker becomes available and unavailable.
|
||||
*/
|
||||
public boolean isBrokerAvailable() {
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
|
||||
+35
-54
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-16
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-7
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-19
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+35
-31
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -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 — 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
|
||||
*/
|
||||
|
||||
+2
-17
@@ -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 — 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>
|
||||
|
||||
+9
-7
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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">
|
||||
|
||||
+1
-1
@@ -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
-16
@@ -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
|
||||
|
||||
+1
-1
@@ -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=<transaction attribute string>}
|
||||
*
|
||||
* <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.
|
||||
|
||||
+7
-16
@@ -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);
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+3
-3
@@ -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());
|
||||
|
||||
+3
-1
@@ -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());
|
||||
|
||||
+1
-1
@@ -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.
|
||||
*
|
||||
|
||||
+1
-1
@@ -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
-3
@@ -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
|
||||
|
||||
+1
-5
@@ -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));
|
||||
|
||||
+5
-3
@@ -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
|
||||
|
||||
+3
-3
@@ -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/*_*/*_{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/*_*/*_{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
Reference in New Issue
Block a user