Merge branch 'gh-1001'
This commit is contained in:
		
						commit
						7dd6ae76c6
					
				| 
						 | 
				
			
			@ -151,6 +151,12 @@
 | 
			
		|||
			<artifactId>commons-dbcp</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Annotation processing -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Test -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>ch.qos.logback</groupId>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
{"properties": [
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.git.properties",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "Resource reference to a generated git info properties file."
 | 
			
		||||
  }
 | 
			
		||||
]}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -390,6 +390,12 @@
 | 
			
		|||
			<artifactId>aspectjweaver</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Annotation processing -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Test -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.autoconfigure.jdbc;
 | 
			
		||||
 | 
			
		||||
import com.zaxxer.hikari.HikariDataSource;
 | 
			
		||||
import org.apache.commons.dbcp.BasicDataSource;
 | 
			
		||||
import org.apache.tomcat.jdbc.pool.DataSource;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Expose the metadata of the supported data sources. Only used to harvest
 | 
			
		||||
 * the relevant properties metadata.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class DataSourceConfigMetadata {
 | 
			
		||||
 | 
			
		||||
	@ConfigurationProperties(DataSourceProperties.PREFIX)
 | 
			
		||||
	public DataSource tomcatDataSource() {
 | 
			
		||||
		return (DataSource) DataSourceBuilder.create().type(DataSource.class).build();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@ConfigurationProperties(DataSourceProperties.PREFIX)
 | 
			
		||||
	public HikariDataSource hikariDataSource() {
 | 
			
		||||
		return (HikariDataSource) DataSourceBuilder.create().type(HikariDataSource.class).build();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@ConfigurationProperties(DataSourceProperties.PREFIX)
 | 
			
		||||
	public BasicDataSource dbcpDataSource() {
 | 
			
		||||
		return (BasicDataSource)DataSourceBuilder.create().type(BasicDataSource.class).build();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB
 | 
			
		|||
				.get(this.classLoader);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected String getDriverClassName() {
 | 
			
		||||
	public String getDriverClassName() {
 | 
			
		||||
		if (StringUtils.hasText(this.driverClassName)) {
 | 
			
		||||
			Assert.state(ClassUtils.isPresent(this.driverClassName, null),
 | 
			
		||||
					"Cannot load driver class: " + this.driverClassName);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomize
 | 
			
		|||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
 | 
			
		||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +61,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
 | 
			
		|||
 | 
			
		||||
	private String contextPath;
 | 
			
		||||
 | 
			
		||||
	@NestedConfigurationProperty
 | 
			
		||||
	private Ssl ssl;
 | 
			
		||||
 | 
			
		||||
	@NotNull
 | 
			
		||||
| 
						 | 
				
			
			@ -381,4 +383,5 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
{"properties": [
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.aop.auto",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically adds @EnableAspectJAutoProxy.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.aop.proxy-target-class",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).",
 | 
			
		||||
    "defaultValue": false,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.batch.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Execute all Spring Batch jobs in the context on startup.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.data.elasticsearch.repositories.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically enable Elasticsearch repositories.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.data.jpa.repositories.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically enable JPA repositories.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.data.mongo.repositories.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically enable Mongo repositories.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.data.solr.repositories.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically enable Solr repositories.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.jmx.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically expose management beans to the JMX domain",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.jpa.open-in-view",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.mobile.devicedelegatingviewresolver.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Enable device view resolver.",
 | 
			
		||||
    "defaultValue": false,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.mobile.sitepreference.enabled",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Enable SitePreferenceHandler.",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.social.auto-connection-views",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "description": "Automatically enable the connection status view for supported providers.",
 | 
			
		||||
    "defaultValue": false,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.view.prefix",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "Spring MVC view prefix.",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.view.suffix",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "Spring MVC view suffix.",
 | 
			
		||||
  }
 | 
			
		||||
]}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +159,11 @@
 | 
			
		|||
				<artifactId>spring-boot-autoconfigure</artifactId>
 | 
			
		||||
				<version>1.2.0.BUILD-SNAPSHOT</version>
 | 
			
		||||
			</dependency>
 | 
			
		||||
			<dependency>
 | 
			
		||||
				<groupId>org.springframework.boot</groupId>
 | 
			
		||||
				<artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
				<version>1.2.0.BUILD-SNAPSHOT</version>
 | 
			
		||||
			</dependency>
 | 
			
		||||
			<dependency>
 | 
			
		||||
				<groupId>org.springframework.boot</groupId>
 | 
			
		||||
				<artifactId>spring-boot-dependency-tools</artifactId>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,234 @@
 | 
			
		|||
[appendix]
 | 
			
		||||
[[configuration-metadata]]
 | 
			
		||||
== Configuration meta-data
 | 
			
		||||
Spring Boot jars are shipped with meta-data files that provide details of all supported
 | 
			
		||||
configuration properties. The files are designed to allow IDE developers to offer
 | 
			
		||||
contextual help and "`code completion`" as users are working with `application.properies`
 | 
			
		||||
or `application.yml` files.
 | 
			
		||||
 | 
			
		||||
The majority of the meta-data file is generated automatically at compile time by
 | 
			
		||||
processing all items annotated with `@ConfigurationProperties`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-format]]
 | 
			
		||||
=== Meta-data format
 | 
			
		||||
Configuration meta-data files are located inside jars under
 | 
			
		||||
`META-INF/spring-configuration-metadata.json` They use a simple JSON format with items
 | 
			
		||||
categorized under either "`groups`" or "`properties`":
 | 
			
		||||
 | 
			
		||||
[source,json,indent=0]
 | 
			
		||||
----
 | 
			
		||||
	{"groups": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "server",
 | 
			
		||||
			"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
 | 
			
		||||
			"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
 | 
			
		||||
		}
 | 
			
		||||
		...
 | 
			
		||||
	],"properties": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "server.port",
 | 
			
		||||
			"type": "java.lang.Integer",
 | 
			
		||||
			"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"name": "server.servlet-path",
 | 
			
		||||
			"type": "java.lang.String",
 | 
			
		||||
			"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
 | 
			
		||||
			"defaultValue": "/"
 | 
			
		||||
		}
 | 
			
		||||
		...
 | 
			
		||||
	]}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
Each "`property`" is a configuration item that the user specifies with a given value.
 | 
			
		||||
For example `server.port` and `server.servlet-path` might be specified in
 | 
			
		||||
`application.properties` as follows:
 | 
			
		||||
 | 
			
		||||
[source,properties,indent=0]
 | 
			
		||||
