diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/InetAddressEditor.java b/spring-boot/src/main/java/org/springframework/boot/bind/InetAddressEditor.java deleted file mode 100644 index 2175fde7fc..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/InetAddressEditor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.beans.PropertyEditor; -import java.beans.PropertyEditorSupport; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * {@link PropertyEditor} for {@link InetAddress} objects. - * - * @author Dave Syer - */ -@Deprecated -public class InetAddressEditor extends PropertyEditorSupport { - - @Override - public String getAsText() { - return ((InetAddress) getValue()).getHostAddress(); - } - - @Override - public void setAsText(String text) throws IllegalArgumentException { - try { - setValue(InetAddress.getByName(text)); - } - catch (UnknownHostException ex) { - throw new IllegalArgumentException("Cannot locate host", ex); - } - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/OriginCapablePropertyValue.java b/spring-boot/src/main/java/org/springframework/boot/bind/OriginCapablePropertyValue.java deleted file mode 100644 index 9332ed48b6..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/OriginCapablePropertyValue.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import org.springframework.beans.PropertyValue; -import org.springframework.core.env.PropertySource; - -/** - * A {@link PropertyValue} that can provide information about its origin. - * - * @author Andy Wilkinson - */ -@Deprecated -class OriginCapablePropertyValue extends PropertyValue { - - private static final String ATTRIBUTE_PROPERTY_ORIGIN = "propertyOrigin"; - - private final PropertyOrigin origin; - - OriginCapablePropertyValue(PropertyValue propertyValue) { - this(propertyValue.getName(), propertyValue.getValue(), - (PropertyOrigin) propertyValue.getAttribute(ATTRIBUTE_PROPERTY_ORIGIN)); - } - - OriginCapablePropertyValue(String name, Object value, String originName, - PropertySource originSource) { - this(name, value, new PropertyOrigin(originSource, originName)); - } - - OriginCapablePropertyValue(String name, Object value, PropertyOrigin origin) { - super(name, value); - this.origin = origin; - setAttribute(ATTRIBUTE_PROPERTY_ORIGIN, origin); - } - - public PropertyOrigin getOrigin() { - return this.origin; - } - - @Override - public String toString() { - String name = this.origin != null ? this.origin.getName() : this.getName(); - String source = this.origin.getSource() != null - ? this.origin.getSource().getName() : "unknown"; - return "'" + name + "' from '" + source + "'"; - } - - public static PropertyOrigin getOrigin(PropertyValue propertyValue) { - if (propertyValue instanceof OriginCapablePropertyValue) { - return ((OriginCapablePropertyValue) propertyValue).getOrigin(); - } - return new OriginCapablePropertyValue(propertyValue).getOrigin(); - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/PatternPropertyNamePatternsMatcher.java b/spring-boot/src/main/java/org/springframework/boot/bind/PatternPropertyNamePatternsMatcher.java deleted file mode 100644 index b95883d5cc..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/PatternPropertyNamePatternsMatcher.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Collection; - -import org.springframework.util.PatternMatchUtils; - -/** - * {@link PropertyNamePatternsMatcher} that delegates to - * {@link PatternMatchUtils#simpleMatch(String[], String)}. - * - * @author Phillip Webb - * @since 1.2.0 - */ -@Deprecated -class PatternPropertyNamePatternsMatcher implements PropertyNamePatternsMatcher { - - private final String[] patterns; - - PatternPropertyNamePatternsMatcher(Collection patterns) { - this.patterns = (patterns == null ? new String[] {} - : patterns.toArray(new String[patterns.size()])); - } - - @Override - public boolean matches(String propertyName) { - return PatternMatchUtils.simpleMatch(this.patterns, propertyName); - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/PropertyNamePatternsMatcher.java b/spring-boot/src/main/java/org/springframework/boot/bind/PropertyNamePatternsMatcher.java deleted file mode 100644 index 7ac154149e..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/PropertyNamePatternsMatcher.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -/** - * Strategy interface used to check if a property name matches specific criteria. - * - * @author Phillip Webb - * @since 1.2.0 - */ -@Deprecated -interface PropertyNamePatternsMatcher { - - PropertyNamePatternsMatcher ALL = new PropertyNamePatternsMatcher() { - - @Override - public boolean matches(String propertyName) { - return true; - } - - }; - - PropertyNamePatternsMatcher NONE = new PropertyNamePatternsMatcher() { - - @Override - public boolean matches(String propertyName) { - return false; - } - - }; - - /** - * Return {@code true} of the property name matches. - * @param propertyName the property name - * @return {@code true} if the property name matches - */ - boolean matches(String propertyName); - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/PropertyOrigin.java b/spring-boot/src/main/java/org/springframework/boot/bind/PropertyOrigin.java deleted file mode 100644 index d07de560af..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/PropertyOrigin.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import org.springframework.core.env.PropertySource; - -/** - * The origin of a property, specifically its source and its name before any prefix was - * removed. - * - * @author Andy Wilkinson - * @since 1.3.0 - */ -@Deprecated -public class PropertyOrigin { - - private final PropertySource source; - - private final String name; - - PropertyOrigin(PropertySource source, String name) { - this.name = name; - this.source = source; - } - - public PropertySource getSource() { - return this.source; - } - - public String getName() { - return this.name; - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java b/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java deleted file mode 100644 index a7a7c4632d..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.PropertyValues; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.core.env.CompositePropertySource; -import org.springframework.core.env.EnumerablePropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.core.env.PropertySources; -import org.springframework.core.env.PropertySourcesPropertyResolver; -import org.springframework.util.Assert; -import org.springframework.validation.DataBinder; - -/** - * A {@link PropertyValues} implementation backed by a {@link PropertySources}, bridging - * the two abstractions and allowing (for instance) a regular {@link DataBinder} to be - * used with the latter. - * - * @author Dave Syer - * @author Phillip Webb - */ -@Deprecated -public class PropertySourcesPropertyValues implements PropertyValues { - - private static final Pattern COLLECTION_PROPERTY = Pattern - .compile("\\[(\\d+)\\](\\.\\S+)?"); - - private final PropertySources propertySources; - - private final Collection nonEnumerableFallbackNames; - - private final PropertyNamePatternsMatcher includes; - - private final Map propertyValues = new LinkedHashMap<>(); - - private final ConcurrentHashMap> collectionOwners = new ConcurrentHashMap<>(); - - private final boolean resolvePlaceholders; - - /** - * Create a new PropertyValues from the given PropertySources. - * @param propertySources a PropertySources instance - */ - public PropertySourcesPropertyValues(PropertySources propertySources) { - this(propertySources, true); - } - - /** - * Create a new PropertyValues from the given PropertySources that will optionally - * resolve placeholders. - * @param propertySources a PropertySources instance - * @param resolvePlaceholders {@code true} if placeholders should be resolved. - * @since 1.5.2 - */ - public PropertySourcesPropertyValues(PropertySources propertySources, - boolean resolvePlaceholders) { - this(propertySources, (Collection) null, PropertyNamePatternsMatcher.ALL, - resolvePlaceholders); - } - - /** - * Create a new PropertyValues from the given PropertySources. - * @param propertySources a PropertySources instance - * @param includePatterns property name patterns to include from system properties and - * environment variables - * @param nonEnumerableFallbackNames the property names to try in lieu of an - * {@link EnumerablePropertySource}. - */ - public PropertySourcesPropertyValues(PropertySources propertySources, - Collection includePatterns, - Collection nonEnumerableFallbackNames) { - this(propertySources, nonEnumerableFallbackNames, - new PatternPropertyNamePatternsMatcher(includePatterns), true); - } - - /** - * Create a new PropertyValues from the given PropertySources. - * @param propertySources a PropertySources instance - * @param nonEnumerableFallbackNames the property names to try in lieu of an - * {@link EnumerablePropertySource}. - * @param includes the property name patterns to include - * @param resolvePlaceholders flag to indicate the placeholders should be resolved - */ - PropertySourcesPropertyValues(PropertySources propertySources, - Collection nonEnumerableFallbackNames, - PropertyNamePatternsMatcher includes, boolean resolvePlaceholders) { - Assert.notNull(propertySources, "PropertySources must not be null"); - Assert.notNull(includes, "Includes must not be null"); - MutablePropertySources mutablePropertySources = new MutablePropertySources( - propertySources); - mutablePropertySources.remove(ConfigurationPropertySources.PROPERTY_SOURCE_NAME); - propertySources = mutablePropertySources; - this.propertySources = propertySources; - this.nonEnumerableFallbackNames = nonEnumerableFallbackNames; - this.includes = includes; - this.resolvePlaceholders = resolvePlaceholders; - PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver( - propertySources); - for (PropertySource source : propertySources) { - processPropertySource(source, resolver); - } - } - - private void processPropertySource(PropertySource source, - PropertySourcesPropertyResolver resolver) { - if (source instanceof CompositePropertySource) { - processCompositePropertySource((CompositePropertySource) source, resolver); - } - else if (source instanceof EnumerablePropertySource) { - processEnumerablePropertySource((EnumerablePropertySource) source, - resolver, this.includes); - } - else { - processNonEnumerablePropertySource(source, resolver); - } - } - - private void processCompositePropertySource(CompositePropertySource source, - PropertySourcesPropertyResolver resolver) { - for (PropertySource nested : source.getPropertySources()) { - processPropertySource(nested, resolver); - } - } - - private void processEnumerablePropertySource(EnumerablePropertySource source, - PropertySourcesPropertyResolver resolver, - PropertyNamePatternsMatcher includes) { - if (source.getPropertyNames().length > 0) { - for (String propertyName : source.getPropertyNames()) { - if (includes.matches(propertyName)) { - Object value = getEnumerableProperty(source, resolver, propertyName); - putIfAbsent(propertyName, value, source); - } - } - } - } - - private Object getEnumerableProperty(EnumerablePropertySource source, - PropertySourcesPropertyResolver resolver, String propertyName) { - try { - if (this.resolvePlaceholders) { - return resolver.getProperty(propertyName, Object.class); - } - } - catch (RuntimeException ex) { - // Probably could not resolve placeholders, ignore it here - } - return source.getProperty(propertyName); - } - - private void processNonEnumerablePropertySource(PropertySource source, - PropertySourcesPropertyResolver resolver) { - // We can only do exact matches for non-enumerable property names, but - // that's better than nothing... - if (this.nonEnumerableFallbackNames == null) { - return; - } - for (String propertyName : this.nonEnumerableFallbackNames) { - if (!source.containsProperty(propertyName)) { - continue; - } - Object value = null; - try { - value = resolver.getProperty(propertyName, Object.class); - } - catch (RuntimeException ex) { - // Probably could not convert to Object, weird, but ignorable - } - if (value == null) { - value = source.getProperty(propertyName.toUpperCase()); - } - putIfAbsent(propertyName, value, source); - } - } - - @Override - public PropertyValue[] getPropertyValues() { - Collection values = this.propertyValues.values(); - return values.toArray(new PropertyValue[values.size()]); - } - - @Override - public PropertyValue getPropertyValue(String propertyName) { - PropertyValue propertyValue = this.propertyValues.get(propertyName); - if (propertyValue != null) { - return propertyValue; - } - for (PropertySource source : this.propertySources) { - Object value = source.getProperty(propertyName); - propertyValue = putIfAbsent(propertyName, value, source); - if (propertyValue != null) { - return propertyValue; - } - } - return null; - } - - private PropertyValue putIfAbsent(String propertyName, Object value, - PropertySource source) { - if (value != null && !this.propertyValues.containsKey(propertyName)) { - PropertySource collectionOwner = this.collectionOwners.putIfAbsent( - COLLECTION_PROPERTY.matcher(propertyName).replaceAll("[]"), source); - if (collectionOwner == null || collectionOwner == source) { - PropertyValue propertyValue = new OriginCapablePropertyValue(propertyName, - value, propertyName, source); - this.propertyValues.put(propertyName, propertyValue); - return propertyValue; - } - } - return null; - } - - @Override - public PropertyValues changesSince(PropertyValues old) { - MutablePropertyValues changes = new MutablePropertyValues(); - // for each property value in the new set - for (PropertyValue newValue : getPropertyValues()) { - // if there wasn't an old one, add it - PropertyValue oldValue = old.getPropertyValue(newValue.getName()); - if (oldValue == null || !oldValue.equals(newValue)) { - changes.addPropertyValue(newValue); - } - } - return changes; - } - - @Override - public boolean contains(String propertyName) { - return getPropertyValue(propertyName) != null; - } - - @Override - public boolean isEmpty() { - return this.propertyValues.isEmpty(); - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedBindingNotWritablePropertyException.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedBindingNotWritablePropertyException.java deleted file mode 100644 index 747d42ebb1..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedBindingNotWritablePropertyException.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import org.springframework.beans.NotWritablePropertyException; - -/** - * A custom {@link NotWritablePropertyException} that is thrown when a failure occurs - * during relaxed binding. - * - * @author Andy Wilkinson - * @since 1.3.0 - * @see RelaxedDataBinder - */ -@Deprecated -public class RelaxedBindingNotWritablePropertyException - extends NotWritablePropertyException { - - private final String message; - - private final PropertyOrigin propertyOrigin; - - RelaxedBindingNotWritablePropertyException(NotWritablePropertyException ex, - PropertyOrigin propertyOrigin) { - super(ex.getBeanClass(), ex.getPropertyName()); - this.propertyOrigin = propertyOrigin; - this.message = "Failed to bind '" + propertyOrigin.getName() + "' from '" - + propertyOrigin.getSource().getName() + "' to '" + ex.getPropertyName() - + "' property on '" + ex.getBeanClass().getName() + "'"; - } - - @Override - public String getMessage() { - return this.message; - } - - public PropertyOrigin getPropertyOrigin() { - return this.propertyOrigin; - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedConversionService.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedConversionService.java deleted file mode 100644 index 9e83127e60..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedConversionService.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.EnumSet; -import java.util.Set; - -import org.springframework.core.convert.ConversionFailedException; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterFactory; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.util.Assert; - -/** - * Internal {@link ConversionService} used by {@link RelaxedDataBinder} to support - * additional relaxed conversion. - * - * @author Phillip Webb - * @author Stephane Nicoll - * @since 1.1.0 - */ -@Deprecated -class RelaxedConversionService implements ConversionService { - - private final ConversionService conversionService; - - private final GenericConversionService additionalConverters; - - /** - * Create a new {@link RelaxedConversionService} instance. - * @param conversionService and option root conversion service - */ - RelaxedConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - this.additionalConverters = new GenericConversionService(); - DefaultConversionService.addCollectionConverters(this.additionalConverters); - this.additionalConverters - .addConverterFactory(new StringToEnumIgnoringCaseConverterFactory()); - this.additionalConverters.addConverter(new StringToCharArrayConverter()); - } - - @Override - public boolean canConvert(Class sourceType, Class targetType) { - return (this.conversionService != null - && this.conversionService.canConvert(sourceType, targetType)) - || this.additionalConverters.canConvert(sourceType, targetType); - } - - @Override - public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { - return (this.conversionService != null - && this.conversionService.canConvert(sourceType, targetType)) - || this.additionalConverters.canConvert(sourceType, targetType); - } - - @Override - @SuppressWarnings("unchecked") - public T convert(Object source, Class targetType) { - Assert.notNull(targetType, "The targetType 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) { - if (this.conversionService != null) { - try { - return this.conversionService.convert(source, sourceType, targetType); - } - catch (ConversionFailedException ex) { - // Ignore and try the additional converters - } - } - return this.additionalConverters.convert(source, sourceType, targetType); - } - - /** - * Clone of Spring's package private StringToEnumConverterFactory, but ignoring the - * case of the source. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static class StringToEnumIgnoringCaseConverterFactory - implements ConverterFactory { - - @Override - public Converter getConverter(Class targetType) { - Class enumType = targetType; - while (enumType != null && !enumType.isEnum()) { - enumType = enumType.getSuperclass(); - } - Assert.notNull(enumType, "The target type " + targetType.getName() - + " does not refer to an enum"); - return new StringToEnum(enumType); - } - - private class StringToEnum implements Converter { - - private final Class enumType; - - StringToEnum(Class enumType) { - this.enumType = enumType; - } - - @Override - public T convert(String source) { - if (source.isEmpty()) { - // It's an empty enum identifier: reset the enum value to null. - return null; - } - source = source.trim(); - for (T candidate : (Set) EnumSet.allOf(this.enumType)) { - RelaxedNames names = new RelaxedNames( - candidate.name().replace('_', '-').toLowerCase()); - for (String name : names) { - if (name.equals(source)) { - return candidate; - } - } - if (candidate.name().equalsIgnoreCase(source)) { - return candidate; - } - } - throw new IllegalArgumentException("No enum constant " - + this.enumType.getCanonicalName() + "." + source); - } - - } - - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java deleted file mode 100644 index 3c025d7ca8..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java +++ /dev/null @@ -1,722 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; -import org.springframework.beans.InvalidPropertyException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.NotWritablePropertyException; -import org.springframework.beans.PropertyValue; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; -import org.springframework.validation.AbstractPropertyBindingResult; -import org.springframework.validation.BeanPropertyBindingResult; -import org.springframework.validation.DataBinder; - -/** - * Binder implementation that allows caller to bind to maps and also allows property names - * to match a bit loosely (if underscores or dashes are removed and replaced with camel - * case for example). - * - * @author Dave Syer - * @author Phillip Webb - * @author Stephane Nicoll - * @author Andy Wilkinson - * @see RelaxedNames - */ -@Deprecated -public class RelaxedDataBinder extends DataBinder { - - private static final Object BLANK = new Object(); - - private String namePrefix; - - private boolean ignoreNestedProperties; - - private MultiValueMap nameAliases = new LinkedMultiValueMap<>(); - - /** - * Create a new {@link RelaxedDataBinder} instance. - * @param target the target into which properties are bound - */ - public RelaxedDataBinder(Object target) { - super(wrapTarget(target)); - } - - /** - * Create a new {@link RelaxedDataBinder} instance. - * @param target the target into which properties are bound - * @param namePrefix An optional prefix to be used when reading properties - */ - public RelaxedDataBinder(Object target, String namePrefix) { - super(wrapTarget(target), - (StringUtils.hasLength(namePrefix) ? namePrefix : DEFAULT_OBJECT_NAME)); - this.namePrefix = cleanNamePrefix(namePrefix); - } - - private String cleanNamePrefix(String namePrefix) { - if (!StringUtils.hasLength(namePrefix)) { - return null; - } - return (namePrefix.endsWith(".") ? namePrefix : namePrefix + "."); - } - - /** - * Flag to disable binding of nested properties (i.e. those with period separators in - * their paths). Can be useful to disable this if the name prefix is empty and you - * don't want to ignore unknown fields. - * @param ignoreNestedProperties the flag to set (default false) - */ - public void setIgnoreNestedProperties(boolean ignoreNestedProperties) { - this.ignoreNestedProperties = ignoreNestedProperties; - } - - /** - * Set name aliases. - * @param aliases a map of property name to aliases - */ - public void setNameAliases(Map> aliases) { - this.nameAliases = new LinkedMultiValueMap<>(aliases); - } - - /** - * Add aliases to the {@link DataBinder}. - * @param name the property name to alias - * @param alias aliases for the property names - * @return this instance - */ - public RelaxedDataBinder withAlias(String name, String... alias) { - for (String value : alias) { - this.nameAliases.add(name, value); - } - return this; - } - - @Override - protected void doBind(MutablePropertyValues propertyValues) { - super.doBind(modifyProperties(propertyValues, getTarget())); - } - - /** - * Modify the property values so that period separated property paths are valid for - * map keys. Also creates new maps for properties of map type that are null (assuming - * all maps are potentially nested). The standard bracket {@code[...]} dereferencing - * is also accepted. - * @param propertyValues the property values - * @param target the target object - * @return modified property values - */ - private MutablePropertyValues modifyProperties(MutablePropertyValues propertyValues, - Object target) { - propertyValues = getPropertyValuesForNamePrefix(propertyValues); - if (target instanceof MapHolder) { - propertyValues = addMapPrefix(propertyValues); - } - BeanWrapper wrapper = new BeanWrapperImpl(target); - wrapper.setConversionService( - new RelaxedConversionService(getConversionService())); - wrapper.setAutoGrowNestedPaths(true); - List sortedValues = new ArrayList<>(); - Set modifiedNames = new HashSet<>(); - List sortedNames = getSortedPropertyNames(propertyValues); - for (String name : sortedNames) { - PropertyValue propertyValue = propertyValues.getPropertyValue(name); - PropertyValue modifiedProperty = modifyProperty(wrapper, propertyValue); - if (modifiedNames.add(modifiedProperty.getName())) { - sortedValues.add(modifiedProperty); - } - } - return new MutablePropertyValues(sortedValues); - } - - private List getSortedPropertyNames(MutablePropertyValues propertyValues) { - List names = new LinkedList<>(); - for (PropertyValue propertyValue : propertyValues.getPropertyValueList()) { - names.add(propertyValue.getName()); - } - sortPropertyNames(names); - return names; - } - - /** - * Sort by name so that parent properties get processed first (e.g. 'foo.bar' before - * 'foo.bar.spam'). Don't use Collections.sort() because the order might be - * significant for other property names (it shouldn't be but who knows what people - * might be relying on, e.g. HSQL has a JDBCXADataSource where "databaseName" is a - * synonym for "url"). - * @param names the names to sort - */ - private void sortPropertyNames(List names) { - for (String name : new ArrayList<>(names)) { - int propertyIndex = names.indexOf(name); - BeanPath path = new BeanPath(name); - for (String prefix : path.prefixes()) { - int prefixIndex = names.indexOf(prefix); - if (prefixIndex >= propertyIndex) { - // The child property has a parent in the list in the wrong order - names.remove(name); - names.add(prefixIndex, name); - } - } - } - } - - private MutablePropertyValues addMapPrefix(MutablePropertyValues propertyValues) { - MutablePropertyValues rtn = new MutablePropertyValues(); - for (PropertyValue pv : propertyValues.getPropertyValues()) { - rtn.add("map." + pv.getName(), pv.getValue()); - } - return rtn; - } - - private MutablePropertyValues getPropertyValuesForNamePrefix( - MutablePropertyValues propertyValues) { - if (!StringUtils.hasText(this.namePrefix) && !this.ignoreNestedProperties) { - return propertyValues; - } - MutablePropertyValues rtn = new MutablePropertyValues(); - for (PropertyValue value : propertyValues.getPropertyValues()) { - String name = value.getName(); - for (String prefix : new RelaxedNames(stripLastDot(this.namePrefix))) { - for (String separator : new String[] { ".", "_" }) { - String candidate = (StringUtils.hasLength(prefix) ? prefix + separator - : prefix); - if (name.startsWith(candidate)) { - name = name.substring(candidate.length()); - if (!(this.ignoreNestedProperties && name.contains("."))) { - PropertyOrigin propertyOrigin = OriginCapablePropertyValue - .getOrigin(value); - rtn.addPropertyValue(new OriginCapablePropertyValue(name, - value.getValue(), propertyOrigin)); - } - } - } - } - } - return rtn; - } - - private String stripLastDot(String string) { - if (StringUtils.hasLength(string) && string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - return string; - } - - private PropertyValue modifyProperty(BeanWrapper target, - PropertyValue propertyValue) { - String name = propertyValue.getName(); - String normalizedName = normalizePath(target, name); - if (!normalizedName.equals(name)) { - return new PropertyValue(normalizedName, propertyValue.getValue()); - } - return propertyValue; - } - - /** - * Normalize a bean property path to a format understood by a BeanWrapper. This is - * used so that - *
    - *
  • Fuzzy matching can be employed for bean property names
  • - *
  • Period separators can be used instead of indexing ([...]) for map keys
  • - *
- * @param wrapper a bean wrapper for the object to bind - * @param path the bean path to bind - * @return a transformed path with correct bean wrapper syntax - */ - protected String normalizePath(BeanWrapper wrapper, String path) { - return initializePath(wrapper, new BeanPath(path), 0); - } - - @Override - protected AbstractPropertyBindingResult createBeanPropertyBindingResult() { - return new RelaxedBeanPropertyBindingResult(getTarget(), getObjectName(), - isAutoGrowNestedPaths(), getAutoGrowCollectionLimit(), - getConversionService()); - } - - private String initializePath(BeanWrapper wrapper, BeanPath path, int index) { - String prefix = path.prefix(index); - String key = path.name(index); - if (path.isProperty(index)) { - key = getActualPropertyName(wrapper, prefix, key); - path.rename(index, key); - } - if (path.name(++index) == null) { - return path.toString(); - } - String name = path.prefix(index); - TypeDescriptor descriptor = wrapper.getPropertyTypeDescriptor(name); - if (descriptor == null || descriptor.isMap()) { - if (isMapValueStringType(descriptor) - || isBlanked(wrapper, name, path.name(index))) { - path.collapseKeys(index); - } - path.mapIndex(index); - extendMapIfNecessary(wrapper, path, index); - } - else if (descriptor.isCollection()) { - extendCollectionIfNecessary(wrapper, path, index); - } - else if (descriptor.getType().equals(Object.class)) { - if (isBlanked(wrapper, name, path.name(index))) { - path.collapseKeys(index); - } - path.mapIndex(index); - if (path.isLastNode(index)) { - wrapper.setPropertyValue(path.toString(), BLANK); - } - else { - String next = path.prefix(index + 1); - if (wrapper.getPropertyValue(next) == null) { - wrapper.setPropertyValue(next, new LinkedHashMap()); - } - } - } - return initializePath(wrapper, path, index); - } - - private boolean isMapValueStringType(TypeDescriptor descriptor) { - if (descriptor == null || descriptor.getMapValueTypeDescriptor() == null) { - return false; - } - if (Properties.class.isAssignableFrom(descriptor.getObjectType())) { - // Properties is declared as Map but we know it's really - // Map - return true; - } - Class valueType = descriptor.getMapValueTypeDescriptor().getObjectType(); - return (valueType != null && CharSequence.class.isAssignableFrom(valueType)); - } - - @SuppressWarnings("rawtypes") - private boolean isBlanked(BeanWrapper wrapper, String propertyName, String key) { - Object value = (wrapper.isReadableProperty(propertyName) - ? wrapper.getPropertyValue(propertyName) : null); - if (value instanceof Map) { - if (((Map) value).get(key) == BLANK) { - return true; - } - } - return false; - } - - private void extendCollectionIfNecessary(BeanWrapper wrapper, BeanPath path, - int index) { - String name = path.prefix(index); - TypeDescriptor elementDescriptor = wrapper.getPropertyTypeDescriptor(name) - .getElementTypeDescriptor(); - if (!elementDescriptor.isMap() && !elementDescriptor.isCollection() - && !elementDescriptor.getType().equals(Object.class)) { - return; - } - Object extend = new LinkedHashMap(); - if (!elementDescriptor.isMap() && path.isArrayIndex(index)) { - extend = new ArrayList<>(); - } - wrapper.setPropertyValue(path.prefix(index + 1), extend); - } - - private void extendMapIfNecessary(BeanWrapper wrapper, BeanPath path, int index) { - String name = path.prefix(index); - TypeDescriptor parent = wrapper.getPropertyTypeDescriptor(name); - if (parent == null) { - return; - } - TypeDescriptor descriptor = parent.getMapValueTypeDescriptor(); - if (descriptor == null) { - descriptor = TypeDescriptor.valueOf(Object.class); - } - if (!descriptor.isMap() && !descriptor.isCollection() - && !descriptor.getType().equals(Object.class)) { - return; - } - String extensionName = path.prefix(index + 1); - if (wrapper.isReadableProperty(extensionName)) { - Object currentValue = wrapper.getPropertyValue(extensionName); - if ((descriptor.isCollection() && currentValue instanceof Collection) - || (!descriptor.isCollection() && currentValue instanceof Map)) { - return; - } - } - Object extend = new LinkedHashMap(); - if (descriptor.isCollection()) { - extend = new ArrayList<>(); - } - if (descriptor.getType().equals(Object.class) && path.isLastNode(index)) { - extend = BLANK; - } - wrapper.setPropertyValue(extensionName, extend); - } - - private String getActualPropertyName(BeanWrapper target, String prefix, String name) { - String propertyName = resolvePropertyName(target, prefix, name); - if (propertyName == null) { - propertyName = resolveNestedPropertyName(target, prefix, name); - } - return (propertyName == null ? name : propertyName); - } - - private String resolveNestedPropertyName(BeanWrapper target, String prefix, - String name) { - StringBuilder candidate = new StringBuilder(); - for (String field : name.split("[_\\-\\.]")) { - candidate.append(candidate.length() > 0 ? "." : ""); - candidate.append(field); - String nested = resolvePropertyName(target, prefix, candidate.toString()); - if (nested != null) { - Class type = target.getPropertyType(nested); - if ((type != null) && Map.class.isAssignableFrom(type)) { - // Special case for map property (gh-3836). - return nested + "[" + name.substring(candidate.length() + 1) + "]"; - } - String propertyName = resolvePropertyName(target, - joinString(prefix, nested), - name.substring(candidate.length() + 1)); - if (propertyName != null) { - return joinString(nested, propertyName); - } - } - } - return null; - } - - private String resolvePropertyName(BeanWrapper target, String prefix, String name) { - Iterable names = getNameAndAliases(name); - for (String nameOrAlias : names) { - for (String candidate : new RelaxedNames(nameOrAlias)) { - try { - if (target.getPropertyType(joinString(prefix, candidate)) != null) { - return candidate; - } - } - catch (InvalidPropertyException ex) { - // swallow and continue - } - } - } - return null; - } - - private String joinString(String prefix, String name) { - return (StringUtils.hasLength(prefix) ? prefix + "." + name : name); - } - - private Iterable getNameAndAliases(String name) { - List aliases = this.nameAliases.get(name); - if (aliases == null) { - return Collections.singleton(name); - } - List nameAndAliases = new ArrayList<>(aliases.size() + 1); - nameAndAliases.add(name); - nameAndAliases.addAll(aliases); - return nameAndAliases; - } - - private static Object wrapTarget(Object target) { - if (target instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) target; - target = new MapHolder(map); - } - return target; - } - - /** - * Holder to allow Map targets to be bound. - */ - static class MapHolder { - - private Map map; - - MapHolder(Map map) { - this.map = map; - } - - public void setMap(Map map) { - this.map = map; - } - - public Map getMap() { - return this.map; - } - - } - - /** - * A path though properties of a bean. - */ - private static class BeanPath { - - private List nodes; - - BeanPath(String path) { - this.nodes = splitPath(path); - } - - public List prefixes() { - List prefixes = new ArrayList<>(); - for (int index = 1; index < this.nodes.size(); index++) { - prefixes.add(prefix(index)); - } - return prefixes; - } - - public boolean isLastNode(int index) { - return index >= this.nodes.size() - 1; - } - - private List splitPath(String path) { - List nodes = new ArrayList<>(); - String current = extractIndexedPaths(path, nodes); - for (String name : StringUtils.delimitedListToStringArray(current, ".")) { - if (StringUtils.hasText(name)) { - nodes.add(new PropertyNode(name)); - } - } - return nodes; - } - - private String extractIndexedPaths(String path, List nodes) { - int startRef = path.indexOf("["); - String current = path; - while (startRef >= 0) { - if (startRef > 0) { - nodes.addAll(splitPath(current.substring(0, startRef))); - } - int endRef = current.indexOf("]", startRef); - if (endRef > 0) { - String sub = current.substring(startRef + 1, endRef); - if (sub.matches("[0-9]+")) { - nodes.add(new ArrayIndexNode(sub)); - } - else { - nodes.add(new MapIndexNode(sub)); - } - } - current = current.substring(endRef + 1); - startRef = current.indexOf("["); - } - return current; - } - - public void collapseKeys(int index) { - List revised = new ArrayList<>(); - for (int i = 0; i < index; i++) { - revised.add(this.nodes.get(i)); - } - StringBuilder builder = new StringBuilder(); - for (int i = index; i < this.nodes.size(); i++) { - if (i > index) { - builder.append("."); - } - builder.append(this.nodes.get(i).name); - } - revised.add(new PropertyNode(builder.toString())); - this.nodes = revised; - } - - public void mapIndex(int index) { - PathNode node = this.nodes.get(index); - if (node instanceof PropertyNode) { - node = ((PropertyNode) node).mapIndex(); - } - this.nodes.set(index, node); - } - - public String prefix(int index) { - return range(0, index); - } - - public void rename(int index, String name) { - this.nodes.get(index).name = name; - } - - public String name(int index) { - if (index < this.nodes.size()) { - return this.nodes.get(index).name; - } - return null; - } - - private String range(int start, int end) { - StringBuilder builder = new StringBuilder(); - for (int i = start; i < end; i++) { - PathNode node = this.nodes.get(i); - builder.append(node); - } - if (builder.toString().startsWith(("."))) { - builder.replace(0, 1, ""); - } - return builder.toString(); - } - - public boolean isArrayIndex(int index) { - return this.nodes.get(index) instanceof ArrayIndexNode; - } - - public boolean isProperty(int index) { - return this.nodes.get(index) instanceof PropertyNode; - } - - @Override - public String toString() { - return prefix(this.nodes.size()); - } - - private static class PathNode { - - protected String name; - - PathNode(String name) { - this.name = name; - } - - } - - private static class ArrayIndexNode extends PathNode { - - ArrayIndexNode(String name) { - super(name); - } - - @Override - public String toString() { - return "[" + this.name + "]"; - } - - } - - private static class MapIndexNode extends PathNode { - - MapIndexNode(String name) { - super(name); - } - - @Override - public String toString() { - return "[" + this.name + "]"; - } - - } - - private static class PropertyNode extends PathNode { - - PropertyNode(String name) { - super(name); - } - - public MapIndexNode mapIndex() { - return new MapIndexNode(this.name); - } - - @Override - public String toString() { - return "." + this.name; - } - - } - - } - - /** - * Extended version of {@link BeanPropertyBindingResult} to support relaxed binding. - */ - private static class RelaxedBeanPropertyBindingResult - extends BeanPropertyBindingResult { - - private RelaxedConversionService conversionService; - - RelaxedBeanPropertyBindingResult(Object target, String objectName, - boolean autoGrowNestedPaths, int autoGrowCollectionLimit, - ConversionService conversionService) { - super(target, objectName, autoGrowNestedPaths, autoGrowCollectionLimit); - this.conversionService = new RelaxedConversionService(conversionService); - } - - @Override - protected BeanWrapper createBeanWrapper() { - BeanWrapper beanWrapper = new RelaxedBeanWrapper(getTarget()); - beanWrapper.setConversionService(this.conversionService); - beanWrapper.registerCustomEditor(InetAddress.class, new InetAddressEditor()); - return beanWrapper; - } - - } - - /** - * Extended version of {@link BeanWrapperImpl} to support relaxed binding. - */ - private static class RelaxedBeanWrapper extends BeanWrapperImpl { - - private static final Set BENIGN_PROPERTY_SOURCE_NAMES; - - static { - Set names = new HashSet<>(); - names.add(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); - names.add(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME); - BENIGN_PROPERTY_SOURCE_NAMES = Collections.unmodifiableSet(names); - } - - RelaxedBeanWrapper(Object target) { - super(target); - } - - @Override - public void setPropertyValue(PropertyValue pv) throws BeansException { - try { - super.setPropertyValue(pv); - } - catch (NotWritablePropertyException ex) { - PropertyOrigin origin = OriginCapablePropertyValue.getOrigin(pv); - if (isBenign(origin)) { - logger.debug("Ignoring benign property binding failure", ex); - return; - } - if (origin == null) { - throw ex; - } - throw new RelaxedBindingNotWritablePropertyException(ex, origin); - } - } - - private boolean isBenign(PropertyOrigin origin) { - String name = (origin == null ? null : origin.getSource().getName()); - return BENIGN_PROPERTY_SOURCE_NAMES.contains(name); - } - - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java deleted file mode 100644 index 63c82fa04b..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.springframework.util.StringUtils; - -/** - * Generates relaxed name variations from a given source. - * - * @author Phillip Webb - * @author Dave Syer - * @see RelaxedDataBinder - */ -@Deprecated -public final class RelaxedNames implements Iterable { - - private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])"); - - private static final Pattern SEPARATED_TO_CAMEL_CASE_PATTERN = Pattern - .compile("[_\\-.]"); - - private final String name; - - private final Set values = new LinkedHashSet<>(); - - /** - * Create a new {@link RelaxedNames} instance. - * @param name the source name. For the maximum number of variations specify the name - * using dashed notation (e.g. {@literal my-property-name} - */ - public RelaxedNames(String name) { - this.name = (name == null ? "" : name); - initialize(RelaxedNames.this.name, this.values); - } - - @Override - public Iterator iterator() { - return this.values.iterator(); - } - - private void initialize(String name, Set values) { - if (values.contains(name)) { - return; - } - for (Variation variation : Variation.values()) { - for (Manipulation manipulation : Manipulation.values()) { - String result = name; - result = manipulation.apply(result); - result = variation.apply(result); - values.add(result); - initialize(result, values); - } - } - } - - /** - * Name variations. - */ - enum Variation { - - NONE { - - @Override - public String apply(String value) { - return value; - } - - }, - - LOWERCASE { - - @Override - public String apply(String value) { - return value.isEmpty() ? value : value.toLowerCase(); - } - - }, - - UPPERCASE { - - @Override - public String apply(String value) { - return value.isEmpty() ? value : value.toUpperCase(); - } - - }; - - public abstract String apply(String value); - - } - - /** - * Name manipulations. - */ - enum Manipulation { - - NONE { - - @Override - public String apply(String value) { - return value; - } - - }, - - HYPHEN_TO_UNDERSCORE { - - @Override - public String apply(String value) { - return value.indexOf('-') != -1 ? value.replace('-', '_') : value; - } - - }, - - UNDERSCORE_TO_PERIOD { - - @Override - public String apply(String value) { - return value.indexOf('_') != -1 ? value.replace('_', '.') : value; - } - - }, - - PERIOD_TO_UNDERSCORE { - - @Override - public String apply(String value) { - return value.indexOf('.') != -1 ? value.replace('.', '_') : value; - } - - }, - - CAMELCASE_TO_UNDERSCORE { - - @Override - public String apply(String value) { - if (value.isEmpty()) { - return value; - } - Matcher matcher = CAMEL_CASE_PATTERN.matcher(value); - if (!matcher.find()) { - return value; - } - matcher = matcher.reset(); - StringBuffer result = new StringBuffer(); - while (matcher.find()) { - matcher.appendReplacement(result, matcher.group(1) + '_' - + StringUtils.uncapitalize(matcher.group(2))); - } - matcher.appendTail(result); - return result.toString(); - } - - }, - - CAMELCASE_TO_HYPHEN { - - @Override - public String apply(String value) { - if (value.isEmpty()) { - return value; - } - Matcher matcher = CAMEL_CASE_PATTERN.matcher(value); - if (!matcher.find()) { - return value; - } - matcher = matcher.reset(); - StringBuffer result = new StringBuffer(); - while (matcher.find()) { - matcher.appendReplacement(result, matcher.group(1) + '-' - + StringUtils.uncapitalize(matcher.group(2))); - } - matcher.appendTail(result); - return result.toString(); - } - - }, - - SEPARATED_TO_CAMELCASE { - - @Override - public String apply(String value) { - return separatedToCamelCase(value, false); - } - - }, - - CASE_INSENSITIVE_SEPARATED_TO_CAMELCASE { - - @Override - public String apply(String value) { - return separatedToCamelCase(value, true); - } - - }; - - private static final char[] SUFFIXES = new char[] { '_', '-', '.' }; - - public abstract String apply(String value); - - private static String separatedToCamelCase(String value, - boolean caseInsensitive) { - if (value.isEmpty()) { - return value; - } - StringBuilder builder = new StringBuilder(); - for (String field : SEPARATED_TO_CAMEL_CASE_PATTERN.split(value)) { - field = (caseInsensitive ? field.toLowerCase() : field); - builder.append( - builder.length() == 0 ? field : StringUtils.capitalize(field)); - } - char lastChar = value.charAt(value.length() - 1); - for (char suffix : SUFFIXES) { - if (lastChar == suffix) { - builder.append(suffix); - break; - } - } - return builder.toString(); - } - - } - - /** - * Return a {@link RelaxedNames} for the given source camelCase source name. - * @param name the source name in camelCase - * @return the relaxed names - */ - public static RelaxedNames forCamelCase(String name) { - StringBuilder result = new StringBuilder(); - for (char c : name.toCharArray()) { - result.append(Character.isUpperCase(c) && result.length() > 0 - && result.charAt(result.length() - 1) != '-' - ? "-" + Character.toLowerCase(c) : c); - } - return new RelaxedNames(result.toString()); - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/StringToCharArrayConverter.java b/spring-boot/src/main/java/org/springframework/boot/bind/StringToCharArrayConverter.java deleted file mode 100644 index 17f9116564..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/StringToCharArrayConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import org.springframework.core.convert.converter.Converter; - -/** - * Converts a String to a Char Array. - * - * @author Phillip Webb - */ -@Deprecated -class StringToCharArrayConverter implements Converter { - - @Override - public char[] convert(String source) { - return source.toCharArray(); - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/YamlConfigurationFactory.java b/spring-boot/src/main/java/org/springframework/boot/bind/YamlConfigurationFactory.java deleted file mode 100644 index a9629da835..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/YamlConfigurationFactory.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.MessageSource; -import org.springframework.context.MessageSourceAware; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.util.StreamUtils; -import org.springframework.validation.BeanPropertyBindingResult; -import org.springframework.validation.BindException; -import org.springframework.validation.BindingResult; -import org.springframework.validation.ObjectError; -import org.springframework.validation.Validator; - -/** - * Validate some YAML by binding it to an object of a specified type and then optionally - * running a {@link Validator} over it. - * - * @param the configuration type - * @author Luke Taylor - * @author Dave Syer - */ -@Deprecated -public class YamlConfigurationFactory - implements FactoryBean, MessageSourceAware, InitializingBean { - - private static final Log logger = LogFactory.getLog(YamlConfigurationFactory.class); - - private final Class type; - - private String yaml; - - private Resource resource; - - private T configuration; - - private Validator validator; - - private MessageSource messageSource; - - private Map, Map> propertyAliases = Collections.emptyMap(); - - /** - * Sets a validation constructor which will be applied to the YAML doc to see whether - * it matches the expected JavaBean. - * @param type the root type - */ - public YamlConfigurationFactory(Class type) { - Assert.notNull(type, "Root type must not be null"); - this.type = type; - } - - /** - * Set the message source. - * @param messageSource the message source - */ - @Override - public void setMessageSource(MessageSource messageSource) { - this.messageSource = messageSource; - } - - /** - * Set the property aliases. - * @param propertyAliases the property aliases - */ - public void setPropertyAliases(Map, Map> propertyAliases) { - this.propertyAliases = new HashMap<>(propertyAliases); - } - - /** - * Set the YAML. - * @param yaml the YAML - */ - public void setYaml(String yaml) { - this.yaml = yaml; - } - - /** - * Set the resource. - * @param resource the resource - */ - public void setResource(Resource resource) { - this.resource = resource; - } - - /** - * Set the validator. - * @param validator the validator - */ - public void setValidator(Validator validator) { - this.validator = validator; - } - - @Override - @SuppressWarnings("unchecked") - public void afterPropertiesSet() throws Exception { - if (this.yaml == null) { - Assert.state(this.resource != null, "Resource should not be null"); - this.yaml = StreamUtils.copyToString(this.resource.getInputStream(), - Charset.defaultCharset()); - } - Assert.state(this.yaml != null, "Yaml document should not be null: " - + "either set it directly or set the resource to load it from"); - if (logger.isTraceEnabled()) { - logger.trace(String.format("Yaml document is %n%s", this.yaml)); - } - Constructor constructor = new YamlJavaBeanPropertyConstructor(this.type, - this.propertyAliases); - this.configuration = (T) (new Yaml(constructor)).load(this.yaml); - if (this.validator != null) { - validate(); - } - } - - private void validate() throws BindException { - BindingResult errors = new BeanPropertyBindingResult(this.configuration, - "configuration"); - this.validator.validate(this.configuration, errors); - if (errors.hasErrors()) { - logger.error("YAML configuration failed validation"); - for (ObjectError error : errors.getAllErrors()) { - logger.error(getErrorMessage(error)); - } - throw new BindException(errors); - } - } - - private Object getErrorMessage(ObjectError error) { - if (this.messageSource != null) { - Locale locale = Locale.getDefault(); - return this.messageSource.getMessage(error, locale) + " (" + error + ")"; - } - return error; - } - - @Override - public Class getObjectType() { - if (this.configuration == null) { - return Object.class; - } - return this.configuration.getClass(); - } - - @Override - public boolean isSingleton() { - return true; - } - - @Override - public T getObject() throws Exception { - if (this.configuration == null) { - afterPropertiesSet(); - } - return this.configuration; - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/YamlJavaBeanPropertyConstructor.java b/spring-boot/src/main/java/org/springframework/boot/bind/YamlJavaBeanPropertyConstructor.java deleted file mode 100644 index f3b726e492..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/YamlJavaBeanPropertyConstructor.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.beans.IntrospectionException; -import java.util.HashMap; -import java.util.Map; - -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.introspector.Property; -import org.yaml.snakeyaml.introspector.PropertyUtils; -import org.yaml.snakeyaml.nodes.NodeId; - -/** - * Extended version of snakeyaml's Constructor class to facilitate mapping custom YAML - * keys to JavaBean property names. - * - * @author Luke Taylor - */ -@Deprecated -public class YamlJavaBeanPropertyConstructor extends Constructor { - - private final Map, Map> properties = new HashMap<>(); - - private final PropertyUtils propertyUtils = new PropertyUtils(); - - public YamlJavaBeanPropertyConstructor(Class theRoot) { - super(theRoot); - this.yamlClassConstructors.put(NodeId.mapping, - new CustomPropertyConstructMapping()); - } - - public YamlJavaBeanPropertyConstructor(Class theRoot, - Map, Map> propertyAliases) { - this(theRoot); - for (Class key : propertyAliases.keySet()) { - Map map = propertyAliases.get(key); - if (map != null) { - for (String alias : map.keySet()) { - addPropertyAlias(alias, key, map.get(alias)); - } - } - } - } - - /** - * Adds an alias for a JavaBean property name on a particular type. The values of YAML - * keys with the alias name will be mapped to the JavaBean property. - * @param alias the alias to map - * @param type the type of property - * @param name the property name - */ - protected final void addPropertyAlias(String alias, Class type, String name) { - Map typeMap = this.properties.get(type); - if (typeMap == null) { - typeMap = new HashMap<>(); - this.properties.put(type, typeMap); - } - try { - typeMap.put(alias, this.propertyUtils.getProperty(type, name)); - } - catch (IntrospectionException ex) { - throw new RuntimeException(ex); - } - } - - /** - * Custom {@code ConstructMapping} to resolve properties. - */ - class CustomPropertyConstructMapping extends ConstructMapping { - - @Override - protected Property getProperty(Class type, String name) - throws IntrospectionException { - Map forType = YamlJavaBeanPropertyConstructor.this.properties - .get(type); - Property property = (forType == null ? null : forType.get(name)); - return (property == null ? super.getProperty(type, name) : property); - } - - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/package-info.java b/spring-boot/src/main/java/org/springframework/boot/bind/package-info.java deleted file mode 100644 index 530a69301b..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/bind/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Classes and utilities to help when binding spring based configuration files to objects. - * - * @see org.springframework.boot.bind.RelaxedDataBinder - * @see org.springframework.boot.bind.YamlConfigurationFactory - */ -package org.springframework.boot.bind; diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java deleted file mode 100644 index 0c7640fbf0..0000000000 --- a/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.boot.bind.RelaxedDataBinderTests.TargetWithNestedObject; -import org.springframework.context.expression.MapAccessor; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -public class BindingPreparationTests { - - @Test - public void testBeanWrapperCreatesNewMaps() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - // For a nested map, you only have to get an element of it for it to be created - wrapper.getPropertyValue("nested[foo]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - } - - @Test - public void testBeanWrapperCreatesNewMapEntries() throws Exception { - TargetWithNestedMapOfBean target = new TargetWithNestedMapOfBean(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - // For a nested map, you only have to get an element of it for it to be created - wrapper.getPropertyValue("nested[foo]"); - wrapper.setPropertyValue("nested[foo].foo", "bar"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[foo]")).isNotNull(); - } - - @Test - public void testListOfBeansWithList() throws Exception { - TargetWithNestedListOfBeansWithList target = new TargetWithNestedListOfBeansWithList(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - binder.normalizePath(wrapper, "nested[0].list[1]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[0].list[1]")).isNotNull(); - } - - @Test - public void testListOfBeansWithListAndNoPeriod() throws Exception { - TargetWithNestedListOfBeansWithList target = new TargetWithNestedListOfBeansWithList(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - binder.normalizePath(wrapper, "nested[0]list[1]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[0].list[1]")).isNotNull(); - } - - @Test - public void testAutoGrowWithFuzzyNameCapitals() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - String result = binder.normalizePath(wrapper, "NESTED[foo][bar]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat("nested[foo][bar]").isEqualTo(result); - assertThat(wrapper.getPropertyValue("nested[foo][bar]")).isNotNull(); - } - - @Test - public void testAutoGrowWithFuzzyNameUnderscores() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - String result = binder.normalizePath(wrapper, "nes_ted[foo][bar]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat("nested[foo][bar]").isEqualTo(result); - assertThat(wrapper.getPropertyValue("nested[foo][bar]")).isNotNull(); - } - - @Test - public void testAutoGrowNewNestedMapOfMaps() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - String result = binder.normalizePath(wrapper, "nested[foo][bar]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat("nested[foo][bar]").isEqualTo(result); - assertThat(wrapper.getPropertyValue("nested[foo][bar]")).isNotNull(); - } - - @Test - public void testAutoGrowNewNestedMapOfBeans() throws Exception { - TargetWithNestedMapOfBean target = new TargetWithNestedMapOfBean(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - String result = binder.normalizePath(wrapper, "nested[foo].foo"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat("nested[foo].foo").isEqualTo(result); - assertThat(wrapper.getPropertyValue("nested[foo]")).isNotNull(); - } - - @Test - public void testAutoGrowNewNestedMapOfBeansWithPeriod() throws Exception { - TargetWithNestedMapOfBean target = new TargetWithNestedMapOfBean(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - String result = binder.normalizePath(wrapper, "nested.foo.foo"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat("nested[foo].foo").isEqualTo(result); - } - - @Test - public void testAutoGrowNewNestedMapOfListOfString() throws Exception { - TargetWithNestedMapOfListOfString target = new TargetWithNestedMapOfListOfString(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - binder.normalizePath(wrapper, "nested[foo][0]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[foo]")).isNotNull(); - } - - @Test - public void testAutoGrowListOfMaps() throws Exception { - TargetWithNestedListOfMaps target = new TargetWithNestedListOfMaps(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - binder.normalizePath(wrapper, "nested[0][foo]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[0]")).isNotNull(); - } - - @Test - public void testAutoGrowListOfLists() throws Exception { - TargetWithNestedListOfLists target = new TargetWithNestedListOfLists(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - RelaxedDataBinder binder = new RelaxedDataBinder(target); - binder.normalizePath(wrapper, "nested[0][1]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - assertThat(wrapper.getPropertyValue("nested[0][1]")).isNotNull(); - } - - @Test - public void testBeanWrapperCreatesNewNestedMaps() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - // For a nested map, you only have to get an element of it for it to be created - wrapper.getPropertyValue("nested[foo]"); - // To decide what type to create for nested[foo] we need to look ahead and see - // what the user is trying to bind it to, e.g. if nested[foo][bar] then it's a map - wrapper.setPropertyValue("nested[foo]", new LinkedHashMap()); - // But it might equally well be a collection, if nested[foo][0] - wrapper.setPropertyValue("nested[foo]", new ArrayList<>()); - // Then it would have to be actually bound to get the list to auto-grow - wrapper.setPropertyValue("nested[foo][0]", "bar"); - assertThat(wrapper.getPropertyValue("nested[foo][0]")).isNotNull(); - } - - @Test - public void testBeanWrapperCreatesNewObjects() throws Exception { - TargetWithNestedObject target = new TargetWithNestedObject(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - // For a nested object, you have to set a property for it to be created - wrapper.setPropertyValue("nested.foo", "bar"); - wrapper.getPropertyValue("nested"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - } - - @Test - public void testBeanWrapperLists() throws Exception { - TargetWithNestedMapOfListOfString target = new TargetWithNestedMapOfListOfString(); - BeanWrapperImpl wrapper = new BeanWrapperImpl(target); - wrapper.setAutoGrowNestedPaths(true); - TypeDescriptor descriptor = wrapper.getPropertyTypeDescriptor("nested"); - assertThat(descriptor.isMap()).isTrue(); - wrapper.getPropertyValue("nested[foo]"); - assertThat(wrapper.getPropertyValue("nested")).isNotNull(); - // You also need to bind to a value here - wrapper.setPropertyValue("nested[foo][0]", "bar"); - wrapper.getPropertyValue("nested[foo][0]"); - assertThat(wrapper.getPropertyValue("nested[foo]")).isNotNull(); - } - - @Test - @Ignore("Work in progress") - public void testExpressionLists() throws Exception { - TargetWithNestedMapOfListOfString target = new TargetWithNestedMapOfListOfString(); - LinkedHashMap> map = new LinkedHashMap<>(); - // map.put("foo", Arrays.asList("bar")); - target.setNested(map); - SpelExpressionParser parser = new SpelExpressionParser(); - StandardEvaluationContext context = new StandardEvaluationContext(target); - context.addPropertyAccessor(new MapAccessor()); - Expression expression = parser.parseExpression("nested.foo"); - assertThat(expression.getValue(context)).isNotNull(); - } - - public static class TargetWithNestedMap { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfListOfString { - - private Map> nested; - - public Map> getNested() { - return this.nested; - } - - public void setNested(Map> nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedListOfMaps { - - private List> nested; - - public List> getNested() { - return this.nested; - } - - public void setNested(List> nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedListOfLists { - - private List> nested; - - public List> getNested() { - return this.nested; - } - - public void setNested(List> nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedListOfBeansWithList { - - private List nested; - - public List getNested() { - return this.nested; - } - - public void setNested(List nested) { - this.nested = nested; - } - - } - - public static class TargetWithList { - - private List list; - - public List getList() { - return this.list; - } - - public void setList(List list) { - this.list = list; - } - - } - - public static class TargetWithNestedMapOfBean { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class VanillaTarget { - - private String foo; - - public String getFoo() { - return this.foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - } - -} diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java deleted file mode 100644 index ba840ce17a..0000000000 --- a/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Collections; -import java.util.Set; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.bind.ConverterBindingTests.TestConfig; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link ConfigurationProperties} binding with custom converters. - * - * @author Dave Syer - * @author Stephane Nicoll - */ -@RunWith(SpringRunner.class) -@DirtiesContext -@ContextConfiguration(classes = TestConfig.class, loader = SpringApplicationBindContextLoader.class) -@TestPropertySource(properties = { "foo=one", "bar=two" }) -public class ConverterBindingTests { - - @Value("${foo:}") - private String foo; - - @Value("${bar:}") - private String bar; - - @Autowired - private Wrapper properties; - - @Test - public void overridingOfPropertiesOrderOfAtPropertySources() { - assertThat(this.properties.getFoo().name).isEqualTo(this.foo); - assertThat(this.properties.getBar().name).isEqualTo(this.bar); - } - - @Configuration - @EnableConfigurationProperties(Wrapper.class) - public static class TestConfig { - - @Bean - @ConfigurationPropertiesBinding - public Converter converter() { - return new Converter() { - - @Override - public Foo convert(String source) { - return new Foo(source); - } - }; - } - - @Bean - public GenericConverter genericConverter() { - return new GenericConverter() { - @Override - public Set getConvertibleTypes() { - return Collections - .singleton(new ConvertiblePair(String.class, Bar.class)); - } - - @Override - public Object convert(Object source, TypeDescriptor sourceType, - TypeDescriptor targetType) { - return new Bar((String) source); - } - }; - } - - @Bean - public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } - - } - - public static class Foo { - - private final String name; - - public Foo(String name) { - this.name = name; - } - - } - - public static class Bar { - - private final String name; - - public Bar(String name) { - this.name = name; - } - - } - - @ConfigurationProperties - public static class Wrapper { - - private Foo foo; - - private Bar bar; - - public Foo getFoo() { - return this.foo; - } - - public void setFoo(Foo foo) { - this.foo = foo; - } - - public Bar getBar() { - return this.bar; - } - - public void setBar(Bar bar) { - this.bar = bar; - } - - } - -} diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java deleted file mode 100644 index c2a9285b51..0000000000 --- a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java +++ /dev/null @@ -1,1125 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import javax.validation.Constraint; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import javax.validation.Payload; -import javax.validation.constraints.NotNull; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.NotWritablePropertyException; -import org.springframework.context.support.StaticMessageSource; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.support.PropertiesLoaderUtils; -import org.springframework.validation.BindingResult; -import org.springframework.validation.DataBinder; -import org.springframework.validation.FieldError; -import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link RelaxedDataBinder}. - * - * @author Dave Syer - * @author Phillip Webb - * @author Stephane Nicoll - */ -public class RelaxedDataBinderTests { - - @Rule - public ExpectedException expected = ExpectedException.none(); - - private ConversionService conversionService; - - @Test - public void testBindString() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "foo: bar"); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindChars() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "bar: foo"); - assertThat(new String(target.getBar())).isEqualTo("foo"); - } - - @Test - public void testBindStringWithPrefix() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "test.foo: bar", "test"); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindStringWithPrefixDotSuffix() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "some.test.foo: bar", "some.test."); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindFromEnvironmentStyleWithPrefix() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "TEST_FOO: bar", "test"); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindToCamelCaseFromEnvironmentStyleWithPrefix() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "TEST_FOO_BAZ: bar", "test"); - assertThat(target.getFooBaz()).isEqualTo("bar"); - } - - @Test - public void testBindToCamelCaseFromEnvironmentStyle() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "test.FOO_BAZ: bar", "test"); - assertThat(target.getFooBaz()).isEqualTo("bar"); - } - - @Test - public void testBindFromEnvironmentStyleWithNestedPrefix() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "TEST_IT_FOO: bar", "test.it"); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindCapitals() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "FOO: bar"); - assertThat(target.getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindUnderscoreInActualPropertyName() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "foo-bar: bar"); - assertThat(target.getFoo_bar()).isEqualTo("bar"); - } - - @Test - public void testBindUnderscoreToCamelCase() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "foo_baz: bar"); - assertThat(target.getFooBaz()).isEqualTo("bar"); - } - - @Test - public void testBindHyphen() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "foo-baz: bar"); - assertThat(target.getFooBaz()).isEqualTo("bar"); - } - - @Test - public void testBindCamelCase() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "fooBaz: bar"); - assertThat(target.getFooBaz()).isEqualTo("bar"); - } - - @Test - public void testBindNumber() throws Exception { - VanillaTarget target = new VanillaTarget(); - bind(target, "foo: bar\n" + "value: 123"); - assertThat(target.getValue()).isEqualTo(123); - } - - @Test - public void testSimpleValidation() throws Exception { - ValidatedTarget target = new ValidatedTarget(); - BindingResult result = bind(target, ""); - assertThat(result.getErrorCount()).isEqualTo(1); - } - - @Test - public void testRequiredFieldsValidation() throws Exception { - TargetWithValidatedMap target = new TargetWithValidatedMap(); - BindingResult result = bind(target, "info[foo]: bar"); - assertThat(result.getErrorCount()).isEqualTo(2); - for (FieldError error : result.getFieldErrors()) { - System.err.println( - new StaticMessageSource().getMessage(error, Locale.getDefault())); - } - } - - @Test - public void testAllowedFields() throws Exception { - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, null); - binder.setAllowedFields("foo"); - binder.setIgnoreUnknownFields(false); - BindingResult result = bind(binder, target, - "foo: bar\n" + "value: 123\n" + "bar: spam"); - assertThat(target.getValue()).isEqualTo(0); - assertThat(target.getFoo()).isEqualTo("bar"); - assertThat(result.getErrorCount()).isEqualTo(0); - } - - @Test - public void testDisallowedFields() throws Exception { - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, null); - // Disallowed fields are not unknown... - binder.setDisallowedFields("foo", "bar"); - binder.setIgnoreUnknownFields(false); - BindingResult result = bind(binder, target, - "foo: bar\n" + "value: 123\n" + "bar: spam"); - assertThat(target.getValue()).isEqualTo(123); - assertThat(target.getFoo()).isNull(); - assertThat(result.getErrorCount()).isEqualTo(0); - } - - @Test - public void testBindNested() throws Exception { - TargetWithNestedObject target = new TargetWithNestedObject(); - bind(target, "nested.foo: bar\n" + "nested.value: 123"); - assertThat(target.getNested().getValue()).isEqualTo(123); - } - - @Test - public void testBindRelaxedNestedValue() throws Exception { - TargetWithNestedObject target = new TargetWithNestedObject(); - bind(target, "nested_foo_Baz: bar\n" + "nested_value: 123"); - assertThat(target.getNested().getFooBaz()).isEqualTo("bar"); - assertThat(target.getNested().getValue()).isEqualTo(123); - } - - @Test - public void testBindRelaxedNestedCamelValue() throws Exception { - TargetWithNestedObject target = new TargetWithNestedObject(); - bind(target, "another_nested_foo_Baz: bar\n" + "another-nested_value: 123"); - assertThat(target.getAnotherNested().getFooBaz()).isEqualTo("bar"); - assertThat(target.getAnotherNested().getValue()).isEqualTo(123); - } - - @Test - public void testBindNestedWithEnvironmentStyle() throws Exception { - TargetWithNestedObject target = new TargetWithNestedObject(); - bind(target, "nested_foo: bar\n" + "nested_value: 123"); - assertThat(target.getNested().getValue()).isEqualTo(123); - } - - @Test - public void testBindNestedList() throws Exception { - TargetWithNestedList target = new TargetWithNestedList(); - bind(target, "nested[0]: bar\nnested[1]: foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindNestedListOfBean() throws Exception { - TargetWithNestedListOfBean target = new TargetWithNestedListOfBean(); - bind(target, "nested[0].foo: bar\nnested[1].foo: foo"); - assertThat(target.getNested().get(0).getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindNestedListOfBeanWithList() throws Exception { - TargetWithNestedListOfBeanWithList target = new TargetWithNestedListOfBeanWithList(); - bind(target, "nested[0].nested[0].foo: bar\nnested[1].nested[0].foo: foo"); - assertThat(target.getNested().get(0).getNested().get(0).getFoo()) - .isEqualTo("bar"); - } - - @Test - public void testBindNestedListCommaDelimitedOnly() throws Exception { - TargetWithNestedList target = new TargetWithNestedList(); - this.conversionService = new DefaultConversionService(); - bind(target, "nested: bar,foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindNestedSetCommaDelimitedOnly() throws Exception { - TargetWithNestedSet target = new TargetWithNestedSet(); - this.conversionService = new DefaultConversionService(); - bind(target, "nested: bar,foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test(expected = NotWritablePropertyException.class) - public void testBindNestedReadOnlyListCommaSeparated() throws Exception { - TargetWithReadOnlyNestedList target = new TargetWithReadOnlyNestedList(); - this.conversionService = new DefaultConversionService(); - bind(target, "nested: bar,foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindNestedReadOnlyListIndexed() throws Exception { - TargetWithReadOnlyNestedList target = new TargetWithReadOnlyNestedList(); - this.conversionService = new DefaultConversionService(); - bind(target, "nested[0]: bar\nnested[1]:foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindDoubleNestedReadOnlyListIndexed() throws Exception { - TargetWithReadOnlyDoubleNestedList target = new TargetWithReadOnlyDoubleNestedList(); - this.conversionService = new DefaultConversionService(); - bind(target, "bean.nested[0]:bar\nbean.nested[1]:foo"); - assertThat(target.getBean().getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindNestedReadOnlyCollectionIndexed() throws Exception { - TargetWithReadOnlyNestedCollection target = new TargetWithReadOnlyNestedCollection(); - this.conversionService = new DefaultConversionService(); - bind(target, "nested[0]: bar\nnested[1]:foo"); - assertThat(target.getNested().toString()).isEqualTo("[bar, foo]"); - } - - @Test - public void testBindNestedMap() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested.foo: bar\n" + "nested.value: 123"); - assertThat(target.getNested().get("value")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapPropsWithUnderscores() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested_foo: bar\n" + "nested_value: 123"); - assertThat(target.getNested().get("value")).isEqualTo("123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - } - - @Test - public void testBindNestedUntypedMap() throws Exception { - TargetWithNestedUntypedMap target = new TargetWithNestedUntypedMap(); - bind(target, "nested.foo: bar\n" + "nested.value: 123"); - assertThat(target.getNested().get("value")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfString() throws Exception { - TargetWithNestedMapOfString target = new TargetWithNestedMapOfString(); - bind(target, "nested.foo: bar\n" + "nested.value.foo: 123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - assertThat(target.getNested().get("value.foo")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfStringWithUnderscore() throws Exception { - TargetWithNestedMapOfString target = new TargetWithNestedMapOfString(); - bind(target, "nested_foo: bar\n" + "nested_value_foo: 123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - assertThat(target.getNested().get("value_foo")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfStringWithUnderscoreAndUpperCase() throws Exception { - TargetWithNestedMapOfString target = new TargetWithNestedMapOfString(); - bind(target, "NESTED_FOO: bar\n" + "NESTED_VALUE_FOO: 123"); - assertThat(target.getNested().get("FOO")).isEqualTo("bar"); - assertThat(target.getNested().get("VALUE_FOO")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfStringReferenced() throws Exception { - TargetWithNestedMapOfString target = new TargetWithNestedMapOfString(); - bind(target, "nested.foo: bar\n" + "nested[value.foo]: 123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - assertThat(target.getNested().get("value.foo")).isEqualTo("123"); - } - - @Test - public void testBindNestedProperties() throws Exception { - TargetWithNestedProperties target = new TargetWithNestedProperties(); - bind(target, "nested.foo: bar\n" + "nested.value.foo: 123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - assertThat(target.getNested().get("value.foo")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfEnum() throws Exception { - this.conversionService = new DefaultConversionService(); - TargetWithNestedMapOfEnum target = new TargetWithNestedMapOfEnum(); - bind(target, "nested.this: bar\n" + "nested.ThAt: 123"); - assertThat(target.getNested().get(Bingo.THIS)).isEqualTo("bar"); - assertThat(target.getNested().get(Bingo.THAT)).isEqualTo("123"); - } - - @Test - public void testBindNestedMapOfEnumRelaxedNames() throws Exception { - this.conversionService = new DefaultConversionService(); - TargetWithNestedMapOfEnum target = new TargetWithNestedMapOfEnum(); - bind(target, "nested.the-other: bar\n" + "nested.that_other: 123"); - assertThat(target.getNested().get(Bingo.THE_OTHER)).isEqualTo("bar"); - assertThat(target.getNested().get(Bingo.THAT_OTHER)).isEqualTo("123"); - } - - @Test - public void testBindNestedMapBracketReferenced() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested[foo]: bar\n" + "nested[value]: 123"); - assertThat(target.getNested().get("value")).isEqualTo("123"); - } - - @Test - public void testBindNestedMapBracketReferencedAndPeriods() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested[foo]: bar\n" + "nested[foo.value]: 123"); - assertThat(target.getNested().get("foo.value")).isEqualTo("123"); - } - - @SuppressWarnings("unchecked") - @Test - public void testBindDoubleNestedMapWithDotInKeys() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested.foo: bar.key\n" + "nested[bar.key].spam: bucket\n" - + "nested[bar.key].value: 123\nnested[bar.key].foo: crap"); - assertThat(target.getNested()).hasSize(2); - Map nestedMap = (Map) target.getNested() - .get("bar.key"); - assertThat(nestedMap).as("nested map should be registered with 'bar.key'") - .isNotNull(); - assertThat(nestedMap).hasSize(3); - assertThat(nestedMap.get("value")).isEqualTo("123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar.key"); - assertThat(target.getNested().containsValue(target.getNested())).isFalse(); - } - - @SuppressWarnings("unchecked") - @Test - public void testBindDoubleNestedMap() throws Exception { - TargetWithNestedMap target = new TargetWithNestedMap(); - bind(target, "nested.foo: bar\n" + "nested.bar.spam: bucket\n" - + "nested.bar.value: 123\nnested.bar.foo: crap"); - assertThat(target.getNested()).hasSize(2); - assertThat(((Map) target.getNested().get("bar"))).hasSize(3); - assertThat(((Map) target.getNested().get("bar")).get("value")) - .isEqualTo("123"); - assertThat(target.getNested().get("foo")).isEqualTo("bar"); - assertThat(target.getNested().containsValue(target.getNested())).isFalse(); - } - - @Test - public void testBindNestedMapOfListOfString() throws Exception { - TargetWithNestedMapOfListOfString target = new TargetWithNestedMapOfListOfString(); - bind(target, "nested.foo[0]: bar\n" + "nested.bar[0]: bucket\n" - + "nested.bar[1]: 123\nnested.bar[2]: crap"); - assertThat(target.getNested()).hasSize(2); - assertThat(target.getNested().get("bar")).hasSize(3); - assertThat(target.getNested().get("bar").get(1)).isEqualTo("123"); - assertThat(target.getNested().get("foo").toString()).isEqualTo("[bar]"); - } - - @Test - public void testBindNestedMapOfBean() throws Exception { - TargetWithNestedMapOfBean target = new TargetWithNestedMapOfBean(); - bind(target, "nested.foo.foo: bar\n" + "nested.bar.foo: bucket"); - assertThat(target.getNested()).hasSize(2); - assertThat(target.getNested().get("bar").getFoo()).isEqualTo("bucket"); - } - - @Test - public void testBindNestedMapOfListOfBean() throws Exception { - TargetWithNestedMapOfListOfBean target = new TargetWithNestedMapOfListOfBean(); - bind(target, "nested.foo[0].foo: bar\n" + "nested.bar[0].foo: bucket\n" - + "nested.bar[1].value: 123\nnested.bar[2].foo: crap"); - assertThat(target.getNested()).hasSize(2); - assertThat(target.getNested().get("bar")).hasSize(3); - assertThat(target.getNested().get("bar").get(1).getValue()).isEqualTo(123); - assertThat(target.getNested().get("foo").get(0).getFoo()).isEqualTo("bar"); - } - - @Test - public void testBindErrorTypeMismatch() throws Exception { - VanillaTarget target = new VanillaTarget(); - BindingResult result = bind(target, "foo: bar\n" + "value: foo"); - assertThat(result.getErrorCount()).isEqualTo(1); - } - - @Test - public void testBindErrorNotWritable() throws Exception { - this.expected.expectMessage("property 'spam'"); - this.expected.expectMessage("not writable"); - VanillaTarget target = new VanillaTarget(); - BindingResult result = bind(target, "spam: bar\n" + "value: 123"); - assertThat(result.getErrorCount()).isEqualTo(1); - } - - @Test - public void testBindErrorNotWritableWithPrefix() throws Exception { - VanillaTarget target = new VanillaTarget(); - BindingResult result = bind(target, "spam: bar\n" + "vanilla.value: 123", - "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getValue()).isEqualTo(123); - } - - @Test - public void testOnlyTopLevelFields() throws Exception { - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, null); - binder.setIgnoreUnknownFields(false); - binder.setIgnoreNestedProperties(true); - BindingResult result = bind(binder, target, - "foo: bar\n" + "value: 123\n" + "nested.bar: spam"); - assertThat(target.getValue()).isEqualTo(123); - assertThat(target.getFoo()).isEqualTo("bar"); - assertThat(result.getErrorCount()).isEqualTo(0); - } - - @Test - public void testNoNestedFields() throws Exception { - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, "foo"); - binder.setIgnoreUnknownFields(false); - binder.setIgnoreNestedProperties(true); - BindingResult result = bind(binder, target, - "foo.foo: bar\n" + "foo.value: 123\n" + "foo.nested.bar: spam"); - assertThat(target.getValue()).isEqualTo(123); - assertThat(target.getFoo()).isEqualTo("bar"); - assertThat(result.getErrorCount()).isEqualTo(0); - } - - @Test - public void testBindMap() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, "spam: bar\n" + "vanilla.value: 123", - "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.get("value")).isEqualTo("123"); - } - - @Test - public void testBindMapWithClashInProperties() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, - "vanilla.spam: bar\n" + "vanilla.spam.value: 123", "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target).hasSize(2); - assertThat(target.get("spam")).isEqualTo("bar"); - assertThat(target.get("spam.value")).isEqualTo("123"); - } - - @Test - public void testBindMapWithDeepClashInProperties() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, - "vanilla.spam.foo: bar\n" + "vanilla.spam.foo.value: 123", "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - @SuppressWarnings("unchecked") - Map map = (Map) target.get("spam"); - assertThat(map.get("foo.value")).isEqualTo("123"); - } - - @Test - public void testBindMapWithDifferentDeepClashInProperties() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, - "vanilla.spam.bar: bar\n" + "vanilla.spam.bar.value: 123", "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - @SuppressWarnings("unchecked") - Map map = (Map) target.get("spam"); - assertThat(map.get("bar.value")).isEqualTo("123"); - } - - @Test - public void testBindShallowMap() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, "vanilla.spam: bar\n" + "vanilla.value: 123", - "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.get("value")).isEqualTo("123"); - } - - @Test - public void testBindMapNestedMap() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, "spam: bar\n" + "vanilla.foo.value: 123", - "vanilla"); - assertThat(result.getErrorCount()).isEqualTo(0); - @SuppressWarnings("unchecked") - Map map = (Map) target.get("foo"); - assertThat(map.get("value")).isEqualTo("123"); - } - - @SuppressWarnings("unchecked") - @Test - public void testBindOverlappingNestedMaps() throws Exception { - Map target = new LinkedHashMap<>(); - BindingResult result = bind(target, "a.b.c.d: abc\na.b.c1.d1: efg"); - assertThat(result.getErrorCount()).isEqualTo(0); - - Map a = (Map) target.get("a"); - Map b = (Map) a.get("b"); - Map c = (Map) b.get("c"); - assertThat(c.get("d")).isEqualTo("abc"); - - Map c1 = (Map) b.get("c1"); - assertThat(c1.get("d1")).isEqualTo("efg"); - } - - @Test - public void testBindCaseInsensitiveEnumsWithoutConverter() throws Exception { - VanillaTarget target = new VanillaTarget(); - doTestBindCaseInsensitiveEnums(target); - } - - @Test - public void testBindCaseInsensitiveEnumsWithConverter() throws Exception { - VanillaTarget target = new VanillaTarget(); - this.conversionService = new DefaultConversionService(); - doTestBindCaseInsensitiveEnums(target); - } - - @Test - public void testBindWithoutAlias() throws Exception { - VanillaTarget target = new VanillaTarget(); - MutablePropertyValues properties = new MutablePropertyValues(); - properties.add("flub", "a"); - properties.add("foo", "b"); - new RelaxedDataBinder(target).bind(properties); - assertThat(target.getFooBaz()).isNull(); - assertThat(target.getFoo()).isEqualTo("b"); - } - - @Test - public void testBindWithAlias() throws Exception { - VanillaTarget target = new VanillaTarget(); - MutablePropertyValues properties = new MutablePropertyValues(); - properties.add("flub", "a"); - properties.add("foo", "b"); - new RelaxedDataBinder(target).withAlias("flub", "fooBaz").bind(properties); - assertThat(target.getFooBaz()).isEqualTo("a"); - assertThat(target.getFoo()).isEqualTo("b"); - } - - @Test - public void testMixed() throws Exception { - // gh-3385 - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, "test"); - MutablePropertyValues values = new MutablePropertyValues(); - values.add("test.FOO_BAZ", "boo"); - values.add("test.foo-baz", "bar"); - binder.bind(values); - assertThat(target.getFooBaz()).isEqualTo("boo"); - } - - @Test - public void testIndexBounds() throws Exception { - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, "test"); - MutablePropertyValues values = new MutablePropertyValues(); - values.add("test.objects[0]", "teststring"); - binder.bind(values); - assertThat(target.getObjects()).containsExactly("teststring"); - } - - @Test - public void testMixedWithUpperCaseWord() throws Exception { - // gh-6803 - VanillaTarget target = new VanillaTarget(); - RelaxedDataBinder binder = getBinder(target, "test"); - MutablePropertyValues values = new MutablePropertyValues(); - values.add("test.mixed-u-p-p-e-r", "foo"); - binder.bind(values); - assertThat(target.getMixedUPPER()).isEqualTo("foo"); - } - - private void doTestBindCaseInsensitiveEnums(VanillaTarget target) throws Exception { - BindingResult result = bind(target, "bingo: THIS"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.THIS); - - result = bind(target, "bingo: oR"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.or); - - result = bind(target, "bingo: that"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.THAT); - - result = bind(target, "bingo: the-other"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.THE_OTHER); - - result = bind(target, "bingo: the_other"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.THE_OTHER); - - result = bind(target, "bingo: The_Other"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingo()).isEqualTo(Bingo.THE_OTHER); - - result = bind(target, "bingos: The_Other"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingos()).contains(Bingo.THE_OTHER); - - result = bind(target, "bingos: The_Other, that"); - assertThat(result.getErrorCount()).isEqualTo(0); - assertThat(target.getBingos()).contains(Bingo.THE_OTHER, Bingo.THAT); - } - - private BindingResult bind(Object target, String values) throws Exception { - return bind(target, values, null); - } - - private BindingResult bind(Object target, String values, String namePrefix) - throws Exception { - return bind(getBinder(target, namePrefix), target, values); - } - - private RelaxedDataBinder getBinder(Object target, String namePrefix) { - RelaxedDataBinder binder = new RelaxedDataBinder(target, namePrefix); - binder.setIgnoreUnknownFields(false); - LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean(); - validatorFactoryBean.afterPropertiesSet(); - binder.setValidator(validatorFactoryBean); - binder.setConversionService(this.conversionService); - return binder; - } - - private BindingResult bind(DataBinder binder, Object target, String values) - throws Exception { - Properties properties = PropertiesLoaderUtils - .loadProperties(new ByteArrayResource(values.getBytes())); - binder.bind(new MutablePropertyValues(properties)); - binder.validate(); - - return binder.getBindingResult(); - } - - @Documented - @Target({ ElementType.FIELD }) - @Retention(RetentionPolicy.RUNTIME) - @Constraint(validatedBy = RequiredKeysValidator.class) - public @interface RequiredKeys { - - String[] value(); - - String message() default "Required fields are not provided for field ''{0}''"; - - Class[] groups() default {}; - - Class[] payload() default {}; - - } - - public static class RequiredKeysValidator - implements ConstraintValidator> { - - private String[] fields; - - @Override - public void initialize(RequiredKeys constraintAnnotation) { - this.fields = constraintAnnotation.value(); - } - - @Override - public boolean isValid(Map value, - ConstraintValidatorContext context) { - boolean valid = true; - for (String field : this.fields) { - if (!value.containsKey(field)) { - context.buildConstraintViolationWithTemplate( - "Missing field ''" + field + "''").addConstraintViolation(); - valid = false; - } - } - return valid; - } - - } - - public static class TargetWithValidatedMap { - - @RequiredKeys({ "foo", "value" }) - private Map info; - - public Map getInfo() { - return this.info; - } - - public void setInfo(Map nested) { - this.info = nested; - } - - } - - public static class TargetWithNestedMap { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - @SuppressWarnings("rawtypes") - public static class TargetWithNestedUntypedMap { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedProperties { - - private Properties nested; - - public Properties getNested() { - return this.nested; - } - - public void setNested(Properties nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfString { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfEnum { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfListOfString { - - private Map> nested; - - public Map> getNested() { - return this.nested; - } - - public void setNested(Map> nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfListOfBean { - - private Map> nested; - - public Map> getNested() { - return this.nested; - } - - public void setNested(Map> nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedMapOfBean { - - private Map nested; - - public Map getNested() { - return this.nested; - } - - public void setNested(Map nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedList { - - private List nested; - - public List getNested() { - return this.nested; - } - - public void setNested(List nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedListOfBean { - - private List nested; - - public List getNested() { - return this.nested; - } - - public void setNested(List nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedListOfBeanWithList { - - private List nested; - - public List getNested() { - return this.nested; - } - - public void setNested(List nested) { - this.nested = nested; - } - - } - - public static class TargetWithReadOnlyNestedList { - - private final List nested = new ArrayList<>(); - - public List getNested() { - return this.nested; - } - - } - - public static class TargetWithReadOnlyDoubleNestedList { - - TargetWithReadOnlyNestedList bean = new TargetWithReadOnlyNestedList(); - - public TargetWithReadOnlyNestedList getBean() { - return this.bean; - } - - } - - public static class TargetWithReadOnlyNestedCollection { - - private final Collection nested = new ArrayList<>(); - - public Collection getNested() { - return this.nested; - } - - } - - public static class TargetWithNestedSet { - - private Set nested = new LinkedHashSet<>(); - - public Set getNested() { - return this.nested; - } - - public void setNested(Set nested) { - this.nested = nested; - } - - } - - public static class TargetWithNestedObject { - - private VanillaTarget nested; - - private VanillaTarget anotherNested; - - public VanillaTarget getNested() { - return this.nested; - } - - public void setNested(VanillaTarget nested) { - this.nested = nested; - } - - public VanillaTarget getAnotherNested() { - return this.anotherNested; - } - - public void setAnotherNested(VanillaTarget anotherNested) { - this.anotherNested = anotherNested; - } - - } - - public static class VanillaTarget { - - private String foo; - - private char[] bar; - - private int value; - - private String foo_bar; - - private String fooBaz; - - private Bingo bingo; - - private List bingos; - - private List objects; - - private String mixedUPPER; - - public char[] getBar() { - return this.bar; - } - - public void setBar(char[] bar) { - this.bar = bar; - } - - public int getValue() { - return this.value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getFoo() { - return this.foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - public String getFoo_bar() { - return this.foo_bar; - } - - public void setFoo_bar(String foo_bar) { - this.foo_bar = foo_bar; - } - - public String getFooBaz() { - return this.fooBaz; - } - - public void setFooBaz(String fooBaz) { - this.fooBaz = fooBaz; - } - - public Bingo getBingo() { - return this.bingo; - } - - public void setBingo(Bingo bingo) { - this.bingo = bingo; - } - - public List getBingos() { - return this.bingos; - } - - public void setBingos(List bingos) { - this.bingos = bingos; - } - - public List getObjects() { - return this.objects; - } - - public void setObjects(List objects) { - this.objects = objects; - } - - public String getMixedUPPER() { - return this.mixedUPPER; - } - - public void setMixedUPPER(String mixedUPPER) { - this.mixedUPPER = mixedUPPER; - } - - } - - enum Bingo { - - THIS, or, THAT, THE_OTHER, THAT_OTHER - - } - - public static class ValidatedTarget { - - @NotNull - private String foo; - - public String getFoo() { - return this.foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - } - -} diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/SpringApplicationBindContextLoader.java b/spring-boot/src/test/java/org/springframework/boot/bind/SpringApplicationBindContextLoader.java deleted file mode 100644 index ad44ba61ec..0000000000 --- a/spring-boot/src/test/java/org/springframework/boot/bind/SpringApplicationBindContextLoader.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.WebApplicationType; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.test.context.ContextLoader; -import org.springframework.test.context.MergedContextConfiguration; -import org.springframework.test.context.support.AbstractContextLoader; -import org.springframework.test.context.support.TestPropertySourceUtils; - -/** - * {@link ContextLoader} used with binding tests. - * - * @author Phillip Webb - */ -class SpringApplicationBindContextLoader extends AbstractContextLoader { - - private static final String[] NO_SUFFIXES = new String[] {}; - - @Override - public ApplicationContext loadContext(MergedContextConfiguration config) - throws Exception { - SpringApplication application = new SpringApplication(); - application.setMainApplicationClass(config.getTestClass()); - application.setWebApplicationType(WebApplicationType.NONE); - application.setSources( - new LinkedHashSet(Arrays.asList(config.getClasses()))); - ConfigurableEnvironment environment = new StandardEnvironment(); - Map properties = new LinkedHashMap<>(); - properties.put("spring.jmx.enabled", "false"); - properties.putAll(TestPropertySourceUtils - .convertInlinedPropertiesToMap(config.getPropertySourceProperties())); - environment.getPropertySources().addAfter( - StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, - new MapPropertySource("integrationTest", properties)); - application.setEnvironment(environment); - return application.run(); - } - - @Override - public ApplicationContext loadContext(String... locations) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected String[] getResourceSuffixes() { - return NO_SUFFIXES; - } - - @Override - protected String getResourceSuffix() { - throw new UnsupportedOperationException(); - } - -} diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/YamlConfigurationFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/YamlConfigurationFactoryTests.java deleted file mode 100644 index eb4270acc7..0000000000 --- a/spring-boot/src/test/java/org/springframework/boot/bind/YamlConfigurationFactoryTests.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.bind; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.validation.Validation; -import javax.validation.constraints.NotNull; - -import org.junit.Test; -import org.yaml.snakeyaml.error.YAMLException; - -import org.springframework.context.support.StaticMessageSource; -import org.springframework.validation.BindException; -import org.springframework.validation.Validator; -import org.springframework.validation.beanvalidation.SpringValidatorAdapter; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link YamlConfigurationFactory} - * - * @author Dave Syer - */ -public class YamlConfigurationFactoryTests { - - private Validator validator; - - private final Map, Map> aliases = new HashMap<>(); - - private Foo createFoo(final String yaml) throws Exception { - YamlConfigurationFactory factory = new YamlConfigurationFactory<>(Foo.class); - factory.setYaml(yaml); - factory.setPropertyAliases(this.aliases); - factory.setValidator(this.validator); - factory.setMessageSource(new StaticMessageSource()); - factory.afterPropertiesSet(); - return factory.getObject(); - } - - private Jee createJee(final String yaml) throws Exception { - YamlConfigurationFactory factory = new YamlConfigurationFactory<>(Jee.class); - factory.setYaml(yaml); - factory.setPropertyAliases(this.aliases); - factory.setValidator(this.validator); - factory.setMessageSource(new StaticMessageSource()); - factory.afterPropertiesSet(); - return factory.getObject(); - } - - @Test - public void testValidYamlLoadsWithNoErrors() throws Exception { - Foo foo = createFoo("name: blah\nbar: blah"); - assertThat(foo.bar).isEqualTo("blah"); - } - - @Test - public void testValidYamlWithAliases() throws Exception { - this.aliases.put(Foo.class, Collections.singletonMap("foo-name", "name")); - Foo foo = createFoo("foo-name: blah\nbar: blah"); - assertThat(foo.name).isEqualTo("blah"); - } - - @Test(expected = YAMLException.class) - public void unknownPropertyCausesLoadFailure() throws Exception { - createFoo("hi: hello\nname: foo\nbar: blah"); - } - - @Test(expected = BindException.class) - public void missingPropertyCausesValidationError() throws Exception { - this.validator = new SpringValidatorAdapter( - Validation.buildDefaultValidatorFactory().getValidator()); - createFoo("bar: blah"); - } - - @Test - public void testWithPeriodInKey() throws Exception { - Jee jee = createJee("mymap:\n ? key1.key2\n : value"); - assertThat(jee.mymap.get("key1.key2")).isEqualTo("value"); - } - - private static class Foo { - - @NotNull - public String name; - - public String bar; - - } - - private static class Jee { - - public Map mymap; - - } - -}