This commit is contained in:
Phillip Webb 2015-06-25 12:00:48 -07:00
parent bedca634c9
commit 7879743b9f
9 changed files with 64 additions and 52 deletions

View File

@ -76,7 +76,7 @@ public class DevToolsProperties {
private long pollInterval = DEFAULT_RESTART_POLL_INTERVAL;
/**
* Amount of quiet time (in milliseconds) requited without any classpath changes
* Amount of quiet time (in milliseconds) required without any classpath changes
* before a restart is triggered.
*/
private long quietPeriod = DEFAULT_RESTART_QUIET_PERIOD;

View File

@ -261,6 +261,8 @@ following attributes:
provider for more details).
|===
[[configuration-metadata-repeated-items]]
==== Repeated meta-data items
It is perfectly acceptable for "`property`" and "`group`" objects with the same name to
@ -282,7 +284,6 @@ property, you can provide additional meta-data that:
==== Value hints
The `name` attribute of each hint refers to the `name` of a property. In the initial
example above, we provide 3 values for the `server.tomcat.compression` property: `on`,
`off` and `force`.
@ -327,8 +328,9 @@ assistance for the keys, you could add the following to
NOTE: Of course, you should have an `Enum` for those two values instead. This is by far
the most effective approach to auto-completion if your IDE supports it.
==== Provider hints
==== Provider hints
Providers are a powerful way of attaching semantics to a property. We define in the section
below the official providers that you can use for your own hints. Bare in mind however that
your favorite IDE may implement some of these or none of them. It could eventually provide
@ -369,8 +371,8 @@ can handle. If no provider for a given property is supported, no special content
assistance is provided either.
===== Any
===== Any
The **any** provider permits any additional values to be provided. Regular value
validation based on the property type should be applied if this is supported.
@ -402,8 +404,9 @@ other value is also allowed:
]}
----
===== Class reference
===== Class reference
The **class-reference** provider auto-completes classes available in the project. This
provider supports these parameters:
@ -445,8 +448,9 @@ property that defines the `JspServlet` class name to use:
]}
----
===== Enum
===== Enum
The **enum** provider auto-completes the values of the `Enum` class referenced via the
`target` parameter. This provider supports these parameters:
@ -485,8 +489,8 @@ TIP: This is useful when you don't want your configuration classes to rely on cl
that may not be on the classpath.
===== Logger name
===== Logger name
The **logger-name** provider auto-completes valid logger names. Typically, package and
class names available in the current project can be auto-completed. Specific frameworks
may have extra magic logger names that could be supported as well.
@ -552,8 +556,8 @@ level:
----
===== Spring bean reference
===== Spring bean reference
The **spring-bean-reference** provider auto-completes the beans that are defined in
the configuration of the current project. This provider supports these parameters:
@ -588,6 +592,8 @@ that defines the name of the `MBeanServer` bean to use:
]}
----
[[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
@ -635,6 +641,7 @@ annotation processor also supports the use of the `@Data`, `@Getter` and `@Sette
annotations.
[[configuration-metadata-nested-properties]]
==== Nested properties
The annotation processor will automatically consider inner classes as nested properties.

View File

@ -44,8 +44,10 @@ public class ItemHint implements Comparable<ItemHint> {
public ItemHint(String name, List<ValueHint> values, List<ProviderHint> providers) {
this.name = toCanonicalName(name);
this.values = (values != null ? new ArrayList<ValueHint>(values) : new ArrayList<ValueHint>());
this.providers = (providers != null ? new ArrayList<ProviderHint>(providers) : new ArrayList<ProviderHint>());
this.values = (values != null ? new ArrayList<ValueHint>(values)
: new ArrayList<ValueHint>());
this.providers = (providers != null ? new ArrayList<ProviderHint>(providers)
: new ArrayList<ProviderHint>());
}
private String toCanonicalName(String name) {
@ -76,7 +78,8 @@ public class ItemHint implements Comparable<ItemHint> {
}
public static ItemHint newHint(String name, ValueHint... values) {
return new ItemHint(name, Arrays.asList(values), Collections.<ProviderHint>emptyList());
return new ItemHint(name, Arrays.asList(values),
Collections.<ProviderHint> emptyList());
}
@Override
@ -113,8 +116,10 @@ public class ItemHint implements Comparable<ItemHint> {
}
public static class ProviderHint {
private final String name;
private final Map<String,Object> parameters;
private final Map<String, Object> parameters;
public ProviderHint(String name, Map<String, Object> parameters) {
this.name = name;
@ -122,18 +127,19 @@ public class ItemHint implements Comparable<ItemHint> {
}
public String getName() {
return name;
return this.name;
}
public Map<String, Object> getParameters() {
return parameters;
return this.parameters;
}
@Override
public String toString() {
return "Provider{" + "name='" + this.name + ", parameters=" + this.parameters +
'}';
return "Provider{" + "name='" + this.name + ", parameters=" + this.parameters
+ '}';
}
}
}

View File

@ -110,10 +110,13 @@ public class JsonMarshaller {
for (ItemHint.ProviderHint providerHint : hint.getProviders()) {
JSONObject providerHintObject = new JSONOrderedObject();
providerHintObject.put("name", providerHint.getName());
if (providerHint.getParameters() != null && !providerHint.getParameters().isEmpty()) {
if (providerHint.getParameters() != null
&& !providerHint.getParameters().isEmpty()) {
JSONObject parametersObject = new JSONOrderedObject();
for (Map.Entry<String, Object> entry : providerHint.getParameters().entrySet()) {
parametersObject.put(entry.getKey(), extractItemValue(entry.getValue()));
for (Map.Entry<String, Object> entry : providerHint.getParameters()
.entrySet()) {
parametersObject.put(entry.getKey(),
extractItemValue(entry.getValue()));
}
providerHintObject.put("parameters", parametersObject);
}
@ -218,7 +221,7 @@ public class JsonMarshaller {
private ItemHint.ProviderHint toProviderHint(JSONObject object) {
String name = object.getString("name");
Map<String,Object> parameters = new HashMap<String,Object>();
Map<String, Object> parameters = new HashMap<String, Object>();
if (object.has("parameters")) {
JSONObject parametersObject = object.getJSONObject("parameters");
for (Object k : parametersObject.keySet()) {

View File

@ -330,7 +330,6 @@ public class ConfigurationMetadataAnnotationProcessorTests {
@Test
public void mergingOfAdditionalProperty() throws Exception {
File additionalMetadataFile = createAdditionalMetadataFile();
JSONObject property = new JSONObject();
property.put("name", "foo");
property.put("type", "java.lang.String");
@ -339,12 +338,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
properties.put(property);
JSONObject additionalMetadata = new JSONObject();
additionalMetadata.put("properties", properties);
writeMetadata(additionalMetadataFile, additionalMetadata);
ConfigurationMetadata metadata = compile(SimpleProperties.class);
assertThat(metadata, containsProperty("simple.comparator"));
assertThat(metadata,
containsProperty("foo", String.class)
.fromSource(AdditionalMetadata.class));
@ -354,7 +350,6 @@ public class ConfigurationMetadataAnnotationProcessorTests {
public void mergingOfSimpleHint() throws Exception {
writeAdditionalHints(ItemHint.newHint("simple.the-name", new ItemHint.ValueHint(
"boot", "Bla bla"), new ItemHint.ValueHint("spring", null)));
ConfigurationMetadata metadata = compile(SimpleProperties.class);
assertThat(metadata,
containsHint("simple.the-name").withValue(0, "boot", "Bla bla")
@ -365,7 +360,6 @@ public class ConfigurationMetadataAnnotationProcessorTests {
public void mergingOfHintWithNonCanonicalName() throws Exception {
writeAdditionalHints(ItemHint.newHint("simple.theName", new ItemHint.ValueHint(
"boot", "Bla bla")));
ConfigurationMetadata metadata = compile(SimpleProperties.class);
assertThat(metadata,
containsHint("simple.the-name").withValue(0, "boot", "Bla bla"));
@ -373,16 +367,16 @@ public class ConfigurationMetadataAnnotationProcessorTests {
@Test
public void mergingOfHintWithProvider() throws Exception {
writeAdditionalHints(
new ItemHint("simple.theName", Collections.<ItemHint.ValueHint>emptyList(), Arrays.asList(
new ItemHint.ProviderHint("first", Collections.<String,Object>singletonMap("target", "org.foo")),
new ItemHint.ProviderHint("second", null))
));
writeAdditionalHints(new ItemHint("simple.theName",
Collections.<ItemHint.ValueHint> emptyList(), Arrays.asList(
new ItemHint.ProviderHint("first", Collections
.<String, Object> singletonMap("target", "org.foo")),
new ItemHint.ProviderHint("second", null))));
ConfigurationMetadata metadata = compile(SimpleProperties.class);
assertThat(metadata, containsHint("simple.the-name")
.withProvider("first", "target", "org.foo")
.withProvider("second"));
assertThat(metadata,
containsHint("simple.the-name")
.withProvider("first", "target", "org.foo")
.withProvider("second"));
}
@Test

View File

@ -212,10 +212,12 @@ public class ConfigurationMetadataMatchers {
private final List<ProviderHintMatcher> providers;
public ContainsHintMatcher(String name) {
this(name, new ArrayList<ValueHintMatcher>(), new ArrayList<ProviderHintMatcher>());
this(name, new ArrayList<ValueHintMatcher>(),
new ArrayList<ProviderHintMatcher>());
}
public ContainsHintMatcher(String name, List<ValueHintMatcher> values, List<ProviderHintMatcher> providers) {
public ContainsHintMatcher(String name, List<ValueHintMatcher> values,
List<ProviderHintMatcher> providers) {
this.name = name;
this.values = values;
this.providers = providers;
@ -273,14 +275,17 @@ public class ConfigurationMetadataMatchers {
return new ContainsHintMatcher(this.name, values, this.providers);
}
public ContainsHintMatcher withProvider(int index, String provider, Map<String,Object> parameters) {
List<ProviderHintMatcher> providers = new ArrayList<ProviderHintMatcher>(this.providers);
public ContainsHintMatcher withProvider(int index, String provider,
Map<String, Object> parameters) {
List<ProviderHintMatcher> providers = new ArrayList<ProviderHintMatcher>(
this.providers);
providers.add(new ProviderHintMatcher(index, provider, parameters));
return new ContainsHintMatcher(this.name, this.values, providers);
}
public ContainsHintMatcher withProvider(String provider, String key, Object value) {
return withProvider(this.providers.size(), provider, Collections.singletonMap(key, value));
return withProvider(this.providers.size(), provider,
Collections.singletonMap(key, value));
}
public ContainsHintMatcher withProvider(String provider) {
@ -359,9 +364,8 @@ public class ConfigurationMetadataMatchers {
if (this.index + 1 > hint.getProviders().size()) {
return false;
}
ItemHint.ProviderHint providerHint = hint.getProviders().get(index);
if (this.name != null
&& !this.name.equals(providerHint.getName())) {
ItemHint.ProviderHint providerHint = hint.getProviders().get(this.index);
if (this.name != null && !this.name.equals(providerHint.getName())) {
return false;
}
if (this.parameters != null) {

View File

@ -58,8 +58,8 @@ public class JsonMarshallerTests {
metadata.add(ItemHint.newHint("a.b"));
metadata.add(ItemHint.newHint("c", new ItemHint.ValueHint(123, "hey"),
new ItemHint.ValueHint(456, null)));
metadata.add(new ItemHint("d", null, Arrays.asList(
new ItemHint.ProviderHint("first", Collections.<String,Object>singletonMap("target", "foo")),
metadata.add(new ItemHint("d", null, Arrays.asList(new ItemHint.ProviderHint(
"first", Collections.<String, Object> singletonMap("target", "foo")),
new ItemHint.ProviderHint("second", null))));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonMarshaller marshaller = new JsonMarshaller();
@ -81,8 +81,7 @@ public class JsonMarshallerTests {
assertThat(read, containsHint("a.b"));
assertThat(read,
containsHint("c").withValue(0, 123, "hey").withValue(1, 456, null));
assertThat(read, containsHint("d")
.withProvider("first", "target", "foo")
assertThat(read, containsHint("d").withProvider("first", "target", "foo")
.withProvider("second"));
}

View File

@ -206,9 +206,9 @@ public class LoggingApplicationListener implements GenericApplicationListener {
system.initialize(logConfig, logFile);
}
catch (Exception ex) {
System.err
.println("Logging system failed to initialize using configuration from '"
+ logConfig + "'");
// NOTE: We can't use the logger here to report the problem
System.err.println("Logging system failed to initialize "
+ "using configuration from '" + logConfig + "'");
ex.printStackTrace(System.err);
throw new IllegalStateException(ex);
}

View File

@ -108,10 +108,9 @@ public class OutputCapture implements TestRule {
/**
* Verify that the output is matched by the supplied {@code matcher}. Verification is
* performed after the test method has executed.
*
* @param matcher the matcher
*/
public void expect(Matcher<String> matcher) {
public void expect(Matcher<? super String> matcher) {
this.matchers.add(matcher);
}