Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Buildmaster 83c6d10095 Release v5.3.6 2021-04-13 11:08:55 +00:00
140 changed files with 1190 additions and 2501 deletions
+23 -21
View File
@@ -1,7 +1,7 @@
plugins {
id 'io.spring.dependency-management' version '1.0.9.RELEASE' apply false
id 'io.spring.nohttp' version '0.0.5.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.5.0' apply false
id 'org.jetbrains.kotlin.jvm' version '1.4.32' apply false
id 'org.jetbrains.dokka' version '0.10.1' apply false
id 'org.asciidoctor.jvm.convert' version '3.1.0'
id 'org.asciidoctor.jvm.pdf' version '3.1.0'
@@ -9,9 +9,8 @@ plugins {
id "io.freefair.aspectj" version '5.1.1' apply false
id "com.github.ben-manes.versions" version '0.28.0'
id "com.github.johnrengelman.shadow" version "6.1.0" apply false
id "me.champeau.jmh" version "0.6.4" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.0" apply false
id "org.unbroken-dome.xjc" version '2.0.0' apply false
id "me.champeau.gradle.jmh" version "0.5.2" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.4.32" apply false
}
ext {
@@ -27,15 +26,14 @@ configure(allprojects) { project ->
dependencyManagement {
imports {
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.3"
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.2"
mavenBom "io.netty:netty-bom:4.1.63.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.7"
mavenBom "io.projectreactor:reactor-bom:2020.0.6"
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR9"
mavenBom "io.rsocket:rsocket-bom:1.1.0"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.40.v20210413"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.0"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.39.v20210325"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.4.32"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.4.3"
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.0"
mavenBom "org.junit:junit-bom:5.7.1"
}
dependencies {
@@ -56,7 +54,7 @@ configure(allprojects) { project ->
entry 'aspectjtools'
entry 'aspectjweaver'
}
dependencySet(group: 'org.codehaus.groovy', version: '3.0.8') {
dependencySet(group: 'org.codehaus.groovy', version: '3.0.7') {
entry 'groovy'
entry 'groovy-jsr223'
entry 'groovy-templates' // requires findbugs for warning-free compilation
@@ -72,13 +70,13 @@ configure(allprojects) { project ->
dependency "com.caucho:hessian:4.0.63"
dependency "com.fasterxml:aalto-xml:1.2.2"
dependency("com.fasterxml.woodstox:woodstox-core:6.2.6") {
dependency("com.fasterxml.woodstox:woodstox-core:6.2.4") {
exclude group: "stax", name: "stax-api"
}
dependency "com.google.code.gson:gson:2.8.6"
dependency "com.google.protobuf:protobuf-java-util:3.15.8"
dependency "com.google.protobuf:protobuf-java-util:3.15.5"
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
dependency("com.thoughtworks.xstream:xstream:1.4.16") {
dependency("com.thoughtworks.xstream:xstream:1.4.15") {
exclude group: "xpp3", name: "xpp3_min"
exclude group: "xmlpull", name: "xmlpull"
}
@@ -92,10 +90,14 @@ configure(allprojects) { project ->
}
dependency "org.ogce:xpp3:1.1.6"
dependency "org.yaml:snakeyaml:1.28"
dependencySet(group: 'org.jetbrains.kotlinx', version: '1.0.1') {
entry 'kotlinx-serialization-core'
entry 'kotlinx-serialization-json'
}
dependency "com.h2database:h2:1.4.200"
dependency "com.github.ben-manes.caffeine:caffeine:2.9.1"
dependency "com.github.librepdf:openpdf:1.3.26"
dependency "com.github.ben-manes.caffeine:caffeine:2.9.0"
dependency "com.github.librepdf:openpdf:1.3.25"
dependency "com.rometools:rome:1.15.0"
dependency "commons-io:commons-io:2.5"
dependency "io.vavr:vavr:0.10.3"
@@ -122,7 +124,7 @@ configure(allprojects) { project ->
dependency "net.sf.ehcache:ehcache:2.10.6"
dependency "org.ehcache:jcache:1.0.1"
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core:5.4.31.Final"
dependency "org.hibernate:hibernate-core:5.4.30.Final"
dependency "org.hibernate:hibernate-validator:6.2.0.Final"
dependency "org.webjars:webjars-locator-core:0.46"
dependency "org.webjars:underscorejs:1.8.3"
@@ -196,7 +198,7 @@ configure(allprojects) { project ->
exclude group: "org.hamcrest", name: "hamcrest-core"
}
}
dependencySet(group: 'org.mockito', version: '3.9.0') {
dependencySet(group: 'org.mockito', version: '3.8.0') {
entry('mockito-core') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
@@ -204,10 +206,10 @@ configure(allprojects) { project ->
}
dependency "io.mockk:mockk:1.10.2"
dependency("net.sourceforge.htmlunit:htmlunit:2.49.1") {
dependency("net.sourceforge.htmlunit:htmlunit:2.48.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:htmlunit-driver:2.49.1") {
dependency("org.seleniumhq.selenium:htmlunit-driver:2.48.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
@@ -316,7 +318,7 @@ configure([rootProject] + javaProjects) { project ->
kotlinOptions {
languageVersion = "1.3"
apiVersion = "1.3"
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings"]
freeCompilerArgs = ["-Xjsr305=strict"]
allWarningsAsErrors = true
}
}
@@ -336,7 +338,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
toolVersion = "8.42"
toolVersion = "8.41"
configDirectory.set(rootProject.file("src/checkstyle"))
}
+1 -1
View File
@@ -5,7 +5,7 @@ github-repo: "https://github.com/spring-projects/spring-framework.git"
github-repo-name: "spring-projects/spring-framework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "main"
branch: "master"
milestone: "5.3.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
+8 -56
View File
@@ -18,6 +18,9 @@ anchors:
ARTIFACTORY_USERNAME: ((artifactory-username))
ARTIFACTORY_PASSWORD: ((artifactory-password))
build-project-task-params: &build-project-task-params
privileged: true
timeout: ((task-timeout))
params:
BRANCH: ((branch))
<<: *gradle-enterprise-task-params
docker-resource-source: &docker-resource-source
@@ -51,11 +54,6 @@ resource_types:
source:
repository: dpb587/github-status-resource
tag: master
- name: pull-request
type: registry-image
source:
repository: teliaoss/github-pr-resource
tag: v0.23.0
- name: slack-notification
type: registry-image
source:
@@ -95,14 +93,6 @@ resources:
username: ((artifactory-username))
password: ((artifactory-password))
build_name: ((build-name))
- name: git-pull-request
type: pull-request
icon: source-pull
source:
access_token: ((github-ci-pull-request-token))
repository: ((github-repo-name))
base_branch: ((branch))
ignore_paths: ["ci/*"]
- name: repo-status-build
type: github-status-resource
icon: eye-check-outline
@@ -172,10 +162,7 @@ jobs:
- task: build-project
image: ci-image
file: git-repo/ci/tasks/build-project.yml
privileged: true
timeout: ((task-timeout))
params:
<<: *build-project-task-params
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-build
@@ -230,11 +217,10 @@ jobs:
- task: check-project
image: ci-image
file: git-repo/ci/tasks/check-project.yml
privileged: true
timeout: ((task-timeout))
params:
MAIN_TOOLCHAIN: 8
TEST_TOOLCHAIN: 11
<<: *build-project-task-params
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk11-build
@@ -258,11 +244,10 @@ jobs:
- task: check-project
image: ci-image
file: git-repo/ci/tasks/check-project.yml
privileged: true
timeout: ((task-timeout))
params:
MAIN_TOOLCHAIN: 8
TEST_TOOLCHAIN: 15
<<: *build-project-task-params
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk15-build
@@ -272,37 +257,6 @@ jobs:
<<: *slack-fail-params
- put: repo-status-jdk15-build
params: { state: "success", commit: "git-repo" }
- name: build-pull-requests
serial: true
public: true
plan:
- get: ci-image
- get: git-repo
resource: git-pull-request
trigger: true
version: every
- do:
- put: git-pull-request
params:
path: git-repo
status: pending
- task: build-pr
image: ci-image
file: git-repo/ci/tasks/build-pr.yml
privileged: true
timeout: ((task-timeout))
params:
<<: *build-project-task-params
on_success:
put: git-pull-request
params:
path: git-repo
status: success
on_failure:
put: git-pull-request
params:
path: git-repo
status: failure
- name: stage-milestone
serial: true
plan:
@@ -458,5 +412,3 @@ groups:
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
- name: "ci-images"
jobs: ["build-ci-images"]
- name: "pull-requests"
jobs: [ "build-pull-requests" ]
-8
View File
@@ -1,8 +0,0 @@
#!/bin/bash
set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check
popd > /dev/null
+2 -2
View File
@@ -4,6 +4,6 @@ set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK11,JDK15 \
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Dorg.gradle.java.installations.fromEnv=JDK11,JDK15 \
-PmainToolchain=$MAIN_TOOLCHAIN -PtestToolchain=$TEST_TOOLCHAIN --no-daemon --max-workers=4 check
popd > /dev/null
-19
View File
@@ -1,19 +0,0 @@
---
platform: linux
inputs:
- name: git-repo
caches:
- path: gradle
params:
BRANCH:
CI: true
GRADLE_ENTERPRISE_ACCESS_KEY:
GRADLE_ENTERPRISE_CACHE_USERNAME:
GRADLE_ENTERPRISE_CACHE_PASSWORD:
GRADLE_ENTERPRISE_URL: https://ge.spring.io
run:
path: bash
args:
- -ec
- |
${PWD}/git-repo/ci/scripts/build-pr.sh
+1 -1
View File
@@ -1,4 +1,4 @@
version=5.3.7
version=5.3.6
org.gradle.jvmargs=-Xmx1536M
org.gradle.caching=true
org.gradle.parallel=true
+18
View File
@@ -108,3 +108,21 @@ task eclipseBuildship(type: Copy) {
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
// Filter 'build' folder
eclipse.project.file.withXml {
def node = it.asNode()
def filteredResources = node.get("filteredResources")
if(filteredResources) {
node.remove(filteredResources)
}
def filterNode = node.appendNode("filteredResources").appendNode("filter")
filterNode.appendNode("id", "1359048889071")
filterNode.appendNode("name", "")
filterNode.appendNode("type", "30")
def matcherNode = filterNode.appendNode("matcher")
matcherNode.appendNode("id", "org.eclipse.ui.ide.multiFilter")
matcherNode.appendNode("arguments", "1.0-projectRelativePath-matches-false-false-build")
}
+3 -3
View File
@@ -4,12 +4,12 @@ apply plugin: 'org.springframework.build.optional-dependencies'
// Uncomment the following for Shadow support in the jmhJar block.
// Currently commented out due to ZipException: archive is not a ZIP archive
// apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'me.champeau.jmh'
apply plugin: 'me.champeau.gradle.jmh'
apply from: "$rootDir/gradle/publications.gradle"
dependencies {
jmh 'org.openjdk.jmh:jmh-core:1.28'
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.28'
jmh 'org.openjdk.jmh:jmh-core:1.25'
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.25'
jmh 'net.sf.jopt-simple:jopt-simple:4.6'
}
+15 -73
View File
@@ -11,8 +11,6 @@
* <li>a JDK11 toolchain for compiling and running the test SourceSet
* </ul>
*
* By default, the build will fall back to using the current JDK and 1.8 language level for all sourceSets.
*
* Gradle will automatically detect JDK distributions in well-known locations.
* The following command will list the detected JDKs on the host.
* {@code
@@ -25,41 +23,19 @@
* /opt/openjdk/java11
* $ echo JDK15
* /opt/openjdk/java15
* $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK11,JDK15 check
* $ ./gradlew -Dorg.gradle.java.installations.fromEnv=JDK11,JDK15 check
* }
*
* @author Brian Clozel
* @author Sam Brannen
*/
def mainToolchainConfigured() {
return project.hasProperty('mainToolchain') && project.mainToolchain
}
def testToolchainConfigured() {
return project.hasProperty('testToolchain') && project.testToolchain
}
def mainToolchainLanguageVersion() {
if (mainToolchainConfigured()) {
return JavaLanguageVersion.of(project.mainToolchain.toString())
}
return JavaLanguageVersion.of(8)
}
def testToolchainLanguageVersion() {
if (testToolchainConfigured()) {
return JavaLanguageVersion.of(project.testToolchain.toString())
}
return mainToolchainLanguageVersion()
}
plugins.withType(JavaPlugin) {
// Configure the Java Toolchain if the 'mainToolchain' is configured
if (mainToolchainConfigured()) {
// Configure the Java Toolchain if the 'mainToolchain' property is defined
if (project.hasProperty('mainToolchain') && project.mainToolchain) {
def mainLanguageVersion = JavaLanguageVersion.of(project.mainToolchain.toString())
java {
toolchain {
languageVersion = mainToolchainLanguageVersion()
languageVersion = mainLanguageVersion
}
}
}
@@ -70,8 +46,8 @@ plugins.withType(JavaPlugin) {
}
}
// Configure a specific Java Toolchain for compiling and running tests if the 'testToolchain' property is defined
if (testToolchainConfigured()) {
def testLanguageVersion = testToolchainLanguageVersion()
if (project.hasProperty('testToolchain') && project.testToolchain) {
def testLanguageVersion = JavaLanguageVersion.of(project.testToolchain.toString());
tasks.withType(JavaCompile).matching { it.name.contains("Test") }.configureEach {
javaCompiler = javaToolchains.compilerFor {
languageVersion = testLanguageVersion
@@ -87,17 +63,17 @@ plugins.withType(JavaPlugin) {
plugins.withType(GroovyPlugin) {
// Fallback to JDK8
if (!mainToolchainConfigured()) {
if (!project.hasProperty('mainToolchain')) {
compileGroovy {
sourceCompatibility = JavaVersion.VERSION_1_8
}
}
}
// Configure the Kotlin compiler if the 'mainToolchain' property is defined
pluginManager.withPlugin("kotlin") {
// Configure the Kotlin compiler if the 'mainToolchain' property is defined
if (mainToolchainConfigured()) {
def mainLanguageVersion = mainToolchainLanguageVersion()
if (project.hasProperty('mainToolchain') && project.mainToolchain) {
def mainLanguageVersion = JavaLanguageVersion.of(project.mainToolchain.toString());
def compiler = javaToolchains.compilerFor {
languageVersion = mainLanguageVersion
}
@@ -130,9 +106,9 @@ pluginManager.withPlugin("kotlin") {
}
}
}
if (testToolchainConfigured()) {
def testLanguageVersion = testToolchainLanguageVersion()
if (project.hasProperty('testToolchain') && project.testToolchain) {
def testLanguageVersion = JavaLanguageVersion.of(project.testToolchain.toString());
def compiler = javaToolchains.compilerFor {
languageVersion = testLanguageVersion
}
@@ -145,38 +121,4 @@ pluginManager.withPlugin("kotlin") {
}
}
}
}
// Configure the JMH plugin to use the toolchain for generating and running JMH bytecode
pluginManager.withPlugin("me.champeau.jmh") {
if (mainToolchainConfigured() || testToolchainConfigured()) {
tasks.matching { it.name.contains('jmh') && it.hasProperty('javaLauncher') }.configureEach {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(testToolchainLanguageVersion())
})
}
tasks.withType(JavaCompile).matching { it.name.contains("Jmh") }.configureEach {
javaCompiler = javaToolchains.compilerFor {
languageVersion = testToolchainLanguageVersion()
}
}
}
}
// Store resolved Toolchain JVM information as custom values in the build scan.
rootProject.ext {
resolvedMainToolchain = false
resolvedTestToolchain = false
}
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (mainToolchainConfigured() && !resolvedMainToolchain && task instanceof JavaCompile && task.javaCompiler.isPresent()) {
def metadata = task.javaCompiler.get().metadata
task.project.buildScan.value('Main toolchain', "$metadata.vendor $metadata.languageVersion ($metadata.installationPath)")
resolvedMainToolchain = true
}
if (testToolchainConfigured() && !resolvedTestToolchain && task instanceof Test && task.javaLauncher.isPresent()) {
def metadata = task.javaLauncher.get().metadata
task.project.buildScan.value('Test toolchain', "$metadata.vendor $metadata.languageVersion ($metadata.installationPath)")
resolvedTestToolchain = true
}
}
}
+6
View File
@@ -45,6 +45,12 @@ rootProject.children.each {project ->
settings.gradle.projectsLoaded {
gradleEnterprise {
buildScan {
if (settings.gradle.rootProject.hasProperty('mainToolchain')) {
value("Main toolchain", 'JDK' + settings.gradle.rootProject.getProperty('mainToolchain'))
}
if (settings.gradle.rootProject.hasProperty('testToolchain')) {
value("Test toolchain", 'JDK' + settings.gradle.rootProject.getProperty('testToolchain'))
}
File buildDir = settings.gradle.rootProject.getBuildDir()
buildDir.mkdirs()
new File(buildDir, "build-scan-uri.txt").text = "(build scan not generated)"
@@ -510,7 +510,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
if (specificInterceptors.length > 0) {
// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
// specificInterceptors may equals PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
if (commonInterceptors.length > 0) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2012 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.
@@ -23,9 +23,9 @@ import org.springframework.util.StringUtils;
/**
* Editor for {@code java.util.Locale}, to directly populate a Locale property.
*
* <p>Expects the same syntax as Locale's {@code toString()}, i.e. language +
* <p>Expects the same syntax as Locale's {@code toString}, i.e. language +
* optionally country + optionally variant, separated by "_" (e.g. "en", "en_US").
* Also accepts spaces as separators, as an alternative to underscores.
* Also accepts spaces as separators, as alternative to underscores.
*
* @author Juergen Hoeller
* @since 26.05.2003
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -44,6 +44,8 @@ public class PropertyComparator<T> implements Comparator<T> {
private final SortDefinition sortDefinition;
private final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(false);
/**
* Create a new PropertyComparator for the given SortDefinition.
@@ -113,9 +115,8 @@ public class PropertyComparator<T> implements Comparator<T> {
// (similar to JSTL EL). If the property doesn't exist in the
// first place, let the exception through.
try {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(false);
beanWrapper.setWrappedInstance(obj);
return beanWrapper.getPropertyValue(this.sortDefinition.getProperty());
this.beanWrapper.setWrappedInstance(obj);
return this.beanWrapper.getPropertyValue(this.sortDefinition.getProperty());
}
catch (BeansException ex) {
logger.debug("PropertyComparator could not access property - treating as null for sorting", ex);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.context.index.processor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -45,6 +46,9 @@ import javax.lang.model.element.TypeElement;
*/
public class CandidateComponentsIndexer implements Processor {
private static final Set<ElementKind> TYPE_KINDS =
Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS, ElementKind.INTERFACE));
private MetadataStore metadataStore;
private MetadataCollector metadataCollector;
@@ -132,8 +136,7 @@ public class CandidateComponentsIndexer implements Processor {
private static List<TypeElement> staticTypesIn(Iterable<? extends Element> elements) {
List<TypeElement> list = new ArrayList<>();
for (Element element : elements) {
if ((element.getKind().isClass() || element.getKind() == ElementKind.INTERFACE) &&
element.getModifiers().contains(Modifier.STATIC) && element instanceof TypeElement) {
if (TYPE_KINDS.contains(element.getKind()) && element.getModifiers().contains(Modifier.STATIC)) {
list.add((TypeElement) element);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -48,7 +48,7 @@ class IndexedStereotypesProvider implements StereotypesProvider {
public Set<String> getStereotypes(Element element) {
Set<String> stereotypes = new LinkedHashSet<>();
ElementKind kind = element.getKind();
if (!kind.isClass() && kind != ElementKind.INTERFACE) {
if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
return stereotypes;
}
Set<Element> seen = new HashSet<>();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -130,8 +130,8 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void afterPropertiesSet() throws CacheException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing EhCache CacheManager" +
if (logger.isInfoEnabled()) {
logger.info("Initializing EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
@@ -188,8 +188,8 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void destroy() {
if (this.cacheManager != null && this.locallyManaged) {
if (logger.isDebugEnabled()) {
logger.debug("Shutting down EhCache CacheManager" +
if (logger.isInfoEnabled()) {
logger.info("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
this.cacheManager.shutdown();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -221,11 +221,11 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
}
catch (NoUniqueBeanDefinitionException ex) {
throw new IllegalStateException("No CacheResolver specified, and no unique bean of type " +
"CacheManager found. Mark one as primary or declare a specific CacheManager to use.", ex);
"CacheManager found. Mark one as primary or declare a specific CacheManager to use.");
}
catch (NoSuchBeanDefinitionException ex) {
throw new IllegalStateException("No CacheResolver specified, and no bean of type CacheManager found. " +
"Register a CacheManager bean or remove the @EnableCaching annotation from your configuration.", ex);
"Register a CacheManager bean or remove the @EnableCaching annotation from your configuration.");
}
}
this.initialized = true;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -57,18 +57,17 @@ public abstract class MessageSourceSupport {
/**
* Set whether to always apply the {@code MessageFormat} rules, parsing even
* messages without arguments.
* <p>Default is {@code false}: Messages without arguments are by default
* returned as-is, without parsing them through {@code MessageFormat}.
* Set this to {@code true} to enforce {@code MessageFormat} for all messages,
* expecting all message texts to be written with {@code MessageFormat} escaping.
* <p>For example, {@code MessageFormat} expects a single quote to be escaped
* as two adjacent single quotes ({@code "''"}). If your message texts are all
* written with such escaping, even when not defining argument placeholders,
* you need to set this flag to {@code true}. Otherwise, only message texts
* with actual arguments are supposed to be written with {@code MessageFormat}
* escaping.
* Set whether to always apply the {@code MessageFormat} rules,
* parsing even messages without arguments.
* <p>Default is "false": Messages without arguments are by default
* returned as-is, without parsing them through MessageFormat.
* Set this to "true" to enforce MessageFormat for all messages,
* expecting all message texts to be written with MessageFormat escaping.
* <p>For example, MessageFormat expects a single quote to be escaped
* as "''". If your message texts are all written with such escaping,
* even when not defining argument placeholders, you need to set this
* flag to "true". Else, only message texts with actual arguments
* are supposed to be written with MessageFormat escaping.
* @see java.text.MessageFormat
*/
public void setAlwaysUseMessageFormat(boolean alwaysUseMessageFormat) {
@@ -76,7 +75,7 @@ public abstract class MessageSourceSupport {
}
/**
* Return whether to always apply the {@code MessageFormat} rules, parsing even
* Return whether to always apply the MessageFormat rules, parsing even
* messages without arguments.
*/
protected boolean isAlwaysUseMessageFormat() {
@@ -151,10 +150,10 @@ public abstract class MessageSourceSupport {
}
/**
* Create a {@code MessageFormat} for the given message and Locale.
* @param msg the message to create a {@code MessageFormat} for
* @param locale the Locale to create a {@code MessageFormat} for
* @return the {@code MessageFormat} instance
* Create a MessageFormat for the given message and Locale.
* @param msg the message to create a MessageFormat for
* @param locale the Locale to create a MessageFormat for
* @return the MessageFormat instance
*/
protected MessageFormat createMessageFormat(String msg, Locale locale) {
return new MessageFormat(msg, locale);
@@ -27,7 +27,7 @@ import java.lang.annotation.Target;
*
* <p>Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
* Can be applied to {@link java.util.Date}, {@link java.util.Calendar}, {@link Long} (for
* millisecond timestamps) as well as JSR-310 {@code java.time} value types.
* millisecond timestamps) as well as JSR-310 {@code java.time} and Joda-Time value types.
*
* <p>For style-based formatting, set the {@link #style} attribute to the desired style pattern code.
* The first character of the code is the date style, and the second character is the time style.
@@ -219,11 +219,9 @@ public class DateFormatter implements Formatter<Date> {
}
}
if (this.source != null) {
ParseException parseException = new ParseException(
throw new ParseException(
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
ex.getErrorOffset());
parseException.initCause(ex);
throw parseException;
}
// else rethrow original exception
throw ex;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -177,8 +177,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
* Set up the ExecutorService.
*/
public void initialize() {
if (logger.isDebugEnabled()) {
logger.debug("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
if (logger.isInfoEnabled()) {
logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (!this.threadNamePrefixSet && this.beanName != null) {
setThreadNamePrefix(this.beanName + "-");
@@ -214,8 +214,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
* @see java.util.concurrent.ExecutorService#shutdownNow()
*/
public void shutdown() {
if (logger.isDebugEnabled()) {
logger.debug("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
if (logger.isInfoEnabled()) {
logger.info("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (this.executor != null) {
if (this.waitForTasksToCompleteOnShutdown) {
@@ -157,11 +157,6 @@ abstract class CronField {
return this.type;
}
@SuppressWarnings("unchecked")
protected static <T extends Temporal & Comparable<? super T>> T cast(Temporal temporal) {
return (T) temporal;
}
/**
* Represents the type of cron field, i.e. seconds, minutes, hours,
@@ -241,17 +236,16 @@ abstract class CronField {
*/
public <T extends Temporal & Comparable<? super T>> T elapseUntil(T temporal, int goal) {
int current = get(temporal);
ValueRange range = temporal.range(this.field);
if (current < goal) {
if (range.isValidIntValue(goal)) {
return cast(temporal.with(this.field, goal));
}
else {
// goal is invalid, eg. 29th Feb, lets try to get as close as possible
return this.field.getBaseUnit().addTo(temporal, goal - current);
T result = this.field.getBaseUnit().addTo(temporal, goal - current);
current = get(result);
if (current > goal) { // can occur due to daylight saving, see gh-26744
result = this.field.getBaseUnit().addTo(result, goal - current);
}
return result;
}
else {
ValueRange range = temporal.range(this.field);
long amount = goal + range.getMaximum() - current + 1 - range.getMinimum();
return this.field.getBaseUnit().addTo(temporal, amount);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -326,6 +326,12 @@ final class QuartzCronField extends CronField {
}
}
@SuppressWarnings("unchecked")
private static <T extends Temporal & Comparable<? super T>> T cast(Temporal temporal) {
return (T) temporal;
}
@Override
public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
T result = adjust(temporal);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -66,8 +66,7 @@ public class ConcurrentModel extends ConcurrentHashMap<String, Object> implement
@Override
@Nullable
public Object put(String key, @Nullable Object value) {
public Object put(String key, Object value) {
if (value != null) {
return super.put(key, value);
}
@@ -1,70 +0,0 @@
/*
* 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.
* 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.validation.annotation;
import java.lang.annotation.Annotation;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
/**
* Utility class for handling validation annotations.
* Mainly for internal use within the framework.
*
* @author Christoph Dreis
* @since 5.3.7
*/
public abstract class ValidationAnnotationUtils {
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/**
* Determine any validation hints by the given annotation.
* <p>This implementation checks for {@code @javax.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param ann the annotation (potentially a validation annotation)
* @return the validation hints to apply (possibly an empty array),
* or {@code null} if this annotation does not trigger any validation
*/
@Nullable
public static Object[] determineValidationHints(Annotation ann) {
Class<? extends Annotation> annotationType = ann.annotationType();
String annotationName = annotationType.getName();
if ("javax.validation.Valid".equals(annotationName)) {
return EMPTY_OBJECT_ARRAY;
}
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
if (validatedAnn != null) {
Object hints = validatedAnn.value();
return convertValidationHints(hints);
}
if (annotationType.getSimpleName().startsWith("Valid")) {
Object hints = AnnotationUtils.getValue(ann);
return convertValidationHints(hints);
}
return null;
}
private static Object[] convertValidationHints(@Nullable Object hints) {
if (hints == null) {
return EMPTY_OBJECT_ARRAY;
}
return (hints instanceof Object[] ? (Object[]) hints : new Object[]{hints});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -19,8 +19,6 @@ package org.springframework.cache.config;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
@@ -89,7 +87,6 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
}
catch (IllegalStateException ex) {
assertThat(ex.getMessage().contains("no unique bean of type CacheManager")).isTrue();
assertThat(ex).hasCauseInstanceOf(NoUniqueBeanDefinitionException.class);
}
}
@@ -124,7 +121,6 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
}
catch (IllegalStateException ex) {
assertThat(ex.getMessage().contains("no bean of type CacheManager")).isTrue();
assertThat(ex).hasCauseInstanceOf(NoSuchBeanDefinitionException.class);
}
}
@@ -119,39 +119,6 @@ public class DateFormattingTests {
assertThat(binder.getBindingResult().getFieldValue("styleDate")).isEqualTo("10/31/09");
}
@Test
void styleDateWithInvalidFormat() {
String propertyName = "styleDate";
String propertyValue = "99/01/01";
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add(propertyName, propertyValue);
binder.bind(propertyValues);
BindingResult bindingResult = binder.getBindingResult();
assertThat(bindingResult.getErrorCount()).isEqualTo(1);
FieldError fieldError = bindingResult.getFieldError(propertyName);
TypeMismatchException exception = fieldError.unwrap(TypeMismatchException.class);
assertThat(exception)
.hasMessageContaining("for property 'styleDate'")
.hasCauseInstanceOf(ConversionFailedException.class).getCause()
.hasMessageContaining("for value '99/01/01'")
.hasCauseInstanceOf(IllegalArgumentException.class).getCause()
.hasMessageContaining("Parse attempt failed for value [99/01/01]")
.hasCauseInstanceOf(ParseException.class).getCause()
// Unable to parse date time value "99/01/01" using configuration from
// @org.springframework.format.annotation.DateTimeFormat(pattern=, style=S-, iso=NONE, fallbackPatterns=[])
// We do not check "fallbackPatterns=[]", since the array representation in the toString()
// implementation for annotations changed from [] to {} in Java 9. In addition, strings
// are enclosed in double quotes beginning with Java 9. Thus, we cannot check directly
// for the presence of "style=S-".
.hasMessageContainingAll(
"Unable to parse date time value \"99/01/01\" using configuration from",
"@org.springframework.format.annotation.DateTimeFormat",
"style=", "S-", "iso=NONE")
.hasCauseInstanceOf(ParseException.class).getCause()
.hasMessageStartingWith("Unparseable date: \"99/01/01\"")
.hasNoCause();
}
@Test
void testBindDateArray() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
@@ -363,10 +330,7 @@ public class DateFormattingTests {
.hasMessageContainingAll(
"Unable to parse date time value \"210302\" using configuration from",
"@org.springframework.format.annotation.DateTimeFormat",
"yyyy-MM-dd", "M/d/yy", "yyyyMMdd", "yyyy.MM.dd")
.hasCauseInstanceOf(ParseException.class).getCause()
.hasMessageStartingWith("Unparseable date: \"210302\"")
.hasNoCause();
"yyyy-MM-dd", "M/d/yy", "yyyyMMdd", "yyyy.MM.dd");
}
}
@@ -339,11 +339,10 @@ class DateTimeFormattingTests {
.hasCauseInstanceOf(DateTimeParseException.class).getCause()
// Unable to parse date time value "2009-31-10" using configuration from
// @org.springframework.format.annotation.DateTimeFormat(pattern=, style=SS, iso=DATE, fallbackPatterns=[])
// We do not check "fallbackPatterns=[]", since the array representation in the toString()
// implementation for annotations changed from [] to {} in Java 9.
.hasMessageContainingAll(
"Unable to parse date time value \"2009-31-10\" using configuration from",
"@org.springframework.format.annotation.DateTimeFormat", "iso=DATE")
"@org.springframework.format.annotation.DateTimeFormat",
"iso=DATE", "fallbackPatterns=[]")
.hasCauseInstanceOf(DateTimeParseException.class).getCause()
.hasMessageStartingWith("Text '2009-31-10'")
.hasCauseInstanceOf(DateTimeException.class).getCause()
@@ -1276,14 +1276,6 @@ class CronExpressionTests {
actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
cronExpression = CronExpression.parse("0 10 2 * * *");
last = ZonedDateTime.parse("2013-03-31T01:09:00+01:00[Europe/Amsterdam]");
expected = ZonedDateTime.parse("2013-04-01T02:10:00+02:00[Europe/Amsterdam]");
actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -57,7 +57,7 @@ class CronTriggerTests {
@ParameterizedCronTriggerTest
void matchAll(LocalDateTime localDateTime, TimeZone timeZone) {
void testMatchAll(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * * * *", timeZone);
@@ -66,7 +66,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void matchLastSecond(LocalDateTime localDateTime, TimeZone timeZone) {
void testMatchLastSecond(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * * * *", timeZone);
@@ -76,7 +76,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void matchSpecificSecond(LocalDateTime localDateTime, TimeZone timeZone) {
void testMatchSpecificSecond(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("10 * * * * *", timeZone);
@@ -86,7 +86,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementSecondByOne(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementSecondByOne(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("11 * * * * *", timeZone);
@@ -98,7 +98,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementSecondWithPreviousExecutionTooEarly(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementSecondWithPreviousExecutionTooEarly(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("11 * * * * *", timeZone);
@@ -111,7 +111,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementSecondAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementSecondAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("10 * * * * *", timeZone);
@@ -123,7 +123,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void secondRange(LocalDateTime localDateTime, TimeZone timeZone) {
void testSecondRange(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("10-15 * * * * *", timeZone);
@@ -134,7 +134,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementMinute(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementMinute(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 * * * * *", timeZone);
@@ -152,7 +152,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementMinuteByOne(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementMinuteByOne(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 11 * * * *", timeZone);
@@ -164,7 +164,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementMinuteAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementMinuteAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 10 * * * *", timeZone);
@@ -177,7 +177,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementHour(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementHour(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 * * * *", timeZone);
@@ -198,7 +198,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementHourAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementHourAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 * * * *", timeZone);
@@ -220,7 +220,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementDayOfMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementDayOfMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 * * *", timeZone);
@@ -236,13 +236,13 @@ class CronTriggerTests {
assertThat(this.calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(2);
this.calendar.add(Calendar.DAY_OF_MONTH, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
assertThat(this.calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(3);
}
@ParameterizedCronTriggerTest
void incrementDayOfMonthByOne(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementDayOfMonthByOne(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * 10 * *", timeZone);
@@ -257,7 +257,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementDayOfMonthAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementDayOfMonthAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * 10 * *", timeZone);
@@ -273,7 +273,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void dailyTriggerInShortMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testDailyTriggerInShortMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 * * *", timeZone);
@@ -294,7 +294,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void dailyTriggerInLongMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testDailyTriggerInLongMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 * * *", timeZone);
@@ -315,7 +315,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void dailyTriggerOnDaylightSavingBoundary(LocalDateTime localDateTime, TimeZone timeZone) {
void testDailyTriggerOnDaylightSavingBoundary(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 * * *", timeZone);
@@ -336,7 +336,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 1 * *", timeZone);
@@ -357,7 +357,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementMonthAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementMonthAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 1 * *", timeZone);
@@ -380,7 +380,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void monthlyTriggerInLongMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthlyTriggerInLongMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 31 * *", timeZone);
@@ -396,7 +396,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void monthlyTriggerInShortMonth(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthlyTriggerInShortMonth(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 1 * *", timeZone);
@@ -413,7 +413,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementDayOfWeekByOne(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementDayOfWeekByOne(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * * * 2", timeZone);
@@ -429,7 +429,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void incrementDayOfWeekAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
void testIncrementDayOfWeekAndRollover(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * * * 2", timeZone);
@@ -445,7 +445,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void specificMinuteSecond(LocalDateTime localDateTime, TimeZone timeZone) {
void testSpecificMinuteSecond(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("55 5 * * * *", timeZone);
@@ -459,12 +459,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.HOUR, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void specificHourSecond(LocalDateTime localDateTime, TimeZone timeZone) {
void testSpecificHourSecond(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("55 * 10 * * *", timeZone);
@@ -479,12 +479,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.MINUTE, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void specificMinuteHour(LocalDateTime localDateTime, TimeZone timeZone) {
void testSpecificMinuteHour(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* 5 10 * * *", timeZone);
@@ -500,12 +500,12 @@ class CronTriggerTests {
// next trigger is in one second because second is wildcard
this.calendar.add(Calendar.SECOND, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void specificDayOfMonthSecond(LocalDateTime localDateTime, TimeZone timeZone) {
void testSpecificDayOfMonthSecond(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("55 * * 3 * *", timeZone);
@@ -521,12 +521,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.MINUTE, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void specificDate(LocalDateTime localDateTime, TimeZone timeZone) {
void testSpecificDate(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("* * * 3 11 *", timeZone);
@@ -543,12 +543,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.SECOND, 1);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void nonExistentSpecificDate(LocalDateTime localDateTime, TimeZone timeZone) {
void testNonExistentSpecificDate(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
// TODO: maybe try and detect this as a special case in parser?
@@ -561,7 +561,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void leapYearSpecificDate(LocalDateTime localDateTime, TimeZone timeZone) {
void testLeapYearSpecificDate(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 0 29 2 *", timeZone);
@@ -579,12 +579,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.YEAR, 4);
TriggerContext context2 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context2);
Object actual = localDate = trigger.nextExecutionTime(context2);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void weekDaySequence(LocalDateTime localDateTime, TimeZone timeZone) {
void testWeekDaySequence(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 0 7 ? * MON-FRI", timeZone);
@@ -607,12 +607,12 @@ class CronTriggerTests {
assertThat(actual1).isEqualTo(this.calendar.getTime());
this.calendar.add(Calendar.DAY_OF_MONTH, 1);
TriggerContext context3 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context3);
Object actual = localDate = trigger.nextExecutionTime(context3);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void dayOfWeekIndifferent(LocalDateTime localDateTime, TimeZone timeZone) {
void testDayOfWeekIndifferent(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * 2 * *", timeZone);
@@ -621,7 +621,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void secondIncrementer(LocalDateTime localDateTime, TimeZone timeZone) {
void testSecondIncrementer(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("57,59 * * * * *", timeZone);
@@ -630,7 +630,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void secondIncrementerWithRange(LocalDateTime localDateTime, TimeZone timeZone) {
void testSecondIncrementerWithRange(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("1,3,5 * * * * *", timeZone);
@@ -639,7 +639,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void hourIncrementer(LocalDateTime localDateTime, TimeZone timeZone) {
void testHourIncrementer(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * 4,8,12,16,20 * * *", timeZone);
@@ -648,7 +648,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void dayNames(LocalDateTime localDateTime, TimeZone timeZone) {
void testDayNames(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * * 0-6", timeZone);
@@ -657,7 +657,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void sundayIsZero(LocalDateTime localDateTime, TimeZone timeZone) {
void testSundayIsZero(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * * 0", timeZone);
@@ -666,7 +666,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void sundaySynonym(LocalDateTime localDateTime, TimeZone timeZone) {
void testSundaySynonym(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * * 0", timeZone);
@@ -675,7 +675,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void monthNames(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthNames(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * 1-12 *", timeZone);
@@ -684,7 +684,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void monthNamesMixedCase(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthNamesMixedCase(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * 2 *", timeZone);
@@ -693,91 +693,91 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void secondInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testSecondInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("77 * * * * *", timeZone));
}
@ParameterizedCronTriggerTest
void secondRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testSecondRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("44-77 * * * * *", timeZone));
}
@ParameterizedCronTriggerTest
void minuteInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testMinuteInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* 77 * * * *", timeZone));
}
@ParameterizedCronTriggerTest
void minuteRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testMinuteRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* 44-77 * * * *", timeZone));
}
@ParameterizedCronTriggerTest
void hourInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testHourInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* * 27 * * *", timeZone));
}
@ParameterizedCronTriggerTest
void hourRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testHourRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* * 23-28 * * *", timeZone));
}
@ParameterizedCronTriggerTest
void dayInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testDayInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* * * 45 * *", timeZone));
}
@ParameterizedCronTriggerTest
void dayRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testDayRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* * * 28-45 * *", timeZone));
}
@ParameterizedCronTriggerTest
void monthInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("0 0 0 25 13 ?", timeZone));
}
@ParameterizedCronTriggerTest
void monthInvalidTooSmall(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthInvalidTooSmall(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("0 0 0 25 0 ?", timeZone));
}
@ParameterizedCronTriggerTest
void dayOfMonthInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testDayOfMonthInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("0 0 0 32 12 ?", timeZone));
}
@ParameterizedCronTriggerTest
void monthRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthRangeInvalid(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
assertThatIllegalArgumentException().isThrownBy(() -> new CronTrigger("* * * * 11-13 *", timeZone));
}
@ParameterizedCronTriggerTest
void whitespace(LocalDateTime localDateTime, TimeZone timeZone) {
void testWhitespace(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger1 = new CronTrigger("* * * * 1 *", timeZone);
@@ -786,7 +786,7 @@ class CronTriggerTests {
}
@ParameterizedCronTriggerTest
void monthSequence(LocalDateTime localDateTime, TimeZone timeZone) {
void testMonthSequence(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
CronTrigger trigger = new CronTrigger("0 30 23 30 1/3 ?", timeZone);
@@ -808,33 +808,23 @@ class CronTriggerTests {
// Next trigger is 3 months latter
this.calendar.add(Calendar.MONTH, 3);
TriggerContext context3 = getTriggerContext(localDate);
Object actual = trigger.nextExecutionTime(context3);
Object actual = localDate = trigger.nextExecutionTime(context3);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
@ParameterizedCronTriggerTest
void daylightSavingMissingHour(LocalDateTime localDateTime, TimeZone timeZone) {
void testDaylightSavingMissingHour(LocalDateTime localDateTime, TimeZone timeZone) {
setUp(localDateTime, timeZone);
// This trigger has to be somewhere between 2:00 AM and 3:00 AM, so we
// use a cron expression for 2:10 AM every day.
// This trigger has to be somewhere in between 2am and 3am
CronTrigger trigger = new CronTrigger("0 10 2 * * *", timeZone);
// 2:00 AM on March 31, 2013: start of Daylight Saving Time for CET in 2013.
// Setting up last completion:
// - PST: Sun Mar 31 10:09:54 CEST 2013
// - CET: Sun Mar 31 01:09:54 CET 2013
this.calendar.set(Calendar.DAY_OF_MONTH, 31);
this.calendar.set(Calendar.MONTH, Calendar.MARCH);
this.calendar.set(Calendar.YEAR, 2013);
this.calendar.set(Calendar.HOUR_OF_DAY, 1);
this.calendar.set(Calendar.MINUTE, 9);
this.calendar.set(Calendar.SECOND, 54);
Date lastCompletionTime = this.calendar.getTime();
// Setting up expected next execution time:
// - PST: Sun Mar 31 11:10:00 CEST 2013
// - CET: Mon Apr 01 02:10:00 CEST 2013
Date localDate = this.calendar.getTime();
TriggerContext context1 = getTriggerContext(localDate);
if (timeZone.equals(TimeZone.getTimeZone("CET"))) {
// Clocks go forward an hour so 2am doesn't exist in CET for this localDateTime
this.calendar.add(Calendar.DAY_OF_MONTH, 1);
@@ -842,10 +832,8 @@ class CronTriggerTests {
this.calendar.add(Calendar.HOUR_OF_DAY, 1);
this.calendar.set(Calendar.MINUTE, 10);
this.calendar.set(Calendar.SECOND, 0);
TriggerContext context = getTriggerContext(lastCompletionTime);
Object nextExecutionTime = trigger.nextExecutionTime(context);
assertThat(nextExecutionTime).isEqualTo(this.calendar.getTime());
Object actual = localDate = trigger.nextExecutionTime(context1);
assertThat(actual).isEqualTo(this.calendar.getTime());
}
private static void roundup(Calendar calendar) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -299,7 +299,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@Override
@Nullable
public V remove(@Nullable Object key) {
public V remove(Object key) {
return doTask(key, new Task<V>(TaskOption.RESTRUCTURE_AFTER, TaskOption.SKIP_IF_EMPTY) {
@Override
@Nullable
@@ -316,7 +316,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
@Override
public boolean remove(@Nullable Object key, final @Nullable Object value) {
public boolean remove(Object key, final Object value) {
Boolean result = doTask(key, new Task<Boolean>(TaskOption.RESTRUCTURE_AFTER, TaskOption.SKIP_IF_EMPTY) {
@Override
protected Boolean execute(@Nullable Reference<K, V> ref, @Nullable Entry<K, V> entry) {
@@ -333,7 +333,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
@Override
public boolean replace(@Nullable K key, final @Nullable V oldValue, final @Nullable V newValue) {
public boolean replace(K key, final V oldValue, final V newValue) {
Boolean result = doTask(key, new Task<Boolean>(TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY) {
@Override
protected Boolean execute(@Nullable Reference<K, V> ref, @Nullable Entry<K, V> entry) {
@@ -349,7 +349,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@Override
@Nullable
public V replace(@Nullable K key, final @Nullable V value) {
public V replace(K key, final V value) {
return doTask(key, new Task<V>(TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY) {
@Override
@Nullable
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -211,13 +211,7 @@ public class LinkedCaseInsensitiveMap<V> implements Map<String, V>, Serializable
public V putIfAbsent(String key, @Nullable V value) {
String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key);
if (oldKey != null) {
V oldKeyValue = this.targetMap.get(oldKey);
if (oldKeyValue != null) {
return oldKeyValue;
}
else {
key = oldKey;
}
return this.targetMap.get(oldKey);
}
return this.targetMap.putIfAbsent(key, value);
}
@@ -227,13 +221,7 @@ public class LinkedCaseInsensitiveMap<V> implements Map<String, V>, Serializable
public V computeIfAbsent(String key, Function<? super String, ? extends V> mappingFunction) {
String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key);
if (oldKey != null) {
V oldKeyValue = this.targetMap.get(oldKey);
if (oldKeyValue != null) {
return oldKeyValue;
}
else {
key = oldKey;
}
return this.targetMap.get(oldKey);
}
return this.targetMap.computeIfAbsent(key, mappingFunction);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -68,7 +68,7 @@ public abstract class PatternMatchUtils {
}
return (str.length() >= firstIndex &&
pattern.startsWith(str.substring(0, firstIndex)) &&
pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -28,11 +28,9 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
/**
* Utility class for working with Strings that have placeholder values in them.
* A placeholder takes the form {@code ${name}}. Using {@code PropertyPlaceholderHelper}
* these placeholders can be substituted for user-supplied values.
*
* <p>Values for substitution can be supplied using a {@link Properties} instance or
* Utility class for working with Strings that have placeholder values in them. A placeholder takes the form
* {@code ${name}}. Using {@code PropertyPlaceholderHelper} these placeholders can be substituted for
* user-supplied values. <p> Values for substitution can be supplied using a {@link Properties} instance or
* using a {@link PlaceholderResolver}.
*
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -292,7 +292,7 @@ class StaxEventXMLReader extends AbstractStaxXMLReader {
private void handleDtd(DTD dtd) throws SAXException {
if (getLexicalHandler() != null) {
Location location = dtd.getLocation();
javax.xml.stream.Location location = dtd.getLocation();
getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
}
if (getLexicalHandler() != null) {
@@ -34,7 +34,7 @@ operator fun PropertyResolver.get(key: String) : String? = getProperty(key)
/**
* Extension for [PropertyResolver.getProperty] providing a `getProperty<Foo>(...)`
* variant returning a nullable `Foo`.
* variant returning a nullable [String].
*
* @author Sebastien Deleuze
* @since 5.1
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -99,12 +99,6 @@ class LinkedCaseInsensitiveMapTests {
assertThat(map.computeIfAbsent("key", key2 -> "value1")).isEqualTo("value3");
assertThat(map.computeIfAbsent("KEY", key1 -> "value2")).isEqualTo("value3");
assertThat(map.computeIfAbsent("Key", key -> "value3")).isEqualTo("value3");
assertThat(map.put("null", null)).isNull();
assertThat(map.putIfAbsent("NULL", "value")).isNull();
assertThat(map.put("null", null)).isEqualTo("value");
assertThat(map.computeIfAbsent("NULL", s -> "value")).isEqualTo("value");
assertThat(map.get("null")).isEqualTo("value");
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -49,7 +49,7 @@ public abstract class AbstractExpressionTests {
/**
* Evaluate an expression and check that the actual result matches the
* expectedValue and the class of the result matches the expectedResultType.
* expectedValue and the class of the result matches the expectedClassOfResult.
* @param expression the expression to evaluate
* @param expectedValue the expected result for evaluating the expression
* @param expectedResultType the expected class of the evaluation result
@@ -106,15 +106,15 @@ public abstract class AbstractExpressionTests {
/**
* Evaluate an expression and check that the actual result matches the
* expectedValue and the class of the result matches the expectedResultType.
* expectedValue and the class of the result matches the expectedClassOfResult.
* This method can also check if the expression is writable (for example,
* it is a variable or property reference).
* @param expression the expression to evaluate
* @param expectedValue the expected result for evaluating the expression
* @param expectedResultType the expected class of the evaluation result
* @param expectedClassOfResult the expected class of the evaluation result
* @param shouldBeWritable should the parsed expression be writable?
*/
public void evaluate(String expression, Object expectedValue, Class<?> expectedResultType, boolean shouldBeWritable) {
public void evaluate(String expression, Object expectedValue, Class<?> expectedClassOfResult, boolean shouldBeWritable) {
Expression expr = parser.parseExpression(expression);
assertThat(expr).as("expression").isNotNull();
if (DEBUG) {
@@ -134,7 +134,7 @@ public abstract class AbstractExpressionTests {
else {
assertThat(value).as("Did not get expected value for expression '" + expression + "'.").isEqualTo(expectedValue);
}
assertThat(expectedResultType.equals(resultType)).as("Type of the result was not as expected. Expected '" + expectedResultType +
assertThat(expectedClassOfResult.equals(resultType)).as("Type of the result was not as expected. Expected '" + expectedClassOfResult +
"' but result was of type '" + resultType + "'").isTrue();
assertThat(expr.isWritable(context)).as("isWritable").isEqualTo(shouldBeWritable);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -17,6 +17,7 @@
package org.springframework.expression.spel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -39,79 +40,98 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Sam Brannen
* @author Juergen Hoeller
*/
class SelectionAndProjectionTests {
public class SelectionAndProjectionTests {
@Test
@SuppressWarnings("unchecked")
void selectionWithList() throws Exception {
public void selectionWithList() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.?[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ListTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(0, 1, 2, 3, 4);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(5);
assertThat(list.get(0)).isEqualTo(0);
assertThat(list.get(1)).isEqualTo(1);
assertThat(list.get(2)).isEqualTo(2);
assertThat(list.get(3)).isEqualTo(3);
assertThat(list.get(4)).isEqualTo(4);
}
@Test
void selectFirstItemInList() throws Exception {
public void selectFirstItemInList() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.^[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ListTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(0);
}
@Test
void selectLastItemInList() throws Exception {
public void selectLastItemInList() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.$[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ListTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(4);
}
@Test
@SuppressWarnings("unchecked")
void selectionWithSet() throws Exception {
public void selectionWithSet() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.?[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new SetTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(0, 1, 2, 3, 4);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(5);
assertThat(list.get(0)).isEqualTo(0);
assertThat(list.get(1)).isEqualTo(1);
assertThat(list.get(2)).isEqualTo(2);
assertThat(list.get(3)).isEqualTo(3);
assertThat(list.get(4)).isEqualTo(4);
}
@Test
void selectFirstItemInSet() throws Exception {
public void selectFirstItemInSet() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.^[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new SetTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(0);
}
@Test
void selectLastItemInSet() throws Exception {
public void selectLastItemInSet() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.$[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new SetTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(4);
}
@Test
@SuppressWarnings("unchecked")
void selectionWithIterable() throws Exception {
public void selectionWithIterable() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.?[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new IterableTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(0, 1, 2, 3, 4);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(5);
assertThat(list.get(0)).isEqualTo(0);
assertThat(list.get(1)).isEqualTo(1);
assertThat(list.get(2)).isEqualTo(2);
assertThat(list.get(3)).isEqualTo(3);
assertThat(list.get(4)).isEqualTo(4);
}
@Test
void selectionWithArray() throws Exception {
public void selectionWithArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.?[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
@@ -119,29 +139,36 @@ class SelectionAndProjectionTests {
TypedValue typedValue = new TypedValue(value);
assertThat(typedValue.getTypeDescriptor().getElementTypeDescriptor().getType()).isEqualTo(Integer.class);
Integer[] array = (Integer[]) value;
assertThat(array).containsExactly(0, 1, 2, 3, 4);
assertThat(array.length).isEqualTo(5);
assertThat(array[0]).isEqualTo(0);
assertThat(array[1]).isEqualTo(1);
assertThat(array[2]).isEqualTo(2);
assertThat(array[3]).isEqualTo(3);
assertThat(array[4]).isEqualTo(4);
}
@Test
void selectFirstItemInArray() throws Exception {
public void selectFirstItemInArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.^[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(0);
}
@Test
void selectLastItemInArray() throws Exception {
public void selectLastItemInArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("integers.$[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(4);
}
@Test
void selectionWithPrimitiveArray() throws Exception {
public void selectionWithPrimitiveArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("ints.?[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
@@ -149,41 +176,51 @@ class SelectionAndProjectionTests {
TypedValue typedValue = new TypedValue(value);
assertThat(typedValue.getTypeDescriptor().getElementTypeDescriptor().getType()).isEqualTo(Integer.class);
Integer[] array = (Integer[]) value;
assertThat(array).containsExactly(0, 1, 2, 3, 4);
assertThat(array.length).isEqualTo(5);
assertThat(array[0]).isEqualTo(0);
assertThat(array[1]).isEqualTo(1);
assertThat(array[2]).isEqualTo(2);
assertThat(array[3]).isEqualTo(3);
assertThat(array[4]).isEqualTo(4);
}
@Test
void selectFirstItemInPrimitiveArray() throws Exception {
public void selectFirstItemInPrimitiveArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("ints.^[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(0);
}
@Test
void selectLastItemInPrimitiveArray() throws Exception {
public void selectLastItemInPrimitiveArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("ints.$[#this<5]");
EvaluationContext context = new StandardEvaluationContext(new ArrayTestBean());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(Integer.class);
boolean condition = value instanceof Integer;
assertThat(condition).isTrue();
assertThat(value).isEqualTo(4);
}
@Test
@SuppressWarnings("unchecked")
void selectionWithMap() {
public void selectionWithMap() {
EvaluationContext context = new StandardEvaluationContext(new MapTestBean());
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("colors.?[key.startsWith('b')]");
Map<String, String> colorsMap = (Map<String, String>) exp.getValue(context);
assertThat(colorsMap).containsOnlyKeys("beige", "blue", "brown");
assertThat(colorsMap.size()).isEqualTo(3);
assertThat(colorsMap.containsKey("beige")).isTrue();
assertThat(colorsMap.containsKey("blue")).isTrue();
assertThat(colorsMap.containsKey("brown")).isTrue();
}
@Test
@SuppressWarnings("unchecked")
void selectFirstItemInMap() {
public void selectFirstItemInMap() {
EvaluationContext context = new StandardEvaluationContext(new MapTestBean());
ExpressionParser parser = new SpelExpressionParser();
@@ -195,7 +232,7 @@ class SelectionAndProjectionTests {
@Test
@SuppressWarnings("unchecked")
void selectLastItemInMap() {
public void selectLastItemInMap() {
EvaluationContext context = new StandardEvaluationContext(new MapTestBean());
ExpressionParser parser = new SpelExpressionParser();
@@ -206,43 +243,52 @@ class SelectionAndProjectionTests {
}
@Test
@SuppressWarnings("unchecked")
void projectionWithList() throws Exception {
public void projectionWithList() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("#testList.![wrapper.value]");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("testList", IntegerTestBean.createList());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(5, 6, 7);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(3);
assertThat(list.get(0)).isEqualTo(5);
assertThat(list.get(1)).isEqualTo(6);
assertThat(list.get(2)).isEqualTo(7);
}
@Test
@SuppressWarnings("unchecked")
void projectionWithSet() throws Exception {
public void projectionWithSet() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("#testList.![wrapper.value]");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("testList", IntegerTestBean.createSet());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(5, 6, 7);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(3);
assertThat(list.get(0)).isEqualTo(5);
assertThat(list.get(1)).isEqualTo(6);
assertThat(list.get(2)).isEqualTo(7);
}
@Test
@SuppressWarnings("unchecked")
void projectionWithIterable() throws Exception {
public void projectionWithIterable() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("#testList.![wrapper.value]");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("testList", IntegerTestBean.createIterable());
Object value = expression.getValue(context);
assertThat(value).isInstanceOf(List.class);
List<Integer> list = (List<Integer>) value;
assertThat(list).containsExactly(5, 6, 7);
boolean condition = value instanceof List;
assertThat(condition).isTrue();
List<?> list = (List<?>) value;
assertThat(list.size()).isEqualTo(3);
assertThat(list.get(0)).isEqualTo(5);
assertThat(list.get(1)).isEqualTo(6);
assertThat(list.get(2)).isEqualTo(7);
}
@Test
void projectionWithArray() throws Exception {
public void projectionWithArray() throws Exception {
Expression expression = new SpelExpressionParser().parseRaw("#testArray.![wrapper.value]");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("testArray", IntegerTestBean.createArray());
@@ -251,7 +297,10 @@ class SelectionAndProjectionTests {
TypedValue typedValue = new TypedValue(value);
assertThat(typedValue.getTypeDescriptor().getElementTypeDescriptor().getType()).isEqualTo(Number.class);
Number[] array = (Number[]) value;
assertThat(array).containsExactly(5, 5.9f, 7);
assertThat(array.length).isEqualTo(3);
assertThat(array[0]).isEqualTo(5);
assertThat(array[1]).isEqualTo(5.9f);
assertThat(array[2]).isEqualTo(7);
}
@@ -298,7 +347,12 @@ class SelectionAndProjectionTests {
}
public Iterable<Integer> getIntegers() {
return integers::iterator;
return new Iterable<Integer>() {
@Override
public Iterator<Integer> iterator() {
return integers.iterator();
}
};
}
}
@@ -375,7 +429,12 @@ class SelectionAndProjectionTests {
static Iterable<IntegerTestBean> createIterable() {
final Set<IntegerTestBean> set = createSet();
return set::iterator;
return new Iterable<IntegerTestBean>() {
@Override
public Iterator<IntegerTestBean> iterator() {
return set.iterator();
}
};
}
static IntegerTestBean[] createArray() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -31,12 +31,15 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
* entry for each column, with the column name as key.
*
* <p>The Map implementation to use and the key to use for each column
* in the column Map can be customized by overriding {@link #createColumnMap}
* and {@link #getColumnKey}, respectively.
* in the column Map can be customized through overriding
* {@link #createColumnMap} and {@link #getColumnKey}, respectively.
*
* <p><b>Note:</b> By default, {@code ColumnMapRowMapper} will try to build a linked Map
* <p><b>Note:</b> By default, ColumnMapRowMapper will try to build a linked Map
* with case-insensitive keys, to preserve column order as well as allow any
* casing to be used for column names.
* casing to be used for column names. This requires Commons Collections on the
* classpath (which will be autodetected). Else, the fallback is a standard linked
* HashMap, which will still preserve column order but requires the application
* to specify the column names in the same casing as exposed by the driver.
*
* @author Juergen Hoeller
* @since 1.2
@@ -71,7 +74,6 @@ public class ColumnMapRowMapper implements RowMapper<Map<String, Object>> {
/**
* Determine the key to use for the given column in the column Map.
* <p>By default, the supplied column name will be returned unmodified.
* @param columnName the column name as returned by the ResultSet
* @return the column key to use
* @see java.sql.ResultSetMetaData#getColumnName
@@ -84,9 +86,9 @@ public class ColumnMapRowMapper implements RowMapper<Map<String, Object>> {
* Retrieve a JDBC object value for the specified column.
* <p>The default implementation uses the {@code getObject} method.
* Additionally, this implementation includes a "hack" to get around Oracle
* returning a non standard object for their TIMESTAMP data type.
* @param rs the ResultSet holding the data
* @param index the column index
* returning a non standard object for their TIMESTAMP datatype.
* @param rs is the ResultSet holding the data
* @param index is the column index
* @return the Object returned
* @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -22,9 +22,7 @@ import java.sql.SQLException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.TypeConverter;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -52,7 +50,7 @@ public class DataClassRowMapper<T> extends BeanPropertyRowMapper<T> {
private String[] constructorParameterNames;
@Nullable
private TypeDescriptor[] constructorParameterTypes;
private Class<?>[] constructorParameterTypes;
/**
@@ -77,13 +75,9 @@ public class DataClassRowMapper<T> extends BeanPropertyRowMapper<T> {
super.initialize(mappedClass);
this.mappedConstructor = BeanUtils.getResolvableConstructor(mappedClass);
int paramCount = this.mappedConstructor.getParameterCount();
if (paramCount > 0) {
if (this.mappedConstructor.getParameterCount() > 0) {
this.constructorParameterNames = BeanUtils.getParameterNames(this.mappedConstructor);
this.constructorParameterTypes = new TypeDescriptor[paramCount];
for (int i = 0; i < paramCount; i++) {
this.constructorParameterTypes[i] = new TypeDescriptor(new MethodParameter(this.mappedConstructor, i));
}
this.constructorParameterTypes = this.mappedConstructor.getParameterTypes();
}
}
@@ -96,9 +90,8 @@ public class DataClassRowMapper<T> extends BeanPropertyRowMapper<T> {
args = new Object[this.constructorParameterNames.length];
for (int i = 0; i < args.length; i++) {
String name = underscoreName(this.constructorParameterNames[i]);
TypeDescriptor td = this.constructorParameterTypes[i];
Object value = getColumnValue(rs, rs.findColumn(name), td.getType());
args[i] = tc.convertIfNecessary(value, td.getType(), td);
Class<?> type = this.constructorParameterTypes[i];
args[i] = tc.convertIfNecessary(getColumnValue(rs, rs.findColumn(name), type), type);
}
}
else {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -40,27 +40,22 @@ import org.springframework.jdbc.support.JdbcUtils;
*
* <p>Example:
*
* <pre class="code">
* create table tab (id int unsigned not null primary key, text varchar(100));
* <pre class="code">create table tab (id int unsigned not null primary key, text varchar(100));
* create table tab_sequence (value int not null);
* insert into tab_sequence values(0);</pre>
*
* <p>If {@code cacheSize} is set, the intermediate values are served without querying the
* If "cacheSize" is set, the intermediate values are served without querying the
* database. If the server or your application is stopped or crashes or a transaction
* is rolled back, the unused values will never be served. The maximum hole size in
* numbering is consequently the value of {@code cacheSize}.
* numbering is consequently the value of cacheSize.
*
* <p>It is possible to avoid acquiring a new connection for the incrementer by setting the
* "useNewConnection" property to false. In this case you <i>MUST</i> use a non-transactional
* storage engine like MYISAM when defining the incrementer table.
*
* <p>As of Spring Framework 5.3.7, {@code MySQLMaxValueIncrementer} is compatible with
* <a href="https://dev.mysql.com/doc/refman/8.0/en/mysql-tips.html#safe-updates">MySQL safe updates mode</a>.
*
* @author Jean-Pierre Pawlak
* @author Thomas Risberg
* @author Juergen Hoeller
* @author Sam Brannen
*/
public class MySQLMaxValueIncrementer extends AbstractColumnMaxValueIncrementer {
@@ -146,7 +141,7 @@ public class MySQLMaxValueIncrementer extends AbstractColumnMaxValueIncrementer
String columnName = getColumnName();
try {
stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
" = last_insert_id(" + columnName + " + " + getCacheSize() + ") limit 1");
" = last_insert_id(" + columnName + " + " + getCacheSize() + ")");
}
catch (SQLException ex) {
throw new DataAccessResourceFailureException("Could not increment " + columnName + " for " +
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -135,7 +135,6 @@ public abstract class AbstractRowMapperTests {
given(resultSet.getObject(anyInt(), any(Class.class))).willThrow(new SQLFeatureNotSupportedException());
given(resultSet.getDate(3)).willReturn(new java.sql.Date(1221222L));
given(resultSet.getBigDecimal(4)).willReturn(new BigDecimal("1234.56"));
given(resultSet.getObject(4)).willReturn(new BigDecimal("1234.56"));
given(resultSet.wasNull()).willReturn(type == MockType.TWO);
given(resultSetMetaData.getColumnCount()).willReturn(4);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,11 @@
package org.springframework.jdbc.core;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.test.ConstructorPerson;
import org.springframework.jdbc.core.test.ConstructorPersonWithGenerics;
import static org.assertj.core.api.Assertions.assertThat;
@@ -46,20 +42,4 @@ public class DataClassRowMapperTests extends AbstractRowMapperTests {
mock.verifyClosed();
}
@Test
public void testStaticQueryWithDataClassAndGenerics() throws Exception {
Mock mock = new Mock();
List<ConstructorPersonWithGenerics> result = mock.getJdbcTemplate().query(
"select name, age, birth_date, balance from people",
new DataClassRowMapper<>(ConstructorPersonWithGenerics.class));
assertThat(result.size()).isEqualTo(1);
ConstructorPersonWithGenerics person = result.get(0);
assertThat(person.name()).isEqualTo("Bubba");
assertThat(person.age()).isEqualTo(22L);
assertThat(person.birth_date()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.balance()).isEqualTo(Collections.singletonList(new BigDecimal("1234.56")));
mock.verifyClosed();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,13 +24,13 @@ import java.util.Date;
*/
public class ConstructorPerson {
private final String name;
private String name;
private final long age;
private long age;
private final Date birth_date;
private java.util.Date birth_date;
private final BigDecimal balance;
private BigDecimal balance;
public ConstructorPerson(String name, long age, Date birth_date, BigDecimal balance) {
@@ -42,19 +42,19 @@ public class ConstructorPerson {
public String name() {
return this.name;
return name;
}
public long age() {
return this.age;
return age;
}
public Date birth_date() {
return this.birth_date;
return birth_date;
}
public BigDecimal balance() {
return this.balance;
return balance;
}
}
@@ -1,61 +0,0 @@
/*
* 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.
* 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.jdbc.core.test;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author Juergen Hoeller
*/
public class ConstructorPersonWithGenerics {
private final String name;
private final long age;
private final Date birth_date;
private final List<BigDecimal> balance;
public ConstructorPersonWithGenerics(String name, long age, Date birth_date, List<BigDecimal> balance) {
this.name = name;
this.age = age;
this.birth_date = birth_date;
this.balance = balance;
}
public String name() {
return this.name;
}
public long age() {
return this.age;
}
public Date birth_date() {
return this.birth_date;
}
public List<BigDecimal> balance() {
return this.balance;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -25,7 +25,6 @@ import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.HanaSequenceMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer;
@@ -39,13 +38,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Unit tests for {@link DataFieldMaxValueIncrementer} implementations.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 27.02.2004
*/
class DataFieldMaxValueIncrementerTests {
public class DataFieldMaxValueIncrementerTests {
private final DataSource dataSource = mock(DataSource.class);
@@ -57,7 +53,7 @@ class DataFieldMaxValueIncrementerTests {
@Test
void hanaSequenceMaxValueIncrementer() throws SQLException {
public void testHanaSequenceMaxValueIncrementer() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select myseq.nextval from dummy")).willReturn(resultSet);
@@ -79,7 +75,7 @@ class DataFieldMaxValueIncrementerTests {
}
@Test
void hsqlMaxValueIncrementer() throws SQLException {
public void testHsqlMaxValueIncrementer() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select max(identity()) from myseq")).willReturn(resultSet);
@@ -109,7 +105,7 @@ class DataFieldMaxValueIncrementerTests {
}
@Test
void hsqlMaxValueIncrementerWithDeleteSpecificValues() throws SQLException {
public void testHsqlMaxValueIncrementerWithDeleteSpecificValues() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select max(identity()) from myseq")).willReturn(resultSet);
@@ -140,7 +136,7 @@ class DataFieldMaxValueIncrementerTests {
}
@Test
void mySQLMaxValueIncrementer() throws SQLException {
public void testMySQLMaxValueIncrementer() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select last_insert_id()")).willReturn(resultSet);
@@ -160,14 +156,14 @@ class DataFieldMaxValueIncrementerTests {
assertThat(incrementer.nextStringValue()).isEqualTo("3");
assertThat(incrementer.nextLongValue()).isEqualTo(4);
verify(statement, times(2)).executeUpdate("update myseq set seq = last_insert_id(seq + 2) limit 1");
verify(statement, times(2)).executeUpdate("update myseq set seq = last_insert_id(seq + 2)");
verify(resultSet, times(2)).close();
verify(statement, times(2)).close();
verify(connection, times(2)).close();
}
@Test
void oracleSequenceMaxValueIncrementer() throws SQLException {
public void testOracleSequenceMaxValueIncrementer() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select myseq.nextval from dual")).willReturn(resultSet);
@@ -189,7 +185,7 @@ class DataFieldMaxValueIncrementerTests {
}
@Test
void postgresSequenceMaxValueIncrementer() throws SQLException {
public void testPostgresSequenceMaxValueIncrementer() throws SQLException {
given(dataSource.getConnection()).willReturn(connection);
given(connection.createStatement()).willReturn(statement);
given(statement.executeQuery("select nextval('myseq')")).willReturn(resultSet);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -179,23 +179,6 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
}
/**
* Return a current session count, indicating the number of sessions currently
* cached by this connection factory.
* @since 5.3.7
*/
public int getCachedSessionCount() {
int count = 0;
synchronized (this.cachedSessions) {
for (Deque<Session> sessionList : this.cachedSessions.values()) {
synchronized (sessionList) {
count += sessionList.size();
}
}
}
return count;
}
/**
* Resets the Session cache as well.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,6 @@ import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.netty.client.TcpClientTransport;
import io.rsocket.transport.netty.client.WebsocketClientTransport;
import org.reactivestreams.Publisher;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -50,7 +49,7 @@ import org.springframework.util.MimeType;
* @author Brian Clozel
* @since 5.2
*/
public interface RSocketRequester extends Disposable {
public interface RSocketRequester {
/**
* Return the underlying {@link RSocketClient} used to make requests with.
@@ -111,27 +110,6 @@ public interface RSocketRequester extends Disposable {
*/
RequestSpec metadata(Object metadata, @Nullable MimeType mimeType);
/**
* Shortcut method that delegates to the same on the underlying
* {@link #rsocketClient()} in order to close the connection from the
* underlying transport and notify subscribers.
* @since 5.3.7
*/
@Override
default void dispose() {
rsocketClient().dispose();
}
/**
* Shortcut method that delegates to the same on the underlying
* {@link #rsocketClient()}.
* @since 5.3.7
*/
@Override
default boolean isDisposed() {
return rsocketClient().isDisposed();
}
/**
* Obtain a builder to create a client {@link RSocketRequester} by connecting
* to an RSocket server.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -42,16 +42,10 @@ public abstract class AbstractBrokerRegistration {
private final List<String> destinationPrefixes;
/**
* Create a new broker registration.
* @param clientInboundChannel the inbound channel
* @param clientOutboundChannel the outbound channel
* @param destinationPrefixes the destination prefixes
*/
public AbstractBrokerRegistration(SubscribableChannel clientInboundChannel,
MessageChannel clientOutboundChannel, @Nullable String[] destinationPrefixes) {
Assert.notNull(clientInboundChannel, "'clientInboundChannel' must not be null");
Assert.notNull(clientOutboundChannel, "'clientInboundChannel' must not be null");
Assert.notNull(clientOutboundChannel, "'clientOutboundChannel' must not be null");
this.clientInboundChannel = clientInboundChannel;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -40,16 +40,8 @@ public class SimpleBrokerRegistration extends AbstractBrokerRegistration {
private String selectorHeaderName = "selector";
/**
* Create a new {@code SimpleBrokerRegistration}.
* @param clientInboundChannel the inbound channel
* @param clientOutboundChannel the outbound channel
* @param destinationPrefixes the destination prefixes
*/
public SimpleBrokerRegistration(SubscribableChannel clientInboundChannel,
MessageChannel clientOutboundChannel, String[] destinationPrefixes) {
super(clientInboundChannel, clientOutboundChannel, destinationPrefixes);
public SimpleBrokerRegistration(SubscribableChannel inChannel, MessageChannel outChannel, String[] prefixes) {
super(inChannel, outChannel, prefixes);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -68,12 +68,6 @@ public class StompBrokerRelayRegistration extends AbstractBrokerRegistration {
private String userRegistryBroadcast;
/**
* Create a new {@code StompBrokerRelayRegistration}.
* @param clientInboundChannel the inbound channel
* @param clientOutboundChannel the outbound channel
* @param destinationPrefixes the destination prefixes
*/
public StompBrokerRelayRegistration(SubscribableChannel clientInboundChannel,
MessageChannel clientOutboundChannel, String[] destinationPrefixes) {
@@ -166,10 +166,7 @@ public class InvocableHandlerMethodTests {
@SuppressWarnings("unused")
static class Handler {
public Handler() {
}
private static class Handler {
public String handle(Integer intArg, String stringArg) {
return intArg + "-" + stringArg;
@@ -184,7 +181,7 @@ public class InvocableHandlerMethodTests {
}
static class ExceptionRaisingArgumentResolver implements HandlerMethodArgumentResolver {
private static class ExceptionRaisingArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
@@ -183,8 +183,6 @@ public class InvocableHandlerMethodTests {
private AtomicReference<String> result = new AtomicReference<>();
public Handler() {
}
public String getResult() {
return this.result.get();
+44 -12
View File
@@ -1,24 +1,56 @@
plugins {
id "org.unbroken-dome.xjc"
}
description = "Spring Object/XML Marshalling"
configurations {
jibx
xjc
}
dependencies {
jibx "org.jibx:jibx-bind:1.3.3"
jibx "org.apache.bcel:bcel:6.0"
xjc "javax.xml.bind:jaxb-api:2.3.1"
xjc "com.sun.xml.bind:jaxb-core:2.3.0.1"
xjc "com.sun.xml.bind:jaxb-impl:2.3.0.1"
xjc "com.sun.xml.bind:jaxb-xjc:2.3.1"
xjc "com.sun.activation:javax.activation:1.2.0"
}
xjc {
xjcVersion = '2.2'
}
sourceSets {
test {
xjcTargetPackage = 'org.springframework.oxm.jaxb.test'
ext.genSourcesDir = "${buildDir}/generated-sources"
ext.flightSchema = "${projectDir}/src/test/resources/org/springframework/oxm/flight.xsd"
task genJaxb {
ext.sourcesDir = "${genSourcesDir}/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
inputs.files(flightSchema).withPathSensitivity(PathSensitivity.RELATIVE)
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
classpath: configurations.xjc.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
xjc(destdir: sourcesDir, schema: flightSchema,
package: "org.springframework.oxm.jaxb.test") {
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
debugLevel: "lines,vars,source",
classpath: configurations.xjc.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
@@ -35,7 +67,7 @@ dependencies {
testCompile("org.codehaus.jettison:jettison") {
exclude group: "stax", module: "stax-api"
}
//testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile("org.xmlunit:xmlunit-assertj")
testCompile("org.xmlunit:xmlunit-matchers")
testRuntime("com.sun.xml.bind:jaxb-core")
@@ -44,7 +76,7 @@ dependencies {
// JiBX compiler is currently not compatible with JDK 9+.
// If customJavaHome has been set, we assume the custom JDK version is 9+.
if ((JavaVersion.current() == JavaVersion.VERSION_1_8) && !project.hasProperty("testToolchain")) {
if ((JavaVersion.current() == JavaVersion.VERSION_1_8) && !System.getProperty("customJavaSourceVersion")) {
compileTestJava {
def bindingXml = "${projectDir}/src/test/resources/org/springframework/oxm/jibx/binding.xml"
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -78,7 +78,7 @@ import static org.xmlunit.diff.DifferenceEvaluators.downgradeDifferencesToEqual;
* @author Biju Kunjummen
* @author Sam Brannen
*/
class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
public class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
private static final String CONTEXT_PATH = "org.springframework.oxm.jaxb.test";
@@ -104,7 +104,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
@Test
void marshalSAXResult() throws Exception {
public void marshalSAXResult() throws Exception {
ContentHandler contentHandler = mock(ContentHandler.class);
SAXResult result = new SAXResult(contentHandler);
marshaller.marshal(flights, result);
@@ -124,7 +124,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test
void lazyInit() throws Exception {
public void lazyInit() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(CONTEXT_PATH);
marshaller.setLazyInit(true);
@@ -137,44 +137,48 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test
void properties() throws Exception {
public void properties() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(CONTEXT_PATH);
marshaller.setMarshallerProperties(
Collections.singletonMap(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE));
Collections.<String, Object>singletonMap(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE));
marshaller.afterPropertiesSet();
}
@Test
void noContextPathOrClassesToBeBound() throws Exception {
public void noContextPathOrClassesToBeBound() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
assertThatIllegalArgumentException().isThrownBy(marshaller::afterPropertiesSet);
assertThatIllegalArgumentException().isThrownBy(
marshaller::afterPropertiesSet);
}
@Test
void testInvalidContextPath() throws Exception {
public void testInvalidContextPath() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("ab");
assertThatExceptionOfType(UncategorizedMappingException.class).isThrownBy(marshaller::afterPropertiesSet);
assertThatExceptionOfType(UncategorizedMappingException.class).isThrownBy(
marshaller::afterPropertiesSet);
}
@Test
void marshalInvalidClass() throws Exception {
public void marshalInvalidClass() throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(FlightType.class);
marshaller.afterPropertiesSet();
Result result = new StreamResult(new StringWriter());
Flights flights = new Flights();
assertThatExceptionOfType(XmlMappingException.class).isThrownBy(() -> marshaller.marshal(flights, result));
assertThatExceptionOfType(XmlMappingException.class).isThrownBy(() ->
marshaller.marshal(flights, result));
}
@Test
void supportsContextPath() throws Exception {
public void supportsContextPath() throws Exception {
testSupports();
}
@Test
void supportsClassesToBeBound() throws Exception {
public void supportsClassesToBeBound() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Flights.class, FlightType.class);
marshaller.afterPropertiesSet();
@@ -182,7 +186,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test
void supportsPackagesToScan() throws Exception {
public void supportsPackagesToScan() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(CONTEXT_PATH);
marshaller.afterPropertiesSet();
@@ -220,11 +224,11 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
private void testSupportsPrimitives() {
final Primitives primitives = new Primitives();
ReflectionUtils.doWithMethods(Primitives.class, method -> {
ReflectionUtils.doWithMethods(Primitives.class, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Type returnType = method.getGenericReturnType();
assertThat(marshaller.supports(returnType))
.as("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(9) + ">")
.isTrue();
assertThat(marshaller.supports(returnType)).as("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(9) + ">").isTrue();
try {
// make sure the marshalling does not result in errors
Object returnValue = method.invoke(primitives);
@@ -233,18 +237,22 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
catch (InvocationTargetException e) {
throw new AssertionError(e.getMessage(), e);
}
},
method -> method.getName().startsWith("primitive")
);
}
}, new ReflectionUtils.MethodFilter() {
@Override
public boolean matches(Method method) {
return method.getName().startsWith("primitive");
}
});
}
private void testSupportsStandardClasses() throws Exception {
final StandardClasses standardClasses = new StandardClasses();
ReflectionUtils.doWithMethods(StandardClasses.class, method -> {
ReflectionUtils.doWithMethods(StandardClasses.class, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Type returnType = method.getGenericReturnType();
assertThat(marshaller.supports(returnType))
.as("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(13) + ">")
.isTrue();
assertThat(marshaller.supports(returnType)).as("Jaxb2Marshaller does not support JAXBElement<" + method.getName().substring(13) + ">").isTrue();
try {
// make sure the marshalling does not result in errors
Object returnValue = method.invoke(standardClasses);
@@ -253,13 +261,17 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
catch (InvocationTargetException e) {
throw new AssertionError(e.getMessage(), e);
}
},
method -> method.getName().startsWith("standardClass")
);
}
}, new ReflectionUtils.MethodFilter() {
@Override
public boolean matches(Method method) {
return method.getName().startsWith("standardClass");
}
});
}
@Test
void supportsXmlRootElement() throws Exception {
public void supportsXmlRootElement() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(DummyRootElement.class, DummyType.class);
marshaller.afterPropertiesSet();
@@ -272,7 +284,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
@Test
void marshalAttachments() throws Exception {
public void marshalAttachments() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(BinaryObject.class);
marshaller.setMtomEnabled(true);
@@ -292,7 +304,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test // SPR-10714
void marshalAWrappedObjectHoldingAnXmlElementDeclElement() throws Exception {
public void marshalAWrappedObjectHoldingAnXmlElementDeclElement() throws Exception {
marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("org.springframework.oxm.jaxb");
marshaller.afterPropertiesSet();
@@ -306,7 +318,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test // SPR-10806
void unmarshalStreamSourceWithXmlOptions() throws Exception {
public void unmarshalStreamSourceWithXmlOptions() throws Exception {
final javax.xml.bind.Unmarshaller unmarshaller = mock(javax.xml.bind.Unmarshaller.class);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller() {
@Override
@@ -340,7 +352,7 @@ class Jaxb2MarshallerTests extends AbstractMarshallerTests<Jaxb2Marshaller> {
}
@Test // SPR-10806
void unmarshalSaxSourceWithXmlOptions() throws Exception {
public void unmarshalSaxSourceWithXmlOptions() throws Exception {
final javax.xml.bind.Unmarshaller unmarshaller = mock(javax.xml.bind.Unmarshaller.class);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller() {
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -31,7 +31,6 @@ import javax.xml.transform.stream.StreamSource;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.oxm.AbstractUnmarshallerTests;
import org.springframework.oxm.jaxb.test.FlightType;
@@ -57,7 +56,7 @@ public class Jaxb2UnmarshallerTests extends AbstractUnmarshallerTests<Jaxb2Marsh
protected Jaxb2Marshaller createUnmarshaller() throws Exception {
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setContextPath("org.springframework.oxm.jaxb.test");
unmarshaller.setSchema(new FileSystemResource("src/test/schema/flight.xsd"));
unmarshaller.setSchema(new ClassPathResource("org/springframework/oxm/flight.xsd"));
unmarshaller.afterPropertiesSet();
return unmarshaller;
}
@@ -1,20 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~ 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.
-->
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://samples.springframework.org/flight"
xmlns:tns="http://samples.springframework.org/flight">
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="https://samples.springframework.org/order"
xmlns:tns="https://samples.springframework.org/order">
<element name="order">
<complexType>
<sequence>
<element name="order-item" type="tns:orderItemType"
maxOccurs="unbounded">
</element>
</sequence>
</complexType>
</element>
<complexType name="orderItemType">
<attribute name="id" type="string" />
<attribute name="quantity" type="int" />
</complexType>
</schema>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -315,8 +315,8 @@ public class MockServletContext implements ServletContext {
return resourcePaths;
}
catch (InvalidPathException | IOException ex ) {
if (logger.isDebugEnabled()) {
logger.debug("Could not get resource paths for " +
if (logger.isWarnEnabled()) {
logger.warn("Could not get resource paths for " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -339,8 +339,8 @@ public class MockServletContext implements ServletContext {
throw ex;
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not get URL for resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not get URL for resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -360,8 +360,8 @@ public class MockServletContext implements ServletContext {
return resource.getInputStream();
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not open InputStream for resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not open InputStream for resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -476,8 +476,8 @@ public class MockServletContext implements ServletContext {
return resource.getFile().getAbsolutePath();
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not determine real path of resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not determine real path of resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -373,16 +373,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
for (NameValuePair param : this.webRequest.getRequestParameters()) {
if (param instanceof KeyDataPair) {
KeyDataPair pair = (KeyDataPair) param;
File file = pair.getFile();
MockPart part;
if (file != null) {
part = new MockPart(pair.getName(), file.getName(), readAllBytes(file));
part.getHeaders().setContentType(MediaType.valueOf(pair.getMimeType()));
}
else { // mimic empty file upload
part = new MockPart(pair.getName(), "", null);
part.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
}
MockPart part = new MockPart(pair.getName(), pair.getFile().getName(), readAllBytes(pair.getFile()));
part.getHeaders().setContentType(MediaType.valueOf(pair.getMimeType()));
request.addPart(part);
}
else {
@@ -496,6 +496,7 @@ class MockHttpServletResponseTests {
String expiryDate = "Tue, 8 Oct 2019 19:50:00 GMT";
String cookieValue = "SESSION=123; Path=/; Expires=" + expiryDate;
response.addHeader(SET_COOKIE, cookieValue);
System.err.println(response.getCookie("SESSION"));
assertThat(response.getHeader(SET_COOKIE)).isEqualTo(cookieValue);
assertNumCookies(1);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -67,7 +67,7 @@ class TimedTransactionalSpringExtensionTests {
event(test("WithExceededJUnitJupiterTimeout"),
finishedWithFailure(
instanceOf(TimeoutException.class),
message(msg -> msg.endsWith("timed out after 10 milliseconds")))));
message(msg -> msg.endsWith("timed out after 50 milliseconds")))));
}
@@ -83,10 +83,10 @@ class TimedTransactionalSpringExtensionTests {
}
@Test
@Timeout(value = 10, unit = TimeUnit.MILLISECONDS)
@Timeout(value = 50, unit = TimeUnit.MILLISECONDS)
void transactionalWithExceededJUnitJupiterTimeout() throws Exception {
assertThatTransaction().isActive();
Thread.sleep(200);
Thread.sleep(100);
}
@Test
@@ -97,11 +97,11 @@ class TimedTransactionalSpringExtensionTests {
}
@Test
@Timeout(value = 10, unit = TimeUnit.MILLISECONDS)
@Timeout(value = 50, unit = TimeUnit.MILLISECONDS)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
void notTransactionalWithExceededJUnitJupiterTimeout() throws Exception {
assertThatTransaction().isNotActive();
Thread.sleep(200);
Thread.sleep(100);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -76,14 +76,14 @@ public class TimedSpringRunnerTests {
}
// Should Fail due to timeout.
@Test(timeout = 10)
@Test(timeout = 100)
public void jUnitTimeoutWithSleep() throws Exception {
Thread.sleep(200);
}
// Should Fail due to timeout.
@Test
@Timed(millis = 10)
@Timed(millis = 100)
public void springTimeoutWithSleep() throws Exception {
Thread.sleep(200);
}
@@ -97,7 +97,7 @@ public class TimedSpringRunnerTests {
// Should Fail due to timeout.
@Test
@MetaTimedWithOverride(millis = 10)
@MetaTimedWithOverride(millis = 100)
public void springTimeoutWithSleepAndMetaAnnotationAndOverride() throws Exception {
Thread.sleep(200);
}
@@ -110,7 +110,7 @@ public class TimedSpringRunnerTests {
}
}
@Timed(millis = 10)
@Timed(millis = 100)
@Retention(RetentionPolicy.RUNTIME)
private static @interface MetaTimed {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,8 @@
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
@@ -54,7 +52,6 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.SoftAssertions.assertSoftly;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
/**
@@ -426,7 +423,8 @@ public class HtmlUnitRequestBuilderTests {
}
@Test // gh-24926
public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithFileToUploadAsParameter() throws Exception {
public void buildRequestParameterMapViaWebRequestDotSetFileToUploadAsParameter() throws Exception {
webRequest.setRequestParameters(Collections.singletonList(
new KeyDataPair("key",
new ClassPathResource("org/springframework/test/web/htmlunit/test.txt").getFile(),
@@ -434,7 +432,7 @@ public class HtmlUnitRequestBuilderTests {
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);
assertThat(actualRequest.getParts()).hasSize(1);
assertThat(actualRequest.getParts().size()).isEqualTo(1);
Part part = actualRequest.getPart("key");
assertThat(part).isNotNull();
assertThat(part.getName()).isEqualTo("key");
@@ -443,30 +441,6 @@ public class HtmlUnitRequestBuilderTests {
assertThat(part.getContentType()).isEqualTo(MimeType.TEXT_PLAIN);
}
@Test // gh-26799
public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithNullFileToUploadAsParameter() throws Exception {
webRequest.setRequestParameters(Collections.singletonList(new KeyDataPair("key", null, null, null, (Charset) null)));
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);
assertThat(actualRequest.getParts()).hasSize(1);
Part part = actualRequest.getPart("key");
assertSoftly(softly -> {
softly.assertThat(part).isNotNull();
softly.assertThat(part.getName()).as("name").isEqualTo("key");
softly.assertThat(part.getSize()).as("size").isEqualTo(0);
try {
softly.assertThat(part.getInputStream()).isEmpty();
}
catch (IOException ex) {
softly.fail("failed to get InputStream", ex);
}
softly.assertThat(part.getSubmittedFileName()).as("filename").isEqualTo("");
softly.assertThat(part.getContentType()).as("content-type").isEqualTo("application/octet-stream");
});
}
@Test
public void buildRequestParameterMapFromSingleQueryParam() throws Exception {
webRequest.setUrl(new URL("https://example.com/example/?name=value"));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -28,7 +28,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -320,7 +320,7 @@ public abstract class TransactionSynchronizationManager {
else {
// Sort lazily here, not in registerSynchronization.
List<TransactionSynchronization> sortedSynchs = new ArrayList<>(synchs);
OrderComparator.sort(sortedSynchs);
AnnotationAwareOrderComparator.sort(sortedSynchs);
return Collections.unmodifiableList(sortedSynchs);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -57,13 +57,14 @@ public enum HttpMethod {
/**
* Determine whether this {@code HttpMethod} matches the given method value.
* @param method the HTTP method as a String
* Determine whether this {@code HttpMethod} matches the given
* method value.
* @param method the method value as a String
* @return {@code true} if it matches, {@code false} otherwise
* @since 4.2.4
*/
public boolean matches(String method) {
return name().equals(method);
return (this == resolve(method));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -416,13 +416,6 @@ public enum HttpStatus {
NETWORK_AUTHENTICATION_REQUIRED(511, Series.SERVER_ERROR, "Network Authentication Required");
private static final HttpStatus[] VALUES;
static {
VALUES = values();
}
private final int value;
private final Series series;
@@ -557,8 +550,7 @@ public enum HttpStatus {
*/
@Nullable
public static HttpStatus resolve(int statusCode) {
// used cached VALUES instead of values() to prevent array allocation
for (HttpStatus status : VALUES) {
for (HttpStatus status : values()) {
if (status.value == statusCode) {
return status;
}
@@ -19,7 +19,9 @@ package org.springframework.http.codec.multipart;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -61,6 +63,8 @@ import org.springframework.util.Assert;
*/
public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements HttpMessageReader<Part> {
private static final String IDENTIFIER = "spring-multipart";
private int maxInMemorySize = 256 * 1024;
private int maxHeadersSize = 8 * 1024;
@@ -73,7 +77,7 @@ public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements
private Scheduler blockingOperationScheduler = Schedulers.boundedElastic();
private FileStorage fileStorage = FileStorage.tempDirectory(this::getBlockingOperationScheduler);
private Mono<Path> fileStorageDirectory = Mono.defer(this::defaultFileStorageDirectory).cache();
private Charset headersCharset = StandardCharsets.UTF_8;
@@ -143,7 +147,10 @@ public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements
*/
public void setFileStorageDirectory(Path fileStorageDirectory) throws IOException {
Assert.notNull(fileStorageDirectory, "FileStorageDirectory must not be null");
this.fileStorage = FileStorage.fromPath(fileStorageDirectory);
if (!Files.exists(fileStorageDirectory)) {
Files.createDirectory(fileStorageDirectory);
}
this.fileStorageDirectory = Mono.just(fileStorageDirectory);
}
/**
@@ -161,10 +168,6 @@ public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements
this.blockingOperationScheduler = blockingOperationScheduler;
}
private Scheduler getBlockingOperationScheduler() {
return this.blockingOperationScheduler;
}
/**
* When set to {@code true}, the {@linkplain Part#content() part content}
* is streamed directly from the parsed input buffer stream, and not stored
@@ -227,7 +230,7 @@ public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements
this.maxHeadersSize, this.headersCharset);
return PartGenerator.createParts(tokens, this.maxParts, this.maxInMemorySize, this.maxDiskUsagePerPart,
this.streaming, this.fileStorage.directory(), this.blockingOperationScheduler);
this.streaming, this.fileStorageDirectory, this.blockingOperationScheduler);
});
}
@@ -247,4 +250,16 @@ public class DefaultPartHttpMessageReader extends LoggingCodecSupport implements
return null;
}
@SuppressWarnings("BlockingMethodInNonBlockingContext")
private Mono<Path> defaultFileStorageDirectory() {
return Mono.fromCallable(() -> {
Path tempDirectory = Paths.get(System.getProperty("java.io.tmpdir"), IDENTIFIER);
if (!Files.exists(tempDirectory)) {
Files.createDirectory(tempDirectory);
}
return tempDirectory;
}).subscribeOn(this.blockingOperationScheduler);
}
}
@@ -1,128 +0,0 @@
/*
* 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.
* 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.http.codec.multipart;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
/**
* Represents a directory used to store parts larger than
* {@link DefaultPartHttpMessageReader#setMaxInMemorySize(int)}.
*
* @author Arjen Poutsma
* @since 5.3.7
*/
abstract class FileStorage {
private static final Log logger = LogFactory.getLog(FileStorage.class);
protected FileStorage() {
}
/**
* Get the mono of the directory to store files in.
*/
public abstract Mono<Path> directory();
/**
* Create a new {@code FileStorage} from a user-specified path. Creates the
* path if it does not exist.
*/
public static FileStorage fromPath(Path path) throws IOException {
if (!Files.exists(path)) {
Files.createDirectory(path);
}
return new PathFileStorage(path);
}
/**
* Create a new {@code FileStorage} based a on a temporary directory.
* @param scheduler scheduler to use for blocking operations
*/
public static FileStorage tempDirectory(Supplier<Scheduler> scheduler) {
return new TempFileStorage(scheduler);
}
private static final class PathFileStorage extends FileStorage {
private final Mono<Path> directory;
public PathFileStorage(Path directory) {
this.directory = Mono.just(directory);
}
@Override
public Mono<Path> directory() {
return this.directory;
}
}
private static final class TempFileStorage extends FileStorage {
private static final String IDENTIFIER = "spring-multipart-";
private final Supplier<Scheduler> scheduler;
private volatile Mono<Path> directory = tempDirectory();
public TempFileStorage(Supplier<Scheduler> scheduler) {
this.scheduler = scheduler;
}
@Override
public Mono<Path> directory() {
return this.directory
.flatMap(this::createNewDirectoryIfDeleted)
.subscribeOn(this.scheduler.get());
}
private Mono<Path> createNewDirectoryIfDeleted(Path directory) {
if (!Files.exists(directory)) {
// Some daemons remove temp directories. Let's create a new one.
Mono<Path> newDirectory = tempDirectory();
this.directory = newDirectory;
return newDirectory;
}
else {
return Mono.just(directory);
}
}
private static Mono<Path> tempDirectory() {
return Mono.fromCallable(() -> {
Path directory = Files.createTempDirectory(IDENTIFIER);
if (logger.isDebugEnabled()) {
logger.debug("Created temporary storage directory: " + directory);
}
return directory;
}).cache();
}
}
}
@@ -578,6 +578,9 @@ final class PartGenerator extends BaseSubscriber<MultipartParser.Token> {
private WritingFileState createFileState(Path directory) {
try {
if (!Files.exists(directory)) {
Files.createDirectory(directory);
}
Path tempFile = Files.createTempFile(directory, null, ".multipart");
if (logger.isTraceEnabled()) {
logger.trace("Storing multipart data in file " + tempFile);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -17,13 +17,11 @@
package org.springframework.http.codec.multipart;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
@@ -80,16 +78,12 @@ import org.springframework.util.Assert;
*/
public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implements HttpMessageReader<Part> {
private static final String FILE_STORAGE_DIRECTORY_PREFIX = "synchronoss-file-upload-";
private int maxInMemorySize = 256 * 1024;
private long maxDiskUsagePerPart = -1;
private int maxParts = -1;
private Path fileStorageDirectory = createTempDirectory();
/**
* Configure the maximum amount of memory that is allowed to use per part.
@@ -150,22 +144,6 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
return this.maxParts;
}
/**
* Set the directory used to store parts larger than
* {@link #setMaxInMemorySize(int) maxInMemorySize}. By default, a new
* temporary directory is created.
* @throws IOException if an I/O error occurs, or the parent directory
* does not exist
* @since 5.3.7
*/
public void setFileStorageDirectory(Path fileStorageDirectory) throws IOException {
Assert.notNull(fileStorageDirectory, "FileStorageDirectory must not be null");
if (!Files.exists(fileStorageDirectory)) {
Files.createDirectory(fileStorageDirectory);
}
this.fileStorageDirectory = fileStorageDirectory;
}
@Override
public List<MediaType> getReadableMediaTypes() {
@@ -189,7 +167,7 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
@Override
public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {
return Flux.create(new SynchronossPartGenerator(message, this.fileStorageDirectory))
return Flux.create(new SynchronossPartGenerator(message))
.doOnNext(part -> {
if (!Hints.isLoggingSuppressed(hints)) {
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " +
@@ -205,15 +183,6 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
return Mono.error(new UnsupportedOperationException("Cannot read multipart request body into single Part"));
}
private static Path createTempDirectory() {
try {
return Files.createTempDirectory(FILE_STORAGE_DIRECTORY_PREFIX);
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
/**
* Subscribe to the input stream and feed the Synchronoss parser. Then listen
@@ -225,17 +194,14 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
private final LimitedPartBodyStreamStorageFactory storageFactory = new LimitedPartBodyStreamStorageFactory();
private final Path fileStorageDirectory;
@Nullable
private NioMultipartParserListener listener;
@Nullable
private NioMultipartParser parser;
public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, Path fileStorageDirectory) {
public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage) {
this.inputMessage = inputMessage;
this.fileStorageDirectory = fileStorageDirectory;
}
@Override
@@ -252,7 +218,6 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
this.parser = Multipart
.multipart(context)
.saveTemporaryFilesTo(this.fileStorageDirectory.toString())
.usePartBodyStreamStorageFactory(this.storageFactory)
.forNIO(this.listener);
@@ -68,10 +68,10 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
@Nullable
private volatile Subscriber<? super T> subscriber;
private volatile boolean completionPending;
private volatile boolean completionBeforeDemand;
@Nullable
private volatile Throwable errorPending;
private volatile Throwable errorBeforeDemand;
private final String logPrefix;
@@ -186,7 +186,7 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
*/
private boolean readAndPublish() throws IOException {
long r;
while ((r = this.demand) > 0 && (this.state.get() != State.COMPLETED)) {
while ((r = this.demand) > 0 && !this.state.get().equals(State.COMPLETED)) {
T data = read();
if (data != null) {
if (r != Long.MAX_VALUE) {
@@ -222,30 +222,27 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
// Protect from infinite recursion in Undertow, where we can't check if data
// is available, so all we can do is to try to read.
// Generally, no need to check if we just came out of readAndPublish()...
if (oldState != State.READING) {
if (!oldState.equals(State.READING)) {
checkOnDataAvailable();
}
}
}
private boolean handlePendingCompletionOrError() {
private void handleCompletionOrErrorBeforeDemand() {
State state = this.state.get();
if (state == State.DEMAND || state == State.NO_DEMAND) {
if (this.completionPending) {
rsReadLogger.trace(getLogPrefix() + "Processing pending completion");
if (!state.equals(State.UNSUBSCRIBED) && !state.equals(State.SUBSCRIBING)) {
if (this.completionBeforeDemand) {
rsReadLogger.trace(getLogPrefix() + "Completed before demand");
this.state.get().onAllDataRead(this);
return true;
}
Throwable ex = this.errorPending;
Throwable ex = this.errorBeforeDemand;
if (ex != null) {
if (rsReadLogger.isTraceEnabled()) {
rsReadLogger.trace(getLogPrefix() + "Processing pending completion with error: " + ex);
rsReadLogger.trace(getLogPrefix() + "Completed with error before demand: " + ex);
}
this.state.get().onError(this, ex);
return true;
}
}
return false;
}
private Subscription createSubscription() {
@@ -308,7 +305,7 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
publisher.subscriber = subscriber;
subscriber.onSubscribe(subscription);
publisher.changeState(SUBSCRIBING, NO_DEMAND);
publisher.handlePendingCompletionOrError();
publisher.handleCompletionOrErrorBeforeDemand();
}
else {
throw new IllegalStateException("Failed to transition to SUBSCRIBING, " +
@@ -318,14 +315,14 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
@Override
<T> void onAllDataRead(AbstractListenerReadPublisher<T> publisher) {
publisher.completionPending = true;
publisher.handlePendingCompletionOrError();
publisher.completionBeforeDemand = true;
publisher.handleCompletionOrErrorBeforeDemand();
}
@Override
<T> void onError(AbstractListenerReadPublisher<T> publisher, Throwable ex) {
publisher.errorPending = ex;
publisher.handlePendingCompletionOrError();
publisher.errorBeforeDemand = ex;
publisher.handleCompletionOrErrorBeforeDemand();
}
},
@@ -344,14 +341,14 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
@Override
<T> void onAllDataRead(AbstractListenerReadPublisher<T> publisher) {
publisher.completionPending = true;
publisher.handlePendingCompletionOrError();
publisher.completionBeforeDemand = true;
publisher.handleCompletionOrErrorBeforeDemand();
}
@Override
<T> void onError(AbstractListenerReadPublisher<T> publisher, Throwable ex) {
publisher.errorPending = ex;
publisher.handlePendingCompletionOrError();
publisher.errorBeforeDemand = ex;
publisher.handleCompletionOrErrorBeforeDemand();
}
},
@@ -382,17 +379,14 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
boolean demandAvailable = publisher.readAndPublish();
if (demandAvailable) {
publisher.changeToDemandState(READING);
publisher.handlePendingCompletionOrError();
}
else {
publisher.readingPaused();
if (publisher.changeState(READING, NO_DEMAND)) {
if (!publisher.handlePendingCompletionOrError()) {
// Demand may have arrived since readAndPublish returned
long r = publisher.demand;
if (r > 0) {
publisher.changeToDemandState(NO_DEMAND);
}
// Demand may have arrived since readAndPublish returned
long r = publisher.demand;
if (r > 0) {
publisher.changeToDemandState(NO_DEMAND);
}
}
}
@@ -414,18 +408,6 @@ public abstract class AbstractListenerReadPublisher<T> implements Publisher<T> {
publisher.changeToDemandState(NO_DEMAND);
}
}
@Override
<T> void onAllDataRead(AbstractListenerReadPublisher<T> publisher) {
publisher.completionPending = true;
publisher.handlePendingCompletionOrError();
}
@Override
<T> void onError(AbstractListenerReadPublisher<T> publisher, Throwable ex) {
publisher.errorPending = ex;
publisher.handlePendingCompletionOrError();
}
},
COMPLETED {
@@ -329,7 +329,7 @@ public abstract class AbstractListenerWriteFlushProcessor<T> implements Processo
public <T> void onComplete(AbstractListenerWriteFlushProcessor<T> processor) {
processor.sourceCompleted = true;
// A competing write might have completed very quickly
if (processor.state.get() == State.REQUESTED) {
if (processor.state.get().equals(State.REQUESTED)) {
handleSourceCompleted(processor);
}
}
@@ -151,11 +151,10 @@ public abstract class AbstractListenerWriteProcessor<T> implements Processor<T,
* container.
*/
public final void onWritePossible() {
State state = this.state.get();
if (rsWriteLogger.isTraceEnabled()) {
rsWriteLogger.trace(getLogPrefix() + "onWritePossible [" + state + "]");
rsWriteLogger.trace(getLogPrefix() + "onWritePossible");
}
state.onWritePossible(this);
this.state.get().onWritePossible(this);
}
/**
@@ -183,14 +182,14 @@ public abstract class AbstractListenerWriteProcessor<T> implements Processor<T,
cancel();
for (;;) {
State prev = this.state.get();
if (prev == State.COMPLETED) {
if (prev.equals(State.COMPLETED)) {
break;
}
if (this.state.compareAndSet(prev, State.COMPLETED)) {
if (rsWriteLogger.isTraceEnabled()) {
rsWriteLogger.trace(getLogPrefix() + prev + " -> " + this.state);
}
if (prev != State.WRITING) {
if (!prev.equals(State.WRITING)) {
discardCurrentData();
}
break;
@@ -430,7 +429,7 @@ public abstract class AbstractListenerWriteProcessor<T> implements Processor<T,
public <T> void onComplete(AbstractListenerWriteProcessor<T> processor) {
processor.sourceCompleted = true;
// A competing write might have completed very quickly
if (processor.state.get() == State.REQUESTED) {
if (processor.state.get().equals(State.REQUESTED)) {
processor.changeStateToComplete(State.REQUESTED);
}
}
@@ -441,7 +440,7 @@ public abstract class AbstractListenerWriteProcessor<T> implements Processor<T,
public <T> void onComplete(AbstractListenerWriteProcessor<T> processor) {
processor.sourceCompleted = true;
// A competing write might have completed very quickly
if (processor.state.get() == State.REQUESTED) {
if (processor.state.get().equals(State.REQUESTED)) {
processor.changeStateToComplete(State.REQUESTED);
}
}
@@ -157,7 +157,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
// Check for existing error attribute first
if (DispatcherType.ASYNC == request.getDispatcherType()) {
if (DispatcherType.ASYNC.equals(request.getDispatcherType())) {
Throwable ex = (Throwable) request.getAttribute(WRITE_ERROR_ATTRIBUTE_NAME);
throw new ServletException("Failed to create response content", ex);
}
@@ -182,14 +182,14 @@ class WriteResultPublisher implements Publisher<Void> {
@Override
void publishComplete(WriteResultPublisher publisher) {
publisher.completedBeforeSubscribed = true;
if(State.SUBSCRIBED == publisher.state.get()) {
if(State.SUBSCRIBED.equals(publisher.state.get())) {
publisher.state.get().publishComplete(publisher);
}
}
@Override
void publishError(WriteResultPublisher publisher, Throwable ex) {
publisher.errorBeforeSubscribed = ex;
if(State.SUBSCRIBED == publisher.state.get()) {
if(State.SUBSCRIBED.equals(publisher.state.get())) {
publisher.state.get().publishError(publisher, ex);
}
}
@@ -203,14 +203,14 @@ class WriteResultPublisher implements Publisher<Void> {
@Override
void publishComplete(WriteResultPublisher publisher) {
publisher.completedBeforeSubscribed = true;
if(State.SUBSCRIBED == publisher.state.get()) {
if(State.SUBSCRIBED.equals(publisher.state.get())) {
publisher.state.get().publishComplete(publisher);
}
}
@Override
void publishError(WriteResultPublisher publisher, Throwable ex) {
publisher.errorBeforeSubscribed = ex;
if(State.SUBSCRIBED == publisher.state.get()) {
if(State.SUBSCRIBED.equals(publisher.state.get())) {
publisher.state.get().publishError(publisher, ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -34,7 +34,7 @@ import org.springframework.web.server.ServerWebExchange;
/**
* Specialized {@link org.springframework.validation.DataBinder} to perform data
* binding from URL query parameters or form data in the request data to Java objects.
* binding from URL query params or form data in the request data to Java objects.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
@@ -64,7 +64,7 @@ public class WebExchangeDataBinder extends WebDataBinder {
/**
* Bind query parameters, form data, or multipart form data to the binder target.
* Bind query params, form data, and or multipart form data to the binder target.
* @param exchange the current exchange
* @return a {@code Mono<Void>} when binding is complete
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2012 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.
@@ -85,11 +85,10 @@ public abstract class SpringBeanAutowiringSupport {
bpp.processInjection(target);
}
else {
if (logger.isWarnEnabled()) {
logger.warn("Current WebApplicationContext is not available for processing of " +
if (logger.isDebugEnabled()) {
logger.debug("Current WebApplicationContext is not available for processing of " +
ClassUtils.getShortName(target.getClass()) + ": " +
"Make sure this class gets constructed in a Spring web application after the" +
"Spring WebApplicationContext has been initialized. Proceeding without injection.");
"Make sure this class gets constructed in a Spring web application. Proceeding without injection.");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -138,12 +138,7 @@ public class CorsConfiguration {
* {@code @CrossOrigin}, via {@link #applyPermitDefaultValues()}.
*/
public void setAllowedOrigins(@Nullable List<String> allowedOrigins) {
this.allowedOrigins = (allowedOrigins != null ?
allowedOrigins.stream().map(this::trimTrailingSlash).collect(Collectors.toList()) : null);
}
private String trimTrailingSlash(String origin) {
return origin.endsWith("/") ? origin.substring(0, origin.length() - 1) : origin;
this.allowedOrigins = (allowedOrigins != null ? new ArrayList<>(allowedOrigins) : null);
}
/**
@@ -164,7 +159,6 @@ public class CorsConfiguration {
else if (this.allowedOrigins == DEFAULT_PERMIT_ALL && CollectionUtils.isEmpty(this.allowedOriginPatterns)) {
setAllowedOrigins(DEFAULT_PERMIT_ALL);
}
origin = trimTrailingSlash(origin);
this.allowedOrigins.add(origin);
}
@@ -215,7 +209,6 @@ public class CorsConfiguration {
if (this.allowedOriginPatterns == null) {
this.allowedOriginPatterns = new ArrayList<>(4);
}
originPattern = trimTrailingSlash(originPattern);
this.allowedOriginPatterns.add(new OriginPattern(originPattern));
if (this.allowedOrigins == DEFAULT_PERMIT_ALL) {
this.allowedOrigins = null;
@@ -482,6 +475,7 @@ public class CorsConfiguration {
* @return the combined {@code CorsConfiguration}, or {@code this}
* configuration if the supplied configuration is {@code null}
*/
@Nullable
public CorsConfiguration combine(@Nullable CorsConfiguration other) {
if (other == null) {
return this;
@@ -549,31 +543,30 @@ public class CorsConfiguration {
/**
* Check the origin of the request against the configured allowed origins.
* @param origin the origin to check
* @param requestOrigin the origin to check
* @return the origin to use for the response, or {@code null} which
* means the request origin is not allowed
*/
@Nullable
public String checkOrigin(@Nullable String origin) {
if (!StringUtils.hasText(origin)) {
public String checkOrigin(@Nullable String requestOrigin) {
if (!StringUtils.hasText(requestOrigin)) {
return null;
}
String originToCheck = trimTrailingSlash(origin);
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
if (this.allowedOrigins.contains(ALL)) {
validateAllowCredentials();
return ALL;
}
for (String allowedOrigin : this.allowedOrigins) {
if (originToCheck.equalsIgnoreCase(allowedOrigin)) {
return origin;
if (requestOrigin.equalsIgnoreCase(allowedOrigin)) {
return requestOrigin;
}
}
}
if (!ObjectUtils.isEmpty(this.allowedOriginPatterns)) {
for (OriginPattern p : this.allowedOriginPatterns) {
if (p.getDeclaredPattern().equals(ALL) || p.getPattern().matcher(originToCheck).matches()) {
return origin;
if (p.getDeclaredPattern().equals(ALL) || p.getPattern().matcher(requestOrigin).matches()) {
return requestOrigin;
}
}
}
@@ -25,7 +25,6 @@ import org.springframework.web.server.ServerWebExchange;
*
* @author Rossen Stoyanchev
* @since 5.3.4
* @see PreFlightRequestWebFilter
*/
public interface PreFlightRequestHandler {
@@ -1,57 +0,0 @@
/*
* 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.
* 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.web.cors.reactive;
import reactor.core.publisher.Mono;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
/**
* WebFilter that handles pre-flight requests through a
* {@link PreFlightRequestHandler} and bypasses the rest of the chain.
*
* <p>A WebFlux application can simply inject PreFlightRequestHandler and use
* it to create an instance of this WebFilter since {@code @EnableWebFlux}
* declares {@code DispatcherHandler} as a bean and that is a
* PreFlightRequestHandler.
*
* @author Rossen Stoyanchev
* @since 5.3.7
*/
public class PreFlightRequestWebFilter implements WebFilter {
private final PreFlightRequestHandler handler;
/**
* Create an instance that will delegate to the given handler.
*/
public PreFlightRequestWebFilter(PreFlightRequestHandler handler) {
Assert.notNull(handler, "PreFlightRequestHandler is required");
this.handler = handler;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return (CorsUtils.isPreFlightRequest(exchange.getRequest()) ?
this.handler.handlePreFlight(exchange) : chain.filter(exchange));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -17,7 +17,6 @@
package org.springframework.web.method.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -38,16 +37,16 @@ import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.SmartValidator;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.ValidationAnnotationUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -77,7 +76,6 @@ import org.springframework.web.multipart.support.StandardServletPartUtils;
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @author Sebastien Deleuze
* @author Vladislav Kisel
* @since 3.1
*/
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
@@ -258,14 +256,6 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
String paramName = paramNames[i];
Class<?> paramType = paramTypes[i];
Object value = webRequest.getParameterValues(paramName);
// Since WebRequest#getParameter exposes a single-value parameter as an array
// with a single element, we unwrap the single value in such cases, analogous
// to WebExchangeDataBinder.addBindValue(Map<String, Object>, String, List<?>).
if (ObjectUtils.isArray(value) && Array.getLength(value) == 1) {
value = Array.get(value, 0);
}
if (value == null) {
if (fieldDefaultPrefix != null) {
value = webRequest.getParameter(fieldDefaultPrefix + paramName);
@@ -279,7 +269,6 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
}
}
try {
MethodParameter methodParam = new FieldAwareConstructorParameter(ctor, i, paramName);
if (value == null && methodParam.isOptional()) {
@@ -373,7 +362,7 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
*/
protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
for (Annotation ann : parameter.getParameterAnnotations()) {
Object[] validationHints = ValidationAnnotationUtils.determineValidationHints(ann);
Object[] validationHints = determineValidationHints(ann);
if (validationHints != null) {
binder.validate(validationHints);
break;
@@ -399,7 +388,7 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
Class<?> targetType, String fieldName, @Nullable Object value) {
for (Annotation ann : parameter.getParameterAnnotations()) {
Object[] validationHints = ValidationAnnotationUtils.determineValidationHints(ann);
Object[] validationHints = determineValidationHints(ann);
if (validationHints != null) {
for (Validator validator : binder.getValidators()) {
if (validator instanceof SmartValidator) {
@@ -417,6 +406,26 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
}
/**
* Determine any validation triggered by the given annotation.
* @param ann the annotation (potentially a validation annotation)
* @return the validation hints to apply (possibly an empty array),
* or {@code null} if this annotation does not trigger any validation
* @since 5.1
*/
@Nullable
private Object[] determineValidationHints(Annotation ann) {
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
if (hints == null) {
return new Object[0];
}
return (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
}
return null;
}
/**
* Whether to raise a fatal bind exception on validation errors.
* <p>The default implementation delegates to {@link #isBindExceptionRequired(MethodParameter)}.
@@ -85,7 +85,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
private static final String HOST_PATTERN = "(" + HOST_IPV6_PATTERN + "|" + HOST_IPV4_PATTERN + ")";
private static final String PORT_PATTERN = "(.[^/?#]*(?:\\{[^/]+?})?)";
private static final String PORT_PATTERN = "(\\d*(?:\\{[^/]+?})?)";
private static final String PATH_PATTERN = "([^?#]*)";
@@ -1,82 +0,0 @@
/*
* 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.
* 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.http.codec.multipart;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Arjen Poutsma
*/
class FileStorageTests {
@Test
void fromPath() throws IOException {
Path path = Files.createTempFile("spring", "test");
FileStorage storage = FileStorage.fromPath(path);
Mono<Path> directory = storage.directory();
StepVerifier.create(directory)
.expectNext(path)
.verifyComplete();
}
@Test
void tempDirectory() {
FileStorage storage = FileStorage.tempDirectory(Schedulers::boundedElastic);
Mono<Path> directory = storage.directory();
StepVerifier.create(directory)
.consumeNextWith(path -> {
assertThat(path).exists();
StepVerifier.create(directory)
.expectNext(path)
.verifyComplete();
})
.verifyComplete();
}
@Test
void tempDirectoryDeleted() {
FileStorage storage = FileStorage.tempDirectory(Schedulers::boundedElastic);
Mono<Path> directory = storage.directory();
StepVerifier.create(directory)
.consumeNextWith(path1 -> {
try {
Files.delete(path1);
StepVerifier.create(directory)
.consumeNextWith(path2 -> assertThat(path2).isNotEqualTo(path1))
.verifyComplete();
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
})
.verifyComplete();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -72,7 +72,7 @@ public class JsonbHttpMessageConverterTests {
public void readTyped() throws IOException {
String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
MyBean result = (MyBean) this.converter.read(MyBean.class, inputMessage);
@@ -90,7 +90,7 @@ public class JsonbHttpMessageConverterTests {
public void readUntyped() throws IOException {
String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
assertThat(result.get("string")).isEqualTo("Foo");
@@ -167,9 +167,9 @@ public class JsonbHttpMessageConverterTests {
}
@Test
public void readInvalidJson() {
public void readInvalidJson() throws IOException {
String body = "FooBar";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
this.converter.read(MyBean.class, inputMessage));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -32,11 +32,10 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -49,22 +48,23 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Brian Clozel
* @author Sam Brannen
*/
@TestInstance(Lifecycle.PER_CLASS)
class WebRequestDataBinderIntegrationTests {
public class WebRequestDataBinderIntegrationTests {
private final PartsServlet partsServlet = new PartsServlet();
private static Server jettyServer;
private final PartListServlet partListServlet = new PartListServlet();
private static final PartsServlet partsServlet = new PartsServlet();
private static final PartListServlet partListServlet = new PartListServlet();
private final RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
private Server jettyServer;
protected static String baseUrl;
private String baseUrl;
protected static MediaType contentType;
@BeforeAll
void startJettyServer() throws Exception {
public static void startJettyServer() throws Exception {
// Let server pick its own random, available port.
jettyServer = new Server(0);
@@ -89,7 +89,7 @@ class WebRequestDataBinderIntegrationTests {
}
@AfterAll
void stopJettyServer() throws Exception {
public static void stopJettyServer() throws Exception {
if (jettyServer != null) {
jettyServer.stop();
}
@@ -97,7 +97,7 @@ class WebRequestDataBinderIntegrationTests {
@Test
void partsBinding() {
public void partsBinding() {
PartsBean bean = new PartsBean();
partsServlet.setBean(bean);
@@ -113,7 +113,7 @@ class WebRequestDataBinderIntegrationTests {
}
@Test
void partListBinding() {
public void partListBinding() {
PartListBean bean = new PartListBean();
partListServlet.setBean(bean);
@@ -143,7 +143,7 @@ class WebRequestDataBinderIntegrationTests {
response.setStatus(HttpServletResponse.SC_OK);
}
void setBean(T bean) {
public void setBean(T bean) {
this.bean = bean;
}
}
@@ -151,9 +151,9 @@ class WebRequestDataBinderIntegrationTests {
private static class PartsBean {
private Part firstPart;
public Part firstPart;
private Part secondPart;
public Part secondPart;
public Part getFirstPart() {
return firstPart;
@@ -182,7 +182,7 @@ class WebRequestDataBinderIntegrationTests {
private static class PartListBean {
private List<Part> partList;
public List<Part> partList;
public List<Part> getPartList() {
return partList;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -282,24 +282,15 @@ public class CorsConfigurationTests {
@Test
public void checkOriginAllowed() {
// "*" matches
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("*");
// "*" does not match together with allowCredentials
config.setAllowCredentials(true);
assertThatIllegalArgumentException().isThrownBy(() -> config.checkOrigin("https://domain.com"));
// specific origin matches Origin header with or without trailing "/"
config.setAllowedOrigins(Collections.singletonList("https://domain.com"));
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com/");
// specific origin with trailing "/" matches Origin header with or without trailing "/"
config.setAllowedOrigins(Collections.singletonList("https://domain.com/"));
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com/");
config.setAllowCredentials(false);
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -170,19 +170,10 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedOrigin("https://DOMAIN2.com");
this.processor.processRequest(this.conf, this.request, this.response);
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
}
@Test // gh-26892
public void actualRequestTrailingSlashOriginMatch() throws Exception {
this.request.setMethod(HttpMethod.GET.name());
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com/");
this.conf.addAllowedOrigin("https://domain2.com");
this.processor.processRequest(this.conf, this.request, this.response);
assertThat(this.response.getHeaders(HttpHeaders.VARY)).contains(HttpHeaders.ORIGIN,
HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -172,22 +172,10 @@ public class DefaultCorsProcessorTests {
this.processor.process(this.conf, exchange);
ServerHttpResponse response = exchange.getResponse();
assertThat((Object) response.getStatusCode()).isNull();
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
}
@Test // gh-26892
public void actualRequestTrailingSlashOriginMatch() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest
.method(HttpMethod.GET, "http://localhost/test.html")
.header(HttpHeaders.ORIGIN, "https://domain2.com/"));
this.conf.addAllowedOrigin("https://domain2.com");
this.processor.process(this.conf, exchange);
ServerHttpResponse response = exchange.getResponse();
assertThat(response.getHeaders().get(VARY)).contains(ORIGIN,
ACCESS_CONTROL_REQUEST_METHOD, ACCESS_CONTROL_REQUEST_HEADERS);
assertThat((Object) response.getStatusCode()).isNull();
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 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.
@@ -19,7 +19,6 @@ package org.springframework.web.method.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -27,7 +26,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
@@ -60,7 +58,6 @@ import static org.mockito.Mockito.verify;
* Test fixture with {@link ModelAttributeMethodProcessor}.
*
* @author Rossen Stoyanchev
* @author Vladislav Kisel
*/
public class ModelAttributeMethodProcessorTests {
@@ -76,7 +73,6 @@ public class ModelAttributeMethodProcessorTests {
private MethodParameter paramModelAttr;
private MethodParameter paramBindingDisabledAttr;
private MethodParameter paramNonSimpleType;
private MethodParameter beanWithConstructorArgs;
private MethodParameter returnParamNamedModelAttr;
private MethodParameter returnParamNonSimpleType;
@@ -90,7 +86,7 @@ public class ModelAttributeMethodProcessorTests {
Method method = ModelAttributeHandler.class.getDeclaredMethod("modelAttribute",
TestBean.class, Errors.class, int.class, TestBean.class,
TestBean.class, TestBean.class, TestBeanWithConstructorArgs.class);
TestBean.class, TestBean.class);
this.paramNamedValidModelAttr = new SynthesizingMethodParameter(method, 0);
this.paramErrors = new SynthesizingMethodParameter(method, 1);
@@ -98,7 +94,6 @@ public class ModelAttributeMethodProcessorTests {
this.paramModelAttr = new SynthesizingMethodParameter(method, 3);
this.paramBindingDisabledAttr = new SynthesizingMethodParameter(method, 4);
this.paramNonSimpleType = new SynthesizingMethodParameter(method, 5);
this.beanWithConstructorArgs = new SynthesizingMethodParameter(method, 6);
method = getClass().getDeclaredMethod("annotatedReturnValue");
this.returnParamNamedModelAttr = new MethodParameter(method, -1);
@@ -269,26 +264,6 @@ public class ModelAttributeMethodProcessorTests {
assertThat(this.container.getModel().get("testBean")).isSameAs(testBean);
}
@Test // gh-25182
public void resolveConstructorListArgumentFromCommaSeparatedRequestParameter() throws Exception {
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
mockRequest.addParameter("listOfStrings", "1,2");
ServletWebRequest requestWithParam = new ServletWebRequest(mockRequest);
WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
given(factory.createBinder(any(), any(), eq("testBeanWithConstructorArgs")))
.willAnswer(invocation -> {
WebRequestDataBinder binder = new WebRequestDataBinder(invocation.getArgument(1));
// Add conversion service which will convert "1,2" to a list
binder.setConversionService(new DefaultFormattingConversionService());
return binder;
});
Object resolved = this.processor.resolveArgument(this.beanWithConstructorArgs, this.container, requestWithParam, factory);
assertThat(resolved).isInstanceOf(TestBeanWithConstructorArgs.class);
assertThat(((TestBeanWithConstructorArgs) resolved).listOfStrings).containsExactly("1", "2");
}
private void testGetAttributeFromModel(String expectedAttrName, MethodParameter param) throws Exception {
Object target = new TestBean();
@@ -355,20 +330,10 @@ public class ModelAttributeMethodProcessorTests {
int intArg,
@ModelAttribute TestBean defaultNameAttr,
@ModelAttribute(name="noBindAttr", binding=false) @Valid TestBean noBindAttr,
TestBean notAnnotatedAttr,
TestBeanWithConstructorArgs beanWithConstructorArgs) {
TestBean notAnnotatedAttr) {
}
}
static class TestBeanWithConstructorArgs {
final List<String> listOfStrings;
public TestBeanWithConstructorArgs(List<String> listOfStrings) {
this.listOfStrings = listOfStrings;
}
}
@ModelAttribute("modelAttrName") @SuppressWarnings("unused")
private String annotatedReturnValue() {
@@ -38,7 +38,6 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Unit tests for {@link UriComponentsBuilder}.
@@ -1273,28 +1272,4 @@ class UriComponentsBuilderTests {
assertThat(path).isEqualTo("/home/path");
}
@Test
void validPort() {
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:52567/path").build();
assertThat(uriComponents.getPort()).isEqualTo(52567);
assertThat(uriComponents.getPath()).isEqualTo("/path");
uriComponents = UriComponentsBuilder.fromUriString("http://localhost:52567?trace=false").build();
assertThat(uriComponents.getPort()).isEqualTo(52567);
assertThat(uriComponents.getQuery()).isEqualTo("trace=false");
uriComponents = UriComponentsBuilder.fromUriString("http://localhost:52567#fragment").build();
assertThat(uriComponents.getPort()).isEqualTo(52567);
assertThat(uriComponents.getFragment()).isEqualTo("fragment");
}
@Test
void verifyInvalidPort() {
String url = "http://localhost:port/path";
assertThatThrownBy(() -> UriComponentsBuilder.fromUriString(url).build().toUri())
.isInstanceOf(NumberFormatException.class);
assertThatThrownBy(() -> UriComponentsBuilder.fromHttpUrl(url).build().toUri())
.isInstanceOf(NumberFormatException.class);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -315,8 +315,8 @@ public class MockServletContext implements ServletContext {
return resourcePaths;
}
catch (InvalidPathException | IOException ex ) {
if (logger.isDebugEnabled()) {
logger.debug("Could not get resource paths for " +
if (logger.isWarnEnabled()) {
logger.warn("Could not get resource paths for " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -339,8 +339,8 @@ public class MockServletContext implements ServletContext {
throw ex;
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not get URL for resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not get URL for resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -360,8 +360,8 @@ public class MockServletContext implements ServletContext {
return resource.getInputStream();
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not open InputStream for resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not open InputStream for resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -476,8 +476,8 @@ public class MockServletContext implements ServletContext {
return resource.getFile().getAbsolutePath();
}
catch (InvalidPathException | IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not determine real path of resource " +
if (logger.isWarnEnabled()) {
logger.warn("Could not determine real path of resource " +
(resource != null ? resource : resourceLocation), ex);
}
return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ public class CorsRegistration {
private final String pathPattern;
private CorsConfiguration config;
private final CorsConfiguration config;
public CorsRegistration(String pathPattern) {
@@ -46,14 +46,10 @@ public class CorsRegistration {
/**
* Set the origins for which cross-origin requests are allowed from a browser.
* Please, refer to {@link CorsConfiguration#setAllowedOrigins(List)} for
* format details and other considerations.
*
* <p>By default, all origins are allowed, but if
* {@link #allowedOriginPatterns(String...) allowedOriginPatterns} is also
* set, then that takes precedence.
* @see #allowedOriginPatterns(String...)
* A list of origins for which cross-origin requests are allowed. Please,
* see {@link CorsConfiguration#setAllowedOrigins(List)} for details.
* <p>By default all origins are allowed unless {@code originPatterns} is
* also set in which case {@code originPatterns} is used instead.
*/
public CorsRegistration allowedOrigins(String... origins) {
this.config.setAllowedOrigins(Arrays.asList(origins));
@@ -61,11 +57,9 @@ public class CorsRegistration {
}
/**
* Alternative to {@link #allowedOrigins(String...)} that supports more
* flexible patterns for specifying the origins for which cross-origin
* requests are allowed from a browser. Please, refer to
* {@link CorsConfiguration#setAllowedOriginPatterns(List)} for format
* details and other considerations.
* Alternative to {@link #allowCredentials} that supports origins declared
* via wildcard patterns. Please, see
* @link CorsConfiguration#setAllowedOriginPatterns(List)} for details.
* <p>By default this is not set.
* @since 5.3
*/
@@ -149,7 +143,7 @@ public class CorsRegistration {
* @since 5.3
*/
public CorsRegistration combine(CorsConfiguration other) {
this.config = this.config.combine(other);
this.config.combine(other);
return this;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -17,6 +17,7 @@
package org.springframework.web.reactive.function.client;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -206,7 +207,9 @@ class DefaultClientResponse implements ClientResponse {
.onErrorReturn(IllegalStateException.class::isInstance, EMPTY)
.map(bodyBytes -> {
HttpRequest request = this.requestSupplier.get();
Charset charset = headers().contentType().map(MimeType::getCharset).orElse(null);
Charset charset = headers().contentType()
.map(MimeType::getCharset)
.orElse(StandardCharsets.ISO_8859_1);
int statusCode = rawStatusCode();
HttpStatus httpStatus = HttpStatus.resolve(statusCode);
if (httpStatus != null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -39,13 +39,6 @@ public interface ExchangeFilterFunction {
* in the chain, to be invoked via
* {@linkplain ExchangeFunction#exchange(ClientRequest) invoked} in order to
* proceed with the exchange, or not invoked to shortcut the chain.
*
* <p><strong>Note:</strong> When a filter handles the response after the
* call to {@link ExchangeFunction#exchange}, extra care must be taken to
* always consume its content or otherwise propagate it downstream for
* further handling, for example by the {@link WebClient}. Please, see the
* reference documentation for more details on this.
*
* @param request the current request
* @param next the next exchange function in the chain
* @return the filtered response
@@ -43,14 +43,6 @@ public interface ExchangeFunction {
/**
* Exchange the given request for a {@link ClientResponse} promise.
*
* <p><strong>Note:</strong> When calling this method from an
* {@link ExchangeFilterFunction} that handles the response in some way,
* extra care must be taken to always consume its content or otherwise
* propagate it downstream for further handling, for example by the
* {@link WebClient}. Please, see the reference documentation for more
* details on this.
*
* @param request the request to exchange
* @return the delayed response
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -50,7 +50,7 @@ public class UnknownHttpStatusCodeException extends WebClientResponseException {
* @since 5.1.4
*/
public UnknownHttpStatusCodeException(
int statusCode, HttpHeaders headers, byte[] responseBody, @Nullable Charset responseCharset,
int statusCode, HttpHeaders headers, byte[] responseBody, Charset responseCharset,
@Nullable HttpRequest request) {
super("Unknown status code [" + statusCode + "]", statusCode, "",
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@@ -186,6 +186,13 @@ public interface WebClient {
*/
Builder baseUrl(String baseUrl);
/**
* Configure default URI variable values that will be used when expanding
* URI templates using a {@link Map}.
* @param defaultUriVariables the default values to use
* @see #baseUrl(String)
* @see #uriBuilderFactory(UriBuilderFactory)
*/
/**
* Configure default URL variable values to use when expanding URI
* templates with a {@link Map}. Effectively a shortcut for:

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