diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/build.gradle index 43a7ac73f2..a7bde3691b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/build.gradle @@ -27,4 +27,7 @@ dependencies { testImplementation("org.mockito:mockito-core") testImplementation("org.projectlombok:lombok") testImplementation("org.springframework:spring-core") + testImplementation("org.apache.commons:commons-dbcp2") { + exclude group: "commons-logging", module: "commons-logging" + } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index c34a83f8d6..5e55b564d8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -21,10 +21,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.time.Duration; import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Collections; import java.util.Deque; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -105,7 +102,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor static final String AUTO_CONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration"; - private static final Set SUPPORTED_OPTIONS = Collections.singleton(ADDITIONAL_METADATA_LOCATIONS_OPTION); + private static final Set SUPPORTED_OPTIONS = Set.of(ADDITIONAL_METADATA_LOCATIONS_OPTION); private MetadataStore metadataStore; @@ -138,8 +135,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } protected Set endpointAnnotations() { - return new HashSet<>(Arrays.asList(CONTROLLER_ENDPOINT_ANNOTATION, ENDPOINT_ANNOTATION, JMX_ENDPOINT_ANNOTATION, - REST_CONTROLLER_ENDPOINT_ANNOTATION, SERVLET_ENDPOINT_ANNOTATION, WEB_ENDPOINT_ANNOTATION)); + return Set.of(CONTROLLER_ENDPOINT_ANNOTATION, ENDPOINT_ANNOTATION, JMX_ENDPOINT_ANNOTATION, + REST_CONTROLLER_ENDPOINT_ANNOTATION, SERVLET_ENDPOINT_ANNOTATION, WEB_ENDPOINT_ANNOTATION); } protected String readOperationAnnotation() { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java index 6d4cc6c3d2..88751f65c4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,30 +50,22 @@ import org.springframework.boot.configurationprocessor.metadata.ItemDeprecation; * * @author Stephane Nicoll * @author Scott Frederick + * @author Moritz Halbritter */ class MetadataGenerationEnvironment { private static final String NULLABLE_ANNOTATION = "org.springframework.lang.Nullable"; - private static final Set TYPE_EXCLUDES; - static { - Set excludes = new HashSet<>(); - excludes.add("com.zaxxer.hikari.IConnectionCustomizer"); - excludes.add("groovy.lang.MetaClass"); - excludes.add("groovy.text.markup.MarkupTemplateEngine"); - excludes.add("java.io.Writer"); - excludes.add("java.io.PrintWriter"); - excludes.add("java.lang.ClassLoader"); - excludes.add("java.util.concurrent.ThreadFactory"); - excludes.add("jakarta.jms.XAConnectionFactory"); - excludes.add("javax.sql.DataSource"); - excludes.add("javax.sql.XADataSource"); - excludes.add("org.apache.tomcat.jdbc.pool.PoolConfiguration"); - excludes.add("org.apache.tomcat.jdbc.pool.Validator"); - excludes.add("org.flywaydb.core.api.callback.FlywayCallback"); - excludes.add("org.flywaydb.core.api.resolver.MigrationResolver"); - TYPE_EXCLUDES = Collections.unmodifiableSet(excludes); - } + private static final Set TYPE_EXCLUDES = Set.of("com.zaxxer.hikari.IConnectionCustomizer", + "groovy.lang.MetaClass", "groovy.text.markup.MarkupTemplateEngine", "java.io.Writer", "java.io.PrintWriter", + "java.lang.ClassLoader", "java.util.concurrent.ThreadFactory", "jakarta.jms.XAConnectionFactory", + "javax.sql.DataSource", "javax.sql.XADataSource", "org.apache.tomcat.jdbc.pool.PoolConfiguration", + "org.apache.tomcat.jdbc.pool.Validator", "org.flywaydb.core.api.callback.FlywayCallback", + "org.flywaydb.core.api.resolver.MigrationResolver"); + + private static final Set DEPRECATION_EXCLUDES = Set.of( + "org.apache.commons.dbcp2.BasicDataSource#getPassword", + "org.apache.commons.dbcp2.BasicDataSource#getUsername"); private final TypeUtils typeUtils; @@ -162,6 +154,13 @@ class MetadataGenerationEnvironment { } boolean isDeprecated(Element element) { + if (element == null) { + return false; + } + String elementName = element.getEnclosingElement() + "#" + element.getSimpleName(); + if (DEPRECATION_EXCLUDES.contains(elementName)) { + return false; + } if (isElementDeprecated(element)) { return true; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java index d1a831a951..bc58efcde3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; import org.springframework.boot.configurationprocessor.metadata.ItemMetadata; import org.springframework.boot.configurationprocessor.metadata.Metadata; +import org.springframework.boot.configurationsample.deprecation.Dbcp2Configuration; import org.springframework.boot.configurationsample.record.RecordWithGetter; import org.springframework.boot.configurationsample.recursive.RecursiveProperties; import org.springframework.boot.configurationsample.simple.ClassWithNestedProperties; @@ -508,4 +509,11 @@ class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGene assertThat(metadata).doesNotHave(Metadata.withProperty("record-with-getter.bravo")); } + @Test + void shouldNotMarkDbcp2UsernameOrPasswordAsDeprecated() { + ConfigurationMetadata metadata = compile(Dbcp2Configuration.class); + assertThat(metadata).has(Metadata.withProperty("spring.datasource.dbcp2.username").withNoDeprecation()); + assertThat(metadata).has(Metadata.withProperty("spring.datasource.dbcp2.password").withNoDeprecation()); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/deprecation/Dbcp2Configuration.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/deprecation/Dbcp2Configuration.java new file mode 100644 index 0000000000..556fd05531 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/deprecation/Dbcp2Configuration.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2024 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.configurationsample.deprecation; + +import org.apache.commons.dbcp2.BasicDataSource; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +/** + * Test configuration for DBCP2 {@link BasicDataSource}. + * + * @author Moritz Halbritter + */ +public class Dbcp2Configuration { + + @ConfigurationProperties(prefix = "spring.datasource.dbcp2") + BasicDataSource basicDataSource() { + return new BasicDataSource(); + } + +}