----
 | 
			
		||||
	server.port=9090
 | 
			
		||||
	server.servlet-path=/home
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
The "`groups`" are higher level items that don't themselves specify a value, but instead
 | 
			
		||||
provide a contextual grouping for properties. For example the `server.port` and
 | 
			
		||||
`server.servlet-path` properties are part of the `server` group.
 | 
			
		||||
 | 
			
		||||
NOTE: It is not required that every "`property`" has a "`group`", some properties might
 | 
			
		||||
just exist in their own right.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-group-attributes]]
 | 
			
		||||
==== Group Attributes
 | 
			
		||||
The JSON object contained in the `groups` array can contain the following attributes:
 | 
			
		||||
 | 
			
		||||
[cols="1,1,4"]
 | 
			
		||||
|===
 | 
			
		||||
|Name | Type |Purpose
 | 
			
		||||
 | 
			
		||||
|`name`
 | 
			
		||||
| String
 | 
			
		||||
| The full name of the group. This attribute is mandatory.
 | 
			
		||||
 | 
			
		||||
|`type`
 | 
			
		||||
| String
 | 
			
		||||
| The class name of the data type of the group. For example, if the group was based
 | 
			
		||||
  on a class annotated with `@ConfigurationProperties` the attribute would contain the
 | 
			
		||||
  fully qualified name of that class. If it was based on a `@Bean` method, it would be
 | 
			
		||||
  the return type of that method. The attribute may be omitted if the type is not known.
 | 
			
		||||
 | 
			
		||||
|`description`
 | 
			
		||||
| String
 | 
			
		||||
| A short description of the group that can be displayed to users. May be omitted if no
 | 
			
		||||
  description is available.
 | 
			
		||||
 | 
			
		||||
|`sourceType`
 | 
			
		||||
| String
 | 
			
		||||
| The class name of the source that contributed this group. For example, if the group
 | 
			
		||||
  was based on a `@Bean` method annotated with `@ConfigurationProperties` this attribute
 | 
			
		||||
  would contain the fully qualified name of the `@Configuration` class containing the
 | 
			
		||||
  method. The attribute may be omitted if the source type is not known.
 | 
			
		||||
 | 
			
		||||
|`sourceMethod`
 | 
			
		||||
| String
 | 
			
		||||
| The full name of the method (include parenthesis and argument types) that contributed
 | 
			
		||||
  this group. For example, the name of a `@ConfigurationProperties` annotated `@Bean`
 | 
			
		||||
  method.  May be omitted if the source method is not known.
 | 
			
		||||
|===
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-property-attributes]]
 | 
			
		||||
==== Property Attributes
 | 
			
		||||
The JSON object contained in the `properties` array can contain the following attributes:
 | 
			
		||||
 | 
			
		||||
[cols="1,1,4"]
 | 
			
		||||
|===
 | 
			
		||||
|Name | Type |Purpose
 | 
			
		||||
 | 
			
		||||
|`name`
 | 
			
		||||
| String
 | 
			
		||||
| The full name of the property. Names are in lowercase dashed form (e.g.
 | 
			
		||||
  `server.servlet-path`). This attribute is mandatory.
 | 
			
		||||
 | 
			
		||||
|`type`
 | 
			
		||||
| String
 | 
			
		||||
| The class name of the data type of the property. For example, `java.lang.String`. This
 | 
			
		||||
  attribute can be used to guide the user as to the types of values that they can enter.
 | 
			
		||||
  For consistency, the type of a primitive is specified using its wrapper counterpart,
 | 
			
		||||
  i.e. `boolean` becomes `java.lang.Boolean`. Note that this class may be a complex type
 | 
			
		||||
  that gets converted from a String as values are bound. May be omitted if the type is
 | 
			
		||||
  not known.
 | 
			
		||||
 | 
			
		||||
|`description`
 | 
			
		||||
| String
 | 
			
		||||
| A short description of the property that can be displayed to users. May be omitted if
 | 
			
		||||
  no description is available.
 | 
			
		||||
 | 
			
		||||
|`sourceType`
 | 
			
		||||
| String
 | 
			
		||||
| The class name of the source that contributed this property. For example, if the
 | 
			
		||||
  property was from a class annotated with `@ConfigurationProperties` this attribute
 | 
			
		||||
  would contain the fully qualified name of that class. May be omitted if the source type
 | 
			
		||||
  is not known.
 | 
			
		||||
 | 
			
		||||
|`sourceMethod`
 | 
			
		||||
| String
 | 
			
		||||
| The full name of the method (include parenthesis and argument types) that contributed
 | 
			
		||||
  this property. For example, the name of a getter in a `@ConfigurationProperties`
 | 
			
		||||
  annotated class.  May be omitted if the source method is not known.
 | 
			
		||||
 | 
			
		||||
|`defaultValue`
 | 
			
		||||
| Object
 | 
			
		||||
| The default value which will be used if the property is not specified. May be omitted
 | 
			
		||||
  if the default value is not known.
 | 
			
		||||
|===
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-repeated-items]]
 | 
			
		||||
==== Repeated meta-data items
 | 
			
		||||
It is perfectly acceptable for "`property`" and "`group`" objects with the same name to
 | 
			
		||||
appear multiple times within a meta-data file. For example, Spring Boot binds
 | 
			
		||||
`spring.datasource` properties to Hikari, Tomcat and DBCP classes, with each potentially
 | 
			
		||||
offering overlap of property names. Consumers of meta-data should take care to ensure
 | 
			
		||||
that they support such scenarios.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-annotation-processor]]
 | 
			
		||||
=== Generating your own meta-data using the annotation processor
 | 
			
		||||
You can easily generate your own configuration meta-data file from items annotated with
 | 
			
		||||
`@ConfigurationProperties` by using the `spring-boot-configuration-processor` jar.
 | 
			
		||||
The jar includes a Java annotation processor which is invoked as your project is
 | 
			
		||||
compiled. To use the processor, simply include `spring-boot-configuration-processor` as
 | 
			
		||||
an optional dependency, for example with Maven you would add:
 | 
			
		||||
 | 
			
		||||
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
 | 
			
		||||
----
 | 
			
		||||
	<dependency>
 | 
			
		||||
		<groupId>org.springframework.boot</groupId>
 | 
			
		||||
		<artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
		<optional>true</optional>
 | 
			
		||||
	</dependency>
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
The annotation will pickup both classes and methods that are annotated with
 | 
			
		||||
`@ConfigurationProperties`. The Javadoc for field values within configuration classes
 | 
			
		||||
will be used to populate the `description` attribute.
 | 
			
		||||
 | 
			
		||||
NOTE: You should only use simple text with `@ConfigurationProperties` field Javadoc since
 | 
			
		||||
