Polish
This commit is contained in:
parent
237defaf18
commit
48db5457f1
|
|
@ -105,16 +105,22 @@ public class EndpointAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HealthEndpoint healthEndpoint() {
|
||||
// The default sensitivity depends on whether all the endpoints by default are
|
||||
// secure or not. User can always override with endpoints.health.sensitive.
|
||||
boolean secure = this.management != null && this.management.getSecurity() != null
|
||||
&& this.management.getSecurity().isEnabled();
|
||||
HealthEndpoint endpoint = new HealthEndpoint(this.healthAggregator,
|
||||
this.healthIndicators);
|
||||
endpoint.setSensitive(secure);
|
||||
endpoint.setSensitive(isHealthEndpointSensitive());
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default health endpoint sensitivity depends on whether all the endpoints by
|
||||
* default are secure or not. User can always override with
|
||||
* {@literal endpoints.health.sensitive}.
|
||||
*/
|
||||
private boolean isHealthEndpointSensitive() {
|
||||
return (this.management != null) && (this.management.getSecurity() != null)
|
||||
&& this.management.getSecurity().isEnabled();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BeansEndpoint beansEndpoint() {
|
||||
|
|
|
|||
|
|
@ -224,7 +224,6 @@ public class ManagementSecurityAutoConfiguration {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
// secure endpoints
|
||||
String[] paths = getEndpointPaths(this.endpointHandlerMapping);
|
||||
if (paths.length > 0 && this.management.getSecurity().isEnabled()) {
|
||||
|
|
@ -237,27 +236,15 @@ public class ManagementSecurityAutoConfiguration {
|
|||
http.requestMatchers().antMatchers(paths);
|
||||
String[] endpointPaths = this.server.getPathsArray(getEndpointPaths(
|
||||
this.endpointHandlerMapping, false));
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests = http
|
||||
.authorizeRequests();
|
||||
authorizeRequests.antMatchers(endpointPaths).permitAll();
|
||||
if (this.endpointHandlerMapping != null) {
|
||||
authorizeRequests.requestMatchers(
|
||||
new PrincipalHandlerRequestMatcher()).permitAll();
|
||||
}
|
||||
authorizeRequests.anyRequest().hasRole(
|
||||
this.management.getSecurity().getRole());
|
||||
configureAuthorizeRequests(endpointPaths, http.authorizeRequests());
|
||||
http.httpBasic();
|
||||
|
||||
// No cookies for management endpoints by default
|
||||
http.csrf().disable();
|
||||
http.sessionManagement().sessionCreationPolicy(
|
||||
this.management.getSecurity().getSessions());
|
||||
|
||||
SpringBootWebSecurityConfiguration.configureHeaders(http.headers(),
|
||||
this.security.getHeaders());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AuthenticationEntryPoint entryPoint() {
|
||||
|
|
@ -266,12 +253,25 @@ public class ManagementSecurityAutoConfiguration {
|
|||
return entryPoint;
|
||||
}
|
||||
|
||||
private void configureAuthorizeRequests(
|
||||
String[] endpointPaths,
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry requests) {
|
||||
requests.antMatchers(endpointPaths).permitAll();
|
||||
if (this.endpointHandlerMapping != null) {
|
||||
requests.requestMatchers(new PrincipalHandlerRequestMatcher())
|
||||
.permitAll();
|
||||
}
|
||||
requests.anyRequest().hasRole(this.management.getSecurity().getRole());
|
||||
}
|
||||
|
||||
private final class PrincipalHandlerRequestMatcher implements RequestMatcher {
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return ManagementWebSecurityConfigurerAdapter.this.endpointHandlerMapping
|
||||
.isPrincipalHandler(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -287,7 +287,6 @@ public class ManagementSecurityAutoConfiguration {
|
|||
if (endpointHandlerMapping == null) {
|
||||
return NO_PATHS;
|
||||
}
|
||||
|
||||
Set<? extends MvcEndpoint> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||
for (MvcEndpoint endpoint : endpoints) {
|
||||
|
|
|
|||
|
|
@ -119,21 +119,17 @@ public class ConfigurationPropertiesReportEndpoint extends
|
|||
* {@link Map}.
|
||||
*/
|
||||
protected Map<String, Object> extract(ApplicationContext context) {
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
Map<String, Object> beans = new HashMap<String, Object>(
|
||||
context.getBeansWithAnnotation(ConfigurationProperties.class));
|
||||
ConfigurationBeanFactoryMetaData beanFactoryMetaData = null;
|
||||
if (context.getBeanNamesForType(ConfigurationBeanFactoryMetaData.class).length == 1) {
|
||||
beanFactoryMetaData = context.getBean(ConfigurationBeanFactoryMetaData.class);
|
||||
beans.putAll(beanFactoryMetaData
|
||||
.getBeansWithFactoryAnnotation(ConfigurationProperties.class));
|
||||
}
|
||||
|
||||
// Serialize beans into map structure and sanitize values
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
configureObjectMapper(mapper);
|
||||
return extract(context, mapper);
|
||||
}
|
||||
|
||||
private Map<String, Object> extract(ApplicationContext context, ObjectMapper mapper) {
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
ConfigurationBeanFactoryMetaData beanFactoryMetaData = getBeanFactoryMetaData(context);
|
||||
Map<String, Object> beans = getConfigurationPropertiesBeans(context,
|
||||
beanFactoryMetaData);
|
||||
for (Map.Entry<String, Object> entry : beans.entrySet()) {
|
||||
String beanName = entry.getKey();
|
||||
Object bean = entry.getValue();
|
||||
|
|
@ -143,14 +139,34 @@ public class ConfigurationPropertiesReportEndpoint extends
|
|||
root.put("properties", sanitize(safeSerialize(mapper, bean, prefix)));
|
||||
result.put(beanName, root);
|
||||
}
|
||||
|
||||
if (context.getParent() != null) {
|
||||
result.put("parent", extract(context.getParent()));
|
||||
result.put("parent", extract(context.getParent(), mapper));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ConfigurationBeanFactoryMetaData getBeanFactoryMetaData(
|
||||
ApplicationContext context) {
|
||||
Map<String, ConfigurationBeanFactoryMetaData> beans = context
|
||||
.getBeansOfType(ConfigurationBeanFactoryMetaData.class);
|
||||
if (beans.size() == 1) {
|
||||
return beans.values().iterator().next();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, Object> getConfigurationPropertiesBeans(
|
||||
ApplicationContext context,
|
||||
ConfigurationBeanFactoryMetaData beanFactoryMetaData) {
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.putAll(context.getBeansWithAnnotation(ConfigurationProperties.class));
|
||||
if (beanFactoryMetaData != null) {
|
||||
beans.putAll(beanFactoryMetaData
|
||||
.getBeansWithFactoryAnnotation(ConfigurationProperties.class));
|
||||
}
|
||||
return beans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cautiously serialize the bean to a map (returning a map with an error message
|
||||
* instead of throwing an exception if there is a problem).
|
||||
|
|
@ -166,7 +182,7 @@ public class ConfigurationPropertiesReportEndpoint extends
|
|||
this.metadata.extractMap(bean, prefix), Map.class));
|
||||
return result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (Exception ex) {
|
||||
return new HashMap<String, Object>(Collections.<String, Object> singletonMap(
|
||||
"error", "Cannot serialize '" + prefix + "'"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,8 @@ public class HealthEndpoint extends AbstractEndpoint<Health> {
|
|||
public HealthEndpoint(HealthAggregator healthAggregator,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
super("health", false, true);
|
||||
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||
|
||||
CompositeHealthIndicator healthIndicator = new CompositeHealthIndicator(
|
||||
healthAggregator);
|
||||
for (Map.Entry<String, HealthIndicator> h : healthIndicators.entrySet()) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@ package org.springframework.boot.actuate.endpoint.mvc;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
|
@ -41,7 +43,6 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
* The semantics of {@code @RequestMapping} should be identical to a normal
|
||||
* {@code @Controller}, but the endpoints should not be annotated as {@code @Controller}
|
||||
* (otherwise they will be mapped by the normal MVC mechanisms).
|
||||
*
|
||||
* <p>
|
||||
* One of the aims of the mapping is to support endpoints that work as HTTP endpoints but
|
||||
* can still provide useful service interfaces when there is no HTTP server (and no Spring
|
||||
|
|
@ -97,59 +98,38 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
@Override
|
||||
protected void registerHandlerMethod(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
|
||||
if (mapping == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> defaultPatterns = mapping.getPatternsCondition().getPatterns();
|
||||
String[] patterns = new String[defaultPatterns.isEmpty() ? 1 : defaultPatterns
|
||||
.size()];
|
||||
|
||||
String path = "";
|
||||
Object bean = handler;
|
||||
if (bean instanceof String) {
|
||||
bean = getApplicationContext().getBean((String) handler);
|
||||
}
|
||||
if (bean instanceof MvcEndpoint) {
|
||||
MvcEndpoint endpoint = (MvcEndpoint) bean;
|
||||
path = endpoint.getPath();
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
String prefix = StringUtils.hasText(this.prefix) ? this.prefix + path : path;
|
||||
if (defaultPatterns.isEmpty()) {
|
||||
patterns[0] = prefix;
|
||||
}
|
||||
else {
|
||||
for (String pattern : defaultPatterns) {
|
||||
patterns[i] = prefix + pattern;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns);
|
||||
|
||||
RequestMappingInfo modified = new RequestMappingInfo(patternsInfo,
|
||||
mapping.getMethodsCondition(), mapping.getParamsCondition(),
|
||||
mapping.getHeadersCondition(), mapping.getConsumesCondition(),
|
||||
mapping.getProducesCondition(), mapping.getCustomCondition());
|
||||
|
||||
String[] patterns = getPatterns(handler, mapping);
|
||||
if (handlesPrincipal(method)) {
|
||||
this.principalHandlers.add(new HandlerMethod(handler, method));
|
||||
}
|
||||
|
||||
super.registerHandlerMethod(handler, method, modified);
|
||||
super.registerHandlerMethod(handler, method, withNewPatterns(mapping, patterns));
|
||||
}
|
||||
|
||||
public boolean isPrincipalHandler(HttpServletRequest request) {
|
||||
HandlerExecutionChain handler;
|
||||
try {
|
||||
handler = getHandler(request);
|
||||
private String[] getPatterns(Object handler, RequestMappingInfo mapping) {
|
||||
String path = getPath(handler);
|
||||
String prefix = StringUtils.hasText(this.prefix) ? this.prefix + path : path;
|
||||
Set<String> defaultPatterns = mapping.getPatternsCondition().getPatterns();
|
||||
if (defaultPatterns.isEmpty()) {
|
||||
return new String[] { prefix };
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
List<String> patterns = new ArrayList<String>(defaultPatterns);
|
||||
for (int i = 0; i < patterns.size(); i++) {
|
||||
patterns.set(i, prefix + patterns.get(i));
|
||||
}
|
||||
return (handler != null && this.principalHandlers.contains(handler.getHandler()));
|
||||
return patterns.toArray(new String[patterns.size()]);
|
||||
}
|
||||
|
||||
private String getPath(Object handler) {
|
||||
if (handler instanceof String) {
|
||||
handler = getApplicationContext().getBean((String) handler);
|
||||
}
|
||||
if (handler instanceof MvcEndpoint) {
|
||||
return ((MvcEndpoint) handler).getPath();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private boolean handlesPrincipal(Method method) {
|
||||
|
|
@ -161,6 +141,32 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
return false;
|
||||
}
|
||||
|
||||
private RequestMappingInfo withNewPatterns(RequestMappingInfo mapping,
|
||||
String[] patternStrings) {
|
||||
PatternsRequestCondition patterns = new PatternsRequestCondition(patternStrings);
|
||||
return new RequestMappingInfo(patterns, mapping.getMethodsCondition(),
|
||||
mapping.getParamsCondition(), mapping.getHeadersCondition(),
|
||||
mapping.getConsumesCondition(), mapping.getProducesCondition(),
|
||||
mapping.getCustomCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given request is mapped to an endpoint and to a method
|
||||
* that includes a {@link Principal} argument.
|
||||
* @param request the http request
|
||||
* @return {@code true} if the request is
|
||||
*/
|
||||
public boolean isPrincipalHandler(HttpServletRequest request) {
|
||||
try {
|
||||
HandlerExecutionChain handlerChain = getHandler(request);
|
||||
Object handler = (handlerChain == null ? null : handlerChain.getHandler());
|
||||
return (handler != null && this.principalHandlers.contains(handler));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prefix the prefix to set
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link EndpointWebMvcAutoConfiguration} of the {@link HealthMvcEndpoint}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class HealthMvcEndpointAutoConfigurationTests {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ import org.springframework.context.annotation.Configuration;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesReportEndpoint} when used with bean methods.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ConfigurationPropertiesReportEndpointMethodAnnotationsTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ import org.springframework.context.annotation.Configuration;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesReportEndpoint} when used with a parent
|
||||
* context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ConfigurationPropertiesReportEndpointParentTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ import org.springframework.context.annotation.Import;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesReportEndpoint} serialization.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesReportEndpoint}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ConfigurationPropertiesReportEndpointTests extends
|
||||
AbstractEndpointTests<ConfigurationPropertiesReportEndpoint> {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ package org.springframework.boot.autoconfigure;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -26,7 +28,6 @@ import org.springframework.beans.factory.BeanFactory;
|
|||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
|
|
@ -90,13 +91,12 @@ public abstract class AutoConfigurationPackages {
|
|||
* @param packageNames the package names to set
|
||||
*/
|
||||
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
|
||||
|
||||
if (registry.containsBeanDefinition(BEAN)) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
|
||||
ConstructorArgumentValues constructorArguments = beanDefinition
|
||||
.getConstructorArgumentValues();
|
||||
constructorArguments.addIndexedArgumentValue(0,
|
||||
augmentBasePackages(constructorArguments, packageNames));
|
||||
addBasePackages(constructorArguments, packageNames));
|
||||
}
|
||||
else {
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
|
|
@ -108,17 +108,14 @@ public abstract class AutoConfigurationPackages {
|
|||
}
|
||||
}
|
||||
|
||||
private static String[] augmentBasePackages(
|
||||
private static String[] addBasePackages(
|
||||
ConstructorArgumentValues constructorArguments, String[] packageNames) {
|
||||
|
||||
ValueHolder valueHolder = constructorArguments.getIndexedArgumentValue(0,
|
||||
List.class);
|
||||
|
||||
List<String> packages = new ArrayList<String>(
|
||||
Arrays.asList((String[]) valueHolder.getValue()));
|
||||
packages.addAll(Arrays.asList(packageNames));
|
||||
|
||||
return packages.toArray(new String[packages.size()]);
|
||||
String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0,
|
||||
String[].class).getValue();
|
||||
Set<String> merged = new LinkedHashSet<String>();
|
||||
merged.addAll(Arrays.asList(existing));
|
||||
merged.addAll(Arrays.asList(packageNames));
|
||||
return merged.toArray(new String[merged.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -165,12 +165,12 @@ public class MongoProperties {
|
|||
public MongoClient createMongoClient(MongoClientOptions options)
|
||||
throws UnknownHostException {
|
||||
try {
|
||||
if (customAddress() || customCredentials()) {
|
||||
if (hasCustomAddress() || hasCustomCredentials()) {
|
||||
if (options == null) {
|
||||
options = MongoClientOptions.builder().build();
|
||||
}
|
||||
List<MongoCredential> credentials = null;
|
||||
if (customCredentials()) {
|
||||
if (hasCustomCredentials()) {
|
||||
credentials = Arrays.asList(MongoCredential.createMongoCRCredential(
|
||||
this.username, getMongoClientDatabase(), this.password));
|
||||
}
|
||||
|
|
@ -187,11 +187,11 @@ public class MongoProperties {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean customAddress() {
|
||||
private boolean hasCustomAddress() {
|
||||
return this.host != null || this.port != null;
|
||||
}
|
||||
|
||||
private boolean customCredentials() {
|
||||
private boolean hasCustomCredentials() {
|
||||
return this.username != null && this.password != null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar;
|
||||
import org.springframework.boot.autoconfigure.packages.one.FirstConfiguration;
|
||||
import org.springframework.boot.autoconfigure.packages.two.SecondConfiguration;
|
||||
import org.springframework.boot.autoconfigure.packagestest.one.FirstConfiguration;
|
||||
import org.springframework.boot.autoconfigure.packagestest.two.SecondConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
|
@ -66,16 +66,12 @@ public class AutoConfigurationPackagesTests {
|
|||
|
||||
@Test
|
||||
public void detectsMultipleAutoConfigurationPackages() {
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
FirstConfiguration.class, SecondConfiguration.class);
|
||||
|
||||
List<String> packages = AutoConfigurationPackages.get(context.getBeanFactory());
|
||||
|
||||
assertThat(
|
||||
packages,
|
||||
hasItems(FirstConfiguration.class.getPackage().getName(),
|
||||
SecondConfiguration.class.getPackage().getName()));
|
||||
Package package1 = FirstConfiguration.class.getPackage();
|
||||
Package package2 = SecondConfiguration.class.getPackage();
|
||||
assertThat(packages, hasItems(package1.getName(), package2.getName()));
|
||||
assertThat(packages, hasSize(2));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,24 +78,20 @@ public class MongoPropertiesTests {
|
|||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
|
||||
MongoClient client = properties.createMongoClient(null);
|
||||
|
||||
assertMongoCredential(client.getCredentialsList().get(0), "user", "secret");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uriCanBeCustomized() throws UnknownHostException {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties
|
||||
.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test");
|
||||
properties.setUri("mongodb://user:secret@mongo1.example.com:12345,"
|
||||
+ "mongo2.example.com:23456/test");
|
||||
MongoClient client = properties.createMongoClient(null);
|
||||
|
||||
List<ServerAddress> allAddresses = client.getAllAddress();
|
||||
assertEquals(2, allAddresses.size());
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
|
||||
List<MongoCredential> credentialsList = client.getCredentialsList();
|
||||
assertEquals(1, credentialsList.size());
|
||||
assertMongoCredential(credentialsList.get(0), "user", "secret");
|
||||
|
|
|
|||
|
|
@ -14,12 +14,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.packages.one;
|
||||
package org.springframework.boot.autoconfigure.packagestest.one;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests.TestRegistrar;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Sample configuration used in {@link AutoConfigurationPackagesTests}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@Import(TestRegistrar.class)
|
||||
public class FirstConfiguration {
|
||||
|
|
@ -14,12 +14,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.packages.two;
|
||||
package org.springframework.boot.autoconfigure.packagestest.two;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests.TestRegistrar;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Sample configuration used in {@link AutoConfigurationPackagesTests}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@Import(TestRegistrar.class)
|
||||
public class SecondConfiguration {
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
|
|
@ -1537,7 +1535,7 @@
|
|||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<!-- Repositories to allow snapshot and milestone BOM imports during
|
||||
<!-- Repositories to allow snapshot and milestone BOM imports during
|
||||
development. This section is stripped out when a full release is prepared. -->
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
|
|
|
|||
|
|
@ -413,16 +413,15 @@ If you don't want to expose endpoints over HTTP you can set the management port
|
|||
[[production-ready-health-access-restrictions]]
|
||||
=== Health endpoint anonymous access restrictions
|
||||
The information exposed by the health endpoint varies depending on whether or not it's
|
||||
accessed anonymously. By default, when accessed anonymously, any details about the server's health
|
||||
are hidden and the endpoint will simply indicate whether or not the server is up or
|
||||
down. Furthermore, when accessed anonymously, the response is cached for a configurable
|
||||
period to prevent the endpoint being used in a denial of service attack.
|
||||
accessed anonymously. By default, when accessed anonymously, any details about the
|
||||
server's health are hidden and the endpoint will simply indicate whether or not the server
|
||||
is up or down. Furthermore, when accessed anonymously, the response is cached for a
|
||||
configurable period to prevent the endpoint being used in a denial of service attack.
|
||||
The `endpoints.health.time-to-live` property is used to configure the caching period in
|
||||
milliseconds. It defaults to 1000, i.e. one second.
|
||||
|
||||
The above-described restrictions can be disabled, thereby allowing anonymous users full
|
||||
access to the health endpoint. To do so, set `endpoints.health.sensitive`
|
||||
to `false`.
|
||||
access to the health endpoint. To do so, set `endpoints.health.sensitive` to `false`.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -70,10 +70,7 @@ public class ConfigurationBeanFactoryMetaData implements BeanFactoryPostProcesso
|
|||
|
||||
public <A extends Annotation> A findFactoryAnnotation(String beanName, Class<A> type) {
|
||||
Method method = findFactoryMethod(beanName);
|
||||
if (method != null) {
|
||||
return AnnotationUtils.findAnnotation(method, type);
|
||||
}
|
||||
return null;
|
||||
return (method == null ? null : AnnotationUtils.findAnnotation(method, type));
|
||||
}
|
||||
|
||||
private Method findFactoryMethod(String beanName) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Really basic JSON parser for when you have nothing else available. Comes with some
|
||||
* limitations with respect to the JSON specification (e.g. only supports String values),
|
||||
* so users will probably prefer to have a library handle things instead (Jackson or Snake
|
||||
* YAML are supported).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see JsonParserFactory
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class BasicJsonParser implements JsonParser {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> parseMap(String json) {
|
||||
if (json != null) {
|
||||
json = json.trim();
|
||||
if (json.startsWith("{")) {
|
||||
return parseMapInternal(json);
|
||||
}
|
||||
else if (json.equals("")) {
|
||||
return new HashMap<String, Object>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> parseList(String json) {
|
||||
if (json != null) {
|
||||
json = json.trim();
|
||||
if (json.startsWith("[")) {
|
||||
return parseListInternal(json);
|
||||
}
|
||||
else if (json.trim().equals("")) {
|
||||
return new ArrayList<Object>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Object> parseListInternal(String json) {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
json = trimLeadingCharacter(trimTrailingCharacter(json, ']'), '[');
|
||||
for (String value : tokenize(json)) {
|
||||
list.add(parseInternal(value));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Object parseInternal(String json) {
|
||||
if (json.startsWith("[")) {
|
||||
return parseListInternal(json);
|
||||
}
|
||||
|
||||
if (json.startsWith("{")) {
|
||||
return parseMapInternal(json);
|
||||
}
|
||||
|
||||
if (json.startsWith("\"")) {
|
||||
return trimTrailingCharacter(trimLeadingCharacter(json, '"'), '"');
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.valueOf(json);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.valueOf(json);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private static String trimTrailingCharacter(String string, char c) {
|
||||
if (string.length() >= 0 && string.charAt(string.length() - 1) == c) {
|
||||
return string.substring(0, string.length() - 1);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
private static String trimLeadingCharacter(String string, char c) {
|
||||
if (string.length() >= 0 && string.charAt(0) == c) {
|
||||
return string.substring(1);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
private Map<String, Object> parseMapInternal(String json) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
json = trimLeadingCharacter(trimTrailingCharacter(json, '}'), '{');
|
||||
for (String pair : tokenize(json)) {
|
||||
String[] values = StringUtils.trimArrayElements(StringUtils.split(pair, ":"));
|
||||
String key = trimLeadingCharacter(trimTrailingCharacter(values[0], '"'), '"');
|
||||
Object value = null;
|
||||
if (values.length > 0) {
|
||||
String string = trimLeadingCharacter(
|
||||
trimTrailingCharacter(values[1], '"'), '"');
|
||||
value = parseInternal(string);
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<String> tokenize(String json) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
int index = 0;
|
||||
int inObject = 0;
|
||||
int inList = 0;
|
||||
StringBuilder build = new StringBuilder();
|
||||
while (index < json.length()) {
|
||||
char current = json.charAt(index);
|
||||
if (current == '{') {
|
||||
inObject++;
|
||||
}
|
||||
if (current == '}') {
|
||||
inObject--;
|
||||
}
|
||||
if (current == '[') {
|
||||
inList++;
|
||||
}
|
||||
if (current == ']') {
|
||||
inList--;
|
||||
}
|
||||
if (current == ',' && inObject == 0 && inList == 0) {
|
||||
list.add(build.toString());
|
||||
build.setLength(0);
|
||||
}
|
||||
else {
|
||||
build.append(current);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (build.length() > 0) {
|
||||
list.add(build.toString());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,12 +21,11 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Thin wrapper to adapt {@link JSONObject} to a {@link JsonParser}.
|
||||
* Thin wrapper to adapt {@link org.json.JSONObject} to a {@link JsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.2.0
|
||||
|
|
@ -37,29 +36,50 @@ public class JsonJsonParser implements JsonParser {
|
|||
@Override
|
||||
public Map<String, Object> parseMap(String json) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> value = (Map<String, Object>) new JSONParser()
|
||||
.parse(json);
|
||||
map.putAll(value);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Cannot parse Json", e);
|
||||
}
|
||||
putAll(map, new JSONObject(json));
|
||||
return map;
|
||||
}
|
||||
|
||||
private void putAll(Map<String, Object> map, JSONObject object) {
|
||||
for (Object key : object.keySet()) {
|
||||
String name = key.toString();
|
||||
Object value = object.get(name);
|
||||
if (value instanceof JSONObject) {
|
||||
Map<String, Object> nested = new LinkedHashMap<String, Object>();
|
||||
putAll(nested, (JSONObject) value);
|
||||
value = nested;
|
||||
}
|
||||
if (value instanceof JSONArray) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
addAll(nested, (JSONArray) value);
|
||||
value = nested;
|
||||
}
|
||||
map.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAll(List<Object> list, JSONArray array) {
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
Object value = array.get(i);
|
||||
if (value instanceof JSONObject) {
|
||||
Map<String, Object> nested = new LinkedHashMap<String, Object>();
|
||||
putAll(nested, (JSONObject) value);
|
||||
value = nested;
|
||||
}
|
||||
if (value instanceof JSONArray) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
addAll(nested, (JSONArray) value);
|
||||
value = nested;
|
||||
}
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> parseList(String json) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> value = (List<Object>) new JSONParser().parse(json);
|
||||
nested.addAll(value);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Cannot parse Json", e);
|
||||
}
|
||||
addAll(nested, new JSONArray(json));
|
||||
return nested;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ import org.springframework.util.ClassUtils;
|
|||
* @author Dave Syer
|
||||
* @see JacksonJsonParser
|
||||
* @see YamlJsonParser
|
||||
* @see SimpleJsonParser
|
||||
* @see JsonSimpleJsonParser
|
||||
* @see JsonJsonParser
|
||||
* @see BasicJsonParser
|
||||
*/
|
||||
public abstract class JsonParserFactory {
|
||||
|
||||
|
|
@ -39,19 +41,19 @@ public abstract class JsonParserFactory {
|
|||
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
|
||||
return new JacksonJsonParser();
|
||||
}
|
||||
if (ClassUtils.isPresent("org.json.JSONObject", null)) {
|
||||
return new JsonJsonParser();
|
||||
}
|
||||
if (ClassUtils.isPresent("org.json.simple.JSONObject", null)) {
|
||||
return new SimpleJsonJsonParser();
|
||||
}
|
||||
if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
|
||||
return new GsonJsonParser();
|
||||
}
|
||||
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
|
||||
return new YamlJsonParser();
|
||||
}
|
||||
return new SimpleJsonParser();
|
||||
if (ClassUtils.isPresent("org.json.simple.JSONObject", null)) {
|
||||
return new JsonSimpleJsonParser();
|
||||
}
|
||||
if (ClassUtils.isPresent("org.json.JSONObject", null)) {
|
||||
return new JsonJsonParser();
|
||||
}
|
||||
return new BasicJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
/**
|
||||
* Thin wrapper to adapt {@link org.json.simple.JSONObject} to a {@link JsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.2.0
|
||||
* @see JsonParserFactory
|
||||
*/
|
||||
public class JsonSimpleJsonParser implements JsonParser {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> parseMap(String json) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> value = (Map<String, Object>) new JSONParser()
|
||||
.parse(json);
|
||||
map.putAll(value);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException("Cannot parse JSON", ex);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> parseList(String json) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> value = (List<Object>) new JSONParser().parse(json);
|
||||
nested.addAll(value);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException("Cannot parse JSON", ex);
|
||||
}
|
||||
return nested;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +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.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Thin wrapper to adapt {@link JSONObject} to a {@link JsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.2.0
|
||||
* @see JsonParserFactory
|
||||
*/
|
||||
public class SimpleJsonJsonParser implements JsonParser {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> parseMap(String json) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
putAll(map, new JSONObject(json));
|
||||
return map;
|
||||
}
|
||||
|
||||
private void putAll(Map<String, Object> map, JSONObject object) {
|
||||
for (Object key : object.keySet()) {
|
||||
String name = key.toString();
|
||||
Object value = object.get(name);
|
||||
if (value instanceof JSONObject) {
|
||||
Map<String, Object> nested = new LinkedHashMap<String, Object>();
|
||||
putAll(nested, (JSONObject) value);
|
||||
value = nested;
|
||||
}
|
||||
if (value instanceof JSONArray) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
addAll(nested, (JSONArray) value);
|
||||
value = nested;
|
||||
}
|
||||
map.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAll(List<Object> list, JSONArray array) {
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
Object value = array.get(i);
|
||||
if (value instanceof JSONObject) {
|
||||
Map<String, Object> nested = new LinkedHashMap<String, Object>();
|
||||
putAll(nested, (JSONObject) value);
|
||||
value = nested;
|
||||
}
|
||||
if (value instanceof JSONArray) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
addAll(nested, (JSONArray) value);
|
||||
value = nested;
|
||||
}
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> parseList(String json) {
|
||||
List<Object> nested = new ArrayList<Object>();
|
||||
addAll(nested, new JSONArray(json));
|
||||
return nested;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,14 +16,6 @@
|
|||
|
||||
package org.springframework.boot.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Really basic JSON parser for when you have nothing else available. Comes with some
|
||||
* limitations with respect to the JSON specification (e.g. only supports String values),
|
||||
|
|
@ -32,140 +24,8 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @author Dave Syer
|
||||
* @see JsonParserFactory
|
||||
* @deprecated since 1.2.0 in favor of {@link BasicJsonParser}.
|
||||
*/
|
||||
public class SimpleJsonParser implements JsonParser {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> parseMap(String json) {
|
||||
if (json != null) {
|
||||
json = json.trim();
|
||||
if (json.startsWith("{")) {
|
||||
return parseMapInternal(json);
|
||||
}
|
||||
else if (json.equals("")) {
|
||||
return new HashMap<String, Object>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> parseList(String json) {
|
||||
if (json != null) {
|
||||
json = json.trim();
|
||||
if (json.startsWith("[")) {
|
||||
return parseListInternal(json);
|
||||
}
|
||||
else if (json.trim().equals("")) {
|
||||
return new ArrayList<Object>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Object> parseListInternal(String json) {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
json = trimLeadingCharacter(trimTrailingCharacter(json, ']'), '[');
|
||||
for (String value : tokenize(json)) {
|
||||
list.add(parseInternal(value));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Object parseInternal(String json) {
|
||||
if (json.startsWith("[")) {
|
||||
return parseListInternal(json);
|
||||
}
|
||||
|
||||
if (json.startsWith("{")) {
|
||||
return parseMapInternal(json);
|
||||
}
|
||||
|
||||
if (json.startsWith("\"")) {
|
||||
return trimTrailingCharacter(trimLeadingCharacter(json, '"'), '"');
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.valueOf(json);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.valueOf(json);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private static String trimTrailingCharacter(String string, char c) {
|
||||
if (string.length() >= 0 && string.charAt(string.length() - 1) == c) {
|
||||
return string.substring(0, string.length() - 1);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
private static String trimLeadingCharacter(String string, char c) {
|
||||
if (string.length() >= 0 && string.charAt(0) == c) {
|
||||
return string.substring(1);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
private Map<String, Object> parseMapInternal(String json) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
json = trimLeadingCharacter(trimTrailingCharacter(json, '}'), '{');
|
||||
for (String pair : tokenize(json)) {
|
||||
String[] values = StringUtils.trimArrayElements(StringUtils.split(pair, ":"));
|
||||
String key = trimLeadingCharacter(trimTrailingCharacter(values[0], '"'), '"');
|
||||
Object value = null;
|
||||
if (values.length > 0) {
|
||||
String string = trimLeadingCharacter(
|
||||
trimTrailingCharacter(values[1], '"'), '"');
|
||||
value = parseInternal(string);
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<String> tokenize(String json) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
int index = 0;
|
||||
int inObject = 0;
|
||||
int inList = 0;
|
||||
StringBuilder build = new StringBuilder();
|
||||
while (index < json.length()) {
|
||||
char current = json.charAt(index);
|
||||
if (current == '{') {
|
||||
inObject++;
|
||||
}
|
||||
if (current == '}') {
|
||||
inObject--;
|
||||
}
|
||||
if (current == '[') {
|
||||
inList++;
|
||||
}
|
||||
if (current == ']') {
|
||||
inList--;
|
||||
}
|
||||
if (current == ',' && inObject == 0 && inList == 0) {
|
||||
list.add(build.toString());
|
||||
build.setLength(0);
|
||||
}
|
||||
else {
|
||||
build.append(current);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (build.length() > 0) {
|
||||
list.add(build.toString());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public class SimpleJsonParser extends BasicJsonParser {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,17 +24,15 @@ import org.junit.Test;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link SimpleJsonParser}.
|
||||
* Base for {@link JsonParser} tests.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class SimpleJsonParserTests {
|
||||
public abstract class AbstractJsonParserTests {
|
||||
|
||||
private final JsonParser parser = getParser();
|
||||
|
||||
protected JsonParser getParser() {
|
||||
return new SimpleJsonParser();
|
||||
}
|
||||
protected abstract JsonParser getParser();
|
||||
|
||||
@Test
|
||||
public void testSimpleMap() {
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.json;
|
||||
|
||||
/**
|
||||
* Tests for {@link BasicJsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class BasicJsonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new BasicJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,10 +21,11 @@ package org.springframework.boot.json;
|
|||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class GsonJsonParserTests extends SimpleJsonParserTests {
|
||||
public class GsonJsonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new GsonJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ package org.springframework.boot.json;
|
|||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class JacksonParserTests extends SimpleJsonParserTests {
|
||||
public class JacksonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new JacksonJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,15 @@
|
|||
package org.springframework.boot.json;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonJsonParser}.
|
||||
* Tests for {@link JsonSimpleJsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class JsonJsonParserTests extends SimpleJsonParserTests {
|
||||
public class JsonJsonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new JsonJsonParser();
|
||||
return new JsonSimpleJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,15 @@
|
|||
package org.springframework.boot.json;
|
||||
|
||||
/**
|
||||
* Tests for {@link SimpleJsonJsonParser}.
|
||||
* Tests for {@link JsonJsonParser}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class SimpleJsonJsonParserTests extends SimpleJsonParserTests {
|
||||
public class SimpleJsonJsonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new SimpleJsonJsonParser();
|
||||
return new JsonJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ package org.springframework.boot.json;
|
|||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class YamlJsonParserTests extends SimpleJsonParserTests {
|
||||
public class YamlJsonParserTests extends AbstractJsonParserTests {
|
||||
|
||||
@Override
|
||||
protected JsonParser getParser() {
|
||||
return new YamlJsonParser();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue