Add processor to generate configuration meta-data
Adds an annotation processor to generates a JSON meta-data file at compile time from @ConfigurationProperties items. Each meta-data file can include an array or 'properties' and 'groups'. A 'property' is a single item that may appear in a Spring Boot 'application.properties' file with a given value. For example, 'server.port' and 'server.context-path' are properties. Each property may optionally include 'type' and 'description' attributes to provide the data type (e.g. `java.lang.Integer`, `java.lang.String`) and some short documentation (taken from the field javadoc) about what the property is for. For consistency, the type of a primitive is translated to its wrapper counterpart, i.e. `boolean` becomes `java.lang.Boolean`. A 'group' provides a higher level grouping of properties. For example the 'server.port' and 'server.context-path' properties are in the 'server' group. Both 'property' and 'group' items may additional have 'sourceType' and 'sourceMethod' attributes to indicate the source that contributed them. Users may use `META-INF/additional-spring-configuration-metadata.json` to manually provide additionally meta-data that is not covered by @ConfigurationProperties objects. The contents of this file will be read and merged with harvested items. The complete meta-data file is finally written to `META-INF/spring-configuration-metadata.json`. See gh-1001pull/1815/head
parent
45b579c439
commit
884c058e57
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-tools</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<name>Spring Boot Configuration Processor</name>
|
||||
<description>Spring Boot Configuration Processor</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Runs in the compiler so dependencies should stick to the bare minimum -->
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- Ensure own annotation processor doens't kick in -->
|
||||
<proc>none</proc>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.Processor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
||||
import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
|
||||
|
||||
/**
|
||||
* Annotation {@link Processor} that writes meta-data file for
|
||||
* {@code @ConfigurationProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@SupportedAnnotationTypes({ ConfigurationMetadataAnnotationProcessor.CONFIGURATION_PROPERTIES_ANNOTATION })
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_6)
|
||||
public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor {
|
||||
|
||||
static final String CONFIGURATION_PROPERTIES_ANNOTATION = "org.springframework.boot."
|
||||
+ "context.properties.ConfigurationProperties";
|
||||
|
||||
private ConfigurationMetadata metadata;
|
||||
|
||||
private TypeUtils typeUtils;
|
||||
|
||||
protected String configurationPropertiesAnnotation() {
|
||||
return CONFIGURATION_PROPERTIES_ANNOTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment env) {
|
||||
super.init(env);
|
||||
this.metadata = new ConfigurationMetadata();
|
||||
this.typeUtils = new TypeUtils(env);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations,
|
||||
RoundEnvironment roundEnv) {
|
||||
for (TypeElement annotation : annotations) {
|
||||
for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
|
||||
processElement(element);
|
||||
}
|
||||
}
|
||||
if (roundEnv.processingOver()) {
|
||||
writeMetaData(this.metadata);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processElement(Element element) {
|
||||
AnnotationMirror annotation = getAnnotation(element,
|
||||
configurationPropertiesAnnotation());
|
||||
String prefix = getPrefix(annotation);
|
||||
if (annotation != null) {
|
||||
if (element instanceof TypeElement) {
|
||||
processAnnotatedTypeElement(prefix, (TypeElement) element);
|
||||
}
|
||||
else if (element instanceof ExecutableElement) {
|
||||
processExecutableElement(prefix, (ExecutableElement) element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnnotatedTypeElement(String prefix, TypeElement element) {
|
||||
String type = this.typeUtils.getType(element);
|
||||
this.metadata.add(ItemMetadata.newGroup(prefix, type, type, null));
|
||||
processTypeElement(prefix, element);
|
||||
}
|
||||
|
||||
private void processExecutableElement(String prefix, ExecutableElement element) {
|
||||
if (element.getModifiers().contains(Modifier.PUBLIC)
|
||||
&& (TypeKind.VOID != element.getReturnType().getKind())) {
|
||||
Element returns = this.processingEnv.getTypeUtils().asElement(
|
||||
element.getReturnType());
|
||||
if (returns instanceof TypeElement) {
|
||||
this.metadata.add(ItemMetadata.newGroup(prefix,
|
||||
this.typeUtils.getType(returns),
|
||||
this.typeUtils.getType(element.getEnclosingElement()),
|
||||
element.toString()));
|
||||
processTypeElement(prefix, (TypeElement) returns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processTypeElement(String prefix, TypeElement element) {
|
||||
TypeElementMembers members = new TypeElementMembers(this.processingEnv, element);
|
||||
processSimpleTypes(prefix, element, members);
|
||||
processNestedTypes(prefix, element, members);
|
||||
}
|
||||
|
||||
private void processSimpleTypes(String prefix, TypeElement element,
|
||||
TypeElementMembers members) {
|
||||
for (Map.Entry<String, ExecutableElement> entry : members.getPublicGetters()
|
||||
.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
ExecutableElement getter = entry.getValue();
|
||||
ExecutableElement setter = members.getPublicSetters().get(name);
|
||||
VariableElement field = members.getFields().get(name);
|
||||
if (setter != null
|
||||
|| this.typeUtils.isCollectionOrMap(getter.getReturnType())) {
|
||||
String dataType = this.typeUtils.getType(getter.getReturnType());
|
||||
String sourceType = this.typeUtils.getType(element);
|
||||
String description = this.typeUtils.getJavaDoc(field);
|
||||
this.metadata.add(ItemMetadata.newProperty(prefix, name, dataType,
|
||||
sourceType, null, description));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNestedTypes(String prefix, TypeElement element,
|
||||
TypeElementMembers members) {
|
||||
for (Map.Entry<String, ExecutableElement> entry : members.getPublicGetters()
|
||||
.entrySet()) {
|
||||
ExecutableElement getter = entry.getValue();
|
||||
Element returnType = this.processingEnv.getTypeUtils().asElement(
|
||||
getter.getReturnType());
|
||||
AnnotationMirror annotation = getAnnotation(getter,
|
||||
configurationPropertiesAnnotation());
|
||||
if (returnType != null && returnType instanceof TypeElement
|
||||
&& annotation == null) {
|
||||
TypeElement returns = (TypeElement) returnType;
|
||||
if (this.typeUtils.isEnclosedIn(returnType, element)) {
|
||||
String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix,
|
||||
entry.getKey());
|
||||
this.metadata.add(ItemMetadata.newGroup(nestedPrefix,
|
||||
this.typeUtils.getType(returns),
|
||||
this.typeUtils.getType(element), getter.toString()));
|
||||
processTypeElement(nestedPrefix, returns);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationMirror getAnnotation(Element element, String type) {
|
||||
for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
|
||||
if (type.equals(annotation.getAnnotationType().toString())) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getPrefix(AnnotationMirror annotation) {
|
||||
Map<String, Object> elementValues = getAnnotationElementValues(annotation);
|
||||
Object prefix = elementValues.get("prefix");
|
||||
if (prefix != null && !"".equals(prefix)) {
|
||||
return (String) prefix;
|
||||
}
|
||||
Object value = elementValues.get("value");
|
||||
if (value != null && !"".equals(value)) {
|
||||
return (String) value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, Object> getAnnotationElementValues(AnnotationMirror annotation) {
|
||||
Map<String, Object> values = new LinkedHashMap<String, Object>();
|
||||
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotation
|
||||
.getElementValues().entrySet()) {
|
||||
values.put(entry.getKey().getSimpleName().toString(), entry.getValue()
|
||||
.getValue());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
protected void writeMetaData(ConfigurationMetadata metadata) {
|
||||
metadata = mergeManualMetadata(metadata);
|
||||
try {
|
||||
FileObject resource = this.processingEnv.getFiler().createResource(
|
||||
StandardLocation.CLASS_OUTPUT, "",
|
||||
"META-INF/spring-configuration-metadata.json");
|
||||
OutputStream outputStream = resource.openOutputStream();
|
||||
try {
|
||||
new JsonMarshaller().write(metadata, outputStream);
|
||||
}
|
||||
finally {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurationMetadata mergeManualMetadata(ConfigurationMetadata metadata) {
|
||||
try {
|
||||
FileObject manualMetadata = this.processingEnv.getFiler().getResource(
|
||||
StandardLocation.CLASS_PATH, "",
|
||||
"META-INF/additional-spring-configuration-metadata.json");
|
||||
InputStream inputStream = manualMetadata.openInputStream();
|
||||
try {
|
||||
ConfigurationMetadata merged = new ConfigurationMetadata(metadata);
|
||||
try {
|
||||
merged.addAll(new JsonMarshaller().read(inputStream));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
|
||||
/**
|
||||
* Provides access to relevant {@link TypeElement} members.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class TypeElementMembers {
|
||||
|
||||
private static final String OBJECT_CLASS_NAME = Object.class.getName();
|
||||
|
||||
private final ProcessingEnvironment env;
|
||||
|
||||
private final Map<String, VariableElement> fields = new LinkedHashMap<String, VariableElement>();
|
||||
|
||||
private final Map<String, ExecutableElement> publicGetters = new LinkedHashMap<String, ExecutableElement>();
|
||||
|
||||
private final Map<String, ExecutableElement> publicSetters = new LinkedHashMap<String, ExecutableElement>();
|
||||
|
||||
public TypeElementMembers(ProcessingEnvironment env, TypeElement element) {
|
||||
this.env = env;
|
||||
process(element);
|
||||
}
|
||||
|
||||
private void process(TypeElement element) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(element
|
||||
.getEnclosedElements())) {
|
||||
processMethod(method);
|
||||
}
|
||||
for (VariableElement field : ElementFilter
|
||||
.fieldsIn(element.getEnclosedElements())) {
|
||||
processField(field);
|
||||
}
|
||||
Element superType = this.env.getTypeUtils().asElement(element.getSuperclass());
|
||||
if (superType != null && superType instanceof TypeElement
|
||||
&& !OBJECT_CLASS_NAME.equals(superType.toString())) {
|
||||
process((TypeElement) superType);
|
||||
}
|
||||
}
|
||||
|
||||
private void processMethod(ExecutableElement method) {
|
||||
if (method.getModifiers().contains(Modifier.PUBLIC)) {
|
||||
String name = method.getSimpleName().toString();
|
||||
if (isGetter(method) && !this.publicGetters.containsKey(name)) {
|
||||
this.publicGetters.put(getAccessorName(name), method);
|
||||
}
|
||||
else if (isSetter(method) && !this.publicSetters.containsKey(name)) {
|
||||
this.publicSetters.put(getAccessorName(name), method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGetter(ExecutableElement method) {
|
||||
String name = method.getSimpleName().toString();
|
||||
return (name.startsWith("get") || name.startsWith("is"))
|
||||
&& method.getParameters().isEmpty()
|
||||
&& (TypeKind.VOID != method.getReturnType().getKind());
|
||||
}
|
||||
|
||||
private boolean isSetter(ExecutableElement method) {
|
||||
final String name = method.getSimpleName().toString();
|
||||
return name.startsWith("set") && method.getParameters().size() == 1
|
||||
&& (TypeKind.VOID == method.getReturnType().getKind());
|
||||
}
|
||||
|
||||
private String getAccessorName(String methodName) {
|
||||
String name = methodName.startsWith("is") ? methodName.substring(2) : methodName
|
||||
.substring(3);
|
||||
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||
return name;
|
||||
}
|
||||
|
||||
private void processField(VariableElement field) {
|
||||
String name = field.getSimpleName().toString();
|
||||
if (!this.fields.containsKey(name)) {
|
||||
this.fields.put(name, field);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, VariableElement> getFields() {
|
||||
return Collections.unmodifiableMap(this.fields);
|
||||
}
|
||||
|
||||
public Map<String, ExecutableElement> getPublicGetters() {
|
||||
return Collections.unmodifiableMap(this.publicGetters);
|
||||
}
|
||||
|
||||
public Map<String, ExecutableElement> getPublicSetters() {
|
||||
return Collections.unmodifiableMap(this.publicSetters);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
/**
|
||||
* Type Utilities.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class TypeUtils {
|
||||
|
||||
private static final Map<TypeKind, Class<?>> PRIMITIVE_WRAPPERS;
|
||||
static {
|
||||
Map<TypeKind, Class<?>> wrappers = new HashMap<TypeKind, Class<?>>();
|
||||
wrappers.put(TypeKind.BOOLEAN, Boolean.class);
|
||||
wrappers.put(TypeKind.BYTE, Byte.class);
|
||||
wrappers.put(TypeKind.CHAR, Character.class);
|
||||
wrappers.put(TypeKind.DOUBLE, Double.class);
|
||||
wrappers.put(TypeKind.FLOAT, Float.class);
|
||||
wrappers.put(TypeKind.INT, Integer.class);
|
||||
wrappers.put(TypeKind.LONG, Long.class);
|
||||
wrappers.put(TypeKind.SHORT, Short.class);
|
||||
PRIMITIVE_WRAPPERS = Collections.unmodifiableMap(wrappers);
|
||||
}
|
||||
|
||||
private final ProcessingEnvironment env;
|
||||
|
||||
private final TypeMirror collectionType;
|
||||
|
||||
private final TypeMirror mapType;
|
||||
|
||||
public TypeUtils(ProcessingEnvironment env) {
|
||||
this.env = env;
|
||||
Types types = env.getTypeUtils();
|
||||
WildcardType wc = types.getWildcardType(null, null);
|
||||
this.collectionType = types.getDeclaredType(this.env.getElementUtils()
|
||||
.getTypeElement(Collection.class.getName()), wc);
|
||||
this.mapType = types.getDeclaredType(
|
||||
this.env.getElementUtils().getTypeElement(Map.class.getName()), wc, wc);
|
||||
|
||||
}
|
||||
|
||||
public String getType(Element element) {
|
||||
return getType(element == null ? null : element.asType());
|
||||
}
|
||||
|
||||
public String getType(TypeMirror type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> wrapper = PRIMITIVE_WRAPPERS.get(type.getKind());
|
||||
if (wrapper != null) {
|
||||
return wrapper.getName();
|
||||
}
|
||||
if (type instanceof DeclaredType) {
|
||||
DeclaredType declaredType = (DeclaredType) type;
|
||||
Element enclosingElement = declaredType.asElement().getEnclosingElement();
|
||||
if (enclosingElement != null && enclosingElement instanceof TypeElement) {
|
||||
return getType(enclosingElement) + "$"
|
||||
+ declaredType.asElement().getSimpleName().toString();
|
||||
}
|
||||
}
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public boolean isCollectionOrMap(TypeMirror type) {
|
||||
return this.env.getTypeUtils().isAssignable(type, this.collectionType)
|
||||
|| this.env.getTypeUtils().isAssignable(type, this.mapType);
|
||||
}
|
||||
|
||||
public boolean isEnclosedIn(Element candidate, TypeElement element) {
|
||||
if (candidate == null || element == null) {
|
||||
return false;
|
||||
}
|
||||
if (candidate.equals(element)) {
|
||||
return true;
|
||||
}
|
||||
return isEnclosedIn(candidate.getEnclosingElement(), element);
|
||||
}
|
||||
|
||||
public String getJavaDoc(Element element) {
|
||||
String javadoc = (element == null ? null : this.env.getElementUtils()
|
||||
.getDocComment(element));
|
||||
if (javadoc != null) {
|
||||
javadoc = javadoc.trim();
|
||||
}
|
||||
return ("".equals(javadoc) ? null : javadoc);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.metadata;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Configuration meta-data.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
* @see ItemMetadata
|
||||
*/
|
||||
public class ConfigurationMetadata {
|
||||
|
||||
private final List<ItemMetadata> items;
|
||||
|
||||
public ConfigurationMetadata() {
|
||||
this.items = new ArrayList<ItemMetadata>();
|
||||
}
|
||||
|
||||
public ConfigurationMetadata(ConfigurationMetadata metadata) {
|
||||
this.items = new ArrayList<ItemMetadata>(metadata.getItems());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item meta-data.
|
||||
* @param itemMetadata the meta-data to add
|
||||
*/
|
||||
public void add(ItemMetadata itemMetadata) {
|
||||
this.items.add(itemMetadata);
|
||||
Collections.sort(this.items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all properties from another {@link ConfigurationMetadata}.
|
||||
* @param metadata the {@link ConfigurationMetadata} instance to merge
|
||||
*/
|
||||
public void addAll(ConfigurationMetadata metadata) {
|
||||
this.items.addAll(metadata.getItems());
|
||||
Collections.sort(this.items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the meta-data properties.
|
||||
*/
|
||||
public List<ItemMetadata> getItems() {
|
||||
return Collections.unmodifiableList(this.items);
|
||||
}
|
||||
|
||||
public static String nestedPrefix(String prefix, String name) {
|
||||
String nestedPrefix = (prefix == null ? "" : prefix);
|
||||
String dashedName = toDashedCase(name);
|
||||
nestedPrefix += ("".equals(nestedPrefix) ? dashedName : "." + dashedName);
|
||||
return nestedPrefix;
|
||||
}
|
||||
|
||||
static String toDashedCase(String name) {
|
||||
StringBuilder dashed = new StringBuilder();
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char c = name.charAt(i);
|
||||
if (Character.isUpperCase(c) && dashed.length() > 0) {
|
||||
dashed.append("-");
|
||||
}
|
||||
dashed.append(Character.toLowerCase(c));
|
||||
}
|
||||
return dashed.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.metadata;
|
||||
|
||||
/**
|
||||
* A group or property meta-data item from some {@link ConfigurationMetadata}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
* @see ConfigurationMetadata
|
||||
*/
|
||||
public class ItemMetadata implements Comparable<ItemMetadata> {
|
||||
|
||||
private final ItemType itemType;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final String sourceType;
|
||||
|
||||
private String sourceMethod;
|
||||
|
||||
ItemMetadata(ItemType itemType, String prefix, String name, String type,
|
||||
String sourceType, String sourceMethod, String description) {
|
||||
super();
|
||||
this.itemType = itemType;
|
||||
this.name = buildName(prefix, name);
|
||||
this.type = type;
|
||||
this.sourceType = sourceType;
|
||||
this.sourceMethod = sourceMethod;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
private String buildName(String prefix, String name) {
|
||||
while (prefix != null && prefix.endsWith(".")) {
|
||||
prefix = prefix.substring(0, prefix.length() - 1);
|
||||
}
|
||||
StringBuilder fullName = new StringBuilder(prefix == null ? "" : prefix);
|
||||
if (fullName.length() > 0 && name != null) {
|
||||
fullName.append(".");
|
||||
}
|
||||
fullName.append(name == null ? "" : ConfigurationMetadata.toDashedCase(name));
|
||||
return fullName.toString();
|
||||
}
|
||||
|
||||
public boolean isOfItemType(ItemType itemType) {
|
||||
return this.itemType == itemType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String getSourceType() {
|
||||
return this.sourceType;
|
||||
}
|
||||
|
||||
public String getSourceMethod() {
|
||||
return this.sourceMethod;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder string = new StringBuilder(this.name);
|
||||
buildToStringProperty(string, "type", this.type);
|
||||
buildToStringProperty(string, "sourceType", this.sourceType);
|
||||
buildToStringProperty(string, "description", this.description);
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
protected final void buildToStringProperty(StringBuilder string, String property,
|
||||
Object value) {
|
||||
if (value != null) {
|
||||
string.append(" ").append(property).append(":").append(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ItemMetadata o) {
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
public static ItemMetadata newGroup(String name, String type, String sourceType,
|
||||
String sourceMethod) {
|
||||
return new ItemMetadata(ItemType.GROUP, name, null, type, sourceType,
|
||||
sourceMethod, null);
|
||||
}
|
||||
|
||||
public static ItemMetadata newProperty(String prefix, String name, String type,
|
||||
String sourceType, String sourceMethod, String description) {
|
||||
return new ItemMetadata(ItemType.PROPERTY, prefix, name, type, sourceType,
|
||||
sourceMethod, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* The item type.
|
||||
*/
|
||||
public static enum ItemType {
|
||||
GROUP, PROPERTY
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.metadata;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata.ItemType;
|
||||
|
||||
/**
|
||||
* Marshaller to write {@link ConfigurationMetadata} as JSON.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class JsonMarshaller {
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private static final int BUFFER_SIZE = 4098;
|
||||
|
||||
public void write(ConfigurationMetadata metadata, OutputStream outputStream)
|
||||
throws IOException {
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("groups", toJsonArray(metadata, ItemType.GROUP));
|
||||
object.put("properties", toJsonArray(metadata, ItemType.PROPERTY));
|
||||
outputStream.write(object.toString(2).getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private JSONArray toJsonArray(ConfigurationMetadata metadata, ItemType itemType) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (ItemMetadata item : metadata.getItems()) {
|
||||
if (item.isOfItemType(itemType)) {
|
||||
jsonArray.put(toJsonObject(item));
|
||||
}
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
private JSONObject toJsonObject(ItemMetadata item) {
|
||||
JSONObject jsonObject = new JSONOrderedObject();
|
||||
jsonObject.put("name", item.getName());
|
||||
putIfPresent(jsonObject, "type", item.getType());
|
||||
putIfPresent(jsonObject, "description", item.getDescription());
|
||||
putIfPresent(jsonObject, "sourceType", item.getSourceType());
|
||||
putIfPresent(jsonObject, "sourceMethod", item.getSourceMethod());
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private void putIfPresent(JSONObject jsonObject, String name, Object value) {
|
||||
if (value != null) {
|
||||
jsonObject.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationMetadata read(InputStream inputStream) throws IOException {
|
||||
ConfigurationMetadata metadata = new ConfigurationMetadata();
|
||||
JSONObject object = new JSONObject(toString(inputStream));
|
||||
JSONArray groups = object.optJSONArray("groups");
|
||||
if (groups != null) {
|
||||
for (int i = 0; i < groups.length(); i++) {
|
||||
metadata.add(toItemMetadata((JSONObject) groups.get(i), ItemType.GROUP));
|
||||
}
|
||||
}
|
||||
JSONArray properties = object.optJSONArray("properties");
|
||||
if (properties != null) {
|
||||
for (int i = 0; i < properties.length(); i++) {
|
||||
metadata.add(toItemMetadata((JSONObject) properties.get(i),
|
||||
ItemType.PROPERTY));
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private ItemMetadata toItemMetadata(JSONObject object, ItemType itemType) {
|
||||
String name = object.getString("name");
|
||||
String type = object.optString("type", null);
|
||||
String description = object.optString("description", null);
|
||||
String sourceType = object.optString("sourceType", null);
|
||||
String sourceMethod = object.optString("sourceMethod", null);
|
||||
return new ItemMetadata(itemType, name, null, type, sourceType, sourceMethod,
|
||||
description);
|
||||
}
|
||||
|
||||
private String toString(InputStream inputStream) throws IOException {
|
||||
StringBuilder out = new StringBuilder();
|
||||
InputStreamReader reader = new InputStreamReader(inputStream, UTF_8);
|
||||
char[] buffer = new char[BUFFER_SIZE];
|
||||
int bytesRead;
|
||||
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||
out.append(buffer, 0, bytesRead);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension to {@link JSONObject} that remembers the order of inserts.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class JSONOrderedObject extends JSONObject {
|
||||
|
||||
private Set<String> keys = new LinkedHashSet<String>();
|
||||
|
||||
@Override
|
||||
public JSONObject put(String key, Object value) throws JSONException {
|
||||
this.keys.add(key);
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set keySet() {
|
||||
return this.keys;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor
|
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||
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.HierarchicalProperties;
|
||||
import org.springframework.boot.configurationsample.simple.NotAnnotated;
|
||||
import org.springframework.boot.configurationsample.simple.SimpleCollectionProperties;
|
||||
import org.springframework.boot.configurationsample.simple.SimplePrefixValueProperties;
|
||||
import org.springframework.boot.configurationsample.simple.SimpleProperties;
|
||||
import org.springframework.boot.configurationsample.simple.SimpleTypeProperties;
|
||||
import org.springframework.boot.configurationsample.specific.InnerClassAnnotatedGetterConfig;
|
||||
import org.springframework.boot.configurationsample.specific.InnerClassProperties;
|
||||
import org.springframework.boot.configurationsample.specific.InnerClassRootConfig;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.containsGroup;
|
||||
import static org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.containsProperty;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationMetadataAnnotationProcessor}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ConfigurationMetadataAnnotationProcessorTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void notAnnotated() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(NotAnnotated.class);
|
||||
assertThat("No config metadata file should have been generated when "
|
||||
+ "no metadata is discovered", metadata, nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleProperties() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
||||
assertThat(metadata, containsGroup("simple").fromSource(SimpleProperties.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("simple.the-name", String.class).fromSource(
|
||||
SimpleProperties.class).withDescription(
|
||||
"The name of this simple properties."));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("simple.flag", Boolean.class).fromSource(
|
||||
SimpleProperties.class).withDescription("A simple flag."));
|
||||
assertThat(metadata, containsProperty("simple.comparator"));
|
||||
assertThat(metadata, not(containsProperty("simple.counter")));
|
||||
assertThat(metadata, not(containsProperty("simple.size")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simplePrefixValueProperties() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(SimplePrefixValueProperties.class);
|
||||
assertThat(metadata,
|
||||
containsGroup("simple").fromSource(SimplePrefixValueProperties.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("simple.name", String.class).fromSource(
|
||||
SimplePrefixValueProperties.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleTypeProperties() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(SimpleTypeProperties.class);
|
||||
assertThat(metadata,
|
||||
containsGroup("simple.type").fromSource(SimpleTypeProperties.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-string", String.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-byte", Byte.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-byte", Byte.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-char", Character.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-char", Character.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-boolean", Boolean.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-boolean", Boolean.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-short", Short.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-short", Short.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-integer", Integer.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-integer", Integer.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-long", Long.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-long", Long.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-double", Double.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-double", Double.class));
|
||||
assertThat(metadata, containsProperty("simple.type.my-float", Float.class));
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.type.my-primitive-float", Float.class));
|
||||
assertThat(metadata.getItems().size(), equalTo(18));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hierarchicalProperties() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(HierarchicalProperties.class);
|
||||
assertThat(metadata,
|
||||
containsGroup("hierarchical").fromSource(HierarchicalProperties.class));
|
||||
assertThat(metadata, containsProperty("hierarchical.first", String.class)
|
||||
.fromSource(HierarchicalProperties.class));
|
||||
assertThat(metadata, containsProperty("hierarchical.second", String.class)
|
||||
.fromSource(HierarchicalProperties.class));
|
||||
assertThat(metadata, containsProperty("hierarchical.third", String.class)
|
||||
.fromSource(HierarchicalProperties.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseCollectionConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(SimpleCollectionProperties.class);
|
||||
// getter and setter
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("collection.integers-to-names",
|
||||
"java.util.Map<java.lang.Integer,java.lang.String>"));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("collection.longs",
|
||||
"java.util.Collection<java.lang.Long>"));
|
||||
assertThat(metadata,
|
||||
containsProperty("collection.floats", "java.util.List<java.lang.Float>"));
|
||||
// getter only
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("collection.names-to-integers",
|
||||
"java.util.Map<java.lang.String,java.lang.Integer>"));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("collection.bytes",
|
||||
"java.util.Collection<java.lang.Byte>"));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("collection.doubles", "java.util.List<java.lang.Double>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleMethodConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(SimpleMethodConfig.class);
|
||||
assertThat(metadata, containsGroup("foo").fromSource(SimpleMethodConfig.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("foo.name", String.class).fromSource(
|
||||
SimpleMethodConfig.Foo.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("foo.flag", Boolean.class).fromSource(
|
||||
SimpleMethodConfig.Foo.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidMethodConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(InvalidMethodConfig.class);
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("something.name", String.class).fromSource(
|
||||
InvalidMethodConfig.class));
|
||||
assertThat(metadata, not(containsProperty("invalid.name")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodAndClassConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(MethodAndClassConfig.class);
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("conflict.name", String.class).fromSource(
|
||||
MethodAndClassConfig.Foo.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("conflict.flag", Boolean.class).fromSource(
|
||||
MethodAndClassConfig.Foo.class));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsProperty("conflict.value", String.class).fromSource(
|
||||
MethodAndClassConfig.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyTypeMethodConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(EmptyTypeMethodConfig.class);
|
||||
assertThat(metadata, not(containsProperty("something.foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void innerClassRootConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(InnerClassRootConfig.class);
|
||||
assertThat(metadata, containsProperty("config.name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void innerClassProperties() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(InnerClassProperties.class);
|
||||
assertThat(metadata,
|
||||
containsGroup("config").fromSource(InnerClassProperties.class));
|
||||
assertThat(metadata,
|
||||
containsGroup("config.first").ofType(InnerClassProperties.Foo.class)
|
||||
.fromSource(InnerClassProperties.class));
|
||||
assertThat(metadata, containsProperty("config.first.name"));
|
||||
assertThat(metadata, containsProperty("config.first.bar.name"));
|
||||
assertThat(metadata,
|
||||
containsProperty("config.the-second", InnerClassProperties.Foo.class)
|
||||
.fromSource(InnerClassProperties.class));
|
||||
assertThat(metadata, containsProperty("config.the-second.name"));
|
||||
assertThat(metadata, containsProperty("config.the-second.bar.name"));
|
||||
assertThat(
|
||||
metadata,
|
||||
containsGroup("config.third").ofType(
|
||||
InnerClassProperties.SimplePojo.class).fromSource(
|
||||
InnerClassProperties.class));
|
||||
assertThat(metadata, containsProperty("config.third.value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void innerClassAnnotatedGetterConfig() throws Exception {
|
||||
ConfigurationMetadata metadata = compile(InnerClassAnnotatedGetterConfig.class);
|
||||
assertThat(metadata, containsProperty("specific.value"));
|
||||
assertThat(metadata, containsProperty("foo.name"));
|
||||
assertThat(metadata, not(containsProperty("specific.foo")));
|
||||
}
|
||||
|
||||
private ConfigurationMetadata compile(Class<?>... types) throws IOException {
|
||||
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor();
|
||||
new TestCompiler(this.temporaryFolder).getTask(types).call(processor);
|
||||
return processor.getMetadata();
|
||||
}
|
||||
|
||||
@SupportedAnnotationTypes({ TestConfigurationMetadataAnnotationProcessor.CONFIGURATION_PROPERTIES_ANNOTATION })
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_6)
|
||||
private static class TestConfigurationMetadataAnnotationProcessor extends
|
||||
ConfigurationMetadataAnnotationProcessor {
|
||||
|
||||
static final String CONFIGURATION_PROPERTIES_ANNOTATION = "org.springframework.boot.configurationsample.ConfigurationProperties";
|
||||
|
||||
private ConfigurationMetadata metadata;
|
||||
|
||||
@Override
|
||||
protected String configurationPropertiesAnnotation() {
|
||||
return CONFIGURATION_PROPERTIES_ANNOTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeMetaData(ConfigurationMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ConfigurationMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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 org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata.ItemType;
|
||||
|
||||
/**
|
||||
* Hamcrest {@link Matcher} to help test {@link ConfigurationMetadata}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ConfigurationMetadataMatchers {
|
||||
|
||||
public static ContainsItemMatcher containsGroup(String name) {
|
||||
return new ContainsItemMatcher(ItemType.GROUP, name);
|
||||
}
|
||||
|
||||
public static ContainsItemMatcher containsGroup(String name, Class<?> type) {
|
||||
return new ContainsItemMatcher(ItemType.GROUP, name).ofType(type);
|
||||
}
|
||||
|
||||
public static ContainsItemMatcher containsGroup(String name, String type) {
|
||||
return new ContainsItemMatcher(ItemType.GROUP, name).ofDataType(type);
|
||||
}
|
||||
|
||||
public static ContainsItemMatcher containsProperty(String name) {
|
||||
return new ContainsItemMatcher(ItemType.PROPERTY, name);
|
||||
}
|
||||
|
||||
public static ContainsItemMatcher containsProperty(String name, Class<?> type) {
|
||||
return new ContainsItemMatcher(ItemType.PROPERTY, name).ofType(type);
|
||||
}
|
||||
|
||||
public static ContainsItemMatcher containsProperty(String name, String type) {
|
||||
return new ContainsItemMatcher(ItemType.PROPERTY, name).ofDataType(type);
|
||||
}
|
||||
|
||||
public static class ContainsItemMatcher extends BaseMatcher<ConfigurationMetadata> {
|
||||
|
||||
private final ItemType itemType;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final Class<?> sourceType;
|
||||
|
||||
private final String description;
|
||||
|
||||
public ContainsItemMatcher(ItemType itemType, String name) {
|
||||
this(itemType, name, null, null, null);
|
||||
}
|
||||
|
||||
public ContainsItemMatcher(ItemType itemType, String name, String type,
|
||||
Class<?> sourceType, String description) {
|
||||
this.itemType = itemType;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.sourceType = sourceType;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
ConfigurationMetadata metadata = (ConfigurationMetadata) item;
|
||||
ItemMetadata itemMetadata = getFirstPropertyWithName(metadata, this.name);
|
||||
if (itemMetadata == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.type != null && !this.type.equals(itemMetadata.getType())) {
|
||||
return false;
|
||||
}
|
||||
if (this.sourceType != null
|
||||
&& !this.sourceType.getName().equals(itemMetadata.getSourceType())) {
|
||||
return false;
|
||||
}
|
||||
if (this.description != null
|
||||
&& !this.description.equals(itemMetadata.getDescription())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
ConfigurationMetadata metadata = (ConfigurationMetadata) item;
|
||||
ItemMetadata property = getFirstPropertyWithName(metadata, this.name);
|
||||
if (property == null) {
|
||||
description.appendText("missing property " + this.name);
|
||||
}
|
||||
else {
|
||||
description.appendText("was property ").appendValue(property);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("metadata containing " + this.name);
|
||||
if (this.type != null) {
|
||||
description.appendText(" dataType ").appendValue(this.type);
|
||||
}
|
||||
if (this.sourceType != null) {
|
||||
description.appendText(" sourceType ").appendValue(this.sourceType);
|
||||
}
|
||||
if (this.description != null) {
|
||||
description.appendText(" description ").appendValue(this.description);
|
||||
}
|
||||
}
|
||||
|
||||
public ContainsItemMatcher ofType(Class<?> dataType) {
|
||||
return new ContainsItemMatcher(this.itemType, this.name, dataType.getName(),
|
||||
this.sourceType, this.description);
|
||||
}
|
||||
|
||||
public ContainsItemMatcher ofDataType(String dataType) {
|
||||
return new ContainsItemMatcher(this.itemType, this.name, dataType,
|
||||
this.sourceType, this.description);
|
||||
}
|
||||
|
||||
public ContainsItemMatcher fromSource(Class<?> sourceType) {
|
||||
return new ContainsItemMatcher(this.itemType, this.name, this.type,
|
||||
sourceType, this.description);
|
||||
}
|
||||
|
||||
public ContainsItemMatcher withDescription(String description) {
|
||||
return new ContainsItemMatcher(this.itemType, this.name, this.type,
|
||||
this.sourceType, description);
|
||||
}
|
||||
|
||||
private ItemMetadata getFirstPropertyWithName(ConfigurationMetadata metadata,
|
||||
String name) {
|
||||
for (ItemMetadata item : metadata.getItems()) {
|
||||
if (item.isOfItemType(this.itemType) && name.equals(item.getName())) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.annotation.processing.Processor;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
/**
|
||||
* Wrapper to make the {@link JavaCompiler} easier to use in tests.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class TestCompiler {
|
||||
|
||||
private final JavaCompiler compiler;
|
||||
|
||||
private final StandardJavaFileManager fileManager;
|
||||
|
||||
public TestCompiler(TemporaryFolder temporaryFolder) throws IOException {
|
||||
this(ToolProvider.getSystemJavaCompiler(), temporaryFolder);
|
||||
}
|
||||
|
||||
public TestCompiler(JavaCompiler compiler, TemporaryFolder temporaryFolder)
|
||||
throws IOException {
|
||||
this.compiler = compiler;
|
||||
this.fileManager = compiler.getStandardFileManager(null, null, null);
|
||||
Iterable<? extends File> temp = Arrays.asList(temporaryFolder.newFolder());
|
||||
this.fileManager.setLocation(StandardLocation.CLASS_OUTPUT, temp);
|
||||
this.fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, temp);
|
||||
}
|
||||
|
||||
public TestCompilationTask getTask(Class<?>... types) {
|
||||
Iterable<? extends JavaFileObject> javaFileObjects = getJavaFileObjects(types);
|
||||
return new TestCompilationTask(this.compiler.getTask(null, this.fileManager,
|
||||
null, null, null, javaFileObjects));
|
||||
}
|
||||
|
||||
private Iterable<? extends JavaFileObject> getJavaFileObjects(Class<?>... types) {
|
||||
File[] files = new File[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
files[i] = getFile(types[i]);
|
||||
}
|
||||
return this.fileManager.getJavaFileObjects(files);
|
||||
}
|
||||
|
||||
private File getFile(Class<?> type) {
|
||||
return new File("src/test/java/" + type.getName().replace(".", "/") + ".java");
|
||||
}
|
||||
|
||||
/**
|
||||
* A compilation task.
|
||||
*/
|
||||
public static class TestCompilationTask {
|
||||
|
||||
private final CompilationTask task;
|
||||
|
||||
public TestCompilationTask(CompilationTask task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public void call(Processor... processors) {
|
||||
this.task.setProcessors(Arrays.asList(processors));
|
||||
if (!this.task.call()) {
|
||||
throw new IllegalStateException("Compilation failed");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.metadata;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.containsGroup;
|
||||
import static org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.containsProperty;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonMarshaller}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JsonMarshallerTests {
|
||||
|
||||
@Test
|
||||
public void marshallAndUnmarshal() throws IOException {
|
||||
ConfigurationMetadata metadata = new ConfigurationMetadata();
|
||||
metadata.add(ItemMetadata.newProperty("a", "b", StringBuffer.class.getName(),
|
||||
InputStream.class.getName(), "sourceMethod", "desc"));
|
||||
metadata.add(ItemMetadata.newProperty("b.c.d", null, null, null, null, null));
|
||||
metadata.add(ItemMetadata.newProperty("c", null, null, null, null, null));
|
||||
metadata.add(ItemMetadata.newProperty("d", null, null, null, null, null));
|
||||
metadata.add(ItemMetadata.newGroup("d", null, null, null));
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
JsonMarshaller marshaller = new JsonMarshaller();
|
||||
marshaller.write(metadata, outputStream);
|
||||
System.out.println(outputStream);
|
||||
ConfigurationMetadata read = marshaller.read(new ByteArrayInputStream(
|
||||
outputStream.toByteArray()));
|
||||
assertThat(read,
|
||||
containsProperty("a.b", StringBuffer.class).fromSource(InputStream.class)
|
||||
.withDescription("desc"));
|
||||
assertThat(read, containsProperty("b.c.d"));
|
||||
assertThat(read, containsProperty("c"));
|
||||
assertThat(read, containsProperty("d"));
|
||||
assertThat(read, containsGroup("d"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Alternative to Spring Boot's {@code @ConfigurationProperties} for testing (removes the
|
||||
* need for a dependency on the real annotation).
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ConfigurationProperties {
|
||||
|
||||
String value() default "";
|
||||
|
||||
String prefix() default "";
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.method;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Sample for testing method configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties("something")
|
||||
public class EmptyTypeMethodConfig {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ConfigurationProperties("something")
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.method;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Sample for testing invalid method configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "something")
|
||||
public class InvalidMethodConfig {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "invalid")
|
||||
InvalidMethodConfig foo() {
|
||||
return new InvalidMethodConfig();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.method;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Sample for testing mixed method and class configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties("conflict")
|
||||
public class MethodAndClassConfig {
|
||||
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "conflict")
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name;
|
||||
|
||||
private boolean flag;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isFlag() {
|
||||
return this.flag;
|
||||
}
|
||||
|
||||
public void setFlag(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.method;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Sample for testing simple method configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class SimpleMethodConfig {
|
||||
|
||||
@ConfigurationProperties(prefix = "foo")
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name;
|
||||
|
||||
private boolean flag;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isFlag() {
|
||||
return this.flag;
|
||||
}
|
||||
|
||||
public void setFlag(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration properties with inherited values.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "hierarchical")
|
||||
public class HierarchicalProperties extends HierarchicalPropertiesParent {
|
||||
|
||||
private String third;
|
||||
|
||||
public String getThird() {
|
||||
return this.third;
|
||||
}
|
||||
|
||||
public void setThird(String third) {
|
||||
this.third = third;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
/**
|
||||
* Grandparent for {@link HierarchicalProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public abstract class HierarchicalPropertiesGrandparent {
|
||||
|
||||
private String first;
|
||||
|
||||
public String getFirst() {
|
||||
return this.first;
|
||||
}
|
||||
|
||||
public void setFirst(String first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
/**
|
||||
* Parent for {@link HierarchicalProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public abstract class HierarchicalPropertiesParent extends
|
||||
HierarchicalPropertiesGrandparent {
|
||||
|
||||
private String second;
|
||||
|
||||
public String getSecond() {
|
||||
return this.second;
|
||||
}
|
||||
|
||||
public void setSecond(String second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
// Useless override
|
||||
|
||||
@Override
|
||||
public String getFirst() {
|
||||
return super.getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirst(String first) {
|
||||
super.setFirst(first);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
|
||||
/**
|
||||
* This has no annotation on purpose to check that no meta-data is generated.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class NotAnnotated {
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties with collections.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "collection")
|
||||
public class SimpleCollectionProperties {
|
||||
|
||||
private Map<Integer, String> integersToNames;
|
||||
|
||||
private Collection<Long> longs;
|
||||
|
||||
private List<Float> floats;
|
||||
|
||||
private final Map<String, Integer> namesToIntegers = new HashMap<String, Integer>();
|
||||
|
||||
private final Collection<Byte> bytes = new LinkedHashSet<Byte>();
|
||||
|
||||
private final List<Double> doubles = new ArrayList<Double>();
|
||||
|
||||
public Map<Integer, String> getIntegersToNames() {
|
||||
return this.integersToNames;
|
||||
}
|
||||
|
||||
public void setIntegersToNames(Map<Integer, String> integersToNames) {
|
||||
this.integersToNames = integersToNames;
|
||||
}
|
||||
|
||||
public Collection<Long> getLongs() {
|
||||
return this.longs;
|
||||
}
|
||||
|
||||
public void setLongs(Collection<Long> longs) {
|
||||
this.longs = longs;
|
||||
}
|
||||
|
||||
public List<Float> getFloats() {
|
||||
return this.floats;
|
||||
}
|
||||
|
||||
public void setFloats(List<Float> floats) {
|
||||
this.floats = floats;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getNamesToIntegers() {
|
||||
return this.namesToIntegers;
|
||||
}
|
||||
|
||||
public Collection<Byte> getBytes() {
|
||||
return this.bytes;
|
||||
}
|
||||
|
||||
public List<Double> getDoubles() {
|
||||
return this.doubles;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties with a simple prefix.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties("simple")
|
||||
public class SimplePrefixValueProperties {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Simple properties.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "simple")
|
||||
public class SimpleProperties {
|
||||
|
||||
/**
|
||||
* The name of this simple properties.
|
||||
*/
|
||||
private String theName = "boot";
|
||||
|
||||
// isFlag is also detected
|
||||
/**
|
||||
* A simple flag.
|
||||
*/
|
||||
private boolean flag;
|
||||
|
||||
// An interface can still be injected because it might have a converter
|
||||
private Comparator<?> comparator;
|
||||
|
||||
// There is only a getter on this instance but we don't know what to do with it ->
|
||||
// ignored
|
||||
private FeatureDescriptor featureDescriptor;
|
||||
|
||||
// There is only a setter on this "simple" property --> ignored
|
||||
@SuppressWarnings("unused")
|
||||
private Long counter;
|
||||
|
||||
// There is only a getter on this "simple" property --> ignored
|
||||
private Integer size;
|
||||
|
||||
public String getTheName() {
|
||||
return this.theName;
|
||||
}
|
||||
|
||||
public void setTheName(String name) {
|
||||
this.theName = name;
|
||||
}
|
||||
|
||||
public boolean isFlag() {
|
||||
return this.flag;
|
||||
}
|
||||
|
||||
public void setFlag(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public Comparator<?> getComparator() {
|
||||
return this.comparator;
|
||||
}
|
||||
|
||||
public void setComparator(Comparator<?> comparator) {
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
public FeatureDescriptor getFeatureDescriptor() {
|
||||
return this.featureDescriptor;
|
||||
}
|
||||
|
||||
public void setCounter(Long counter) {
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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.simple;
|
||||
|
||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Expose simple types to make sure these are detected properly.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "simple.type")
|
||||
public class SimpleTypeProperties {
|
||||
|
||||
private String myString;
|
||||
|
||||
private Byte myByte;
|
||||
|
||||
private byte myPrimitiveByte;
|
||||
|
||||
private Character myChar;
|
||||
|
||||
private char myPrimitiveChar;
|
||||
|
||||
private Boolean myBoolean;
|
||||
|
||||
private boolean myPrimitiveBoolean;
|
||||
|
||||
private Short myShort;
|
||||
|
||||
private short myPrimitiveShort;
|
||||
|
||||
private Integer myInteger;
|
||||
|
||||
private int myPrimitiveInteger;
|
||||
|
||||
private Long myLong;
|
||||
|
||||
private long myPrimitiveLong;
|
||||
|
||||
private Double myDouble;
|
||||
|
||||
private double myPrimitiveDouble;
|
||||
|
||||
private Float myFloat;
|
||||
|
||||
private float myPrimitiveFloat;
|
||||
|
||||
public String getMyString() {
|
||||
return this.myString;
|
||||
}
|
||||
|
||||
public void setMyString(String myString) {
|
||||
this.myString = myString;
|
||||
}
|
||||
|
||||
public Byte getMyByte() {
|
||||
return this.myByte;
|
||||
}
|
||||
|
||||
public void setMyByte(Byte myByte) {
|
||||
this.myByte = myByte;
|
||||
}
|
||||
|
||||
public byte getMyPrimitiveByte() {
|
||||
return this.myPrimitiveByte;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveByte(byte myPrimitiveByte) {
|
||||
this.myPrimitiveByte = myPrimitiveByte;
|
||||
}
|
||||
|
||||
public Character getMyChar() {
|
||||
return this.myChar;
|
||||
}
|
||||
|
||||
public void setMyChar(Character myChar) {
|
||||
this.myChar = myChar;
|
||||
}
|
||||
|
||||
public char getMyPrimitiveChar() {
|
||||
return this.myPrimitiveChar;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveChar(char myPrimitiveChar) {
|
||||
this.myPrimitiveChar = myPrimitiveChar;
|
||||
}
|
||||
|
||||
public Boolean getMyBoolean() {
|
||||
return this.myBoolean;
|
||||
}
|
||||
|
||||
public void setMyBoolean(Boolean myBoolean) {
|
||||
this.myBoolean = myBoolean;
|
||||
}
|
||||
|
||||
public boolean isMyPrimitiveBoolean() {
|
||||
return this.myPrimitiveBoolean;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveBoolean(boolean myPrimitiveBoolean) {
|
||||
this.myPrimitiveBoolean = myPrimitiveBoolean;
|
||||
}
|
||||
|
||||
public Short getMyShort() {
|
||||
return this.myShort;
|
||||
}
|
||||
|
||||
public void setMyShort(Short myShort) {
|
||||
this.myShort = myShort;
|
||||
}
|
||||
|
||||
public short getMyPrimitiveShort() {
|
||||
return this.myPrimitiveShort;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveShort(short myPrimitiveShort) {
|
||||
this.myPrimitiveShort = myPrimitiveShort;
|
||||
}
|
||||
|
||||
public Integer getMyInteger() {
|
||||
return this.myInteger;
|
||||
}
|
||||
|
||||
public void setMyInteger(Integer myInteger) {
|
||||
this.myInteger = myInteger;
|
||||
}
|
||||
|
||||
public int getMyPrimitiveInteger() {
|
||||
return this.myPrimitiveInteger;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveInteger(int myPrimitiveInteger) {
|
||||
this.myPrimitiveInteger = myPrimitiveInteger;
|
||||
}
|
||||
|
||||
public Long getMyLong() {
|
||||
return this.myLong;
|
||||
}
|
||||
|
||||
public void setMyLong(Long myLong) {
|
||||
this.myLong = myLong;
|
||||
}
|
||||
|
||||
public long getMyPrimitiveLong() {
|
||||
return this.myPrimitiveLong;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveLong(long myPrimitiveLong) {
|
||||
this.myPrimitiveLong = myPrimitiveLong;
|
||||
}
|
||||
|
||||
public Double getMyDouble() {
|
||||
return this.myDouble;
|
||||
}
|
||||
|
||||
public void setMyDouble(Double myDouble) {
|
||||
this.myDouble = myDouble;
|
||||
}
|
||||
|
||||
public double getMyPrimitiveDouble() {
|
||||
return this.myPrimitiveDouble;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveDouble(double myPrimitiveDouble) {
|
||||
this.myPrimitiveDouble = myPrimitiveDouble;
|
||||
}
|
||||
|
||||
public Float getMyFloat() {
|
||||
return this.myFloat;
|
||||
}
|
||||
|
||||
public void setMyFloat(Float myFloat) {
|
||||
this.myFloat = myFloat;
|
||||
}
|
||||
|
||||
public float getMyPrimitiveFloat() {
|
||||
return this.myPrimitiveFloat;
|
||||
}
|
||||
|
||||
public void setMyPrimitiveFloat(float myPrimitiveFloat) {
|
||||
this.myPrimitiveFloat = myPrimitiveFloat;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Demonstrate that a method that exposes a root group within an annotated class is
|
||||
* ignored as it should.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties("specific")
|
||||
public class InnerClassAnnotatedGetterConfig {
|
||||
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ConfigurationProperties("foo")
|
||||
public Foo getFoo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Demonstrate the auto-detection of a inner config classes.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "config")
|
||||
public class InnerClassProperties {
|
||||
|
||||
private final Foo first = new Foo();
|
||||
|
||||
private Foo second = new Foo();
|
||||
|
||||
private final SimplePojo third = new SimplePojo();
|
||||
|
||||
public Foo getFirst() {
|
||||
return this.first;
|
||||
}
|
||||
|
||||
public Foo getTheSecond() {
|
||||
return this.second;
|
||||
}
|
||||
|
||||
public void setTheSecond(Foo second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public SimplePojo getThird() {
|
||||
return this.third;
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name;
|
||||
|
||||
private final Bar bar = new Bar();
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Bar getBar() {
|
||||
return this.bar;
|
||||
}
|
||||
|
||||
public static class Bar {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SimplePojo extends
|
||||
org.springframework.boot.configurationsample.specific.SimplePojo {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Sample with a simple inner class config.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class InnerClassRootConfig {
|
||||
|
||||
@ConfigurationProperties(prefix = "config")
|
||||
static class Config {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* POJO for use with samples.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class SimplePojo {
|
||||
|
||||
private int value;
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue