Skip to content

Commit

Permalink
Polish
Browse files Browse the repository at this point in the history
  • Loading branch information
philwebb committed Feb 27, 2018
1 parent c7ed5c3 commit 3e4da3c
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,36 +41,46 @@ public class AppSystemPropertiesTests {

@Test
public void bindWithDefaultUnit() {
this.contextRunner.withPropertyValues("app.system.session-timeout=40",
"app.system.read-timeout=5000").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofSeconds(40));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(5000));
}));
this.contextRunner
.withPropertyValues("app.system.session-timeout=40",
"app.system.read-timeout=5000")
.run(assertBinding((properties) -> {
assertThat(properties.getSessionTimeout())
.isEqualTo(Duration.ofSeconds(40));
assertThat(properties.getReadTimeout())
.isEqualTo(Duration.ofMillis(5000));
}));
}

@Test
public void bindWithExplicitUnit() {
this.contextRunner.withPropertyValues("app.system.session-timeout=1h",
"app.system.read-timeout=5s").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofMinutes(60));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(5000));
}));
"app.system.read-timeout=5s").run(assertBinding((properties) -> {
assertThat(properties.getSessionTimeout())
.isEqualTo(Duration.ofMinutes(60));
assertThat(properties.getReadTimeout())
.isEqualTo(Duration.ofMillis(5000));
}));
}

@Test
public void bindWithIso8601Format() {
this.contextRunner.withPropertyValues("app.system.session-timeout=PT15S",
"app.system.read-timeout=PT0.5S").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofSeconds(15));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(500));
}));
this.contextRunner
.withPropertyValues("app.system.session-timeout=PT15S",
"app.system.read-timeout=PT0.5S")
.run(assertBinding((properties) -> {
assertThat(properties.getSessionTimeout())
.isEqualTo(Duration.ofSeconds(15));
assertThat(properties.getReadTimeout())
.isEqualTo(Duration.ofMillis(500));
}));
}

private ContextConsumer<AssertableApplicationContext> assertBinding(
Consumer<AppSystemProperties> appSystemProperties) {
Consumer<AppSystemProperties> properties) {
return (context) -> {
assertThat(context).hasSingleBean(AppSystemProperties.class);
appSystemProperties.accept(context.getBean(AppSystemProperties.class));
properties.accept(context.getBean(AppSystemProperties.class));
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@
*/
@SpringBootConfiguration
@ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class })
DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class })
class SampleWebClientConfiguration {


@RestController
private static class ExampleController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ static class Config {

@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder()
.setConnectTimeout(1000)
.setReadTimeout(1000);
return new RestTemplateBuilder().setConnectTimeout(1000).setReadTimeout(1000);
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
Expand Down Expand Up @@ -62,16 +61,27 @@ class BindConverter {
BindConverter(ConversionService conversionService,
Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
Assert.notNull(conversionService, "ConversionService must not be null");
this.conversionService = new CompositeConversionService(
new TypeConverterConversionService(propertyEditorInitializer),
conversionService);
List<ConversionService> conversionServices = getConversionServices(
conversionService, propertyEditorInitializer);
this.conversionService = new CompositeConversionService(conversionServices);
}

private List<ConversionService> getConversionServices(
ConversionService conversionService,
Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
List<ConversionService> services = new ArrayList<>();
services.add(new TypeConverterConversionService(propertyEditorInitializer));
services.add(conversionService);
if (!(conversionService instanceof ApplicationConversionService)) {
services.add(ApplicationConversionService.getSharedInstance());
}
return services;
}

public boolean canConvert(Object value, ResolvableType type,
Annotation... annotations) {
TypeDescriptor sourceType = TypeDescriptor.forObject(value);
TypeDescriptor targetType = new ResolvableTypeDescriptor(type, annotations);
return this.conversionService.canConvert(sourceType, targetType);
return this.conversionService.canConvert(TypeDescriptor.forObject(value),
new ResolvableTypeDescriptor(type, annotations));
}

public <T> T convert(Object result, Bindable<T> target) {
Expand All @@ -83,9 +93,8 @@ public <T> T convert(Object value, ResolvableType type, Annotation... annotation
if (value == null) {
return null;
}
TypeDescriptor sourceType = TypeDescriptor.forObject(value);
TypeDescriptor targetType = new ResolvableTypeDescriptor(type, annotations);
return (T) this.conversionService.convert(value, sourceType, targetType);
return (T) this.conversionService.convert(value, TypeDescriptor.forObject(value),
new ResolvableTypeDescriptor(type, annotations));
}

/**
Expand All @@ -100,22 +109,81 @@ private static class ResolvableTypeDescriptor extends TypeDescriptor {

}

/**
* Composite {@link ConversionService} used to call multiple services
*/
static class CompositeConversionService implements ConversionService {

private final List<ConversionService> delegates;

CompositeConversionService(List<ConversionService> delegates) {
this.delegates = delegates;
}

@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null");
return canConvert(
(sourceType != null ? TypeDescriptor.valueOf(sourceType) : null),
TypeDescriptor.valueOf(targetType));
}

@Override
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
for (ConversionService service : this.delegates) {
if (service.canConvert(sourceType, targetType)) {
return true;
}
}
return false;
}

@Override
@SuppressWarnings("unchecked")
public <T> T convert(Object source, Class<T> targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null");
return (T) convert(source, TypeDescriptor.forObject(source),
TypeDescriptor.valueOf(targetType));
}

@Override
public Object convert(Object source, TypeDescriptor sourceType,
TypeDescriptor targetType) {
for (int i = 0; i < this.delegates.size() - 1; i++) {
try {
ConversionService delegate = this.delegates.get(i);
if (delegate.canConvert(sourceType, targetType)) {
return delegate.convert(source, sourceType, targetType);
}
}
catch (ConversionException ex) {
}
}
return this.delegates.get(this.delegates.size() - 1).convert(source,
sourceType, targetType);
}

}

/**
* A {@link ConversionService} implementation that delegates to a
* {@link SimpleTypeConverter}. Allows {@link PropertyEditor} based conversion for
* simple types, arrays and collections.
*/
private static class TypeConverterConversionService extends GenericConversionService {

private SimpleTypeConverter typeConverter;

TypeConverterConversionService(Consumer<PropertyEditorRegistry> initializer) {
this.typeConverter = new SimpleTypeConverter();
addConverter(new TypeConverterConverter(createTypeConverter(initializer)));
ApplicationConversionService.addDelimitedStringConverters(this);
}

private SimpleTypeConverter createTypeConverter(
Consumer<PropertyEditorRegistry> initializer) {
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
if (initializer != null) {
initializer.accept(this.typeConverter);
initializer.accept(typeConverter);
}
addConverter(new TypeConverterConverter(this.typeConverter));
ApplicationConversionService.addDelimitedStringConverters(this);
return typeConverter;
}

@Override
Expand All @@ -135,9 +203,9 @@ public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType)
*/
private static class TypeConverterConverter implements ConditionalGenericConverter {

private SimpleTypeConverter typeConverter;
private final SimpleTypeConverter typeConverter;

TypeConverterConverter(SimpleTypeConverter typeConverter) {
public TypeConverterConverter(SimpleTypeConverter typeConverter) {
this.typeConverter = typeConverter;
}

Expand All @@ -154,18 +222,20 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
@Override
public Object convert(Object source, TypeDescriptor sourceType,
TypeDescriptor targetType) {
return this.typeConverter.convertIfNecessary(source, targetType.getType());
SimpleTypeConverter typeConverter = this.typeConverter;
return typeConverter.convertIfNecessary(source, targetType.getType());
}

private PropertyEditor getPropertyEditor(Class<?> type) {
SimpleTypeConverter typeConverter = this.typeConverter;
if (type == null || type == Object.class
|| Collection.class.isAssignableFrom(type)
|| Map.class.isAssignableFrom(type)) {
return null;
}
PropertyEditor editor = this.typeConverter.getDefaultEditor(type);
PropertyEditor editor = typeConverter.getDefaultEditor(type);
if (editor == null) {
editor = this.typeConverter.findCustomEditor(type, null);
editor = typeConverter.findCustomEditor(type, null);
}
if (editor == null && String.class != type) {
editor = BeanUtils.findEditorByConvention(type);
Expand All @@ -178,66 +248,4 @@ private PropertyEditor getPropertyEditor(Class<?> type) {

}

private static final class CompositeConversionService implements ConversionService {

private final List<ConversionService> delegates;

private CompositeConversionService(
TypeConverterConversionService typeConverterConversionService,
ConversionService conversionService) {
List<ConversionService> delegates = new ArrayList<ConversionService>();
delegates.add(typeConverterConversionService);
delegates.add(conversionService);
if (!(conversionService instanceof ApplicationConversionService)) {
delegates.add(ApplicationConversionService.getSharedInstance());
}
this.delegates = delegates;
}

@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
return canConvert((delegate) -> delegate.canConvert(sourceType, targetType));
}

@Override
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
return canConvert((delegate) -> delegate.canConvert(sourceType, targetType));
}

private boolean canConvert(Predicate<ConversionService> canConvert) {
for (ConversionService delegate : this.delegates) {
if (canConvert.test(delegate)) {
return true;
}
}
return false;
}

@Override
public <T> T convert(Object source, Class<T> targetType) {
Class<?> sourceType = source.getClass();
return convert((delegate) -> delegate.canConvert(sourceType, targetType),
(delegate) -> delegate.convert(source, targetType));
}

@Override
public Object convert(Object source, TypeDescriptor sourceType,
TypeDescriptor targetType) {
return convert((delegate) -> delegate.canConvert(sourceType, targetType),
(delegate) -> delegate.convert(source, sourceType, targetType));
}

public <T> T convert(Predicate<ConversionService> canConvert,
Function<ConversionService, T> convert) {
for (int i = 0; i < this.delegates.size() - 1; i++) {
ConversionService delegate = this.delegates.get(i);
if (canConvert.test(delegate)) {
return convert.apply(delegate);
}
}
return convert.apply(this.delegates.get(this.delegates.size() - 1));
}

}

}
Loading

0 comments on commit 3e4da3c

Please sign in to comment.