Upgrade to Spring 4.1.0 and use Yaml support that migrated from Boot
Closes #813
This commit is contained in:
parent
890fc71967
commit
3145edff3a
|
|
@ -97,7 +97,7 @@
|
||||||
<snakeyaml.version>1.13</snakeyaml.version>
|
<snakeyaml.version>1.13</snakeyaml.version>
|
||||||
<solr.version>4.7.2</solr.version>
|
<solr.version>4.7.2</solr.version>
|
||||||
<spock.version>0.7-groovy-2.0</spock.version>
|
<spock.version>0.7-groovy-2.0</spock.version>
|
||||||
<spring.version>4.0.6.RELEASE</spring.version>
|
<spring.version>4.1.0.BUILD-SNAPSHOT</spring.version>
|
||||||
<spring-amqp.version>1.3.5.RELEASE</spring-amqp.version>
|
<spring-amqp.version>1.3.5.RELEASE</spring-amqp.version>
|
||||||
<spring-batch.version>3.0.1.RELEASE</spring-batch.version>
|
<spring-batch.version>3.0.1.RELEASE</spring-batch.version>
|
||||||
<spring-data-releasetrain.version>Dijkstra-SR1</spring-data-releasetrain.version>
|
<spring-data-releasetrain.version>Dijkstra-SR1</spring-data-releasetrain.version>
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ package org.springframework.boot.env;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||||
import org.springframework.boot.yaml.SpringProfileDocumentMatcher;
|
import org.springframework.boot.yaml.SpringProfileDocumentMatcher;
|
||||||
import org.springframework.boot.yaml.YamlPropertiesFactoryBean;
|
|
||||||
import org.springframework.core.env.PropertiesPropertySource;
|
import org.springframework.core.env.PropertiesPropertySource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ package org.springframework.boot.yaml;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.DocumentMatcher;
|
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchStatus;
|
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -18,8 +18,8 @@ package org.springframework.boot.yaml;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.DocumentMatcher;
|
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchStatus;
|
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link DocumentMatcher} that matches the default profile implicitly but not
|
* A {@link DocumentMatcher} that matches the default profile implicitly but not
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,8 +20,8 @@ import java.util.Arrays;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.DocumentMatcher;
|
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchStatus;
|
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012 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.yaml;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory for Map that reads from a YAML source. YAML is a nice human-readable format for
|
|
||||||
* configuration, and it has some useful hierarchical properties. It's more or less a
|
|
||||||
* superset of JSON, so it has a lot of similar features. If multiple resources are
|
|
||||||
* provided the later ones will override entries in the earlier ones hierarchically - that
|
|
||||||
* is all entries with the same nested key of type Map at any depth are merged. For
|
|
||||||
* example:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* foo:
|
|
||||||
* bar:
|
|
||||||
* one: two
|
|
||||||
* three: four
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* plus (later in the list)
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* foo:
|
|
||||||
* bar:
|
|
||||||
* one: 2
|
|
||||||
* five: six
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* results in an effecive input of
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* foo:
|
|
||||||
* bar:
|
|
||||||
* one: 2
|
|
||||||
* three: four
|
|
||||||
* five: six
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* Note that the value of "foo" in the first document is not simply replaced with the
|
|
||||||
* value in the second, but its nested values are merged.
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class YamlMapFactoryBean extends YamlProcessor implements
|
|
||||||
FactoryBean<Map<String, Object>> {
|
|
||||||
|
|
||||||
private boolean singleton = true;
|
|
||||||
|
|
||||||
private Map<String, Object> instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getObject() {
|
|
||||||
if (!this.singleton || this.instance == null) {
|
|
||||||
final Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
||||||
process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
merge(result, map);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.instance = result;
|
|
||||||
}
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
private void merge(Map<String, Object> output, Map<String, Object> map) {
|
|
||||||
for (Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
Object existing = output.get(key);
|
|
||||||
if (value instanceof Map && existing instanceof Map) {
|
|
||||||
Map<String, Object> result = new LinkedHashMap<String, Object>(
|
|
||||||
(Map) existing);
|
|
||||||
merge(result, (Map) value);
|
|
||||||
output.put(key, result);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
output.put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return Map.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set if a singleton should be created, or a new object on each request otherwise.
|
|
||||||
* Default is <code>true</code> (a singleton).
|
|
||||||
*/
|
|
||||||
public void setSingleton(boolean singleton) {
|
|
||||||
this.singleton = singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingleton() {
|
|
||||||
return this.singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,352 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.yaml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for Yaml factories.
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public abstract class YamlProcessor {
|
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
|
||||||
|
|
||||||
private ResolutionMethod resolutionMethod = ResolutionMethod.OVERRIDE;
|
|
||||||
|
|
||||||
private Resource[] resources = new Resource[0];
|
|
||||||
|
|
||||||
private List<DocumentMatcher> documentMatchers = Collections.emptyList();
|
|
||||||
|
|
||||||
private boolean matchDefault = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A map of document matchers allowing callers to selectively use only some of the
|
|
||||||
* documents in a YAML resource. In YAML documents are separated by <code>---</code>
|
|
||||||
* lines, and each document is converted to properties before the match is made. E.g.
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* environment: dev
|
|
||||||
* url: http://dev.bar.com
|
|
||||||
* name: Developer Setup
|
|
||||||
* ---
|
|
||||||
* environment: prod
|
|
||||||
* url:http://foo.bar.com
|
|
||||||
* name: My Cool App
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* when mapped with
|
|
||||||
* <code>documentMatchers = YamlProcessor.mapMatcher({"environment": "prod"})</code>
|
|
||||||
* would end up as
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* environment=prod
|
|
||||||
* url=http://foo.bar.com
|
|
||||||
* name=My Cool App
|
|
||||||
* url=http://dev.bar.com
|
|
||||||
* </pre>
|
|
||||||
* @param matchers a map of keys to value patterns (regular expressions)
|
|
||||||
*/
|
|
||||||
public void setDocumentMatchers(DocumentMatcher... matchers) {
|
|
||||||
this.documentMatchers = Collections
|
|
||||||
.unmodifiableList(new ArrayList<DocumentMatcher>(Arrays.asList(matchers)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag indicating that a document for which all the
|
|
||||||
* {@link #setDocumentMatchers(DocumentMatcher...) document matchers} abstain will
|
|
||||||
* nevertheless match.
|
|
||||||
* @param matchDefault the flag to set (default true)
|
|
||||||
*/
|
|
||||||
public void setMatchDefault(boolean matchDefault) {
|
|
||||||
this.matchDefault = matchDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to use for resolving resources. Each resource will be converted to a Map, so
|
|
||||||
* this property is used to decide which map entries to keep in the final output from
|
|
||||||
* this factory.
|
|
||||||
* @param resolutionMethod the resolution method to set (defaults to
|
|
||||||
* {@link ResolutionMethod#OVERRIDE}).
|
|
||||||
*/
|
|
||||||
public void setResolutionMethod(ResolutionMethod resolutionMethod) {
|
|
||||||
Assert.notNull(resolutionMethod, "ResolutionMethod must not be null");
|
|
||||||
this.resolutionMethod = resolutionMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param resources the resources to set
|
|
||||||
*/
|
|
||||||
public void setResources(Resource[] resources) {
|
|
||||||
this.resources = (resources == null ? null : resources.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an opportunity for subclasses to process the Yaml parsed from the supplied
|
|
||||||
* resources. Each resource is parsed in turn and the documents inside checked against
|
|
||||||
* the {@link #setDocumentMatchers(DocumentMatcher...) matchers}. If a document
|
|
||||||
* matches it is passed into the callback, along with its representation as
|
|
||||||
* Properties. Depending on the {@link #setResolutionMethod(ResolutionMethod)} not all
|
|
||||||
* of the documents will be parsed.
|
|
||||||
* @param callback a callback to delegate to once matching documents are found
|
|
||||||
*/
|
|
||||||
protected void process(MatchCallback callback) {
|
|
||||||
Yaml yaml = new Yaml();
|
|
||||||
for (Resource resource : this.resources) {
|
|
||||||
boolean found = process(callback, yaml, resource);
|
|
||||||
if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND && found) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
|
||||||
int count = 0;
|
|
||||||
try {
|
|
||||||
if (this.logger.isDebugEnabled()) {
|
|
||||||
this.logger.debug("Loading from YAML: " + resource);
|
|
||||||
}
|
|
||||||
for (Object object : yaml.loadAll(resource.getInputStream())) {
|
|
||||||
if (object != null && process(asMap(object), callback)) {
|
|
||||||
count++;
|
|
||||||
if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.logger.isDebugEnabled()) {
|
|
||||||
this.logger.debug("Loaded " + count + " document"
|
|
||||||
+ (count > 1 ? "s" : "") + " from YAML resource: " + resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
handleProcessError(resource, ex);
|
|
||||||
}
|
|
||||||
return count > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleProcessError(Resource resource, IOException ex) {
|
|
||||||
if (this.resolutionMethod != ResolutionMethod.FIRST_FOUND
|
|
||||||
&& this.resolutionMethod != ResolutionMethod.OVERRIDE_AND_IGNORE) {
|
|
||||||
throw new IllegalStateException(ex);
|
|
||||||
}
|
|
||||||
if (this.logger.isWarnEnabled()) {
|
|
||||||
this.logger.warn("Could not load map from " + resource + ": "
|
|
||||||
+ ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private Map<String, Object> asMap(Object object) {
|
|
||||||
// YAML can have numbers as keys
|
|
||||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
||||||
if (!(object instanceof Map)) {
|
|
||||||
// A document can be a text literal
|
|
||||||
result.put("document", object);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Object, Object> map = (Map<Object, Object>) object;
|
|
||||||
for (Entry<Object, Object> entry : map.entrySet()) {
|
|
||||||
Object value = entry.getValue();
|
|
||||||
if (value instanceof Map) {
|
|
||||||
value = asMap(value);
|
|
||||||
}
|
|
||||||
Object key = entry.getKey();
|
|
||||||
if (key instanceof CharSequence) {
|
|
||||||
result.put(key.toString(), value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// It has to be a map key in this case
|
|
||||||
result.put("[" + key.toString() + "]", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
|
||||||
|
|
||||||
Properties properties = new Properties();
|
|
||||||
assignProperties(properties, map, null);
|
|
||||||
|
|
||||||
if (this.documentMatchers.isEmpty()) {
|
|
||||||
if (this.logger.isDebugEnabled()) {
|
|
||||||
this.logger.debug("Merging document (no matchers set)" + map);
|
|
||||||
}
|
|
||||||
callback.process(properties, map);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MatchStatus result = MatchStatus.ABSTAIN;
|
|
||||||
for (DocumentMatcher matcher : this.documentMatchers) {
|
|
||||||
MatchStatus match = matcher.matches(properties);
|
|
||||||
result = MatchStatus.getMostSpecific(match, result);
|
|
||||||
if (match == MatchStatus.FOUND) {
|
|
||||||
if (this.logger.isDebugEnabled()) {
|
|
||||||
this.logger.debug("Matched document with document matcher: "
|
|
||||||
+ properties);
|
|
||||||
}
|
|
||||||
callback.process(properties, map);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == MatchStatus.ABSTAIN && this.matchDefault) {
|
|
||||||
if (this.logger.isDebugEnabled()) {
|
|
||||||
this.logger.debug("Matched document with default matcher: " + map);
|
|
||||||
}
|
|
||||||
callback.process(properties, map);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.debug("Unmatched document");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assignProperties(Properties properties, Map<String, Object> input,
|
|
||||||
String path) {
|
|
||||||
for (Entry<String, Object> entry : input.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
if (StringUtils.hasText(path)) {
|
|
||||||
if (key.startsWith("[")) {
|
|
||||||
key = path + key;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
key = path + "." + key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object value = entry.getValue();
|
|
||||||
if (value instanceof String) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
else if (value instanceof Map) {
|
|
||||||
// Need a compound key
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> map = (Map<String, Object>) value;
|
|
||||||
assignProperties(properties, map, key);
|
|
||||||
}
|
|
||||||
else if (value instanceof Collection) {
|
|
||||||
// Need a compound key
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Collection<Object> collection = (Collection<Object>) value;
|
|
||||||
int count = 0;
|
|
||||||
for (Object object : collection) {
|
|
||||||
assignProperties(properties,
|
|
||||||
Collections.singletonMap("[" + (count++) + "]", object), key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
properties.put(key, value == null ? "" : value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface used to process properties in a resulting map.
|
|
||||||
*/
|
|
||||||
public interface MatchCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the properties.
|
|
||||||
* @param properties the properties to process
|
|
||||||
* @param map a mutable result map
|
|
||||||
*/
|
|
||||||
void process(Properties properties, Map<String, Object> map);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strategy interface used the test if properties match.
|
|
||||||
*/
|
|
||||||
public interface DocumentMatcher {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if the given properties match.
|
|
||||||
* @param properties the properties to test
|
|
||||||
* @return the status of the match.
|
|
||||||
*/
|
|
||||||
MatchStatus matches(Properties properties);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status returned from {@link DocumentMatcher#matches(Properties)}
|
|
||||||
*/
|
|
||||||
public static enum MatchStatus {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A match was found.
|
|
||||||
*/
|
|
||||||
FOUND,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* No match was found.
|
|
||||||
*/
|
|
||||||
NOT_FOUND,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The matcher should not be considered.
|
|
||||||
*/
|
|
||||||
ABSTAIN;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare two {@link MatchStatus} items, returning the most specific status.
|
|
||||||
*/
|
|
||||||
public static MatchStatus getMostSpecific(MatchStatus a, MatchStatus b) {
|
|
||||||
return a.ordinal() < b.ordinal() ? a : b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolution methods.
|
|
||||||
*/
|
|
||||||
public static enum ResolutionMethod {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace values from earlier in the list.
|
|
||||||
*/
|
|
||||||
OVERRIDE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace values from earlier in the list, ignoring any failures.
|
|
||||||
*/
|
|
||||||
OVERRIDE_AND_IGNORE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take the first resource in the list that exists and use just that.
|
|
||||||
*/
|
|
||||||
FIRST_FOUND
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012 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.yaml;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory for Java Properties that reads from a YAML source. YAML is a nice
|
|
||||||
* human-readable format for configuration, and it has some useful hierarchical
|
|
||||||
* properties. It's more or less a superset of JSON, so it has a lot of similar features.
|
|
||||||
* The Properties created by this factory have nested paths for hierarchical objects, so
|
|
||||||
* for instance this YAML
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* environments:
|
|
||||||
* dev:
|
|
||||||
* url: http://dev.bar.com
|
|
||||||
* name: Developer Setup
|
|
||||||
* prod:
|
|
||||||
* url: http://foo.bar.com
|
|
||||||
* name: My Cool App
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* is transformed into these Properties:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* environments.dev.url=http://dev.bar.com
|
|
||||||
* environments.dev.name=Developer Setup
|
|
||||||
* environments.prod.url=http://foo.bar.com
|
|
||||||
* environments.prod.name=My Cool App
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* Lists are represented as comma-separated values (useful for simple String values) and
|
|
||||||
* also as property keys with <code>[]</code> dereferencers, for example this YAML:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* servers:
|
|
||||||
* - dev.bar.com
|
|
||||||
* - foo.bar.com
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* becomes java Properties like this:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* servers=dev.bar.com,foo.bar.com
|
|
||||||
* servers[0]=dev.bar.com
|
|
||||||
* servers[1]=foo.bar.com
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class YamlPropertiesFactoryBean extends YamlProcessor implements
|
|
||||||
FactoryBean<Properties> {
|
|
||||||
|
|
||||||
private boolean singleton = true;
|
|
||||||
|
|
||||||
private Properties instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Properties getObject() {
|
|
||||||
if (!this.singleton || this.instance == null) {
|
|
||||||
final Properties result = new Properties();
|
|
||||||
process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
result.putAll(properties);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.instance = result;
|
|
||||||
}
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return Properties.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set if a singleton should be created, or a new object on each request otherwise.
|
|
||||||
* Default is <code>true</code> (a singleton).
|
|
||||||
*/
|
|
||||||
public void setSingleton(boolean singleton) {
|
|
||||||
this.singleton = singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingleton() {
|
|
||||||
return this.singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for parsing YAML.
|
* Spring Boot extensions to Spring Framework's support for parsing YAML.
|
||||||
*
|
*
|
||||||
* @see org.springframework.boot.yaml.YamlPropertiesFactoryBean
|
* @see org.springframework.beans.factory.config.YamlPropertiesFactoryBean
|
||||||
* @see org.springframework.boot.yaml.YamlMapFactoryBean
|
* @see org.springframework.beans.factory.config.YamlMapFactoryBean
|
||||||
*/
|
*/
|
||||||
package org.springframework.boot.yaml;
|
package org.springframework.boot.yaml;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,7 +20,7 @@ import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchStatus;
|
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2013 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.yaml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.ResolutionMethod;
|
|
||||||
import org.springframework.core.io.AbstractResource;
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link YamlMapFactoryBean}.
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class YamlMapFactoryBeanTests {
|
|
||||||
|
|
||||||
private final YamlMapFactoryBean factory = new YamlMapFactoryBean();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
|
||||||
this.factory
|
|
||||||
.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
|
||||||
this.factory.setResources(new FileSystemResource[] { new FileSystemResource(
|
|
||||||
"non-exsitent-file.yml") });
|
|
||||||
assertEquals(0, this.factory.getObject().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
|
||||||
this.factory.setResources(new FileSystemResource[] { new FileSystemResource(
|
|
||||||
"non-exsitent-file.yml") });
|
|
||||||
assertEquals(0, this.factory.getObject().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetObject() throws Exception {
|
|
||||||
this.factory.setResources(new ByteArrayResource[] { new ByteArrayResource(
|
|
||||||
"foo: bar".getBytes()) });
|
|
||||||
assertEquals(1, this.factory.getObject().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
public void testOverrideAndremoveDefaults() throws Exception {
|
|
||||||
this.factory.setResources(new ByteArrayResource[] {
|
|
||||||
new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
|
||||||
new ByteArrayResource("foo:\n spam: bar".getBytes()) });
|
|
||||||
assertEquals(1, this.factory.getObject().size());
|
|
||||||
assertEquals(2,
|
|
||||||
((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFirstFound() throws Exception {
|
|
||||||
this.factory.setResolutionMethod(ResolutionMethod.FIRST_FOUND);
|
|
||||||
this.factory.setResources(new Resource[] { new AbstractResource() {
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "non-existent";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream() throws IOException {
|
|
||||||
throw new IOException("planned");
|
|
||||||
}
|
|
||||||
}, new ByteArrayResource("foo:\n spam: bar".getBytes()) });
|
|
||||||
assertEquals(1, this.factory.getObject().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMapWithPeriodsInKey() throws Exception {
|
|
||||||
this.factory.setResources(new ByteArrayResource[] { new ByteArrayResource(
|
|
||||||
"foo:\n ? key1.key2\n : value".getBytes()) });
|
|
||||||
Map<String, Object> map = this.factory.getObject();
|
|
||||||
assertEquals(1, map.size());
|
|
||||||
assertTrue(map.containsKey("foo"));
|
|
||||||
Object object = map.get("foo");
|
|
||||||
assertTrue(object instanceof LinkedHashMap);
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> sub = (Map<String, Object>) object;
|
|
||||||
assertTrue(sub.containsKey("key1.key2"));
|
|
||||||
assertEquals("value", sub.get("key1.key2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +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.
|
|
||||||
*/
|
|
||||||
package org.springframework.boot.yaml;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.rules.ExpectedException;
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchCallback;
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.yaml.snakeyaml.parser.ParserException;
|
|
||||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link YamlProcessor}.
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class YamlProcessorTests {
|
|
||||||
|
|
||||||
private final YamlProcessor processor = new YamlProcessor() {
|
|
||||||
};
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public ExpectedException exception = ExpectedException.none();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayConvertedToIndexedBeanReference() {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nbar: [1,2,3]".getBytes()) });
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals(1, properties.get("bar[0]"));
|
|
||||||
assertEquals(2, properties.get("bar[1]"));
|
|
||||||
assertEquals(3, properties.get("bar[2]"));
|
|
||||||
assertEquals(4, properties.size());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStringResource() throws Exception {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo # a document that is a literal".getBytes()) });
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("foo", map.get("document"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBadDocumentStart() throws Exception {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo # a document\nbar: baz".getBytes()) });
|
|
||||||
this.exception.expect(ParserException.class);
|
|
||||||
this.exception.expectMessage("line 2, column 1");
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBadResource() throws Exception {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()) });
|
|
||||||
this.exception.expect(ScannerException.class);
|
|
||||||
this.exception.expectMessage("line 3, column 1");
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapConvertedToIndexedBeanReference() {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nbar:\n spam: bucket".getBytes()) });
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
// System.err.println(properties);
|
|
||||||
assertEquals("bucket", properties.get("bar.spam"));
|
|
||||||
assertEquals(2, properties.size());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void integerKeyBehaves() {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\n1: bar".getBytes()) });
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("bar", properties.get("[1]"));
|
|
||||||
assertEquals(2, properties.size());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void integerDeepKeyBehaves() {
|
|
||||||
this.processor.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo:\n 1: bar".getBytes()) });
|
|
||||||
this.processor.process(new MatchCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("bar", properties.get("foo[1]"));
|
|
||||||
assertEquals(1, properties.size());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,246 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.yaml;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.rules.ExpectedException;
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.DocumentMatcher;
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.MatchStatus;
|
|
||||||
import org.springframework.boot.yaml.YamlProcessor.ResolutionMethod;
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link YamlPropertiesFactoryBean}.
|
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class YamlPropertiesFactoryBeanTests {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public ExpectedException exception = ExpectedException.none();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResource() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nspam:\n foo: baz".getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
|
||||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBadResource() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()) });
|
|
||||||
this.exception.expect(ScannerException.class);
|
|
||||||
this.exception.expectMessage("line 3, column 1");
|
|
||||||
factory.getObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourcesWithOverride() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] {
|
|
||||||
new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()),
|
|
||||||
new ByteArrayResource("foo:\n bar: spam".getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
|
||||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
|
||||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
|
||||||
public void testLoadResourcesWithInternalOverride() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nspam:\n foo: baz\nfoo: bucket".getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
|
||||||
public void testLoadResourcesWithNestedInternalOverride() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo:\n bar: spam\n foo: baz\nbreak: it\nfoo: bucket".getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourceWithMultipleDocuments() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nspam: baz\n---\nfoo: bag".getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo("baz"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourceWithSelectedDocuments() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()) });
|
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
|
||||||
: MatchStatus.NOT_FOUND;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourceWithDefaultMatch() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setMatchDefault(true);
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()) });
|
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
if (!properties.containsKey("foo")) {
|
|
||||||
return MatchStatus.ABSTAIN;
|
|
||||||
}
|
|
||||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
|
||||||
: MatchStatus.NOT_FOUND;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
|
||||||
assertThat(properties.getProperty("one"), equalTo("two"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourceWithoutDefaultMatch() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setMatchDefault(false);
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()) });
|
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
if (!properties.containsKey("foo")) {
|
|
||||||
return MatchStatus.ABSTAIN;
|
|
||||||
}
|
|
||||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
|
||||||
: MatchStatus.NOT_FOUND;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
|
||||||
assertThat(properties.getProperty("one"), nullValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setMatchDefault(true);
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"one: two\n---\nfoo: bag\nspam: bad\n---\nfoo: bar\nspam: baz".getBytes()) });
|
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
if (!properties.containsKey("foo")) {
|
|
||||||
return MatchStatus.ABSTAIN;
|
|
||||||
}
|
|
||||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
|
||||||
: MatchStatus.NOT_FOUND;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
|
||||||
assertThat(properties.getProperty("one"), equalTo("two"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadNonExistentResource() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResolutionMethod(ResolutionMethod.OVERRIDE_AND_IGNORE);
|
|
||||||
factory.setResources(new Resource[] { new ClassPathResource("no-such-file.yml") });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.size(), equalTo(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadNull() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource("foo: bar\nspam:"
|
|
||||||
.getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
|
||||||
assertThat(properties.getProperty("spam"), equalTo(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadArrayOfString() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource("foo:\n- bar\n- baz"
|
|
||||||
.getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo[0]"), equalTo("bar"));
|
|
||||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadArrayOfObject() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
|
||||||
factory.setResources(new Resource[] { new ByteArrayResource(
|
|
||||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four"
|
|
||||||
.getBytes()) });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
assertThat(properties.getProperty("foo[0].bar.spam"), equalTo("crap"));
|
|
||||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
|
||||||
assertThat(properties.getProperty("foo[2].one"), equalTo("two"));
|
|
||||||
assertThat(properties.getProperty("foo[2].three"), equalTo("four"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
public void testYaml() {
|
|
||||||
Yaml yaml = new Yaml();
|
|
||||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
|
||||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
|
||||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"),
|
|
||||||
equalTo((Object) "baz"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue