下面列出了怎么用org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty的API类实例代码及写法,或者点击链接到github查看源代码。
@EventListener
@Transactional
public void initialize(ApplicationReadyEvent event) {
List<ConfigurationMetadataProperty> metadataProperties = this.resolver.resolve();
this.platforms.forEach(platform -> {
platform.getDeployers().forEach(deployer -> {
List<ConfigurationMetadataPropertyEntity> options = createMetadataPropertyEntities(metadataProperties,
deployer.getType());
deployer.setOptions(options);
this.deployerRepository.save(deployer);
logger.info(String.format(
"Added '%s' platform account '%s' into deployer repository.",
platform.getName(),
deployer.getName()));
});
});
}
@Test
public void testIncludeGroupExcludeProperty() {
this.contextRunner
.withPropertyValues(
"spring.cloud.skipper.server.deployer-properties.group-includes=spring.cloud.deployer.local.port-range",
"spring.cloud.skipper.server.deployer-properties.property-excludes=spring.cloud.deployer.local.port-range.low"
)
.run((context) -> {
SkipperServerProperties skipperServerProperties = context.getBean(SkipperServerProperties.class);
DeployerConfigurationMetadataResolver resolver = new DeployerConfigurationMetadataResolver(
skipperServerProperties.getDeployerProperties());
resolver.setApplicationContext(context);
List<ConfigurationMetadataProperty> data = resolver.resolve();
assertThat(data.size()).isEqualTo(1);
});
}
private DetailedAppRegistrationResource getInfo(ApplicationType type,
String name, String version, Boolean allProperties) {
AppRegistration registration = appRegistryService.find(name, type, version);
if (registration == null) {
throw new NoSuchAppRegistrationException(name, type, version);
}
DetailedAppRegistrationResource result = new DetailedAppRegistrationResource(
assembler.toModel(registration));
List<ConfigurationMetadataProperty> properties = metadataResolver
.listProperties(appRegistryService.getAppMetadataResource(registration), allProperties);
for (ConfigurationMetadataProperty property : properties) {
result.addOption(property);
}
return result;
}
/**
* Retrieve detailed information about a particular application.
* @param type application type
* @param name application name
* @return detailed application information
*/
@RequestMapping(value = "/{type}/{name}", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public DetailedAppRegistrationResource info(
@PathVariable("type") String type,
@PathVariable("name") String name) {
AppRegistration registration = appRegistry.find(name, type);
if (registration == null) {
throw new NoSuchAppRegistrationException(name, type);
}
DetailedAppRegistrationResource result = new DetailedAppRegistrationResource(assembler.toResource(registration));
Resource resource = registration.getResource();
List<ConfigurationMetadataProperty> properties = metadataResolver.listProperties(resource);
for (ConfigurationMetadataProperty property : properties) {
result.addOption(property);
}
return result;
}
private void printProperty(PrintWriter writer, ConfigurationMetadataProperty property) {
writer.print(property.getId());
writer.print('=');
Object defaultValue = property.getDefaultValue();
if (defaultValue != null) {
if (defaultValue.getClass().isArray()) {
defaultValue = Arrays.stream((Object[]) defaultValue)
.map(String::valueOf)
.collect(Collectors.joining(","));
}
writer.print(defaultValue);
}
if (property.getShortDescription() != null) {
writer.print(" # ");
writer.print(property.getShortDescription());
}
writer.println();
}
private void filterProps(String filter) {
DefaultListModel<ConfigurationMetadataProperty> dlmCfgProps = new DefaultListModel<>();
for (ConfigurationMetadataProperty item : sortedProps) {
if (filter == null || item.getId().contains(filter)) {
if (Utils.isErrorDeprecated(item)) {
if (bDeprErrorShow) {
dlmCfgProps.addElement(item);
}
} else {
dlmCfgProps.addElement(item);
}
}
}
lCfgProps.setModel(dlmCfgProps);
if (!dlmCfgProps.isEmpty()) {
lCfgProps.setSelectedIndex(0);
}
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof ConfigurationMetadataProperty) {
ConfigurationMetadataProperty prop = (ConfigurationMetadataProperty) value;
if (prop.isDeprecated()) {
setText(String.format("<html><s>%s", prop.getId()));
if (Utils.isErrorDeprecated(prop)) {
setForeground(UIManager.getColor("nb.errorForeground"));
}
} else {
setText(prop.getId());
}
}
return this;
}
@Override
public int compare(ConfigurationMetadataProperty p1, ConfigurationMetadataProperty p2) {
if (!sortDeprLast) {
return p1.getId().compareTo(p2.getId());
} else {
boolean d1 = p1.isDeprecated();
boolean d2 = p2.isDeprecated();
if (d1 && !d2) {
return 1;
} else if (d2 && !d1) {
return -1;
} else {
return p1.getId().compareTo(p2.getId());
}
}
}
@EventListener
@Transactional
public void initialize(ApplicationReadyEvent event) {
List<ConfigurationMetadataProperty> metadataProperties = this.resolver.resolve();
this.taskPlatforms.forEach(platform -> {
platform.getLaunchers().forEach(launcher -> {
List<ConfigurationMetadataPropertyEntity> options = createMetadataPropertyEntities(metadataProperties,
launcher.getType());
launcher.setOptions(options);
this.launcherRepository.save(launcher);
logger.info(String.format(
"Added '%s' platform account '%s' into Task Launcher repository.",
platform.getName(),
launcher.getName()));
});
});
}
void addValueHintsProposals(final String dsl, AppRegistration appRegistration, final List<CompletionProposal> collector, final String propertyName, final ValueHintProvider[] valueHintProviders){
final Resource metadataResource = this.appRegistry.getAppMetadataResource(appRegistration);
if (metadataResource != null) {
final URLClassLoader classLoader = metadataResolver.createAppClassLoader(metadataResource);
this.doWithClassLoader(classLoader, () -> {
CompletionProposal.Factory proposals = CompletionProposal.expanding(dsl);
List<ConfigurationMetadataProperty> whiteList = metadataResolver.listProperties(metadataResource);
for (ConfigurationMetadataProperty property : metadataResolver.listProperties(metadataResource, true)) {
if (CompletionUtils.isMatchingProperty(propertyName, property, whiteList)) {
for (ValueHintProvider valueHintProvider : valueHintProviders) {
for (ValueHint valueHint : valueHintProvider.generateValueHints(property, classLoader)) {
collector.add(proposals.withSuffix(String.valueOf(valueHint.getValue()),
valueHint.getShortDescription()));
}
}
}
}
return null;
});
}
}
/**
* Return metadata about configuration properties that are documented via <a href=
* "https://docs.spring.io/spring-boot/docs/current/reference/html/configuration-metadata.html">
* Spring Boot configuration metadata</a> and visible in an app.
*
* @param app a Spring Cloud Stream app; typically a Boot uberjar, but directories are
* supported as well
*/
@Override
public List<ConfigurationMetadataProperty> listProperties(Resource app, boolean exhaustive) {
try {
if (app != null) {
if (isDockerSchema(app.getURI())) {
return resolvePropertiesFromContainerImage(app.getURI());
}
else {
Archive archive = resolveAsArchive(app);
return listProperties(archive, exhaustive);
}
}
}
catch (Exception e) {
logger.warn("Failed to retrieve properties for resource:" + app, e);
return Collections.emptyList();
}
return Collections.emptyList();
}
private List<ConfigurationMetadataPropertyEntity> createMetadataPropertyEntities(
List<ConfigurationMetadataProperty> metadataProperties, String type) {
String prefix = KEY_PREFIX + type;
return metadataProperties.stream()
.filter(p -> p.getId().startsWith(prefix))
.map(ConfigurationMetadataPropertyEntity::new)
.collect(Collectors.toList());
}
/**
* Resolve all configuration metadata properties prefixed with {@code spring.cloud.deployer.}
*
* @return the list
*/
public List<ConfigurationMetadataProperty> resolve() {
List<ConfigurationMetadataProperty> metadataProperties = new ArrayList<>();
ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder.create();
try {
Resource[] resources = applicationContext.getResources(CONFIGURATION_METADATA_PATTERN);
for (Resource resource : resources) {
builder.withJsonResource(resource.getInputStream());
}
}
catch (IOException e) {
throw new SkipperException("Unable to read configuration metadata", e);
}
ConfigurationMetadataRepository metadataRepository = builder.build();
Map<String, ConfigurationMetadataGroup> groups = metadataRepository.getAllGroups();
// 1. go through all groups and their properties
// 2. filter 'spring.cloud.deployer.' properties
// 3. pass in only group includes, empty passes through all
// 4. pass in group excludes
// 5. same logic for properties for includes and excludes
// 6. what's left is white/black listed props
groups.values().stream()
.filter(g -> g.getId().startsWith(KEY_PREFIX))
.filter(groupEmptyOrAnyMatch(deployerProperties.getGroupIncludes()))
.filter(groupNoneMatch(deployerProperties.getGroupExcludes()))
.forEach(g -> {
g.getProperties().values().stream()
.filter(propertyEmptyOrAnyMatch(deployerProperties.getPropertyIncludes()))
.filter(propertyNoneMatch(deployerProperties.getPropertyExcludes()))
.forEach(p -> {
metadataProperties.add(p);
});
});
return metadataProperties;
}
/**
* Return whether the given property name should be considered matching the candidate
* configuration property, also taking into account the list of whitelist properties
* (which are tested on their short name).
*/
static boolean isMatchingProperty(String propertyName, ConfigurationMetadataProperty property,
List<ConfigurationMetadataProperty> whiteListedProps) {
if (property.getId().equals(propertyName)) {
return true; // For any prop
} // Handle special case of short form for whitelist
else {
for (ConfigurationMetadataProperty white : whiteListedProps) {
if (property.getId().equals(white.getId())) { // prop#equals() not implemented
return property.getName().equals(propertyName);
}
}
return false;
}
}
@Test
public void testExcludeGroup() {
this.contextRunner
.withPropertyValues(
"spring.cloud.skipper.server.deployer-properties.group-excludes=spring.cloud.deployer.local.port-range"
)
.run((context) -> {
SkipperServerProperties skipperServerProperties = context.getBean(SkipperServerProperties.class);
DeployerConfigurationMetadataResolver resolver = new DeployerConfigurationMetadataResolver(
skipperServerProperties.getDeployerProperties());
resolver.setApplicationContext(context);
List<ConfigurationMetadataProperty> data = resolver.resolve();
assertThat(data.size()).isEqualTo(12);
});
}
@Test
public void deprecatedErrorPropertiesShouldNotBeVisible() {
List<ConfigurationMetadataProperty> properties = resolver
.listProperties(new ClassPathResource("apps/deprecated-error", getClass()));
List<ConfigurationMetadataProperty> full = resolver
.listProperties(new ClassPathResource("apps/deprecated-error", getClass()), true);
assertThat(properties.size(), is(0));
assertThat(full.size(), is(2));
}
@Test
public void testIncludeGroup() {
this.contextRunner
.withPropertyValues(
"spring.cloud.skipper.server.deployer-properties.group-includes=spring.cloud.deployer.local.port-range"
)
.run((context) -> {
SkipperServerProperties skipperServerProperties = context.getBean(SkipperServerProperties.class);
DeployerConfigurationMetadataResolver resolver = new DeployerConfigurationMetadataResolver(
skipperServerProperties.getDeployerProperties());
resolver.setApplicationContext(context);
List<ConfigurationMetadataProperty> data = resolver.resolve();
assertThat(data.size()).isEqualTo(2);
});
}
@Test
public void testIncludeProperty() {
this.contextRunner
.withPropertyValues(
"spring.cloud.skipper.server.deployer-properties.property-includes=spring.cloud.deployer.local.port-range.low"
)
.run((context) -> {
SkipperServerProperties skipperServerProperties = context.getBean(SkipperServerProperties.class);
DeployerConfigurationMetadataResolver resolver = new DeployerConfigurationMetadataResolver(
skipperServerProperties.getDeployerProperties());
resolver.setApplicationContext(context);
List<ConfigurationMetadataProperty> data = resolver.resolve();
assertThat(data.size()).isEqualTo(1);
});
}
@Test
public void testIncludeMultipleProperty() {
this.contextRunner
.withPropertyValues(
"spring.cloud.skipper.server.deployer-properties.property-includes=spring.cloud.deployer.local.port-range.low,spring.cloud.deployer.local.port-range.high"
)
.run((context) -> {
SkipperServerProperties skipperServerProperties = context.getBean(SkipperServerProperties.class);
DeployerConfigurationMetadataResolver resolver = new DeployerConfigurationMetadataResolver(
skipperServerProperties.getDeployerProperties());
resolver.setApplicationContext(context);
List<ConfigurationMetadataProperty> data = resolver.resolve();
assertThat(data.size()).isEqualTo(2);
});
}
public ConfigurationMetadataPropertyEntity(ConfigurationMetadataProperty from) {
super();
setId(from.getId());
setName(from.getName());
setType(from.getType());
setDescription(from.getDescription());
setShortDescription(from.getShortDescription());
setDefaultValue(from.getDefaultValue());
getHints().getKeyHints().addAll(from.getHints().getKeyHints());
getHints().getKeyProviders().addAll(from.getHints().getKeyProviders());
getHints().getValueHints().addAll(from.getHints().getValueHints());
getHints().getValueProviders().addAll(from.getHints().getValueProviders());
setDeprecation(from.getDeprecation());
}
/**
* Return metadata about configuration properties that are documented via
* <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/configuration-metadata.html">
* Spring Boot configuration metadata</a> and visible in an app.
* @param app a Spring Cloud Stream app; typically a Boot uberjar,
* but directories are supported as well
*/
public List<ConfigurationMetadataProperty> listProperties(Resource app, boolean exhaustive) {
try {
Archive archive = resolveAsArchive(app);
return listProperties(archive, exhaustive);
}
catch (IOException e) {
throw new RuntimeException("Failed to list properties for " + app, e);
}
}
@Override
public List<ConfigurationMetadataProperty> listProperties(Resource app, boolean exhaustive) {
for (ApplicationConfigurationMetadataResolver delegate : delegates) {
if (delegate.supports(app)) {
return delegate.listProperties(app, exhaustive);
}
}
return Collections.emptyList();
}
@Test
public void otherPropertiesShouldOnlyBeVisibleInExtensiveCall() {
List<ConfigurationMetadataProperty> properties = resolver.listProperties(new ClassPathResource("apps/filter-processor", getClass()));
assertThat(properties, not(hasItem(configPropertyIdentifiedAs("some.prefix.hidden.by.default.secret"))));
properties = resolver.listProperties(new ClassPathResource("apps/filter-processor", getClass()), true);
assertThat(properties, hasItem(configPropertyIdentifiedAs("some.prefix.hidden.by.default.secret")));
}
@Test
public void shouldReturnEverythingWhenNoDescriptors() {
List<ConfigurationMetadataProperty> properties = resolver.listProperties(new ClassPathResource("apps/no-whitelist", getClass()));
List<ConfigurationMetadataProperty> full = resolver.listProperties(new ClassPathResource("apps/no-whitelist", getClass()), true);
assertThat( properties.size(), greaterThan(0));
assertThat(properties.size(), is(full.size()));
}
/**
* Escapes some special values so that they don't disturb console
* rendering and are easier to read.
*/
private String prettyPrintDefaultValue(ConfigurationMetadataProperty o) {
if (o.getDefaultValue() == null) {
return "<none>";
}
return o.getDefaultValue().toString()
.replace("\n", "\\n")
.replace("\t", "\\t")
.replace("\f", "\\f");
}
/**
* Return whether the given property name should be considered matching the candidate configuration property, also
* taking into account the list of whitelist properties (which are tested on their short name).
*/
static boolean isMatchingProperty(String propertyName, ConfigurationMetadataProperty property, List<ConfigurationMetadataProperty> whiteListedProps) {
if (property.getId().equals(propertyName)) {
return true; // For any prop
} // Handle special case of short form for whitelist
else {
for (ConfigurationMetadataProperty white : whiteListedProps) {
if (property.getId().equals(white.getId())) { // prop#equals() not implemented
return property.getName().equals(propertyName);
}
}
return false;
}
}
@Override
public boolean isExclusive(ConfigurationMetadataProperty property) {
for (ValueProvider valueProvider : property.getValueProviders()) {
if ("any".equals(valueProvider.getName())) {
return false;
}
}
return true;
}
public ConfigurationMetadataPropertyEntity(ConfigurationMetadataProperty from) {
super();
setId(from.getId());
setName(from.getName());
setType(from.getType());
setDescription(from.getDescription());
setShortDescription(from.getShortDescription());
setDefaultValue(from.getDefaultValue());
getHints().getKeyHints().addAll(from.getHints().getKeyHints());
getHints().getKeyProviders().addAll(from.getHints().getKeyProviders());
getHints().getValueHints().addAll(from.getHints().getValueHints());
getHints().getValueProviders().addAll(from.getHints().getValueProviders());
setDeprecation(from.getDeprecation());
}
private void assertNoAmbiguity(List<ConfigurationMetadataProperty> longForms) {
if (longForms.size() > 1) {
Set<String> ids = new HashSet<>(longForms.size());
for (ConfigurationMetadataProperty pty : longForms) {
ids.add(pty.getId());
}
throw new IllegalArgumentException(String.format("Ambiguous short form property '%s' could mean any of %s",
longForms.iterator().next().getName(), ids));
}
}
@TaskAction
public void generatePropertyDocumentation() throws IOException {
ConfigurationMetadataRepository configurationMetadataRepository;
configurationMetadataRepository = ConfigurationMetadataRepositoryJsonBuilder.create()
.withJsonResource(new FileInputStream(getInputFile().getAsFile().get()))
.build();
try (PrintWriter writer = ResourceGroovyMethods.newPrintWriter(getOutputFile().getAsFile().get(), "UTF-8")) {
writer.println("[source,properties,indent=0,subs=\"verbatim,attributes,macros\"]");
writer.println("----");
configurationMetadataRepository.getAllGroups().values().stream()
.sorted(Comparator.comparing(ConfigurationMetadataGroup::getId))
.forEach(group -> {
writer.printf("## %s\n", group.getId());
group.getSources().values()
.stream()
.map(ConfigurationMetadataSource::getShortDescription)
.filter(s -> s != null && !s.isEmpty())
.forEach(d -> writer.printf("# %s\n", d));
group.getProperties().values().stream()
.sorted(Comparator.comparing(ConfigurationMetadataProperty::getId))
.forEach(property -> printProperty(writer, property));
writer.println();
writer.flush();
});
writer.println("----");
}
}