they are not processed before being added to the JSON.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-nested-properties]]
 | 
			
		||||
==== Nested properties
 | 
			
		||||
The annotation processor will automatically consider inner classes as nested properties.
 | 
			
		||||
For example, the following class:
 | 
			
		||||
 | 
			
		||||
[source,java,indent=0,subs="verbatim,quotes,attributes"]
 | 
			
		||||
----
 | 
			
		||||
	@ConfigurationProperties(prefix="server")
 | 
			
		||||
	public class ServerProperties {
 | 
			
		||||
 | 
			
		||||
		private String name;
 | 
			
		||||
 | 
			
		||||
		private Host host;
 | 
			
		||||
 | 
			
		||||
		// ... getter and setters
 | 
			
		||||
 | 
			
		||||
		private static class Host {
 | 
			
		||||
 | 
			
		||||
			private String ip;
 | 
			
		||||
 | 
			
		||||
			private int port;
 | 
			
		||||
 | 
			
		||||
			// ... getter and setters
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
Will produce meta-data information for `server.name`, `server.host.ip` and
 | 
			
		||||
`server.host.port` properties. You can use the `@NestedConfigurationProperty`
 | 
			
		||||
annotation on a field to indicate that a regular (non-inner) class should be treated as
 | 
			
		||||
if it were nested.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[configuration-metadata-additional-metadata]]
 | 
			
		||||
==== Adding additional meta-data
 | 
			
		||||
Spring Boot's configuration file handling is quite flexible; and it often the case that
 | 
			
		||||
properties may exist that are not bound to a `@ConfigurationProperties` bean. To support
 | 
			
		||||
such cases, the annotation processor will automatically merge items from
 | 
			
		||||
`META-INF/additional-spring-configuration-metadata.json` into the main meta-data file.
 | 
			
		||||
 | 
			
		||||
The format of the `additional-spring-configuration-metadata.json` file is exactly the same
 | 
			
		||||
as the regular `spring-configuration-metadata.json`. The additional properties file is
 | 
			
		||||
optional, if you don't have any additional properties, simply don't add it.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
= Appendices
 | 
			
		||||
 | 
			
		||||
include::appendix-application-properties.adoc[]
 | 
			
		||||
include::appendix-configuration-metadata.adoc[]
 | 
			
		||||
include::appendix-auto-configuration-classes.adoc[]
 | 
			
		||||
include::appendix-executable-jar-format.adoc[]
 | 
			
		||||
include::appendix-dependency-versions.adoc[]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,10 @@
 | 
			
		|||
	<properties>
 | 
			
		||||
		<main.basedir>..</main.basedir>
 | 
			
		||||
		<java.version>1.6</java.version>
 | 
			
		||||
		<aether.version>0.9.1.v20140329</aether.version>
 | 
			
		||||
		<json.version>20140107</json.version>
 | 
			
		||||
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
			
		||||
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 | 
			
		||||
		<aether.version>0.9.1.v20140329</aether.version>
 | 
			
		||||
		<json.version>20140107</json.version>
 | 
			
		||||
		<maven.version>3.1.1</maven.version>
 | 
			
		||||
	</properties>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
		<main.basedir>${basedir}/..</main.basedir>
 | 
			
		||||
	</properties>
 | 
			
		||||
	<modules>
 | 
			
		||||
		<module>spring-boot-configuration-processor</module>
 | 
			
		||||
		<module>spring-boot-dependency-tools</module>
 | 
			
		||||
		<module>spring-boot-loader</module>
 | 
			
		||||
		<module>spring-boot-loader-tools</module>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,298 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.Collections;
 | 
			
		||||
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.Diagnostic.Kind;
 | 
			
		||||
import javax.tools.FileObject;
 | 
			
		||||
import javax.tools.StandardLocation;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.FieldValuesParser;
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.javac.JavaCompilerFieldValuesParser;
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
	static final String NESTED_CONFIGURATION_PROPERTY_ANNOTATION = "org.springframework.boot."
 | 
			
		||||
			+ "context.properties.NestedConfigurationProperty";
 | 
			
		||||
 | 
			
		||||
	private ConfigurationMetadata metadata;
 | 
			
		||||
 | 
			
		||||
	private TypeUtils typeUtils;
 | 
			
		||||
 | 
			
		||||
	private FieldValuesParser fieldValuesParser;
 | 
			
		||||
 | 
			
		||||
	protected String configurationPropertiesAnnotation() {
 | 
			
		||||
		return CONFIGURATION_PROPERTIES_ANNOTATION;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected String nestedConfigurationPropertyAnnotation() {
 | 
			
		||||
		return NESTED_CONFIGURATION_PROPERTY_ANNOTATION;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public synchronized void init(ProcessingEnvironment env) {
 | 
			
		||||
		super.init(env);
 | 
			
		||||
		this.metadata = new ConfigurationMetadata();
 | 
			
		||||
		this.typeUtils = new TypeUtils(env);
 | 
			
		||||
		try {
 | 
			
		||||
			this.fieldValuesParser = new JavaCompilerFieldValuesParser(env);
 | 
			
		||||
		}
 | 
			
		||||
		catch (Throwable ex) {
 | 
			
		||||
			this.fieldValuesParser = FieldValuesParser.NONE;
 | 
			
		||||
			logWarning("Field value processing of @ConfigurationProperty meta-data is "
 | 
			
		||||
					+ "not supported");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void logWarning(String msg) {
 | 
			
		||||
		this.processingEnv.getMessager().printMessage(Kind.WARNING, msg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@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);
 | 
			
		||||
		Map<String, Object> fieldValues = getFieldValues(element);
 | 
			
		||||
		processSimpleTypes(prefix, element, members, fieldValues);
 | 
			
		||||
		processNestedTypes(prefix, element, members);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private Map<String, Object> getFieldValues(TypeElement element) {
 | 
			
		||||
		try {
 | 
			
		||||
			return this.fieldValuesParser.getFieldValues(element);
 | 
			
		||||
		}
 | 
			
		||||
		catch (Exception ex) {
 | 
			
		||||
			return Collections.emptyMap();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void processSimpleTypes(String prefix, TypeElement element,
 | 
			
		||||
			TypeElementMembers members, Map<String, Object> fieldValues) {
 | 
			
		||||
		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);
 | 
			
		||||
			boolean isNested = getAnnotation(field,
 | 
			
		||||
					nestedConfigurationPropertyAnnotation()) != null;
 | 
			
		||||
			boolean isCollection = this.typeUtils.isCollectionOrMap(getter
 | 
			
		||||
					.getReturnType());
 | 
			
		||||
			if (!isNested && (setter != null || isCollection)) {
 | 
			
		||||
				String dataType = this.typeUtils.getType(getter.getReturnType());
 | 
			
		||||
				String sourceType = this.typeUtils.getType(element);
 | 
			
		||||
				String description = this.typeUtils.getJavaDoc(field);
 | 
			
		||||
				Object defaultValue = fieldValues.get(name);
 | 
			
		||||
				this.metadata.add(ItemMetadata.newProperty(prefix, name, dataType,
 | 
			
		||||
						sourceType, null, description, defaultValue));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void processNestedTypes(String prefix, TypeElement element,
 | 
			
		||||
			TypeElementMembers members) {
 | 
			
		||||
		for (Map.Entry<String, ExecutableElement> entry : members.getPublicGetters()
 | 
			
		||||
				.entrySet()) {
 | 
			
		||||
			String name = entry.getKey();
 | 
			
		||||
			ExecutableElement getter = entry.getValue();
 | 
			
		||||
			VariableElement field = members.getFields().get(name);
 | 
			
		||||
			Element returnType = this.processingEnv.getTypeUtils().asElement(
 | 
			
		||||
					getter.getReturnType());
 | 
			
		||||
			AnnotationMirror annotation = getAnnotation(getter,
 | 
			
		||||
					configurationPropertiesAnnotation());
 | 
			
		||||
			boolean isNested = getAnnotation(field,
 | 
			
		||||
					nestedConfigurationPropertyAnnotation()) != null;
 | 
			
		||||
			if (returnType != null && returnType instanceof TypeElement
 | 
			
		||||
					&& annotation == null) {
 | 
			
		||||
				TypeElement returns = (TypeElement) returnType;
 | 
			
		||||
				if (this.typeUtils.isEnclosedIn(returnType, element) || isNested) {
 | 
			
		||||
					String nestedPrefix = ConfigurationMetadata
 | 
			
		||||
							.nestedPrefix(prefix, name);
 | 
			
		||||
					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) {
 | 
			
		||||
		if (element != null) {
 | 
			
		||||
			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,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.configurationprocessor.fieldvalues;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import javax.lang.model.element.TypeElement;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.javac.JavaCompilerFieldValuesParser;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parser which can be used to obtain the field values from an {@link TypeElement}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.1.2
 | 
			
		||||
 * @see JavaCompilerFieldValuesParser
 | 
			
		||||
 */
 | 
			
		||||
public interface FieldValuesParser {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Implementation of {@link FieldValuesParser} that always returns an empty
 | 
			
		||||
	 * result.
 | 
			
		||||
	 */
 | 
			
		||||
	public static final FieldValuesParser NONE = new FieldValuesParser() {
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Map<String, Object> getFieldValues(TypeElement element) {
 | 
			
		||||
			return Collections.emptyMap();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return the field values for the given element.
 | 
			
		||||
	 * @param element the element to inspect
 | 
			
		||||
	 * @return a map of field names to values.
 | 
			
		||||
	 * @throws Exception if the values cannot be extracted
 | 
			
		||||
	 */
 | 
			
		||||
	Map<String, Object> getFieldValues(TypeElement element) throws Exception;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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.configurationprocessor.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reflection based access to {@code com.sun.source.tree.ExpressionTree}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class ExpressionTree extends ReflectionWrapper {
 | 
			
		||||
 | 
			
		||||
	private final Class<?> literalTreeType = findClass("com.sun.source.tree.LiteralTree");
 | 
			
		||||
 | 
			
		||||
	private final Method literalValueMethod = findMethod(this.literalTreeType, "getValue");
 | 
			
		||||
 | 
			
		||||
	public ExpressionTree(Object instance) {
 | 
			
		||||
		super(instance);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getKind() throws Exception {
 | 
			
		||||
		return findMethod("getKind").invoke(getInstance()).toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Object getLiteralValue() throws Exception {
 | 
			
		||||
		if (this.literalTreeType.isAssignableFrom(getInstance().getClass())) {
 | 
			
		||||
			return this.literalValueMethod.invoke(getInstance());
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.processing.ProcessingEnvironment;
 | 
			
		||||
import javax.lang.model.element.Modifier;
 | 
			
		||||
import javax.lang.model.element.TypeElement;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.FieldValuesParser;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link FieldValuesParser} implementation for the standard Java compiler.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
public class JavaCompilerFieldValuesParser implements FieldValuesParser {
 | 
			
		||||
 | 
			
		||||
	private final Trees trees;
 | 
			
		||||
 | 
			
		||||
	public JavaCompilerFieldValuesParser(ProcessingEnvironment env) throws Exception {
 | 
			
		||||
		this.trees = Trees.instance(env);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Map<String, Object> getFieldValues(TypeElement element) throws Exception {
 | 
			
		||||
		Tree tree = this.trees.getTree(element);
 | 
			
		||||
		if (tree != null) {
 | 
			
		||||
			FieldCollector fieldCollector = new FieldCollector();
 | 
			
		||||
			tree.accept(fieldCollector);
 | 
			
		||||
			return fieldCollector.getFieldValues();
 | 
			
		||||
		}
 | 
			
		||||
		return Collections.emptyMap();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class FieldCollector implements TreeVisitor {
 | 
			
		||||
 | 
			
		||||
		private static final Map<String, Class<?>> WRAPPER_TYPES;
 | 
			
		||||
		static {
 | 
			
		||||
			Map<String, Class<?>> types = new HashMap<String, Class<?>>();
 | 
			
		||||
			types.put("boolean", Boolean.class);
 | 
			
		||||
			types.put(Boolean.class.getName(), Boolean.class);
 | 
			
		||||
			types.put("byte", Byte.class);
 | 
			
		||||
			types.put(Byte.class.getName(), Byte.class);
 | 
			
		||||
			types.put("short", Short.class);
 | 
			
		||||
			types.put(Short.class.getName(), Short.class);
 | 
			
		||||
			types.put("int", Integer.class);
 | 
			
		||||
			types.put(Integer.class.getName(), Integer.class);
 | 
			
		||||
			types.put("long", Long.class);
 | 
			
		||||
			types.put(Long.class.getName(), Long.class);
 | 
			
		||||
			WRAPPER_TYPES = Collections.unmodifiableMap(types);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static final Map<Class<?>, Object> DEFAULT_TYPE_VALUES;
 | 
			
		||||
		static {
 | 
			
		||||
			Map<Class<?>, Object> values = new HashMap<Class<?>, Object>();
 | 
			
		||||
			values.put(Boolean.class, false);
 | 
			
		||||
			values.put(Byte.class, (byte) 0);
 | 
			
		||||
			values.put(Short.class, (short) 0);
 | 
			
		||||
			values.put(Integer.class, 0);
 | 
			
		||||
			values.put(Long.class, (long) 0);
 | 
			
		||||
			DEFAULT_TYPE_VALUES = Collections.unmodifiableMap(values);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static final Map<String, Object> WELL_KNOWN_STATIC_FINALS;
 | 
			
		||||
		static {
 | 
			
		||||
			Map<String, Object> values = new HashMap<String, Object>();
 | 
			
		||||
			values.put("Boolean.TRUE", true);
 | 
			
		||||
			values.put("Boolean.FALSE", false);
 | 
			
		||||
			WELL_KNOWN_STATIC_FINALS = Collections.unmodifiableMap(values);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private final Map<String, Object> fieldValues = new HashMap<String, Object>();
 | 
			
		||||
 | 
			
		||||
		private final Map<String, Object> staticFinals = new HashMap<String, Object>();
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void visitVariable(VariableTree variable) throws Exception {
 | 
			
		||||
			Set<Modifier> flags = variable.getModifierFlags();
 | 
			
		||||
			if (flags.contains(Modifier.STATIC) && flags.contains(Modifier.FINAL)) {
 | 
			
		||||
				this.staticFinals.put(variable.getName(), getValue(variable));
 | 
			
		||||
			}
 | 
			
		||||
			if (!flags.contains(Modifier.FINAL)) {
 | 
			
		||||
				this.fieldValues.put(variable.getName(), getValue(variable));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private Object getValue(VariableTree variable) throws Exception {
 | 
			
		||||
			ExpressionTree initializer = variable.getInitializer();
 | 
			
		||||
			Class<?> wrapperType = WRAPPER_TYPES.get(variable.getType());
 | 
			
		||||
			if (initializer != null) {
 | 
			
		||||
				if (initializer.getLiteralValue() != null) {
 | 
			
		||||
					return initializer.getLiteralValue();
 | 
			
		||||
				}
 | 
			
		||||
				if (initializer.getKind().equals("IDENTIFIER")) {
 | 
			
		||||
					return this.staticFinals.get(initializer.toString());
 | 
			
		||||
				}
 | 
			
		||||
				if (initializer.getKind().equals("MEMBER_SELECT")) {
 | 
			
		||||
					return WELL_KNOWN_STATIC_FINALS.get(initializer.toString());
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return DEFAULT_TYPE_VALUES.get(wrapperType);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Map<String, Object> getFieldValues() {
 | 
			
		||||
			return this.fieldValues;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for reflection based wrappers. Used to access internal Java classes without
 | 
			
		||||
 * needing tools.jar on the classpath.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class ReflectionWrapper {
 | 
			
		||||
 | 
			
		||||
	private final Class<?> type;
 | 
			
		||||
 | 
			
		||||
	private final Object instance;
 | 
			
		||||
 | 
			
		||||
	public ReflectionWrapper(Object instance) {
 | 
			
		||||
		this.type = instance.getClass();
 | 
			
		||||
		this.instance = instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ReflectionWrapper(String type, Object instance) {
 | 
			
		||||
		this.type = findClass(instance.getClass().getClassLoader(), type);
 | 
			
		||||
		this.instance = instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected final Object getInstance() {
 | 
			
		||||
		return this.instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String toString() {
 | 
			
		||||
		return this.instance.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected Class<?> findClass(String name) {
 | 
			
		||||
		return findClass(getInstance().getClass().getClassLoader(), name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected Method findMethod(String name, Class<?>... parameterTypes) {
 | 
			
		||||
		return findMethod(this.type, name, parameterTypes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected static Class<?> findClass(ClassLoader classLoader, String name) {
 | 
			
		||||
		try {
 | 
			
		||||
			return classLoader.loadClass(name);
 | 
			
		||||
		}
 | 
			
		||||
		catch (ClassNotFoundException ex) {
 | 
			
		||||
			throw new IllegalStateException(ex);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected static Method findMethod(Class<?> type, String name,
 | 
			
		||||
			Class<?>... parameterTypes) {
 | 
			
		||||
		try {
 | 
			
		||||
			return type.getMethod(name, parameterTypes);
 | 
			
		||||
		}
 | 
			
		||||
		catch (Exception ex) {
 | 
			
		||||
			throw new IllegalStateException(ex);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.InvocationHandler;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.lang.reflect.Proxy;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reflection based access to {@code com.sun.source.tree.Tree}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class Tree extends ReflectionWrapper {
 | 
			
		||||
 | 
			
		||||
	private final Class<?> treeVisitorType = findClass("com.sun.source.tree.TreeVisitor");
 | 
			
		||||
 | 
			
		||||
	private final Method acceptMethod = findMethod("accept", this.treeVisitorType,
 | 
			
		||||
			Object.class);
 | 
			
		||||
 | 
			
		||||
	private final Method GET_CLASS_TREE_MEMBERS = findMethod(
 | 
			
		||||
			findClass("com.sun.source.tree.ClassTree"), "getMembers");
 | 
			
		||||
 | 
			
		||||
	public Tree(Object instance) {
 | 
			
		||||
		super("com.sun.source.tree.Tree", instance);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void accept(TreeVisitor visitor) throws Exception {
 | 
			
		||||
		this.acceptMethod.invoke(getInstance(), Proxy.newProxyInstance(getInstance()
 | 
			
		||||
				.getClass().getClassLoader(), new Class<?>[] { this.treeVisitorType },
 | 
			
		||||
				new TreeVisitorInvocationHandler(visitor)), 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * {@link InvocationHandler} to call the {@link TreeVisitor}.
 | 
			
		||||
	 */
 | 
			
		||||
	private class TreeVisitorInvocationHandler implements InvocationHandler {
 | 
			
		||||
 | 
			
		||||
		private TreeVisitor treeVisitor;
 | 
			
		||||
 | 
			
		||||
		public TreeVisitorInvocationHandler(TreeVisitor treeVisitor) {
 | 
			
		||||
			this.treeVisitor = treeVisitor;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		@SuppressWarnings("rawtypes")
 | 
			
		||||
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 | 
			
		||||
			if (method.getName().equals("visitClass")) {
 | 
			
		||||
				if ((Integer) args[1] == 0) {
 | 
			
		||||
					Iterable members = (Iterable) Tree.this.GET_CLASS_TREE_MEMBERS
 | 
			
		||||
							.invoke(args[0]);
 | 
			
		||||
					for (Object member : members) {
 | 
			
		||||
						if (member != null) {
 | 
			
		||||
							Tree.this.acceptMethod.invoke(member, proxy,
 | 
			
		||||
									((Integer) args[1]) + 1);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (method.getName().equals("visitVariable")) {
 | 
			
		||||
				this.treeVisitor.visitVariable(new VariableTree(args[0]));
 | 
			
		||||
			}
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reflection base alternative for {@code com.sun.source.tree.TreeVisitor}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
interface TreeVisitor {
 | 
			
		||||
 | 
			
		||||
	void visitVariable(VariableTree variable) throws Exception;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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.configurationprocessor.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.processing.ProcessingEnvironment;
 | 
			
		||||
import javax.lang.model.element.Element;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reflection based access to {@code com.sun.source.util.Trees}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class Trees extends ReflectionWrapper {
 | 
			
		||||
 | 
			
		||||
	private Trees(Object instance) {
 | 
			
		||||
		super(instance);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Tree getTree(Element element) throws Exception {
 | 
			
		||||
		Object tree = findMethod("getTree", Element.class).invoke(getInstance(), element);
 | 
			
		||||
		return (tree == null ? null : new Tree(tree));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static Trees instance(ProcessingEnvironment env) throws Exception {
 | 
			
		||||
		ClassLoader classLoader = env.getClass().getClassLoader();
 | 
			
		||||
		Class<?> type = findClass(classLoader, "com.sun.source.util.Trees");
 | 
			
		||||
		Method method = findMethod(type, "instance", ProcessingEnvironment.class);
 | 
			
		||||
		return new Trees(method.invoke(null, env));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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.configurationprocessor.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import javax.lang.model.element.Modifier;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reflection based access to {@code com.sun.source.tree.VariableTree}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
class VariableTree extends ReflectionWrapper {
 | 
			
		||||
 | 
			
		||||
	public VariableTree(Object instance) {
 | 
			
		||||
		super(instance);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getName() throws Exception {
 | 
			
		||||
		return findMethod("getName").invoke(getInstance()).toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getType() throws Exception {
 | 
			
		||||
		return findMethod("getType").invoke(getInstance()).toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ExpressionTree getInitializer() throws Exception {
 | 
			
		||||
		Object instance = findMethod("getInitializer").invoke(getInstance());
 | 
			
		||||
		return (instance == null ? null : new ExpressionTree(instance));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings("unchecked")
 | 
			
		||||
	public Set<Modifier> getModifierFlags() throws Exception {
 | 
			
		||||
		Object modifiers = findMethod("getModifiers").invoke(getInstance());
 | 
			
		||||
		if (modifiers == null) {
 | 
			
		||||
			return Collections.emptySet();
 | 
			
		||||
		}
 | 
			
		||||
		return (Set<Modifier>) findMethod(findClass("com.sun.source.tree.ModifiersTree"),
 | 
			
		||||
				"getFlags").invoke(modifiers);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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,138 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
	private Object defaultValue;
 | 
			
		||||
 | 
			
		||||
	ItemMetadata(ItemType itemType, String prefix, String name, String type,
 | 
			
		||||
			String sourceType, String sourceMethod, String description,
 | 
			
		||||
			Object defaultValue) {
 | 
			
		||||
		super();
 | 
			
		||||
		this.itemType = itemType;
 | 
			
		||||
		this.name = buildName(prefix, name);
 | 
			
		||||
		this.type = type;
 | 
			
		||||
		this.sourceType = sourceType;
 | 
			
		||||
		this.sourceMethod = sourceMethod;
 | 
			
		||||
		this.description = description;
 | 
			
		||||
		this.defaultValue = defaultValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Object getDefaultValue() {
 | 
			
		||||
		return this.defaultValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@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);
 | 
			
		||||
		buildToStringProperty(string, "defaultValue", this.defaultValue);
 | 
			
		||||
		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, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static ItemMetadata newProperty(String prefix, String name, String type,
 | 
			
		||||
			String sourceType, String sourceMethod, String description,
 | 
			
		||||
			Object defaultValue) {
 | 
			
		||||
		return new ItemMetadata(ItemType.PROPERTY, prefix, name, type, sourceType,
 | 
			
		||||
				sourceMethod, description, defaultValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The item type.
 | 
			
		||||
	 */
 | 
			
		||||
	public static enum ItemType {
 | 
			
		||||
		GROUP, PROPERTY
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,142 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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());
 | 
			
		||||
		putIfPresent(jsonObject, "defaultValue", item.getDefaultValue());
 | 
			
		||||
		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);
 | 
			
		||||
		Object defaultValue = object.opt("defaultValue");
 | 
			
		||||
		return new ItemMetadata(itemType, name, null, type, sourceType, sourceMethod,
 | 
			
		||||
				description, defaultValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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,293 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 org.springframework.boot.configurationsample.specific.SimplePojo;
 | 
			
		||||
 | 
			
		||||
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.")
 | 
			
		||||
						.withDefaultValue("boot"));
 | 
			
		||||
		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(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";
 | 
			
		||||
 | 
			
		||||
		static final String NESTED_CONFIGURATION_PROPERTY_ANNOTATION = "org.springframework.boot.configurationsample.NestedConfigurationProperty";
 | 
			
		||||
 | 
			
		||||
		private ConfigurationMetadata metadata;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		protected String configurationPropertiesAnnotation() {
 | 
			
		||||
			return CONFIGURATION_PROPERTIES_ANNOTATION;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		protected String nestedConfigurationPropertyAnnotation() {
 | 
			
		||||
			return NESTED_CONFIGURATION_PROPERTY_ANNOTATION;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		protected void writeMetaData(ConfigurationMetadata metadata) {
 | 
			
		||||
			this.metadata = metadata;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ConfigurationMetadata getMetadata() {
 | 
			
		||||
			return this.metadata;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,176 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
		private final Object defaultValue;
 | 
			
		||||
 | 
			
		||||
		public ContainsItemMatcher(ItemType itemType, String name) {
 | 
			
		||||
			this(itemType, name, null, null, null, null);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ContainsItemMatcher(ItemType itemType, String name, String type,
 | 
			
		||||
				Class<?> sourceType, String description, Object defaultValue) {
 | 
			
		||||
			this.itemType = itemType;
 | 
			
		||||
			this.name = name;
 | 
			
		||||
			this.type = type;
 | 
			
		||||
			this.sourceType = sourceType;
 | 
			
		||||
			this.description = description;
 | 
			
		||||
			this.defaultValue = defaultValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@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.defaultValue != null
 | 
			
		||||
					&& !this.defaultValue.equals(itemMetadata.getDefaultValue())) {
 | 
			
		||||
				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.defaultValue != null) {
 | 
			
		||||
				description.appendText(" defaultValue ").appendValue(this.defaultValue);
 | 
			
		||||
			}
 | 
			
		||||
			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, this.defaultValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ContainsItemMatcher ofDataType(String dataType) {
 | 
			
		||||
			return new ContainsItemMatcher(this.itemType, this.name, dataType,
 | 
			
		||||
					this.sourceType, this.description, this.defaultValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ContainsItemMatcher fromSource(Class<?> sourceType) {
 | 
			
		||||
			return new ContainsItemMatcher(this.itemType, this.name, this.type,
 | 
			
		||||
					sourceType, this.description, this.defaultValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ContainsItemMatcher withDescription(String description) {
 | 
			
		||||
			return new ContainsItemMatcher(this.itemType, this.name, this.type,
 | 
			
		||||
					this.sourceType, description, this.defaultValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Matcher<? super ConfigurationMetadata> withDefaultValue(Object defaultValue) {
 | 
			
		||||
			return new ContainsItemMatcher(this.itemType, this.name, this.type,
 | 
			
		||||
					this.sourceType, this.description, defaultValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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,124 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.processing.AbstractProcessor;
 | 
			
		||||
import javax.annotation.processing.ProcessingEnvironment;
 | 
			
		||||
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.Element;
 | 
			
		||||
import javax.lang.model.element.TypeElement;
 | 
			
		||||
 | 
			
		||||
import org.hamcrest.Matcher;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.rules.TemporaryFolder;
 | 
			
		||||
import org.springframework.boot.configurationprocessor.TestCompiler;
 | 
			
		||||
import org.springframework.boot.configurationsample.fieldvalues.FieldValues;
 | 
			
		||||
 | 
			
		||||
import static org.hamcrest.Matchers.equalTo;
 | 
			
		||||
import static org.hamcrest.Matchers.nullValue;
 | 
			
		||||
import static org.junit.Assert.assertThat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Abstract base class for {@link FieldValuesParser} tests.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 */
 | 
			
		||||
public abstract class AbstractFieldValuesProcessorTests {
 | 
			
		||||
 | 
			
		||||
	@Rule
 | 
			
		||||
	public TemporaryFolder temporaryFolder = new TemporaryFolder();
 | 
			
		||||
 | 
			
		||||
	protected abstract FieldValuesParser createProcessor(ProcessingEnvironment env);
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void getFieldValues() throws Exception {
 | 
			
		||||
		TestProcessor processor = new TestProcessor();
 | 
			
		||||
		TestCompiler compiler = new TestCompiler(this.temporaryFolder);
 | 
			
		||||
		compiler.getTask(FieldValues.class).call(processor);
 | 
			
		||||
		Map<String, Object> values = processor.getValues();
 | 
			
		||||
		assertThat(values.get("string"), equalToObject("1"));
 | 
			
		||||
		assertThat(values.get("stringNone"), nullValue());
 | 
			
		||||
		assertThat(values.get("stringConst"), equalToObject("c"));
 | 
			
		||||
		assertThat(values.get("bool"), equalToObject(true));
 | 
			
		||||
		assertThat(values.get("boolNone"), equalToObject(false));
 | 
			
		||||
		assertThat(values.get("boolConst"), equalToObject(true));
 | 
			
		||||
		assertThat(values.get("boolObject"), equalToObject(true));
 | 
			
		||||
		assertThat(values.get("boolObjectNone"), nullValue());
 | 
			
		||||
		assertThat(values.get("boolObjectConst"), equalToObject(true));
 | 
			
		||||
		assertThat(values.get("integer"), equalToObject(1));
 | 
			
		||||
		assertThat(values.get("integerNone"), equalToObject(0));
 | 
			
		||||
		assertThat(values.get("integerConst"), equalToObject(2));
 | 
			
		||||
		assertThat(values.get("integerObject"), equalToObject(3));
 | 
			
		||||
		assertThat(values.get("integerObjectNone"), nullValue());
 | 
			
		||||
		assertThat(values.get("integerObjectConst"), equalToObject(4));
 | 
			
		||||
		assertThat(values.get("object"), equalToObject(123));
 | 
			
		||||
		assertThat(values.get("objectNone"), nullValue());
 | 
			
		||||
		assertThat(values.get("objectConst"), equalToObject("c"));
 | 
			
		||||
		assertThat(values.get("objectInstance"), nullValue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private Matcher<Object> equalToObject(Object object) {
 | 
			
		||||
		return equalTo(object);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@SupportedAnnotationTypes({ "org.springframework.boot.configurationsample.ConfigurationProperties" })
 | 
			
		||||
	@SupportedSourceVersion(SourceVersion.RELEASE_6)
 | 
			
		||||
	private class TestProcessor extends AbstractProcessor {
 | 
			
		||||
 | 
			
		||||
		private FieldValuesParser processor;
 | 
			
		||||
 | 
			
		||||
		private Map<String, Object> values = new HashMap<String, Object>();
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public synchronized void init(ProcessingEnvironment env) {
 | 
			
		||||
			this.processor = createProcessor(env);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public boolean process(Set<? extends TypeElement> annotations,
 | 
			
		||||
				RoundEnvironment roundEnv) {
 | 
			
		||||
			for (TypeElement annotation : annotations) {
 | 
			
		||||
				for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
 | 
			
		||||
					if (element instanceof TypeElement) {
 | 
			
		||||
						try {
 | 
			
		||||
							this.values.putAll(this.processor
 | 
			
		||||
									.getFieldValues((TypeElement) element));
 | 
			
		||||
						}
 | 
			
		||||
						catch (Exception ex) {
 | 
			
		||||
							throw new IllegalStateException(ex);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Map<String, Object> getValues() {
 | 
			
		||||
			return this.values;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues.javac;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.processing.ProcessingEnvironment;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.AbstractFieldValuesProcessorTests;
 | 
			
		||||
import org.springframework.boot.configurationprocessor.fieldvalues.FieldValuesParser;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assume.assumeNoException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for {@link JavaCompilerFieldValuesParser}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 */
 | 
			
		||||
public class JavaCompilerFieldValuesProcessorTests extends
 | 
			
		||||
		AbstractFieldValuesProcessorTests {
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected FieldValuesParser createProcessor(ProcessingEnvironment env) {
 | 
			
		||||
		try {
 | 
			
		||||
			return new JavaCompilerFieldValuesParser(env);
 | 
			
		||||
		}
 | 
			
		||||
		catch (Throwable ex) {
 | 
			
		||||
			assumeNoException(ex);
 | 
			
		||||
			throw new IllegalStateException();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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", "x"));
 | 
			
		||||
		metadata.add(ItemMetadata
 | 
			
		||||
				.newProperty("b.c.d", null, null, null, null, null, null));
 | 
			
		||||
		metadata.add(ItemMetadata.newProperty("c", null, null, null, null, null, 123));
 | 
			
		||||
		metadata.add(ItemMetadata.newProperty("d", null, null, null, null, null, true));
 | 
			
		||||
		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").withDefaultValue("x"));
 | 
			
		||||
		assertThat(read, containsProperty("b.c.d"));
 | 
			
		||||
		assertThat(read, containsProperty("c").withDefaultValue(123));
 | 
			
		||||
		assertThat(read, containsProperty("d").withDefaultValue(true));
 | 
			
		||||
		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,38 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 @NestedConfigurationProperty} for testing (removes
 | 
			
		||||
 * the need for a dependency on the real annotation).
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface NestedConfigurationProperty {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.fieldvalues;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sample object containing fields with initial values.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 */
 | 
			
		||||
@SuppressWarnings("unused")
 | 
			
		||||
@ConfigurationProperties
 | 
			
		||||
public class FieldValues {
 | 
			
		||||
 | 
			
		||||
	private static final String STRING_CONST = "c";
 | 
			
		||||
 | 
			
		||||
	private static final boolean BOOLEAN_CONST = true;
 | 
			
		||||
 | 
			
		||||
	private static final Boolean BOOLEAN_OBJ_CONST = true;
 | 
			
		||||
 | 
			
		||||
	private static final int INTEGER_CONST = 2;
 | 
			
		||||
 | 
			
		||||
	private static final Integer INTEGER_OBJ_CONST = 4;
 | 
			
		||||
 | 
			
		||||
	private String string = "1";
 | 
			
		||||
 | 
			
		||||
	private String stringNone;
 | 
			
		||||
 | 
			
		||||
	private String stringConst = STRING_CONST;
 | 
			
		||||
 | 
			
		||||
	private boolean bool = true;
 | 
			
		||||
 | 
			
		||||
	private boolean boolNone;
 | 
			
		||||
 | 
			
		||||
	private boolean boolConst = BOOLEAN_CONST;
 | 
			
		||||
 | 
			
		||||
	private Boolean boolObject = Boolean.TRUE;
 | 
			
		||||
 | 
			
		||||
	private Boolean boolObjectNone;
 | 
			
		||||
 | 
			
		||||
	private Boolean boolObjectConst = BOOLEAN_OBJ_CONST;
 | 
			
		||||
 | 
			
		||||
	private int integer = 1;
 | 
			
		||||
 | 
			
		||||
	private int integerNone;
 | 
			
		||||
 | 
			
		||||
	private int integerConst = INTEGER_CONST;
 | 
			
		||||
 | 
			
		||||
	private Integer integerObject = 3;
 | 
			
		||||
 | 
			
		||||
	private Integer integerObjectNone;
 | 
			
		||||
 | 
			
		||||
	private Integer integerObjectConst = INTEGER_OBJ_CONST;
 | 
			
		||||
 | 
			
		||||
	private Object object = 123;
 | 
			
		||||
 | 
			
		||||
	private Object objectNone;
 | 
			
		||||
 | 
			
		||||
	private Object objectConst = STRING_CONST;
 | 
			
		||||
 | 
			
		||||
	private Object objectInstance = new StringBuffer();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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,86 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
import org.springframework.boot.configurationsample.NestedConfigurationProperty;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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();
 | 
			
		||||
 | 
			
		||||
	@NestedConfigurationProperty
 | 
			
		||||
	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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +169,12 @@
 | 
			
		|||
			<artifactId>snakeyaml</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Annotation processing -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
			<optional>true</optional>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<!-- Test -->
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.apache.httpcomponents</groupId>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.context.properties;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates that a field in a {@link ConfigurationProperties} object should be treated as
 | 
			
		||||
 * if it were a nested type. This annotation has no bearing on the actual binding
 | 
			
		||||
 * processes, but it is used by the {@code spring-boot-configuration-processor} as a hint
 | 
			
		||||
 * that a field is not bound as a single value.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 * @since 1.2.0
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface NestedConfigurationProperty {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
{"groups": [
 | 
			
		||||
  {
 | 
			
		||||
    "name": "logging",
 | 
			
		||||
    "sourceType": "org.springframework.boot.logging.LoggingApplicationListener"
 | 
			
		||||
  }
 | 
			
		||||
],"properties": [
 | 
			
		||||
  {
 | 
			
		||||
    "name": "logging.config",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "Location of the logging configuration file."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "logging.file",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "The name of the log file."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "logging.path",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "Location of the log file."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.mandatory-file-encoding",
 | 
			
		||||
    "sourceType": "org.springframework.boot.context.FileEncodingApplicationListener",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "description": "The character encoding the application must use."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.application.name",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "sourceType": "org.springframework.boot.context.ContextIdApplicationContextInitializer",
 | 
			
		||||
    "description": "The name of the application."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.application.index",
 | 
			
		||||
    "dataType": "java.lang.Integer",
 | 
			
		||||
    "sourceType": "org.springframework.boot.context.ContextIdApplicationContextInitializer",
 | 
			
		||||
    "description": "Index of the application."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.config.name",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "sourceType": "org.springframework.boot.context.config.ConfigFileApplicationListener",
 | 
			
		||||
    "description": "Config file name",
 | 
			
		||||
    "defaultValue": "application",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.config.location",
 | 
			
		||||
    "dataType": "java.lang.String",
 | 
			
		||||
    "sourceType": "org.springframework.boot.context.config.ConfigFileApplicationListener",
 | 
			
		||||
    "description": "Config file locations",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.main.show-banner",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "sourceType": "org.springframework.boot.SpringApplication",
 | 
			
		||||
    "description": "Display the banner when the application runs",
 | 
			
		||||
    "defaultValue": true,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.main.sources",
 | 
			
		||||
    "dataType": "java.util.Set<java.lang.Object>",
 | 
			
		||||
    "sourceType": "org.springframework.boot.SpringApplication",
 | 
			
		||||
    "description": "Sources (class name, package name or XML resource location) used to create the ApplicationContext."
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "spring.main.web-environment",
 | 
			
		||||
    "dataType": "java.lang.Boolean",
 | 
			
		||||
    "sourceType": "org.springframework.boot.SpringApplication",
 | 
			
		||||
    "description": "Run the application in a web environment (auto-detected by default)"
 | 
			
		||||
  }
 | 
			
		||||
]}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue