Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/2.7.x' into spring-projectsgh-…
Browse files Browse the repository at this point in the history
  • Loading branch information
mhalbritter committed Feb 15, 2022
2 parents 6647836 + 15f4b6c commit fafe05b
Show file tree
Hide file tree
Showing 34 changed files with 386 additions and 195 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.build;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import org.gradle.api.DefaultTask;
import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;

/**
* {@link Task} to generate properties and write them to disk as a properties file.
*
* @author Scott Frederick
*/
public class GeneratePropertiesResource extends DefaultTask {

private final Property<String> propertiesFileName;

private final DirectoryProperty destinationDirectory;

private final Map<String, String> properties = new HashMap<>();

public GeneratePropertiesResource() {
ObjectFactory objects = getProject().getObjects();
this.propertiesFileName = objects.property(String.class);
this.destinationDirectory = objects.directoryProperty();
}

@OutputDirectory
public DirectoryProperty getDestinationDirectory() {
return this.destinationDirectory;
}

@Input
public Property<String> getPropertiesFileName() {
return this.propertiesFileName;
}

public void property(String name, String value) {
this.properties.put(name, value);
}

@Input
public Map<String, String> getProperties() {
return this.properties;
}

@TaskAction
void generatePropertiesFile() throws IOException {
File outputFile = this.destinationDirectory.file(this.propertiesFileName).get().getAsFile();
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
this.properties.forEach((key, value) -> writer.printf("%s=%s\n", key, value));
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -104,6 +104,8 @@ class JavaConventions {

private static final String SOURCE_AND_TARGET_COMPATIBILITY = "1.8";

private static final String SPRING_BOOT_PROPERTIES_FILE = "spring-boot.properties";

void apply(Project project) {
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
project.getPlugins().apply(TestFailuresPlugin.class);
Expand All @@ -112,36 +114,45 @@ void apply(Project project) {
configureJavadocConventions(project);
configureTestConventions(project);
configureJarManifestConventions(project);
configureMetaInfResourcesConventions(project);
configureDependencyManagement(project);
configureToolchain(project);
configureProhibitedDependencyChecks(project);
});
}

private void configureJarManifestConventions(Project project) {
ExtractResources extractLegalResources = project.getTasks().create("extractLegalResources",
ExtractResources.class);
extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal"));
extractLegalResources.setResourcesNames(Arrays.asList("LICENSE.txt", "NOTICE.txt"));
extractLegalResources.property("version", project.getVersion().toString());
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
Set<String> sourceJarTaskNames = sourceSets.stream().map(SourceSet::getSourcesJarTaskName)
.collect(Collectors.toSet());
Set<String> javadocJarTaskNames = sourceSets.stream().map(SourceSet::getJavadocJarTaskName)
.collect(Collectors.toSet());
project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate((evaluated) -> {
jar.metaInf((metaInf) -> metaInf.from(extractLegalResources));
jar.manifest((manifest) -> {
Map<String, Object> attributes = new TreeMap<>();
attributes.put("Automatic-Module-Name", project.getName().replace("-", "."));
attributes.put("Build-Jdk-Spec", SOURCE_AND_TARGET_COMPATIBILITY);
attributes.put("Built-By", "Spring");
attributes.put("Implementation-Title",
determineImplementationTitle(project, sourceJarTaskNames, javadocJarTaskNames, jar));
attributes.put("Implementation-Version", project.getVersion());
manifest.attributes(attributes);
});
}));
project.getTasks().withType(Jar.class,
(jar) -> project.afterEvaluate((evaluated) -> jar.manifest((manifest) -> {
Map<String, Object> attributes = new TreeMap<>();
attributes.put("Automatic-Module-Name", project.getName().replace("-", "."));
attributes.put("Build-Jdk-Spec", SOURCE_AND_TARGET_COMPATIBILITY);
attributes.put("Built-By", "Spring");
attributes.put("Implementation-Title",
determineImplementationTitle(project, sourceJarTaskNames, javadocJarTaskNames, jar));
attributes.put("Implementation-Version", project.getVersion());
manifest.attributes(attributes);
})));
}

private void configureMetaInfResourcesConventions(Project project) {
ExtractResources extractLegalResources = project.getTasks().create("extractLegalResources",
ExtractResources.class);
extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal"));
extractLegalResources.setResourcesNames(Arrays.asList("LICENSE.txt", "NOTICE.txt"));
extractLegalResources.property("version", project.getVersion().toString());
GeneratePropertiesResource generateInfo = project.getTasks().create("generateSpringBootInfo",
GeneratePropertiesResource.class);
generateInfo.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("info"));
generateInfo.getPropertiesFileName().set(SPRING_BOOT_PROPERTIES_FILE);
generateInfo.property("version", project.getVersion().toString());
project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate(
(evaluated) -> jar.metaInf((metaInf) -> metaInf.from(extractLegalResources, generateInfo))));
}

private String determineImplementationTitle(Project project, Set<String> sourceJarTaskNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void jarIncludesLegalFiles() throws IOException {
try (JarFile jar = new JarFile(file)) {
assertThatLicenseIsPresent(jar);
assertThatNoticeIsPresent(jar);
assertThatSpringBootPropertiesIsPresent(jar);
Attributes mainAttributes = jar.getManifest().getMainAttributes();
assertThat(mainAttributes.getValue("Implementation-Title"))
.isEqualTo("Test project for manifest customization");
Expand Down Expand Up @@ -112,6 +113,7 @@ void sourceJarIsBuilt() throws IOException {
try (JarFile jar = new JarFile(file)) {
assertThatLicenseIsPresent(jar);
assertThatNoticeIsPresent(jar);
assertThatSpringBootPropertiesIsPresent(jar);
Attributes mainAttributes = jar.getManifest().getMainAttributes();
assertThat(mainAttributes.getValue("Implementation-Title"))
.isEqualTo("Source for " + this.projectDir.getName());
Expand Down Expand Up @@ -141,6 +143,7 @@ void javadocJarIsBuilt() throws IOException {
try (JarFile jar = new JarFile(file)) {
assertThatLicenseIsPresent(jar);
assertThatNoticeIsPresent(jar);
assertThatSpringBootPropertiesIsPresent(jar);
Attributes mainAttributes = jar.getManifest().getMainAttributes();
assertThat(mainAttributes.getValue("Implementation-Title"))
.isEqualTo("Javadoc for " + this.projectDir.getName());
Expand All @@ -165,6 +168,13 @@ private void assertThatNoticeIsPresent(JarFile jar) throws IOException {
assertThat(noticeContent).doesNotContain("${");
}

private void assertThatSpringBootPropertiesIsPresent(JarFile jar) throws IOException {
JarEntry properties = jar.getJarEntry("META-INF/spring-boot.properties");
assertThat(properties).isNotNull();
String content = FileCopyUtils.copyToString(new InputStreamReader(jar.getInputStream(properties)));
assertThat(content).contains("version=");
}

@Test
void testRetryIsConfiguredWithThreeRetriesOnCI() throws IOException {
try (PrintWriter out = new PrintWriter(new FileWriter(this.buildFile))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public void configure(ConcurrentKafkaListenerContainerFactory<Object, Object> li
configureContainer(listenerFactory.getContainerProperties());
}

@SuppressWarnings("deprecation")
private void configureListenerFactory(ConcurrentKafkaListenerContainerFactory<Object, Object> factory) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
Listener properties = this.properties.getListener();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,8 +24,8 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec;
import org.springframework.security.oauth2.server.resource.introspection.NimbusReactiveOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.SpringReactiveOpaqueTokenIntrospector;
import org.springframework.security.web.server.SecurityWebFilterChain;

/**
Expand All @@ -43,9 +43,9 @@ static class OpaqueTokenIntrospectionClientConfiguration {

@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.opaquetoken.introspection-uri")
NimbusReactiveOpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2ResourceServerProperties properties) {
SpringReactiveOpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2ResourceServerProperties properties) {
OAuth2ResourceServerProperties.Opaquetoken opaqueToken = properties.getOpaquetoken();
return new NimbusReactiveOpaqueTokenIntrospector(opaqueToken.getIntrospectionUri(),
return new SpringReactiveOpaqueTokenIntrospector(opaqueToken.getIntrospectionUri(),
opaqueToken.getClientId(), opaqueToken.getClientSecret());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,8 +26,8 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.SpringOpaqueTokenIntrospector;
import org.springframework.security.web.SecurityFilterChain;

/**
Expand All @@ -46,9 +46,9 @@ static class OpaqueTokenIntrospectionClientConfiguration {

@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.opaquetoken.introspection-uri")
NimbusOpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2ResourceServerProperties properties) {
SpringOpaqueTokenIntrospector opaqueTokenIntrospector(OAuth2ResourceServerProperties properties) {
OAuth2ResourceServerProperties.Opaquetoken opaqueToken = properties.getOpaquetoken();
return new NimbusOpaqueTokenIntrospector(opaqueToken.getIntrospectionUri(), opaqueToken.getClientId(),
return new SpringOpaqueTokenIntrospector(opaqueToken.getIntrospectionUri(), opaqueToken.getClientId(),
opaqueToken.getClientSecret());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
Expand All @@ -42,6 +44,7 @@
* @since 2.6.0
*/
@AutoConfiguration
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnClass({ WebSessionManager.class, Mono.class })
@EnableConfigurationProperties({ WebFluxProperties.class, ServerProperties.class })
public class WebSessionIdResolverAutoConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,35 @@ public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCust
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}

@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
static class ForwardedHeaderFilterConfiguration {

@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
ForwardedHeaderFilterCustomizer tomcatForwardedHeaderFilterCustomizer(ServerProperties serverProperties) {
return (filter) -> filter.setRelativeRedirects(serverProperties.getTomcat().isUseRelativeRedirects());
}

@Bean
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter(
ObjectProvider<ForwardedHeaderFilterCustomizer> customizerProvider) {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
customizerProvider.ifAvailable((customizer) -> customizer.customize(filter));
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}

}

interface ForwardedHeaderFilterCustomizer {

void customize(ForwardedHeaderFilter filter);

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ void testConcurrentKafkaListenerContainerFactoryWithCustomRecordFilterStrategy()
}

@Test
@Deprecated
void testConcurrentKafkaListenerContainerFactoryWithCustomErrorHandler() {
this.contextRunner.withBean("errorHandler", ErrorHandler.class, () -> mock(ErrorHandler.class))
.run((context) -> {
Expand All @@ -522,6 +523,7 @@ void testConcurrentKafkaListenerContainerFactoryWithCustomErrorHandler() {
}

@Test
@Deprecated
void concurrentKafkaListenerContainerFactoryInBatchModeShouldUseBatchErrorHandler() {
this.contextRunner.withBean("batchErrorHandler", BatchErrorHandler.class, () -> mock(BatchErrorHandler.class))
.withPropertyValues("spring.kafka.listener.type=batch").run((context) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration.WebFluxConfig;
import org.springframework.boot.context.properties.source.MutuallyExclusiveConfigurationPropertiesException;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.web.codec.CodecCustomizer;
Expand Down Expand Up @@ -615,6 +619,15 @@ void customSessionCookieConfigurationShouldBeApplied() {
}));
}

@ParameterizedTest
@ValueSource(classes = { ServerProperties.class, WebFluxProperties.class })
void propertiesAreNotEnabledInNonWebApplication(Class<?> propertiesClass) {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class,
WebSessionIdResolverAutoConfiguration.class))
.run((context) -> assertThat(context).doesNotHaveBean(propertiesClass));
}

private ContextConsumer<ReactiveWebApplicationContext> assertExchangeWithSession(
Consumer<MockServerWebExchange> exchange) {
return (context) -> {
Expand Down
Loading

0 comments on commit fafe05b

Please sign in to comment.