Polish
This commit is contained in:
parent
dabe75a281
commit
2dfd916c96
|
@ -103,13 +103,11 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||||
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
|
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
|
||||||
GitProperties properties, ObjectProvider<InfoContributor> infoContributors) {
|
GitProperties properties, ObjectProvider<InfoContributor> infoContributors) {
|
||||||
List<InfoContributor> contributors = infoContributors.orderedStream()
|
List<InfoContributor> contributors = infoContributors.orderedStream()
|
||||||
.map((infoContributor) -> {
|
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||||
if (infoContributor instanceof GitInfoContributor) {
|
? new GitInfoContributor(properties,
|
||||||
return new GitInfoContributor(properties,
|
InfoPropertiesInfoContributor.Mode.FULL)
|
||||||
InfoPropertiesInfoContributor.Mode.FULL);
|
: infoContributor)
|
||||||
}
|
.collect(Collectors.toList());
|
||||||
return infoContributor;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,13 +104,11 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||||
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
|
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
|
||||||
GitProperties properties, ObjectProvider<InfoContributor> infoContributors) {
|
GitProperties properties, ObjectProvider<InfoContributor> infoContributors) {
|
||||||
List<InfoContributor> contributors = infoContributors.orderedStream()
|
List<InfoContributor> contributors = infoContributors.orderedStream()
|
||||||
.map((infoContributor) -> {
|
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||||
if (infoContributor instanceof GitInfoContributor) {
|
? new GitInfoContributor(properties,
|
||||||
return new GitInfoContributor(properties,
|
InfoPropertiesInfoContributor.Mode.FULL)
|
||||||
InfoPropertiesInfoContributor.Mode.FULL);
|
: infoContributor)
|
||||||
}
|
.collect(Collectors.toList());
|
||||||
return infoContributor;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
|
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
|
||||||
|
@ -142,7 +143,7 @@ public class PrometheusMetricsExportAutoConfiguration {
|
||||||
return new PushGateway(new URL(url));
|
return new PushGateway(new URL(url));
|
||||||
}
|
}
|
||||||
catch (MalformedURLException ex) {
|
catch (MalformedURLException ex) {
|
||||||
logger.warn(String.format(
|
logger.warn(LogMessage.format(
|
||||||
"Invalid PushGateway base url '%s': update your configuration to a valid URL",
|
"Invalid PushGateway base url '%s': update your configuration to a valid URL",
|
||||||
url));
|
url));
|
||||||
return new PushGateway(url);
|
return new PushGateway(url);
|
||||||
|
|
|
@ -157,8 +157,8 @@ public class ManagementContextAutoConfiguration {
|
||||||
AbstractApplicationContext context = (AbstractApplicationContext) this.applicationContext;
|
AbstractApplicationContext context = (AbstractApplicationContext) this.applicationContext;
|
||||||
List<BeanFactoryPostProcessor> postProcessors = context
|
List<BeanFactoryPostProcessor> postProcessors = context
|
||||||
.getBeanFactoryPostProcessors();
|
.getBeanFactoryPostProcessors();
|
||||||
return postProcessors.stream().anyMatch((
|
return postProcessors.stream().anyMatch(
|
||||||
postProcessor) -> postProcessor instanceof LazyInitializationBeanFactoryPostProcessor);
|
LazyInitializationBeanFactoryPostProcessor.class::isInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setClassLoaderIfPossible(ConfigurableApplicationContext child) {
|
private void setClassLoaderIfPossible(ConfigurableApplicationContext child) {
|
||||||
|
|
|
@ -56,7 +56,6 @@ public class ManagementContextAutoConfigurationTests {
|
||||||
contextRunner.withPropertyValues("server.port=0", "management.server.port=0").run(
|
contextRunner.withPropertyValues("server.port=0", "management.server.port=0").run(
|
||||||
(context) -> assertThat(tomcatStartedOccurencesIn(this.output.toString()))
|
(context) -> assertThat(tomcatStartedOccurencesIn(this.output.toString()))
|
||||||
.isEqualTo(2));
|
.isEqualTo(2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int tomcatStartedOccurencesIn(String output) {
|
private int tomcatStartedOccurencesIn(String output) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class HttpTraceWebFilter implements WebFilter, Ordered {
|
||||||
Principal principal, WebSession session) {
|
Principal principal, WebSession session) {
|
||||||
ServerWebExchangeTraceableRequest request = new ServerWebExchangeTraceableRequest(
|
ServerWebExchangeTraceableRequest request = new ServerWebExchangeTraceableRequest(
|
||||||
exchange);
|
exchange);
|
||||||
final HttpTrace trace = this.tracer.receivedRequest(request);
|
HttpTrace trace = this.tracer.receivedRequest(request);
|
||||||
exchange.getResponse().beforeCommit(() -> {
|
exchange.getResponse().beforeCommit(() -> {
|
||||||
TraceableServerHttpResponse response = new TraceableServerHttpResponse(
|
TraceableServerHttpResponse response = new TraceableServerHttpResponse(
|
||||||
exchange.getResponse());
|
exchange.getResponse());
|
||||||
|
|
|
@ -38,15 +38,12 @@ class FlywayMigrationScriptMissingFailureAnalyzer
|
||||||
.append("no migration scripts location is configured").toString(),
|
.append("no migration scripts location is configured").toString(),
|
||||||
"Check your Flyway configuration", cause);
|
"Check your Flyway configuration", cause);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
description.append(String.format(
|
description.append(String.format(
|
||||||
"none of the following migration scripts locations could be found:%n%n"));
|
"none of the following migration scripts locations could be found:%n%n"));
|
||||||
cause.getLocations().forEach((location) -> description
|
cause.getLocations().forEach(
|
||||||
.append(String.format("\t- %s%n", location)));
|
(location) -> description.append(String.format("\t- %s%n", location)));
|
||||||
return new FailureAnalysis(description.toString(),
|
return new FailureAnalysis(description.toString(),
|
||||||
"Review the locations above or check your Flyway configuration",
|
"Review the locations above or check your Flyway configuration", cause);
|
||||||
cause);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,11 @@ public class MongoReactiveAutoConfiguration {
|
||||||
return new NettyDriverMongoClientSettingsBuilderCustomizer(settings);
|
return new NettyDriverMongoClientSettingsBuilderCustomizer(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link MongoClientSettingsBuilderCustomizer} to apply Mongo client settings.
|
||||||
|
*/
|
||||||
private static final class NettyDriverMongoClientSettingsBuilderCustomizer
|
private static final class NettyDriverMongoClientSettingsBuilderCustomizer
|
||||||
implements MongoClientSettingsBuilderCustomizer, DisposableBean {
|
implements MongoClientSettingsBuilderCustomizer, DisposableBean {
|
||||||
|
|
||||||
|
@ -111,6 +116,4 @@ public class MongoReactiveAutoConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class RSocketNettyServerCustomizer implements NettyServerCustomizer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpServer apply(HttpServer httpServer) {
|
public HttpServer apply(HttpServer httpServer) {
|
||||||
final ServerTransport.ConnectionAcceptor acceptor = RSocketFactory.receive()
|
ServerTransport.ConnectionAcceptor acceptor = RSocketFactory.receive()
|
||||||
.acceptor(this.messageHandlerAcceptor).toConnectionAcceptor();
|
.acceptor(this.messageHandlerAcceptor).toConnectionAcceptor();
|
||||||
return httpServer.route((routes) -> routes.ws(this.mappingPath,
|
return httpServer.route((routes) -> routes.ws(this.mappingPath,
|
||||||
WebsocketRouteTransport.newHandler(acceptor)));
|
WebsocketRouteTransport.newHandler(acceptor)));
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@ConfigurationProperties("spring.rsocket")
|
@ConfigurationProperties("spring.rsocket")
|
||||||
public class RSocketProperties {
|
public class RSocketProperties {
|
||||||
|
|
||||||
private Server server = new Server();
|
private final Server server = new Server();
|
||||||
|
|
||||||
public Server getServer() {
|
public Server getServer() {
|
||||||
return this.server;
|
return this.server;
|
||||||
|
|
|
@ -77,6 +77,8 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
*/
|
*/
|
||||||
public class SpringBootContextLoader extends AbstractContextLoader {
|
public class SpringBootContextLoader extends AbstractContextLoader {
|
||||||
|
|
||||||
|
private static final String[] NO_ARGS = new String[0];
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApplicationContext loadContext(MergedContextConfiguration config)
|
public ApplicationContext loadContext(MergedContextConfiguration config)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -155,7 +157,7 @@ public class SpringBootContextLoader extends AbstractContextLoader {
|
||||||
protected String[] getArgs(MergedContextConfiguration config) {
|
protected String[] getArgs(MergedContextConfiguration config) {
|
||||||
SpringBootTest annotation = AnnotatedElementUtils
|
SpringBootTest annotation = AnnotatedElementUtils
|
||||||
.findMergedAnnotation(config.getTestClass(), SpringBootTest.class);
|
.findMergedAnnotation(config.getTestClass(), SpringBootTest.class);
|
||||||
return (annotation != null) ? annotation.args() : new String[0];
|
return (annotation != null) ? annotation.args() : NO_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setActiveProfiles(ConfigurableEnvironment environment,
|
private void setActiveProfiles(ConfigurableEnvironment environment,
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.configurationdocs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple builder to help construct Asciidoc markup.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class AsciidocBuilder {
|
||||||
|
|
||||||
|
private static final String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
private final StringBuilder content;
|
||||||
|
|
||||||
|
AsciidocBuilder() {
|
||||||
|
this.content = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsciidocBuilder appendln(Object... items) {
|
||||||
|
append(items);
|
||||||
|
append(NEWLINE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsciidocBuilder append(Object... items) {
|
||||||
|
for (Object item : items) {
|
||||||
|
this.content.append(item);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.content.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,29 +27,30 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
class CompoundKeyEntry extends AbstractConfigurationEntry {
|
class CompoundConfigurationTableEntry extends ConfigurationTableEntry {
|
||||||
|
|
||||||
private Set<String> configurationKeys;
|
private Set<String> configurationKeys;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
CompoundKeyEntry(String key, String description) {
|
CompoundConfigurationTableEntry(String key, String description) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.configurationKeys = new TreeSet<>();
|
this.configurationKeys = new TreeSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addConfigurationKeys(ConfigurationMetadataProperty... properties) {
|
void addConfigurationKeys(ConfigurationMetadataProperty... properties) {
|
||||||
Stream.of(properties)
|
Stream.of(properties).map(ConfigurationMetadataProperty::getId)
|
||||||
.forEach((property) -> this.configurationKeys.add(property.getId()));
|
.forEach(this.configurationKeys::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeAsciidoc(StringBuilder builder) {
|
public void write(AsciidocBuilder builder) {
|
||||||
builder.append("|`+++");
|
builder.append("|`+++");
|
||||||
this.configurationKeys.forEach((key) -> builder.append(key).append(NEWLINE));
|
this.configurationKeys.forEach(builder::appendln);
|
||||||
builder.append("+++`").append(NEWLINE).append("|").append(NEWLINE).append("|+++")
|
builder.appendln("+++`");
|
||||||
.append(this.description).append("+++").append(NEWLINE);
|
builder.appendln("|");
|
||||||
|
builder.appendln("|+++", this.description, "+++");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,6 @@ import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
|
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
|
||||||
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository;
|
|
||||||
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepositoryJsonBuilder;
|
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepositoryJsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,8 +38,21 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepos
|
||||||
*/
|
*/
|
||||||
public class ConfigurationMetadataDocumentWriter {
|
public class ConfigurationMetadataDocumentWriter {
|
||||||
|
|
||||||
public void writeDocument(Path outputDirPath, DocumentOptions options,
|
public void writeDocument(Path outputDirectory, DocumentOptions options,
|
||||||
InputStream... metadataInput) throws IOException {
|
InputStream... metadata) throws IOException {
|
||||||
|
assertValidOutputDirectory(outputDirectory);
|
||||||
|
if (!Files.exists(outputDirectory)) {
|
||||||
|
Files.createDirectory(outputDirectory);
|
||||||
|
}
|
||||||
|
assertMetadata(metadata);
|
||||||
|
List<ConfigurationTable> tables = createConfigTables(
|
||||||
|
getMetadataProperties(metadata), options);
|
||||||
|
for (ConfigurationTable table : tables) {
|
||||||
|
writeConfigurationTable(table, outputDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertValidOutputDirectory(Path outputDirPath) {
|
||||||
if (outputDirPath == null) {
|
if (outputDirPath == null) {
|
||||||
throw new IllegalArgumentException("output path should not be null");
|
throw new IllegalArgumentException("output path should not be null");
|
||||||
}
|
}
|
||||||
|
@ -48,64 +60,33 @@ public class ConfigurationMetadataDocumentWriter {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"output path already exists and is not a directory");
|
"output path already exists and is not a directory");
|
||||||
}
|
}
|
||||||
else if (!Files.exists(outputDirPath)) {
|
|
||||||
Files.createDirectory(outputDirPath);
|
|
||||||
}
|
}
|
||||||
if (metadataInput == null || metadataInput.length < 1) {
|
|
||||||
|
private void assertMetadata(InputStream... metadata) {
|
||||||
|
if (metadata == null || metadata.length < 1) {
|
||||||
throw new IllegalArgumentException("missing input metadata");
|
throw new IllegalArgumentException("missing input metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationMetadataRepository configRepository = ConfigurationMetadataRepositoryJsonBuilder
|
|
||||||
.create(metadataInput).build();
|
|
||||||
Map<String, ConfigurationMetadataProperty> allProperties = configRepository
|
|
||||||
.getAllProperties();
|
|
||||||
|
|
||||||
List<ConfigurationTable> tables = createConfigTables(allProperties, options);
|
|
||||||
|
|
||||||
for (ConfigurationTable table : tables) {
|
|
||||||
Path outputFilePath = outputDirPath.resolve(table.getId() + ".adoc");
|
|
||||||
Files.deleteIfExists(outputFilePath);
|
|
||||||
Files.createFile(outputFilePath);
|
|
||||||
try (OutputStream outputStream = Files.newOutputStream(outputFilePath)) {
|
|
||||||
outputStream
|
|
||||||
.write(table.toAsciidocTable().getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, ConfigurationMetadataProperty> getMetadataProperties(
|
||||||
|
InputStream... metadata) throws IOException {
|
||||||
|
ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder
|
||||||
|
.create(metadata);
|
||||||
|
return builder.build().getAllProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ConfigurationTable> createConfigTables(
|
private List<ConfigurationTable> createConfigTables(
|
||||||
Map<String, ConfigurationMetadataProperty> allProperties,
|
Map<String, ConfigurationMetadataProperty> metadataProperties,
|
||||||
DocumentOptions options) {
|
DocumentOptions options) {
|
||||||
|
List<ConfigurationTable> tables = new ArrayList<>();
|
||||||
final List<ConfigurationTable> tables = new ArrayList<>();
|
List<String> unmappedKeys = metadataProperties.values().stream()
|
||||||
final List<String> unmappedKeys = allProperties.values().stream()
|
.filter((property) -> !property.isDeprecated())
|
||||||
.filter((prop) -> !prop.isDeprecated()).map((prop) -> prop.getId())
|
.map(ConfigurationMetadataProperty::getId).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
Map<String, CompoundConfigurationTableEntry> overrides = getOverrides(
|
||||||
|
metadataProperties, unmappedKeys, options);
|
||||||
final Map<String, CompoundKeyEntry> overrides = getOverrides(allProperties,
|
options.getMetadataSections().forEach(
|
||||||
unmappedKeys, options);
|
(id, keyPrefixes) -> tables.add(createConfigTable(metadataProperties,
|
||||||
|
unmappedKeys, overrides, id, keyPrefixes)));
|
||||||
options.getMetadataSections().forEach((id, keyPrefixes) -> {
|
|
||||||
ConfigurationTable table = new ConfigurationTable(id);
|
|
||||||
tables.add(table);
|
|
||||||
for (String keyPrefix : keyPrefixes) {
|
|
||||||
List<String> matchingOverrides = overrides.keySet().stream()
|
|
||||||
.filter((overrideKey) -> overrideKey.startsWith(keyPrefix))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
matchingOverrides
|
|
||||||
.forEach((match) -> table.addEntry(overrides.remove(match)));
|
|
||||||
}
|
|
||||||
List<String> matchingKeys = unmappedKeys.stream()
|
|
||||||
.filter((key) -> keyPrefixes.stream().anyMatch(key::startsWith))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
for (String matchingKey : matchingKeys) {
|
|
||||||
ConfigurationMetadataProperty property = allProperties.get(matchingKey);
|
|
||||||
table.addEntry(new SingleKeyEntry(property));
|
|
||||||
|
|
||||||
}
|
|
||||||
unmappedKeys.removeAll(matchingKeys);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!unmappedKeys.isEmpty()) {
|
if (!unmappedKeys.isEmpty()) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"The following keys were not written to the documentation: "
|
"The following keys were not written to the documentation: "
|
||||||
|
@ -116,22 +97,21 @@ public class ConfigurationMetadataDocumentWriter {
|
||||||
"The following keys were not written to the documentation: "
|
"The following keys were not written to the documentation: "
|
||||||
+ String.join(", ", overrides.keySet()));
|
+ String.join(", ", overrides.keySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tables;
|
return tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, CompoundKeyEntry> getOverrides(
|
private Map<String, CompoundConfigurationTableEntry> getOverrides(
|
||||||
Map<String, ConfigurationMetadataProperty> allProperties,
|
Map<String, ConfigurationMetadataProperty> metadataProperties,
|
||||||
List<String> unmappedKeys, DocumentOptions options) {
|
List<String> unmappedKeys, DocumentOptions options) {
|
||||||
final Map<String, CompoundKeyEntry> overrides = new HashMap<>();
|
Map<String, CompoundConfigurationTableEntry> overrides = new HashMap<>();
|
||||||
|
|
||||||
options.getOverrides().forEach((keyPrefix, description) -> {
|
options.getOverrides().forEach((keyPrefix, description) -> {
|
||||||
final CompoundKeyEntry entry = new CompoundKeyEntry(keyPrefix, description);
|
CompoundConfigurationTableEntry entry = new CompoundConfigurationTableEntry(
|
||||||
|
keyPrefix, description);
|
||||||
List<String> matchingKeys = unmappedKeys.stream()
|
List<String> matchingKeys = unmappedKeys.stream()
|
||||||
.filter((key) -> key.startsWith(keyPrefix))
|
.filter((key) -> key.startsWith(keyPrefix))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
for (String matchingKey : matchingKeys) {
|
for (String matchingKey : matchingKeys) {
|
||||||
entry.addConfigurationKeys(allProperties.get(matchingKey));
|
entry.addConfigurationKeys(metadataProperties.get(matchingKey));
|
||||||
}
|
}
|
||||||
overrides.put(keyPrefix, entry);
|
overrides.put(keyPrefix, entry);
|
||||||
unmappedKeys.removeAll(matchingKeys);
|
unmappedKeys.removeAll(matchingKeys);
|
||||||
|
@ -139,4 +119,37 @@ public class ConfigurationMetadataDocumentWriter {
|
||||||
return overrides;
|
return overrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ConfigurationTable createConfigTable(
|
||||||
|
Map<String, ConfigurationMetadataProperty> metadataProperties,
|
||||||
|
List<String> unmappedKeys,
|
||||||
|
Map<String, CompoundConfigurationTableEntry> overrides, String id,
|
||||||
|
List<String> keyPrefixes) {
|
||||||
|
ConfigurationTable table = new ConfigurationTable(id);
|
||||||
|
for (String keyPrefix : keyPrefixes) {
|
||||||
|
List<String> matchingOverrides = overrides.keySet().stream()
|
||||||
|
.filter((overrideKey) -> overrideKey.startsWith(keyPrefix))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
matchingOverrides.forEach((match) -> table.addEntry(overrides.remove(match)));
|
||||||
|
}
|
||||||
|
List<String> matchingKeys = unmappedKeys.stream()
|
||||||
|
.filter((key) -> keyPrefixes.stream().anyMatch(key::startsWith))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
for (String matchingKey : matchingKeys) {
|
||||||
|
ConfigurationMetadataProperty property = metadataProperties.get(matchingKey);
|
||||||
|
table.addEntry(new SingleConfigurationTableEntry(property));
|
||||||
|
}
|
||||||
|
unmappedKeys.removeAll(matchingKeys);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeConfigurationTable(ConfigurationTable table, Path outputDirectory)
|
||||||
|
throws IOException {
|
||||||
|
Path outputFilePath = outputDirectory.resolve(table.getId() + ".adoc");
|
||||||
|
Files.deleteIfExists(outputFilePath);
|
||||||
|
Files.createFile(outputFilePath);
|
||||||
|
try (OutputStream outputStream = Files.newOutputStream(outputFilePath)) {
|
||||||
|
outputStream.write(table.toAsciidocTable().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,9 @@ import java.util.TreeSet;
|
||||||
*/
|
*/
|
||||||
class ConfigurationTable {
|
class ConfigurationTable {
|
||||||
|
|
||||||
private static final String NEWLINE = System.lineSeparator();
|
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
||||||
private final Set<AbstractConfigurationEntry> entries;
|
private final Set<ConfigurationTableEntry> entries;
|
||||||
|
|
||||||
ConfigurationTable(String id) {
|
ConfigurationTable(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -42,20 +40,21 @@ class ConfigurationTable {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEntry(AbstractConfigurationEntry... entries) {
|
void addEntry(ConfigurationTableEntry... entries) {
|
||||||
this.entries.addAll(Arrays.asList(entries));
|
this.entries.addAll(Arrays.asList(entries));
|
||||||
}
|
}
|
||||||
|
|
||||||
String toAsciidocTable() {
|
String toAsciidocTable() {
|
||||||
final StringBuilder builder = new StringBuilder();
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
builder.append("[cols=\"1,1,2\", options=\"header\"]").append(NEWLINE);
|
builder.appendln("[cols=\"1,1,2\", options=\"header\"]");
|
||||||
builder.append("|===").append(NEWLINE).append("|Key|Default Value|Description")
|
builder.appendln("|===");
|
||||||
.append(NEWLINE).append(NEWLINE);
|
builder.appendln("|Key|Default Value|Description");
|
||||||
|
builder.appendln();
|
||||||
this.entries.forEach((entry) -> {
|
this.entries.forEach((entry) -> {
|
||||||
entry.writeAsciidoc(builder);
|
entry.write(builder);
|
||||||
builder.append(NEWLINE);
|
builder.appendln();
|
||||||
});
|
});
|
||||||
return builder.append("|===").append(NEWLINE).toString();
|
return builder.appendln("|===").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,12 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationdocs;
|
package org.springframework.boot.configurationdocs;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for entries in {@link ConfigurationTable}.
|
* Abstract class for entries in {@link ConfigurationTable}.
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
abstract class AbstractConfigurationEntry
|
abstract class ConfigurationTableEntry implements Comparable<ConfigurationTableEntry> {
|
||||||
implements Comparable<AbstractConfigurationEntry> {
|
|
||||||
|
|
||||||
protected static final String NEWLINE = System.lineSeparator();
|
|
||||||
|
|
||||||
protected String key;
|
protected String key;
|
||||||
|
|
||||||
|
@ -34,27 +29,27 @@ abstract class AbstractConfigurationEntry
|
||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void writeAsciidoc(StringBuilder builder);
|
public abstract void write(AsciidocBuilder builder);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object obj) {
|
||||||
if (this == o) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (o == null || getClass() != o.getClass()) {
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AbstractConfigurationEntry that = (AbstractConfigurationEntry) o;
|
ConfigurationTableEntry other = (ConfigurationTableEntry) obj;
|
||||||
return this.key.equals(that.key);
|
return this.key.equals(other.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.key);
|
return this.key.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(AbstractConfigurationEntry other) {
|
public int compareTo(ConfigurationTableEntry other) {
|
||||||
return this.key.compareTo(other.getKey());
|
return this.key.compareTo(other.getKey());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.configurationdocs;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table entry containing a single configuration property.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class SingleConfigurationTableEntry extends ConfigurationTableEntry {
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
private final String defaultValue;
|
||||||
|
|
||||||
|
SingleConfigurationTableEntry(ConfigurationMetadataProperty property) {
|
||||||
|
this.key = property.getId();
|
||||||
|
if (property.getType() != null
|
||||||
|
&& property.getType().startsWith("java.util.Map")) {
|
||||||
|
this.key += ".*";
|
||||||
|
}
|
||||||
|
this.description = property.getDescription();
|
||||||
|
this.defaultValue = getDefaultValue(property.getDefaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDefaultValue(Object defaultValue) {
|
||||||
|
if (defaultValue == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (defaultValue.getClass().isArray()) {
|
||||||
|
return Arrays.stream((Object[]) defaultValue).map(Object::toString)
|
||||||
|
.collect(Collectors.joining("," + System.lineSeparator()));
|
||||||
|
}
|
||||||
|
return defaultValue.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(AsciidocBuilder builder) {
|
||||||
|
builder.appendln("|`+", this.key, "+`");
|
||||||
|
writeDefaultValue(builder);
|
||||||
|
writeDescription(builder);
|
||||||
|
builder.appendln();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeDefaultValue(AsciidocBuilder builder) {
|
||||||
|
String defaultValue = (this.defaultValue != null) ? this.defaultValue : "";
|
||||||
|
defaultValue = defaultValue.replace("\\", "\\\\").replace("|",
|
||||||
|
"{vbar}" + System.lineSeparator());
|
||||||
|
if (defaultValue.isEmpty()) {
|
||||||
|
builder.appendln("|");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.appendln("|`+", defaultValue, "+`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeDescription(AsciidocBuilder builder) {
|
||||||
|
if (this.description == null || this.description.isEmpty()) {
|
||||||
|
builder.append("|");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.append("|+++", this.description, "+++");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.configurationdocs;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Table entry containing a single configuration property.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class SingleKeyEntry extends AbstractConfigurationEntry {
|
|
||||||
|
|
||||||
private String defaultValue;
|
|
||||||
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
SingleKeyEntry(ConfigurationMetadataProperty property) {
|
|
||||||
|
|
||||||
this.key = property.getId();
|
|
||||||
if (property.getType() != null
|
|
||||||
&& property.getType().startsWith("java.util.Map")) {
|
|
||||||
this.key += ".*";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.description = property.getDescription();
|
|
||||||
|
|
||||||
if (property.getDefaultValue() != null) {
|
|
||||||
if (property.getDefaultValue().getClass().isArray()) {
|
|
||||||
this.defaultValue = Arrays.stream((Object[]) property.getDefaultValue())
|
|
||||||
.map(Object::toString).collect(Collectors.joining("," + NEWLINE));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.defaultValue = property.getDefaultValue().toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeAsciidoc(StringBuilder builder) {
|
|
||||||
builder.append("|`+").append(this.key).append("+`").append(NEWLINE);
|
|
||||||
String defaultValue = processDefaultValue();
|
|
||||||
if (!defaultValue.isEmpty()) {
|
|
||||||
builder.append("|`+").append(defaultValue).append("+`").append(NEWLINE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
builder.append("|").append(NEWLINE);
|
|
||||||
}
|
|
||||||
if (this.description != null) {
|
|
||||||
builder.append("|+++").append(this.description).append("+++");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
builder.append("|");
|
|
||||||
}
|
|
||||||
builder.append(NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String processDefaultValue() {
|
|
||||||
if (this.defaultValue != null && !this.defaultValue.isEmpty()) {
|
|
||||||
return this.defaultValue.replace("\\", "\\\\").replace("|",
|
|
||||||
"{vbar}" + NEWLINE);
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -23,9 +23,11 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link CompoundConfigurationTableEntry}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
public class CompoundKeyEntryTests {
|
public class CompoundConfigurationTableEntryTests {
|
||||||
|
|
||||||
private static String NEWLINE = System.lineSeparator();
|
private static String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
@ -34,21 +36,17 @@ public class CompoundKeyEntryTests {
|
||||||
ConfigurationMetadataProperty firstProp = new ConfigurationMetadataProperty();
|
ConfigurationMetadataProperty firstProp = new ConfigurationMetadataProperty();
|
||||||
firstProp.setId("spring.test.first");
|
firstProp.setId("spring.test.first");
|
||||||
firstProp.setType("java.lang.String");
|
firstProp.setType("java.lang.String");
|
||||||
|
|
||||||
ConfigurationMetadataProperty secondProp = new ConfigurationMetadataProperty();
|
ConfigurationMetadataProperty secondProp = new ConfigurationMetadataProperty();
|
||||||
secondProp.setId("spring.test.second");
|
secondProp.setId("spring.test.second");
|
||||||
secondProp.setType("java.lang.String");
|
secondProp.setType("java.lang.String");
|
||||||
|
|
||||||
ConfigurationMetadataProperty thirdProp = new ConfigurationMetadataProperty();
|
ConfigurationMetadataProperty thirdProp = new ConfigurationMetadataProperty();
|
||||||
thirdProp.setId("spring.test.third");
|
thirdProp.setId("spring.test.third");
|
||||||
thirdProp.setType("java.lang.String");
|
thirdProp.setType("java.lang.String");
|
||||||
|
CompoundConfigurationTableEntry entry = new CompoundConfigurationTableEntry(
|
||||||
CompoundKeyEntry entry = new CompoundKeyEntry("spring.test",
|
"spring.test", "This is a description.");
|
||||||
"This is a description.");
|
|
||||||
entry.addConfigurationKeys(firstProp, secondProp, thirdProp);
|
entry.addConfigurationKeys(firstProp, secondProp, thirdProp);
|
||||||
StringBuilder builder = new StringBuilder();
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
entry.writeAsciidoc(builder);
|
entry.write(builder);
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+++spring.test.first" + NEWLINE
|
assertThat(builder.toString()).isEqualTo("|`+++spring.test.first" + NEWLINE
|
||||||
+ "spring.test.second" + NEWLINE + "spring.test.third" + NEWLINE + "+++`"
|
+ "spring.test.second" + NEWLINE + "spring.test.third" + NEWLINE + "+++`"
|
||||||
+ NEWLINE + "|" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
+ NEWLINE + "|" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
@ -23,6 +23,8 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link ConfigurationTable}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
public class ConfigurationTableTests {
|
public class ConfigurationTableTests {
|
||||||
|
@ -32,22 +34,18 @@ public class ConfigurationTableTests {
|
||||||
@Test
|
@Test
|
||||||
public void simpleTable() {
|
public void simpleTable() {
|
||||||
ConfigurationTable table = new ConfigurationTable("test");
|
ConfigurationTable table = new ConfigurationTable("test");
|
||||||
|
|
||||||
ConfigurationMetadataProperty first = new ConfigurationMetadataProperty();
|
ConfigurationMetadataProperty first = new ConfigurationMetadataProperty();
|
||||||
first.setId("spring.test.prop");
|
first.setId("spring.test.prop");
|
||||||
first.setDefaultValue("something");
|
first.setDefaultValue("something");
|
||||||
first.setDescription("This is a description.");
|
first.setDescription("This is a description.");
|
||||||
first.setType("java.lang.String");
|
first.setType("java.lang.String");
|
||||||
|
|
||||||
ConfigurationMetadataProperty second = new ConfigurationMetadataProperty();
|
ConfigurationMetadataProperty second = new ConfigurationMetadataProperty();
|
||||||
second.setId("spring.test.other");
|
second.setId("spring.test.other");
|
||||||
second.setDefaultValue("other value");
|
second.setDefaultValue("other value");
|
||||||
second.setDescription("This is another description.");
|
second.setDescription("This is another description.");
|
||||||
second.setType("java.lang.String");
|
second.setType("java.lang.String");
|
||||||
|
table.addEntry(new SingleConfigurationTableEntry(first));
|
||||||
table.addEntry(new SingleKeyEntry(first));
|
table.addEntry(new SingleConfigurationTableEntry(second));
|
||||||
table.addEntry(new SingleKeyEntry(second));
|
|
||||||
|
|
||||||
assertThat(table.toAsciidocTable())
|
assertThat(table.toAsciidocTable())
|
||||||
.isEqualTo("[cols=\"1,1,2\", options=\"header\"]" + NEWLINE + "|==="
|
.isEqualTo("[cols=\"1,1,2\", options=\"header\"]" + NEWLINE + "|==="
|
||||||
+ NEWLINE + "|Key|Default Value|Description" + NEWLINE + NEWLINE
|
+ NEWLINE + "|Key|Default Value|Description" + NEWLINE + NEWLINE
|
||||||
|
|
|
@ -23,9 +23,11 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link SingleConfigurationTableEntry}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
public class SingleKeyEntryTests {
|
public class SingleConfigurationTableEntryTests {
|
||||||
|
|
||||||
private static String NEWLINE = System.lineSeparator();
|
private static String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
@ -36,11 +38,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setDefaultValue("something");
|
property.setDefaultValue("something");
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.lang.String");
|
property.setType("java.lang.String");
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
||||||
+ "|`+something+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
+ "|`+something+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setId("spring.test.prop");
|
property.setId("spring.test.prop");
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.lang.String");
|
property.setType("java.lang.String");
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE + "|"
|
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE + "|"
|
||||||
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
||||||
}
|
}
|
||||||
|
@ -67,11 +65,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setDefaultValue("first|second");
|
property.setDefaultValue("first|second");
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.lang.String");
|
property.setType("java.lang.String");
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
||||||
+ "|`+first{vbar}" + NEWLINE + "second+`" + NEWLINE
|
+ "|`+first{vbar}" + NEWLINE + "second+`" + NEWLINE
|
||||||
+ "|+++This is a description.+++" + NEWLINE);
|
+ "|+++This is a description.+++" + NEWLINE);
|
||||||
|
@ -84,11 +80,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setDefaultValue("first\\second");
|
property.setDefaultValue("first\\second");
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.lang.String");
|
property.setType("java.lang.String");
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString())
|
assertThat(builder.toString())
|
||||||
.isEqualTo("|`+spring.test.prop+`" + NEWLINE + "|`+first\\\\second+`"
|
.isEqualTo("|`+spring.test.prop+`" + NEWLINE + "|`+first\\\\second+`"
|
||||||
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
||||||
|
@ -100,11 +94,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setId("spring.test.prop");
|
property.setId("spring.test.prop");
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.util.Map<java.lang.String,java.lang.String>");
|
property.setType("java.util.Map<java.lang.String,java.lang.String>");
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop.*+`" + NEWLINE + "|"
|
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop.*+`" + NEWLINE + "|"
|
||||||
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
||||||
}
|
}
|
||||||
|
@ -117,11 +109,9 @@ public class SingleKeyEntryTests {
|
||||||
property.setDescription("This is a description.");
|
property.setDescription("This is a description.");
|
||||||
property.setType("java.util.List<java.lang.String>");
|
property.setType("java.util.List<java.lang.String>");
|
||||||
property.setDefaultValue(defaultValue);
|
property.setDefaultValue(defaultValue);
|
||||||
|
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
||||||
SingleKeyEntry entry = new SingleKeyEntry(property);
|
AsciidocBuilder builder = new AsciidocBuilder();
|
||||||
StringBuilder builder = new StringBuilder();
|
entry.write(builder);
|
||||||
entry.writeAsciidoc(builder);
|
|
||||||
|
|
||||||
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
assertThat(builder.toString()).isEqualTo("|`+spring.test.prop+`" + NEWLINE
|
||||||
+ "|`+first," + NEWLINE + "second," + NEWLINE + "third+`" + NEWLINE
|
+ "|`+first," + NEWLINE + "second," + NEWLINE + "third+`" + NEWLINE
|
||||||
+ "|+++This is a description.+++" + NEWLINE);
|
+ "|+++This is a description.+++" + NEWLINE);
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
@ -61,11 +62,8 @@ class ConstructorParameterPropertyDescriptor extends PropertyDescriptor<Variable
|
||||||
|
|
||||||
private Object getDefaultValueFromAnnotation(
|
private Object getDefaultValueFromAnnotation(
|
||||||
MetadataGenerationEnvironment environment, Element element) {
|
MetadataGenerationEnvironment environment, Element element) {
|
||||||
AnnotationMirror defaultValueAnnotation = environment
|
AnnotationMirror annotation = environment.getDefaultValueAnnotation(element);
|
||||||
.getDefaultValueAnnotation(element);
|
List<String> defaultValue = getDefaultValue(environment, annotation);
|
||||||
if (defaultValueAnnotation != null) {
|
|
||||||
List<String> defaultValue = (List<String>) environment
|
|
||||||
.getAnnotationElementValues(defaultValueAnnotation).get("value");
|
|
||||||
if (defaultValue != null) {
|
if (defaultValue != null) {
|
||||||
try {
|
try {
|
||||||
TypeMirror specificType = determineSpecificType(environment);
|
TypeMirror specificType = determineSpecificType(environment);
|
||||||
|
@ -78,13 +76,22 @@ class ConstructorParameterPropertyDescriptor extends PropertyDescriptor<Variable
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ex) {
|
catch (IllegalArgumentException ex) {
|
||||||
environment.getMessager().printMessage(Kind.ERROR, ex.getMessage(),
|
environment.getMessager().printMessage(Kind.ERROR, ex.getMessage(),
|
||||||
element, defaultValueAnnotation);
|
element, annotation);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<String> getDefaultValue(MetadataGenerationEnvironment environment,
|
||||||
|
AnnotationMirror annotation) {
|
||||||
|
if (annotation == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String, Object> values = environment.getAnnotationElementValues(annotation);
|
||||||
|
return (List<String>) values.get("value");
|
||||||
|
}
|
||||||
|
|
||||||
private TypeMirror determineSpecificType(MetadataGenerationEnvironment environment) {
|
private TypeMirror determineSpecificType(MetadataGenerationEnvironment environment) {
|
||||||
TypeMirror candidate = getSource().asType();
|
TypeMirror candidate = getSource().asType();
|
||||||
TypeMirror elementCandidate = environment.getTypeUtils()
|
TypeMirror elementCandidate = environment.getTypeUtils()
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -49,7 +50,24 @@ class MetadataGenerationEnvironment {
|
||||||
|
|
||||||
private static final String NULLABLE_ANNOTATION = "org.springframework.lang.Nullable";
|
private static final String NULLABLE_ANNOTATION = "org.springframework.lang.Nullable";
|
||||||
|
|
||||||
private final Set<String> typeExcludes;
|
private static final Set<String> TYPE_EXCLUDES;
|
||||||
|
static {
|
||||||
|
Set<String> excludes = new HashSet<>();
|
||||||
|
excludes.add("com.zaxxer.hikari.IConnectionCustomizer");
|
||||||
|
excludes.add("groovy.text.markup.MarkupTemplateEngine");
|
||||||
|
excludes.add("java.io.Writer");
|
||||||
|
excludes.add("java.io.PrintWriter");
|
||||||
|
excludes.add("java.lang.ClassLoader");
|
||||||
|
excludes.add("java.util.concurrent.ThreadFactory");
|
||||||
|
excludes.add("javax.jms.XAConnectionFactory");
|
||||||
|
excludes.add("javax.sql.DataSource");
|
||||||
|
excludes.add("javax.sql.XADataSource");
|
||||||
|
excludes.add("org.apache.tomcat.jdbc.pool.PoolConfiguration");
|
||||||
|
excludes.add("org.apache.tomcat.jdbc.pool.Validator");
|
||||||
|
excludes.add("org.flywaydb.core.api.callback.FlywayCallback");
|
||||||
|
excludes.add("org.flywaydb.core.api.resolver.MigrationResolver");
|
||||||
|
TYPE_EXCLUDES = Collections.unmodifiableSet(excludes);
|
||||||
|
}
|
||||||
|
|
||||||
private final TypeUtils typeUtils;
|
private final TypeUtils typeUtils;
|
||||||
|
|
||||||
|
@ -79,7 +97,6 @@ class MetadataGenerationEnvironment {
|
||||||
String deprecatedConfigurationPropertyAnnotation,
|
String deprecatedConfigurationPropertyAnnotation,
|
||||||
String defaultValueAnnotation, String endpointAnnotation,
|
String defaultValueAnnotation, String endpointAnnotation,
|
||||||
String readOperationAnnotation) {
|
String readOperationAnnotation) {
|
||||||
this.typeExcludes = determineTypeExcludes();
|
|
||||||
this.typeUtils = new TypeUtils(environment);
|
this.typeUtils = new TypeUtils(environment);
|
||||||
this.elements = environment.getElementUtils();
|
this.elements = environment.getElementUtils();
|
||||||
this.messager = environment.getMessager();
|
this.messager = environment.getMessager();
|
||||||
|
@ -92,24 +109,6 @@ class MetadataGenerationEnvironment {
|
||||||
this.readOperationAnnotation = readOperationAnnotation;
|
this.readOperationAnnotation = readOperationAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<String> determineTypeExcludes() {
|
|
||||||
Set<String> excludes = new HashSet<>();
|
|
||||||
excludes.add("com.zaxxer.hikari.IConnectionCustomizer");
|
|
||||||
excludes.add("groovy.text.markup.MarkupTemplateEngine");
|
|
||||||
excludes.add("java.io.Writer");
|
|
||||||
excludes.add("java.io.PrintWriter");
|
|
||||||
excludes.add("java.lang.ClassLoader");
|
|
||||||
excludes.add("java.util.concurrent.ThreadFactory");
|
|
||||||
excludes.add("javax.jms.XAConnectionFactory");
|
|
||||||
excludes.add("javax.sql.DataSource");
|
|
||||||
excludes.add("javax.sql.XADataSource");
|
|
||||||
excludes.add("org.apache.tomcat.jdbc.pool.PoolConfiguration");
|
|
||||||
excludes.add("org.apache.tomcat.jdbc.pool.Validator");
|
|
||||||
excludes.add("org.flywaydb.core.api.callback.FlywayCallback");
|
|
||||||
excludes.add("org.flywaydb.core.api.resolver.MigrationResolver");
|
|
||||||
return excludes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FieldValuesParser resolveFieldValuesParser(ProcessingEnvironment env) {
|
private static FieldValuesParser resolveFieldValuesParser(ProcessingEnvironment env) {
|
||||||
try {
|
try {
|
||||||
return new JavaCompilerFieldValuesParser(env);
|
return new JavaCompilerFieldValuesParser(env);
|
||||||
|
@ -147,7 +146,7 @@ class MetadataGenerationEnvironment {
|
||||||
if (typeName.endsWith("[]")) {
|
if (typeName.endsWith("[]")) {
|
||||||
typeName = typeName.substring(0, typeName.length() - 2);
|
typeName = typeName.substring(0, typeName.length() - 2);
|
||||||
}
|
}
|
||||||
return this.typeExcludes.contains(typeName);
|
return TYPE_EXCLUDES.contains(typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeprecated(Element element) {
|
public boolean isDeprecated(Element element) {
|
||||||
|
|
|
@ -164,10 +164,9 @@ class TypeUtils {
|
||||||
return this.types.getDeclaredType(this.env.getElementUtils()
|
return this.types.getDeclaredType(this.env.getElementUtils()
|
||||||
.getTypeElement(Object.class.getName()));
|
.getTypeElement(Object.class.getName()));
|
||||||
}
|
}
|
||||||
else { // return type argument to Collection<...>
|
// return type argument to Collection<...>
|
||||||
return declaredType.getTypeArguments().get(0);
|
return declaredType.getTypeArguments().get(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// recursively walk the supertypes, looking for Collection<...>
|
// recursively walk the supertypes, looking for Collection<...>
|
||||||
for (TypeMirror superType : this.env.getTypeUtils().directSupertypes(type)) {
|
for (TypeMirror superType : this.env.getTypeUtils().directSupertypes(type)) {
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
package org.springframework.boot.cloud;
|
package org.springframework.boot.cloud;
|
||||||
|
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.EnumerablePropertySource;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple detection for well known cloud platforms. For more advanced cloud provider
|
* Simple detection for well known cloud platforms. For more advanced cloud provider
|
||||||
|
@ -73,27 +73,42 @@ public enum CloudPlatform {
|
||||||
* Kubernetes platform.
|
* Kubernetes platform.
|
||||||
*/
|
*/
|
||||||
KUBERNETES {
|
KUBERNETES {
|
||||||
|
|
||||||
|
private static final String SERVICE_HOST_SUFFIX = "_SERVICE_HOST";
|
||||||
|
|
||||||
|
private static final String SERVICE_PORT_SUFFIX = "_SERVICE_PORT";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive(Environment environment) {
|
public boolean isActive(Environment environment) {
|
||||||
if (environment instanceof ConfigurableEnvironment) {
|
if (environment instanceof ConfigurableEnvironment) {
|
||||||
MapPropertySource propertySource = (MapPropertySource) ((ConfigurableEnvironment) environment)
|
return isActive((ConfigurableEnvironment) environment);
|
||||||
.getPropertySources()
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActive(ConfigurableEnvironment environment) {
|
||||||
|
PropertySource<?> environmentPropertySource = environment.getPropertySources()
|
||||||
.get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
|
.get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
|
||||||
if (propertySource != null) {
|
if (environmentPropertySource instanceof EnumerablePropertySource) {
|
||||||
for (String name : propertySource.getPropertyNames()) {
|
return isActive((EnumerablePropertySource<?>) environmentPropertySource);
|
||||||
if (name.endsWith("_SERVICE_HOST")) {
|
}
|
||||||
String serviceName = StringUtils.split(name,
|
return false;
|
||||||
"_SERVICE_HOST")[0];
|
}
|
||||||
if (propertySource
|
|
||||||
.getProperty(serviceName + "_SERVICE_PORT") != null) {
|
private boolean isActive(EnumerablePropertySource<?> environmentPropertySource) {
|
||||||
|
for (String propertyName : environmentPropertySource.getPropertyNames()) {
|
||||||
|
if (propertyName.endsWith(SERVICE_HOST_SUFFIX)) {
|
||||||
|
String serviceName = propertyName.substring(0,
|
||||||
|
propertyName.length() - SERVICE_HOST_SUFFIX.length());
|
||||||
|
if (environmentPropertySource
|
||||||
|
.getProperty(serviceName + SERVICE_PORT_SUFFIX) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -116,6 +116,9 @@ public class ConfigFileApplicationListener
|
||||||
|
|
||||||
private static final Bindable<String[]> STRING_ARRAY = Bindable.of(String[].class);
|
private static final Bindable<String[]> STRING_ARRAY = Bindable.of(String[].class);
|
||||||
|
|
||||||
|
private static final Bindable<List<String>> STRING_LIST = Bindable
|
||||||
|
.listOf(String.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "active profiles" property name.
|
* The "active profiles" property name.
|
||||||
*/
|
*/
|
||||||
|
@ -701,18 +704,6 @@ public class ConfigFileApplicationListener
|
||||||
return new LinkedHashSet<>(list);
|
return new LinkedHashSet<>(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This ensures that the order of active profiles in the {@link Environment}
|
|
||||||
* matches the order in which the profiles were processed.
|
|
||||||
* @param processedProfiles the processed profiles
|
|
||||||
*/
|
|
||||||
private void resetEnvironmentProfiles(List<Profile> processedProfiles) {
|
|
||||||
String[] names = processedProfiles.stream()
|
|
||||||
.filter((profile) -> profile != null && !profile.isDefaultProfile())
|
|
||||||
.map(Profile::getName).toArray(String[]::new);
|
|
||||||
this.environment.setActiveProfiles(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addLoadedPropertySources() {
|
private void addLoadedPropertySources() {
|
||||||
MutablePropertySources destination = this.environment.getPropertySources();
|
MutablePropertySources destination = this.environment.getPropertySources();
|
||||||
List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
|
List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
|
||||||
|
@ -773,8 +764,7 @@ public class ConfigFileApplicationListener
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getDefaultProfiles(Binder binder, String property) {
|
private List<String> getDefaultProfiles(Binder binder, String property) {
|
||||||
return Arrays
|
return binder.bind(property, STRING_LIST).orElse(Collections.emptyList());
|
||||||
.asList(binder.bind(property, STRING_ARRAY).orElse(new String[] {}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,12 +91,10 @@ final class ConfigurationPropertiesBeanDefinitionRegistrar {
|
||||||
if (canBindAtCreationTime(type)) {
|
if (canBindAtCreationTime(type)) {
|
||||||
return ConfigurationPropertiesBeanDefinition.from(beanFactory, name, type);
|
return ConfigurationPropertiesBeanDefinition.from(beanFactory, name, type);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
GenericBeanDefinition definition = new GenericBeanDefinition();
|
GenericBeanDefinition definition = new GenericBeanDefinition();
|
||||||
definition.setBeanClass(type);
|
definition.setBeanClass(type);
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean canBindAtCreationTime(Class<?> type) {
|
private static boolean canBindAtCreationTime(Class<?> type) {
|
||||||
List<Constructor<?>> constructors = determineConstructors(type);
|
List<Constructor<?>> constructors = determineConstructors(type);
|
||||||
|
|
|
@ -72,8 +72,16 @@ class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegist
|
||||||
scanner.addIncludeFilter(new AnnotationTypeFilter(ConfigurationProperties.class));
|
scanner.addIncludeFilter(new AnnotationTypeFilter(ConfigurationProperties.class));
|
||||||
for (String basePackage : packages) {
|
for (String basePackage : packages) {
|
||||||
if (StringUtils.hasText(basePackage)) {
|
if (StringUtils.hasText(basePackage)) {
|
||||||
for (BeanDefinition candidate : scanner
|
scan(beanFactory, registry, scanner, basePackage);
|
||||||
.findCandidateComponents(basePackage)) {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scan(ConfigurableListableBeanFactory beanFactory,
|
||||||
|
BeanDefinitionRegistry registry,
|
||||||
|
ClassPathScanningCandidateComponentProvider scanner, String basePackage)
|
||||||
|
throws LinkageError {
|
||||||
|
for (BeanDefinition candidate : scanner.findCandidateComponents(basePackage)) {
|
||||||
String beanClassName = candidate.getBeanClassName();
|
String beanClassName = candidate.getBeanClassName();
|
||||||
try {
|
try {
|
||||||
Class<?> type = ClassUtils.forName(beanClassName, null);
|
Class<?> type = ClassUtils.forName(beanClassName, null);
|
||||||
|
@ -85,7 +93,5 @@ class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,8 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Class<?>> collectClasses(List<?> values) {
|
private List<Class<?>> collectClasses(List<?> values) {
|
||||||
return values.stream().flatMap((value) -> Arrays.stream((Object[]) value))
|
return values.stream().flatMap((value) -> Arrays.stream((Class<?>[]) value))
|
||||||
.map((o) -> (Class<?>) o).filter((type) -> void.class != type)
|
.filter((type) -> void.class != type).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -58,31 +59,26 @@ class ConstructorParametersBinder implements BeanBinder {
|
||||||
|
|
||||||
private List<Object> bind(BeanPropertyBinder propertyBinder, Bean bean,
|
private List<Object> bind(BeanPropertyBinder propertyBinder, Bean bean,
|
||||||
BindConverter converter) {
|
BindConverter converter) {
|
||||||
List<Object> boundParams = new ArrayList<>();
|
Collection<ConstructorParameter> parameters = bean.getParameters().values();
|
||||||
for (ConstructorParameter parameter : bean.getParameters().values()) {
|
List<Object> boundParameters = new ArrayList<>(parameters.size());
|
||||||
Object bound = bind(parameter, propertyBinder);
|
for (ConstructorParameter parameter : parameters) {
|
||||||
if (bound == null) {
|
Object boundParameter = bind(parameter, propertyBinder);
|
||||||
bound = getDefaultValue(parameter, converter);
|
if (boundParameter == null) {
|
||||||
|
boundParameter = getDefaultValue(parameter, converter);
|
||||||
}
|
}
|
||||||
boundParams.add(bound);
|
boundParameters.add(boundParameter);
|
||||||
}
|
}
|
||||||
return boundParams;
|
return boundParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getDefaultValue(ConstructorParameter parameter,
|
private Object getDefaultValue(ConstructorParameter parameter,
|
||||||
BindConverter converter) {
|
BindConverter converter) {
|
||||||
if (parameter.getDefaultValue() != null) {
|
if (parameter.getDefaultValue() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return converter.convert(parameter.getDefaultValue(), parameter.getType(),
|
return converter.convert(parameter.getDefaultValue(), parameter.getType(),
|
||||||
parameter.getAnnotations());
|
parameter.getAnnotations());
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Class<?> resolve = parameter.getType().resolve();
|
|
||||||
if (resolve != null && resolve.isPrimitive()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object bind(ConstructorParameter parameter,
|
private Object bind(ConstructorParameter parameter,
|
||||||
BeanPropertyBinder propertyBinder) {
|
BeanPropertyBinder propertyBinder) {
|
||||||
|
@ -112,20 +108,9 @@ class ConstructorParametersBinder implements BeanBinder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (KOTLIN_PRESENT && KotlinDetector.isKotlinType(type)) {
|
if (KOTLIN_PRESENT && KotlinDetector.isKotlinType(type)) {
|
||||||
Constructor<?> primaryConstructor = BeanUtils
|
return KotlinBeanProvider.get(type);
|
||||||
.findPrimaryConstructor(type);
|
|
||||||
if (primaryConstructor != null
|
|
||||||
&& primaryConstructor.getParameterCount() > 0) {
|
|
||||||
return KotlinBeanProvider.get(primaryConstructor);
|
|
||||||
}
|
}
|
||||||
}
|
return SimpleBeanProvider.get(type);
|
||||||
else {
|
|
||||||
Constructor<?>[] constructors = type.getDeclaredConstructors();
|
|
||||||
if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
|
|
||||||
return SimpleBeanProvider.get(constructors[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, ConstructorParameter> getParameters() {
|
public Map<String, ConstructorParameter> getParameters() {
|
||||||
|
@ -138,11 +123,59 @@ class ConstructorParametersBinder implements BeanBinder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bean provider for a Kotlin class. Uses the Kotlin constructor to extract the
|
||||||
|
* parameter names.
|
||||||
|
*/
|
||||||
|
private static class KotlinBeanProvider {
|
||||||
|
|
||||||
|
public static Bean get(Class<?> type) {
|
||||||
|
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(type);
|
||||||
|
if (primaryConstructor != null
|
||||||
|
&& primaryConstructor.getParameterCount() > 0) {
|
||||||
|
return get(primaryConstructor);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bean get(Constructor<?> constructor) {
|
||||||
|
KFunction<?> kotlinConstructor = ReflectJvmMapping
|
||||||
|
.getKotlinFunction(constructor);
|
||||||
|
if (kotlinConstructor != null) {
|
||||||
|
return new Bean(constructor, parseParameters(kotlinConstructor));
|
||||||
|
}
|
||||||
|
return SimpleBeanProvider.get(constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, ConstructorParameter> parseParameters(
|
||||||
|
KFunction<?> constructor) {
|
||||||
|
Map<String, ConstructorParameter> parameters = new LinkedHashMap<>();
|
||||||
|
for (KParameter parameter : constructor.getParameters()) {
|
||||||
|
String name = parameter.getName();
|
||||||
|
Type type = ReflectJvmMapping.getJavaType(parameter.getType());
|
||||||
|
Annotation[] annotations = parameter.getAnnotations()
|
||||||
|
.toArray(new Annotation[0]);
|
||||||
|
parameters.computeIfAbsent(name, (s) -> new ConstructorParameter(name,
|
||||||
|
ResolvableType.forType(type), annotations, null));
|
||||||
|
}
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple bean provider that uses `-parameters` to extract the parameter names.
|
* A simple bean provider that uses `-parameters` to extract the parameter names.
|
||||||
*/
|
*/
|
||||||
private static class SimpleBeanProvider {
|
private static class SimpleBeanProvider {
|
||||||
|
|
||||||
|
public static Bean get(Class<?> type) {
|
||||||
|
Constructor<?>[] constructors = type.getDeclaredConstructors();
|
||||||
|
if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
|
||||||
|
return SimpleBeanProvider.get(constructors[0]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static Bean get(Constructor<?> constructor) {
|
public static Bean get(Constructor<?> constructor) {
|
||||||
return new Bean(constructor, parseParameters(constructor));
|
return new Bean(constructor, parseParameters(constructor));
|
||||||
}
|
}
|
||||||
|
@ -157,7 +190,7 @@ class ConstructorParametersBinder implements BeanBinder {
|
||||||
String[] defaultValue = (annotationsByType.length > 0)
|
String[] defaultValue = (annotationsByType.length > 0)
|
||||||
? annotationsByType[0].value() : null;
|
? annotationsByType[0].value() : null;
|
||||||
parameters.computeIfAbsent(name,
|
parameters.computeIfAbsent(name,
|
||||||
(s) -> new ConstructorParameter(name,
|
(key) -> new ConstructorParameter(name,
|
||||||
ResolvableType.forClass(parameter.getType()),
|
ResolvableType.forClass(parameter.getType()),
|
||||||
parameter.getDeclaredAnnotations(), defaultValue));
|
parameter.getDeclaredAnnotations(), defaultValue));
|
||||||
}
|
}
|
||||||
|
@ -166,39 +199,6 @@ class ConstructorParametersBinder implements BeanBinder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A bean provider for a Kotlin class. Uses the Kotlin constructor to extract the
|
|
||||||
* parameter names.
|
|
||||||
*/
|
|
||||||
private static class KotlinBeanProvider {
|
|
||||||
|
|
||||||
public static Bean get(Constructor<?> constructor) {
|
|
||||||
KFunction<?> kotlinConstructor = ReflectJvmMapping
|
|
||||||
.getKotlinFunction(constructor);
|
|
||||||
if (kotlinConstructor != null) {
|
|
||||||
return new Bean(constructor, parseParameters(kotlinConstructor));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return SimpleBeanProvider.get(constructor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, ConstructorParameter> parseParameters(
|
|
||||||
KFunction<?> constructor) {
|
|
||||||
Map<String, ConstructorParameter> parameters = new LinkedHashMap<>();
|
|
||||||
for (KParameter parameter : constructor.getParameters()) {
|
|
||||||
String name = parameter.getName();
|
|
||||||
Type type = ReflectJvmMapping.getJavaType(parameter.getType());
|
|
||||||
Annotation[] annotations = parameter.getAnnotations()
|
|
||||||
.toArray(new Annotation[0]);
|
|
||||||
parameters.computeIfAbsent(name, (s) -> new ConstructorParameter(name,
|
|
||||||
ResolvableType.forType(type), annotations, null));
|
|
||||||
}
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constructor parameter being bound.
|
* A constructor parameter being bound.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -174,7 +174,9 @@ class DefaultLogbackConfiguration {
|
||||||
|
|
||||||
private DataSize getDataSize(String property, DataSize defaultSize) {
|
private DataSize getDataSize(String property, DataSize defaultSize) {
|
||||||
String value = this.patterns.getProperty(property);
|
String value = this.patterns.getProperty(property);
|
||||||
if (value != null) {
|
if (value == null) {
|
||||||
|
return defaultSize;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return DataSize.parse(value);
|
return DataSize.parse(value);
|
||||||
}
|
}
|
||||||
|
@ -183,9 +185,5 @@ class DefaultLogbackConfiguration {
|
||||||
return DataSize.ofBytes(fileSize.getSize());
|
return DataSize.ofBytes(fileSize.getSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return defaultSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,8 +240,8 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||||
@Test
|
@Test
|
||||||
public void springConfigLocations() {
|
public void springConfigLocations() {
|
||||||
String[] locations = getSpringConfigLocations(this.loggingSystem);
|
String[] locations = getSpringConfigLocations(this.loggingSystem);
|
||||||
assertThat(locations).isEqualTo(
|
assertThat(locations).containsExactly("log4j2-spring.properties",
|
||||||
new String[] { "log4j2-spring.properties", "log4j2-spring.xml" });
|
"log4j2-spring.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -20,8 +20,10 @@ import sample.tomcat.service.HelloWorldService;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class SampleController {
|
public class SampleController {
|
||||||
|
@ -32,7 +34,12 @@ public class SampleController {
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String helloWorld() {
|
public String helloWorld() {
|
||||||
return this.helloWorldService.getHelloMessage();
|
throw new RuntimeException("Fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(RuntimeException.class)
|
||||||
|
public ModelAndView handle(RuntimeException ex) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
server.compression.enabled: true
|
server.compression.enabled: true
|
||||||
server.compression.min-response-size: 1
|
server.compression.min-response-size: 1
|
||||||
server.connection-timeout=5000
|
server.connection-timeout=5000
|
||||||
|
|
||||||
|
spring.mvc.log-resolved-exception=true
|
||||||
|
|
Loading…
Reference in New Issue