From 3922808de0d2b1b5e45969334e1c34fd7e89057f Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 2 Dec 2014 17:37:38 +0100 Subject: [PATCH] Add exclusion for well-known property types Previously, any valid property was added to the meta-data of the current group. This can be annoying for types that are not meant to be bound from a simple string value. ClassLoader is one example. A list of well-known types has been added: if the property type matches an element of this list, it is ignored. Fixes gh-2012 --- ...figurationMetadataAnnotationProcessor.java | 5 +- .../TypeElementFilter.java | 52 ++++++++++++ ...ationMetadataAnnotationProcessorTests.java | 33 ++++--- .../specific/ExcludedTypesPojo.java | 85 +++++++++++++++++++ 4 files changed, 160 insertions(+), 15 deletions(-) create mode 100644 spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeElementFilter.java create mode 100644 spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/ExcludedTypesPojo.java diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index 6eef1c5723..124b1d2196 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -75,6 +75,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor private FieldValuesParser fieldValuesParser; + private ElementExcludeFilter elementExcludeFilter = new ElementExcludeFilter(); + protected String configurationPropertiesAnnotation() { return CONFIGURATION_PROPERTIES_ANNOTATION; } @@ -177,10 +179,11 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor VariableElement field = members.getFields().get(name); Element returnType = this.processingEnv.getTypeUtils().asElement( getter.getReturnType()); + boolean isExcluded = this.elementExcludeFilter.isExcluded(returnType); boolean isNested = isNested(returnType, field, element); boolean isCollection = this.typeUtils.isCollectionOrMap(getter .getReturnType()); - if (!isNested && (setter != null || isCollection)) { + if (!isExcluded && !isNested && (setter != null || isCollection)) { String dataType = this.typeUtils.getType(getter.getReturnType()); String sourceType = this.typeUtils.getType(element); String description = this.typeUtils.getJavaDoc(field); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeElementFilter.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeElementFilter.java new file mode 100644 index 0000000000..eb3433fcaf --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeElementFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2014 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 + * + * http://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.configurationprocessor; + +import java.util.HashSet; +import java.util.Set; + +import javax.lang.model.element.Element; + +/** + * Filter to excluded elements that don't make sense to process. + * + * @author Stephane Nicoll + * @since 1.2.0 + */ +class ElementExcludeFilter { + + private final Set excludes = new HashSet(); + + public ElementExcludeFilter() { + add("java.io.Writer"); + add("java.io.PrintWriter"); + add("javax.sql.DataSource"); + add("java.lang.ClassLoader"); + } + + private void add(String className) { + this.excludes.add(className); + } + + public boolean isExcluded(Element element) { + if (element == null) { + return false; + } + return this.excludes.contains(element.toString()); + } + +} diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java index fb2f3510bb..26497113f7 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java @@ -30,7 +30,6 @@ import org.springframework.boot.configurationsample.method.EmptyTypeMethodConfig import org.springframework.boot.configurationsample.method.InvalidMethodConfig; import org.springframework.boot.configurationsample.method.MethodAndClassConfig; import org.springframework.boot.configurationsample.method.SimpleMethodConfig; -import org.springframework.boot.configurationsample.simple.DeprecatedProperties; import org.springframework.boot.configurationsample.simple.HierarchicalProperties; import org.springframework.boot.configurationsample.simple.NotAnnotated; import org.springframework.boot.configurationsample.simple.SimpleCollectionProperties; @@ -38,6 +37,7 @@ import org.springframework.boot.configurationsample.simple.SimplePrefixValueProp import org.springframework.boot.configurationsample.simple.SimpleProperties; import org.springframework.boot.configurationsample.simple.SimpleTypeProperties; import org.springframework.boot.configurationsample.specific.BuilderPojo; +import org.springframework.boot.configurationsample.specific.ExcludedTypesPojo; import org.springframework.boot.configurationsample.specific.InnerClassAnnotatedGetterConfig; import org.springframework.boot.configurationsample.specific.InnerClassProperties; import org.springframework.boot.configurationsample.specific.InnerClassRootConfig; @@ -145,21 +145,16 @@ public class ConfigurationMetadataAnnotationProcessorTests { .fromSource(HierarchicalProperties.class)); } - @SuppressWarnings("deprecation") @Test + @SuppressWarnings("deprecation") public void deprecatedProperties() throws Exception { - ConfigurationMetadata metadata = compile(DeprecatedProperties.class); - assertThat(metadata, containsGroup("deprecated").fromSource(DeprecatedProperties.class)); - assertThat( - metadata, - containsProperty("deprecated.name", String.class) - .fromSource(DeprecatedProperties.class) - .withDeprecated()); - assertThat( - metadata, - containsProperty("deprecated.description", String.class) - .fromSource(DeprecatedProperties.class) - .withDeprecated()); + Class type = org.springframework.boot.configurationsample.simple.DeprecatedProperties.class; + ConfigurationMetadata metadata = compile(type); + assertThat(metadata, containsGroup("deprecated").fromSource(type)); + assertThat(metadata, containsProperty("deprecated.name", String.class) + .fromSource(type).withDeprecated()); + assertThat(metadata, containsProperty("deprecated.description", String.class) + .fromSource(type).withDeprecated()); } @Test @@ -279,6 +274,16 @@ public class ConfigurationMetadataAnnotationProcessorTests { assertThat(metadata, containsProperty("builder.name")); } + @Test + public void excludedTypesPojo() throws IOException { + ConfigurationMetadata metadata = compile(ExcludedTypesPojo.class); + assertThat(metadata, containsProperty("excluded.name")); + assertThat(metadata, not(containsProperty("excluded.class-loader"))); + assertThat(metadata, not(containsProperty("excluded.data-source"))); + assertThat(metadata, not(containsProperty("excluded.print-writer"))); + assertThat(metadata, not(containsProperty("excluded.writer"))); + } + private ConfigurationMetadata compile(Class... types) throws IOException { TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(); new TestCompiler(this.temporaryFolder).getTask(types).call(processor); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/ExcludedTypesPojo.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/ExcludedTypesPojo.java new file mode 100644 index 0000000000..d636ed0ae3 --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/ExcludedTypesPojo.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2014 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 + * + * http://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.specific; + +import java.io.PrintWriter; +import java.io.Writer; + +import javax.sql.DataSource; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +/** + * Sample config with types that should not be added to the meta-data as we have no way to + * bind them from simple strings. + * + * @author Stephane Nicoll + */ +@ConfigurationProperties(prefix = "excluded") +public class ExcludedTypesPojo { + + private String name; + + private ClassLoader classLoader; + + private DataSource dataSource; + + private PrintWriter printWriter; + + private Writer writer; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public ClassLoader getClassLoader() { + return this.classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public DataSource getDataSource() { + return this.dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + public PrintWriter getPrintWriter() { + return this.printWriter; + } + + public void setPrintWriter(PrintWriter printWriter) { + this.printWriter = printWriter; + } + + public Writer getWriter() { + return this.writer; + } + + public void setWriter(Writer writer) { + this.writer = writer; + } + +}